机器学习笔记 - EANet 外部注意论文简读及代码实现

news2024/11/26 0:29:38

一、论文简述

        论文作者提出了一种新的轻量级注意力机制,称之为外部注意力。如图所示,计算自注意力需要首先通过计算自查询向量和自关键字向量之间的仿射关系来计算注意力图,然后通过用该注意力图加权自值向量来生成新的特征图。外部关注的作用不同。我们首先通过计算自查询向量和外部可学习密钥存储器之间的亲和力来计算注意力图,然后通过将该注意力图乘以另一个外部可学习值存储器来生成细化的特征图。

         在实践中,这两个存储器是用线性层实现的,因此可以通过端到端的反向传播来优化。它们独立于单个样本,并在整个数据集中共享,这起到了很强的正则化作用,提高了注意力机制的泛化能力。外部注意力的轻量级本质的关键在于,存储器中的元素数量远小于输入特征中的元素数目,从而产生输入中元素数目线性的计算复杂度。外部存储器旨在学习整个数据集中最具鉴别力的特征,捕捉信息量最大的部分,并排除其他样本中的干扰信息。类似的想法可以在稀疏编码[9]或字典学习中找到。然而,与这些方法不同的是,我们既没有尝试重建输入特征,也没有对注意力图应用任何显式稀疏正则化。

        尽管所提出的外部注意力方法很简单,但它对各种视觉任务都是有效的。由于其简单性,它可以很容易地融入现有流行的基于自注意的架构中,如DANet、SAGAN和T2T Transformer。图3展示了一个典型的架构,该架构将图像语义分割任务的自我注意力替换为外部注意力。我们使用不同的输入模式(图像和点云),对分类、对象检测、语义分割、实例分割和生成等基本视觉任务进行了广泛的实验。结果表明,我们的方法获得的结果与原始的自注意机制及其一些变体相当或更好,以低得多的计算成本。

使用我们提出的外部注意力进行语义分割的EANet架构。

二、相关参考代码

1、基于torch的实现

        外部注意力实现

import numpy as np
import torch
from torch import nn
from torch.nn import init

class ExternalAttention(nn.Module):

    def __init__(self, d_model,S=64):
        super().__init__()
        self.mk=nn.Linear(d_model,S,bias=False)
        self.mv=nn.Linear(S,d_model,bias=False)
        self.softmax=nn.Softmax(dim=1)
        self.init_weights()


    def init_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                init.kaiming_normal_(m.weight, mode='fan_out')
                if m.bias is not None:
                    init.constant_(m.bias, 0)
            elif isinstance(m, nn.BatchNorm2d):
                init.constant_(m.weight, 1)
                init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                init.normal_(m.weight, std=0.001)
                if m.bias is not None:
                    init.constant_(m.bias, 0)

    def forward(self, queries):
        attn=self.mk(queries) #bs,n,S
        attn=self.softmax(attn) #bs,n,S
        attn=attn/torch.sum(attn,dim=2,keepdim=True) #bs,n,S
        out=self.mv(attn) #bs,n,d_model

        return out


if __name__ == '__main__':
    input=torch.randn(50,49,512)
    ea = ExternalAttention(d_model=512,S=8)
    output=ea(input)
    print(output.shape)

        调用参考

input=torch.randn(50,49,512)
ea = ExternalAttention(d_model=512,S=8)
output=ea(input)
print(output.shape)

2、基于tensorflow的EANet实现

        EANet只是用外部注意力代替了Vit中的自我注意力。

        这里的数据集是采用cifar100数据集,首先加载划分数据集,然后配置超参数

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import tensorflow_addons as tfa
import matplotlib.pyplot as plt



num_classes = 100
input_shape = (32, 32, 3)

(x_train, y_train), (x_test, y_test) = keras.datasets.cifar100.load_data()
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
print(f"x_train shape: {x_train.shape} - y_train shape: {y_train.shape}")
print(f"x_test shape: {x_test.shape} - y_test shape: {y_test.shape}")



weight_decay = 0.0001
learning_rate = 0.001
label_smoothing = 0.1
validation_split = 0.2
batch_size = 128
num_epochs = 50
patch_size = 2  # Size of the patches to be extracted from the input images.
num_patches = (input_shape[0] // patch_size) ** 2  # Number of patch
embedding_dim = 64  # Number of hidden units.
mlp_dim = 64
dim_coefficient = 4
num_heads = 4
attention_dropout = 0.2
projection_dropout = 0.2
num_transformer_blocks = 8  # Number of repetitions of the transformer layer

print(f"Patch size: {patch_size} X {patch_size} = {patch_size ** 2} ")
print(f"Patches per image: {num_patches}")

        进行数据增强

data_augmentation = keras.Sequential(
    [
        layers.Normalization(),
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(factor=0.1),
        layers.RandomContrast(factor=0.1),
        layers.RandomZoom(height_factor=0.2, width_factor=0.2),
    ],
    name="data_augmentation",
)
# Compute the mean and the variance of the training data for normalization.
data_augmentation.layers[0].adapt(x_train)

        实现补丁提取和编码层‘

class PatchExtract(layers.Layer):
    def __init__(self, patch_size, **kwargs):
        super().__init__(**kwargs)
        self.patch_size = patch_size

    def call(self, images):
        batch_size = tf.shape(images)[0]
        patches = tf.image.extract_patches(
            images=images,
            sizes=(1, self.patch_size, self.patch_size, 1),
            strides=(1, self.patch_size, self.patch_size, 1),
            rates=(1, 1, 1, 1),
            padding="VALID",
        )
        patch_dim = patches.shape[-1]
        patch_num = patches.shape[1]
        return tf.reshape(patches, (batch_size, patch_num * patch_num, patch_dim))


class PatchEmbedding(layers.Layer):
    def __init__(self, num_patch, embed_dim, **kwargs):
        super().__init__(**kwargs)
        self.num_patch = num_patch
        self.proj = layers.Dense(embed_dim)
        self.pos_embed = layers.Embedding(input_dim=num_patch, output_dim=embed_dim)

    def call(self, patch):
        pos = tf.range(start=0, limit=self.num_patch, delta=1)
        return self.proj(patch) + self.pos_embed(pos)

        实现外部注意力块

def external_attention(
    x, dim, num_heads, dim_coefficient=4, attention_dropout=0, projection_dropout=0
):
    _, num_patch, channel = x.shape
    assert dim % num_heads == 0
    num_heads = num_heads * dim_coefficient

    x = layers.Dense(dim * dim_coefficient)(x)
    # create tensor [batch_size, num_patches, num_heads, dim*dim_coefficient//num_heads]
    x = tf.reshape(
        x, shape=(-1, num_patch, num_heads, dim * dim_coefficient // num_heads)
    )
    x = tf.transpose(x, perm=[0, 2, 1, 3])
    # a linear layer M_k
    attn = layers.Dense(dim // dim_coefficient)(x)
    # normalize attention map
    attn = layers.Softmax(axis=2)(attn)
    # dobule-normalization
    attn = attn / (1e-9 + tf.reduce_sum(attn, axis=-1, keepdims=True))
    attn = layers.Dropout(attention_dropout)(attn)
    # a linear layer M_v
    x = layers.Dense(dim * dim_coefficient // num_heads)(attn)
    x = tf.transpose(x, perm=[0, 2, 1, 3])
    x = tf.reshape(x, [-1, num_patch, dim * dim_coefficient])
    # a linear layer to project original dim
    x = layers.Dense(dim)(x)
    x = layers.Dropout(projection_dropout)(x)
    return x

        实施 MLP

def mlp(x, embedding_dim, mlp_dim, drop_rate=0.2):
    x = layers.Dense(mlp_dim, activation=tf.nn.gelu)(x)
    x = layers.Dropout(drop_rate)(x)
    x = layers.Dense(embedding_dim)(x)
    x = layers.Dropout(drop_rate)(x)
    return x

        实现变压器模块,基于参数配置选择外部注意或是自我关注。

def transformer_encoder(
    x,
    embedding_dim,
    mlp_dim,
    num_heads,
    dim_coefficient,
    attention_dropout,
    projection_dropout,
    attention_type="external_attention",
):
    residual_1 = x
    x = layers.LayerNormalization(epsilon=1e-5)(x)
    if attention_type == "external_attention":
        x = external_attention(
            x,
            embedding_dim,
            num_heads,
            dim_coefficient,
            attention_dropout,
            projection_dropout,
        )
    elif attention_type == "self_attention":
        x = layers.MultiHeadAttention(
            num_heads=num_heads, key_dim=embedding_dim, dropout=attention_dropout
        )(x, x)
    x = layers.add([x, residual_1])
    residual_2 = x
    x = layers.LayerNormalization(epsilon=1e-5)(x)
    x = mlp(x, embedding_dim, mlp_dim)
    x = layers.add([x, residual_2])
    return x

        实施 EANet 模型

def get_model(attention_type="external_attention"):
    inputs = layers.Input(shape=input_shape)
    # Image augment
    x = data_augmentation(inputs)
    # Extract patches.
    x = PatchExtract(patch_size)(x)
    # Create patch embedding.
    x = PatchEmbedding(num_patches, embedding_dim)(x)
    # Create Transformer block.
    for _ in range(num_transformer_blocks):
        x = transformer_encoder(
            x,
            embedding_dim,
            mlp_dim,
            num_heads,
            dim_coefficient,
            attention_dropout,
            projection_dropout,
            attention_type,
        )

    x = layers.GlobalAvgPool1D()(x)
    outputs = layers.Dense(num_classes, activation="softmax")(x)
    model = keras.Model(inputs=inputs, outputs=outputs)
    return model

        进行训练并可视化

model = get_model(attention_type="external_attention")

model.compile(
    loss=keras.losses.CategoricalCrossentropy(label_smoothing=label_smoothing),
    optimizer=tfa.optimizers.AdamW(
        learning_rate=learning_rate, weight_decay=weight_decay
    ),
    metrics=[
        keras.metrics.CategoricalAccuracy(name="accuracy"),
        keras.metrics.TopKCategoricalAccuracy(5, name="top-5-accuracy"),
    ],
)

history = model.fit(
    x_train,
    y_train,
    batch_size=batch_size,
    epochs=num_epochs,
    validation_split=validation_split,
)


model.save('eanet_cifar100.h5')

plt.plot(history.history["loss"], label="train_loss")
plt.plot(history.history["val_loss"], label="val_loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.title("Train and Validation Losses Over Epochs", fontsize=14)
plt.legend()
plt.grid()
plt.show()

         进行验证

loss, accuracy, top_5_accuracy = model.evaluate(x_test, y_test)
print(f"Test loss: {round(loss, 2)}")
print(f"Test accuracy: {round(accuracy * 100, 2)}%")
print(f"Test top 5 accuracy: {round(top_5_accuracy * 100, 2)}%")

三、相关参考

arxiv.org/pdf/2105.02358.pdfhttps://arxiv.org/pdf/2105.02358.pdfExternal-Attention-pytorch/ExternalAttention.py at master · xmu-xiaoma666/External-Attention-pytorch · GitHubhttps://github.com/xmu-xiaoma666/External-Attention-pytorch/blob/master/model/attention/ExternalAttention.py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/629954.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

条款29:假定移动操作不存在、成本高、未使用

移动语义可以说在C11的所有语言特性中占据着首要中的首要地位。“移动容器现在和复制指针一样成本低廉了!”这是你很可能听说过的,类似说法还有“复制临时对象现在已经如此高效,如果刻意在撰写代码总避免它,就无异于犯了过早优化的…

java SSM 程序在线评判系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM 程序在线评判系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采…

PDCA循环

PDCA循环 由美国质量管理专家沃特阿曼德休哈特(Walter A. Shewhart)首先提出的,由戴明采纳、宣传,获得普及,所以又称戴明环。 模型介绍 戴明是一位美国的质量管理大师,却成名于日本。在他的帮助下&#xf…

JQuery 操作Class实现前段交互方案(推荐)

一、JQuery基础控制图片宽度实现动画交互 1.html页面声明周期 //页面生命周期 //页面的数据html,加载完成, 图片ajax视频 在异步加载中 //document.ready---DOMContentLoaded ----小程序onload ---Vue created() //页面加载完成 //window.onload…

二叉树的相关操作

一.二叉树 本文的数据结构基于C语言练习。 C语言中的二叉树是一种数据结构,用于表示具有层次关系的数据集合。它由一个根节点开始,每个节点最多有两个子节点,分别称为左子节点和右子节点。 二叉树有许多相关性质,其中一些重要的包…

记录一下idea黄色警戒线问题

记录一下idea黄色警戒线问题 一、通用文件中解决黄色波浪线问题1.选中File中的Settings进入2.点击Editor,选中Inspections,找到General,找到Dulicated code fragment点击取消 二、SQL文件中黄色警告线 一、通用文件中解决黄色波浪线问题 1.选…

jvm之7种垃圾回收器解读(下)

目录 G1回收器:区域化分代式 G1回收器的特点(优势) 空间整合 可预测的停顿时间模型(即:软实时soft real-time) G1垃圾收集器的缺点 G1回收器的参数设置 G1收集器的常见操作步骤 G1收集器的适用场景 分…

Spring SpringMVC Mybatis 整合 SSM整合 一篇就够了!

SSM详细整合教程 因为XML注解方式实现更加方便,所以我门选用它 文章目录 SSM详细整合教程一、整合思路二、整合步骤0. 前期准备引入Jar包与Web目录创建1. Spring框架编写1.1 创建Application配置文件 2. SpringMvc框架编写2.1 创建Springmvc-config文件2. 2 配置前端…

用栈模拟实现队列(c语言版)

前言 用"栈实现队列",力扣中一道oj题,可以帮助刚接触"栈"和"队列"的新手更好的理解栈和队列这两种结构. 题目来源于力扣: 题目链接:https://leetcode.cn/problems/implement-queue-using-stacks/ 难度:简单 目录 前言一、队列的各接口:1.1 类型…

机器学习实战六步法之数据收集方法(四)

要落地一个机器学习的项目,是有章可循的,通过这六个步骤,小白也能搞定机器学习。 看我闪电六连鞭!🤣 数据收集 数据是机器学习的基础,没有数据一切都是空谈!数据集的数据量和数据的质量往往决…

潮牌搭配APP的设计与实现

摘 要:本文开发过程以android为中心,通过数据库进行的数据访问操作。软件以面向对象的思维进行开发和设计,针对于广大群众进行下载使用,对用户提供了时尚的搭配,带领用户形成自己的一套搭配系统,做自己搭配…

C++ std::thread 与Qt qthread多线程混合编程

C与Qt深度融合:高效设计多线程应用框架 1. C与Qt线程的混合使用1.1 C线程与Qt线程的基本概念1.2 线程间的相互依赖关系1.3 设计合理的代码框架 二、深入理解C和Qt线程模型2.1 C线程模型2.2 Qt线程模型2.3 C和Qt线程模型的比较 三、C和Qt线程间的互操作性3.1 std::th…

Web应用技术(第十六周/END)

本次练习基于how2j的教程完成对SpringBoot的初步学习。 初识Springboot 学习导入:1.第一个基于SpringBoot的项目:(1)application.java:该文件中的核心代码: (2)HelloController.java…

浅结代码混淆2

文章目录 SMC 自解码什么是SMC?原理示例动调 mov混淆 SMC 自解码 什么是SMC? 简而言之,就是程序中的部分代码在运行之前被加密成一段数据,不可反编译,通过程序运行后执行相关的解码功能,对加密…

Nginx搭建Https反向代理,使用阿里云免费SSL证书 - Docker

Docker安装Nginx - 需要有域名 没有docker需提前安装docker,不知怎么安装的请自行百度。 1、拉取镜像 docker pull nginx2、去阿里云或者其他云服务提供商申请免费证书,申请到之后下载下来,上传到服务器 # 创建nginx-proxy目录 mkdir ngi…

软考A计划-系统架构师-官方考试指定教程-(13/15)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

IP签名档PHP开源版:轻松打造网站个性签名档

今天,我们将为大家介绍一个有趣的IP签名档项目。通过将源代码部署在服务器上,您可以轻松地为自己的社交媒体、论坛等地创建一个独特的签名档,使您的网站更加出彩! 接下来,我们将详细向大家展示如何搭建PHP开源版IP签名…

ASP.NET Core Web API入门之一:创建新项目

ASP.NET Core Web API入门之一:创建新项目 一、引言二、创建新项目三、加入Startup类,并替换Program.cs内容四、编辑Program.cs代码五、修改控制器的路由六、运行项目 一、引言 最近闲着,想着没真正从0-1开发过ASP.NET Core Web API的项目&a…

SpringMVC原理分析 | Hello程序

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! SpringMVC Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 Servlet; 拥有结构最清晰的 ServletJSPJav…

uni-app APP、html引入html2canvas截图以及截长图

下载安装html2canvas 方式一,https://www.bootcdn.cn/ CDN网站下载html2canvas插件 这里下载后放在测项目目录common下面 页面中引入 方式二、npm方式安装html2canvas 1、npm方式下载 npm i html2canvas2、引入html2canvas import html2canvas from html2can…