Transformer代码理解

本文介绍了Transformer模型的结构,特别是Embedding层如何将图像分解为小patch并转换为向量,以及自注意力机制的工作原理。作者通过实例和代码解释了这两个关键部分,展示了Transformer从泛化学习到细致化学习的进化过程。


前言

论文中对Transformer的定义

Transformer is the first transduction model relying entirely on self-attention to compute representations of its input and output without using sequence aligned RNNs or convolution。

自从具有强大编码能力的Transformer提出来以后,在机器学习的各大领域中几乎无处不在,而他的效果也确实非常的好。从个人认知的角度来看,从全连接到CNN,再到Transformer的历程,其实是机器学习的模式从一种“泛化式”学习(只看重结果而忽略学习过程的细节)过渡到“条理化”学习形式(开始注重学习过程),再转到“细致化”学习(十分强调学习过程的细节)升级过程。最近也正在学Vision Transformer,看了网上很多博客都做了非常好的总结,奈何自己不懂的地方实在太多,于是自己简单的做一个整理,争取理解透彻。🧐

一、模型结构

整个结构可以将其大致分为3个部分:

  1. Embedding层:将图像转换成一个序列。
  2. Transformer Encoder
  3. MLP Head

这里附上Wz大佬绘制的结构图:
在这里插入图片描述

二、原理解析

1.Linear Projection of Flattened Patches(Embedding层)

在这里插入图片描述

  • 对模型而言,输入的要求是Token(向量)序列,其大小为[num_token,token_dim]
    其实这一结构的主要作用就是将一张图片分解成若干张小图片,再将其小图片转换成向量
  • 结合上面论文中的原理图和下面的图以及代码部分来理解这个过程:
    在这里插入图片描述
class PatchEmbed(nn.Module):
    def __init__(self,img_size=224,patch_size=16,in_c=3,embed_dim=768,norm_layer=None):
        super(PatchEmbed,self).__init__()
        img_size = (img_size,img_size)
        patch_size = (patch_size,patch_size)
        self.img_size = img_size
        self.patch_size = patch_size
        self.grid_size = (img_size[0] // patch_size[0],img_size[1] // patch_size[1])
        self.num_patches = self.grid_size[0] * self.grid_size[1]
         
        self.proj = nn.Conv2d(in_c,embed_dim,kernel_size=patch_size,stride=patch_size)
        self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity()

    def forward(self,x):
        B,C,H,W = x.shape
        assert H==self.img_size[0]  and W ==self.img_size[1],f"Input image size ({H}*{W}) doesn't match model ({sefl.img_size[0]}*{self.img_size[1]})."
        # flatten:[B,C,H,W] -->  [B,C,HW]
        # transpose:[B,C,HW] --> [B,HW,C]
        x = self.proj(x).flatten(2).transpose(1,2)
        x = self.norm(x)
        return x

2.自注意力机制

在这里插入图片描述

  • 具体原理可以参考Wz大佬写的内容,文末附有链接,写的非常详细。
  • 下面结合自己的理解图看代码部分:
    在这里插入图片描述
class Attention(nn.Module):
    def __init__(self,
                dim,    #输入token的dim 
                num_heads = 8,
                qkv_bias = False,
                qk_scale = None,
                attn_drop_ratio = 0.,
                proj_drop_ratio = 0.):
        super(Attention,self).__init__()
        self.num_heads = num_heads
        head_dim = dim // num_heads
        self.scale = qk_scale or head_dim ** -0.5
        self.qkv = nn.Linear(dim,dim*3,bias=qkv_bias)
        self.attn_drop = nn.Dropout(attn_drop_ratio)
        self.proj = nn.Linear(dim,dim)
        self.proj_drop = nn.Dropout(proj_drop_ratio)

    def forward(self, x):
        B,N,C = x.shape
        # [barch_size,num_patches + 1,total_embed_dim]

        qkv = self.qkv(x).reshape(B,N,3,self.num_heads,C // self.num_heads).permute(2,0,3,1,4)
        # self.qkv(): ->[batch_size,num_patches + 1,3*total_embed_dim]
        # reshape:  ->[batch_size,num_patches + 1,3,num_heads,embed_dim_per_head]
        # permute:  ->[3,batch_size,num_heads,num_patches + 1,embed_dim_per_head]

        q,k,v = qkv[0],qkv[1],qkv[2]
        
        # transpose:  ->[batch_size,num_heads,embed_dim_per_head,num_patches + 1]
        # @:  ->[batch_size,num_heads,num_patches + 1,num_patches + 1]
        attn = (q @ k.transpose(-2,-1)) * self.scale
        attn = attn.softmax(dim=-1)
        attn = self.attn_drop(attn)

		# @: multiply -> [batch_size, num_heads, num_patches + 1, embed_dim_per_head]
        # transpose: -> [batch_size, num_patches + 1, num_heads, embed_dim_per_head]
        # reshape: -> [batch_size, num_patches + 1, total_embed_dim]
        x = (attn @ v).transpose(1,2).reshape(B,N,C)
        x = self.proj(x)
        x = self.proj_drop(x)
        return x

参考文章

http://t.csdnimg.cn/Oay5D

Transformer模型是一种用于机器翻译等任务的神经网络架构。它由encoders和decoders两部分组成,其中encoders和decoders都是由多个encoder/decoder堆叠而成。每个encoder包含self-attention和feed forward两个层,而每个decoder包含mask self-attention、encoder-decoder attention和feed forward三个层。这些层的组合形成了Transformer模型的总体结构。 在Transformer模型中,self-attention是一个重要的机制。它允许模型在处理输入序列时同时考虑序列中的所有位置。通过计算每个位置与其他位置的相关性,self-attention可以为每个位置生成一个权重向量,用来表示该位置对其他位置的重要性。这样,模型就可以根据不同位置的重要性来调整输入序列的表示。通过多层的self-attention操作,Transformer模型能够捕捉到序列中的长期依赖关系,从而提高翻译等任务的性能。 关于容易理解Transformer代码,你可以参考一些开源的实现。一个常用的开源项目是"transformers"库,它提供了多种预训练的Transformer模型以及相应的代码示例。你可以通过查阅该库的文档和示例代码来深入理解Transformer模型的实现细节。此外,还可以参考一些教程和博客文章,它们通常会提供更加详细和易于理解代码示例,帮助你更好地理解Transformer模型的工作原理。 请注意,为了更好地理解代码,建议你边阅读边实践,并结合注释来加深理解。同时,也可以参考一些论坛和社区,与其他开发者交流和讨论,以便更好地理解和应用Transformer模型。 参考文献: [引用1] [引用2] [引用3<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Transformer 代码+原理](https://blog.csdn.net/init__/article/details/121585137)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Python Transformer模型笔记.md](https://download.csdn.net/download/weixin_52057528/88226096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaeeeeeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值