【PyTorch][chapter 27][李宏毅深度学习][transformer-1]

2024-08-29 14:44

本文主要是介绍【PyTorch][chapter 27][李宏毅深度学习][transformer-1],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

           

            transformer 是深度学习四大基础架构之一,最早Google 发表在NIPS(NeurIPS 全称神经信息处理系统大会), 是一种seq2seq 的模型.采用的Encoder-Decoder 结构,应用比较广泛。

比如文本生成,语音转换,视频生成.

          相对RNN, LSTM ,transformer 可以并行计算,本篇重点介绍transformer 的Encoder 架构以及实现.

          深度学习四大基础架构

          MLP(BP), CNN, RNN, transformer


目录:

  1.     论文简介
  2.    Transorfomer 模型架构
  3.     Encoder 输入层
  4.     Transformer- Encoder  编码器
  5.     Multi-Head Attention  注意力机制
  6.     LayNorm
  7.    Transformer-Encoder PyTorch实现


一   论文简介  

     1  摘要     Abstract

      1.1   在主流的序列转录模型主要依赖循环,或者卷积神经网络,使用Encoder-Decoder 架构.

      1.2    这篇文章提出了一种新的简单的架构:transformer 核心是self-attention.

      1.3   通过机器翻译实验:  发现模型效果非常好.

   2    结论 Conclusion

    2.1:   这是一种序列转录模型. transformer主要应用了Mulite-Head Attention

    2.2:   实验效果: 在机器翻译效果比其它模型训练速度快,效果好

    2.3:预测该技术在其它领域的应用: 图片生成 ,语音生成 ,视频生成

    2.4:代码位置

3   导言  Introduction

         3.1: 现有技术:在seq2seq 里面常用的是 LSTM, RNN,GRU,CNN.

         3.2  RNN的缺陷:

                                   3.2.1  无法并行计算

                                   3.2.2  当序列特别长的时候,前面的信息会丢失。

                                   3.2.3  当序列特别长的时候,需要特别大的h 矩阵.内存开销大。

          3.3  现有技术 attention已经在编码器,解码器中应用.

          3.4 介绍 transformer 优势: 不再采用了Recurrent  架构,只使用attention 架构

                       3.4.1  可以并行计算,速度特别快

                       3.4.2  长序列,前面的信息不丢失

         

  4    相关工作 relate work

    4.1  现有技术

           4.1.1  cons2s ByteNet 利用卷积神经网络,但是难以处理长序列,优点是多输出通道

           4.1.2 self-attention: 在不同任务都表现不错

           4.1.3 End-to End 模型

   4.2 transformer:

        4.2.1   跟 RNN, Convolution 模型区别,第一个只依赖 self-attention来做

                   Encoder-Encoder的转录模型

        4.2.2 使用了mulite-head attention 

                 mulite-head 是使用cnn里面多输出通道原理


二   模型(model architecture)

                在序列转录模型里面现在较好的一个模型是Encoder-Decoder 架构,

transformer 采用的就是这种架构

               编码器

                           输入:    x_1,x_2,...x_n   

                           输出: z_1,z_2,..z_n

               解码器:  采用自回归模型

                               输入: z_1,z_2,..z_n     输出  y_1 。

                               根据y_1得到y_2

                               根据y_1,y_2得到 y_3

        

     


三  Encoder 输入层  

       

         输入的是一个句子:

         1   先提取词向量信息 X(Input Embedding)(batch_size,seq_length, input_size)

         2   再通过Positional Encoding 提取词向量的位置信息 PE(X)

         3   最后得到 含有位置信息的词向量 X=X+PE(X)

        


四   Transformer- Encoder  编码器

         Encoder 由 N=5 相同的layer 组成.

        每个layer  由2个sub-layer 组成

     4.1  第一个sublayer

     

   

          multi-Head attention->residual add->layerNorm

                          LayerNorm(x+sublayer(x))

4.2     第二个  sub-layer:

 position-wise Feed Forward->residual add->layerNorm

                        LayerNorm(x+sublayer(x))

       4.3    为什么叫simple,因为每个sub-layer 都是相同的

                   同时每个sub-layer 输出都是  d_{model}=512

       4.4  masked

                   这个在Decoder 时候用到

                  原因:  t时刻不应该看到t时刻以后的东西

                   假设query ,key  特征大小都是N

                   计算attention score 的时候,Q_t 只希望看到k_1,k_2,...k_t,

                  不希望看到[k_{t+1},..k_N]

                   方案: 把之后的score 设置成特别小的数-1e10 ,再通过softmax

             计算得到的结果接近为0

           

                 


 

     4.5  FFN

   

 最后还包含一个全连接的feed-forward network . 由两个线性层组成,激活函数是ReLUa_1=ReLu(xW_1+b_1)W_1 \in R^{[512,2048]}

a_2= a_1W_2+b_2:W_1 \in R^{[2048,512]}


五 Multi-Head Attention  注意力机制

    卷积神经网络多通道输出,Multi-Head 也是利用其特性,实现多通道效果

   5.1 模型结构

      把Q,K,V 投影到一个低维度空间,投影到低维空间(head_size=8),然后单独做

Scaled Dot-Product Attention ,最后对得到的结果重新Concat,

h=8,d_{model}=512,d_k=d_v=\frac{d_{model}}{h}=64

   5.2    Scaled Dot-product Attention

         有两种注意力机制 additive attention & dot-product

     这里主要用的是dot-prodct,区别是除以\sqrt{d_k},   除以 \sqrt{d_k} 原因

  当d_k 较小的时候可以不除,论文里面d_k=512/8

 d_k较大的时候,两个向量的内积较大,值最大的做softmax 后接近为1,其它的接近为0,

计算得到的梯度也小 

   


六    LayNorm

      

      6.1 输入shape X.shape  =[batch, feature]

       Batch Normalizaiton ,按列切分样本, 统计其均值和方差,归一化

       layer  Normalizaition ,  按行切分样本, 统计其均值和方差,归一化

   6.2  输入 X.shape =[batch, seq_length, feature]

     Batch Normalization: 按照黑色方向切分样本,flatten后,统计其均值方差

     Layer Normalization:   按照黑色方向切分样本,flatten后,统计其均值方差

      6.3  原因

          在时序预测的时候,样本的seq_length 可能会发生变化

         Batch Nomralization  切出来的样本如下:样本长度变化较大的时候,算出来的均值和方差变化较大。当预测的时候会使用全局的均值和方差,导致误差较大

  

# -*- coding: utf-8 -*-
"""
Created on Mon Aug  5 22:55:46 2024

@author: cxf
"""

import torch
import torch.nn as nn

x = torch.tensor([   [1.0,1.0,1.0],
                     [1.0,2.0,4.0],
                     [1.0,5.0,5.0],
                     [1.0,3.0,4.0]])

batchNorm = nn.BatchNorm1d(num_features=3)

y = batchNorm(x)
print("\n BatchNorm: ",y)
#layerNorm

layerNorm = nn.LayerNorm(3)
out = layerNorm(x)
print("\n layerNorm: ",out)


七  代码实现

   论文超参数

   

# -*- coding: utf-8 -*-
"""
Created on Sun Aug 25 15:36:03 2024@author: cxf
"""
import torch
import torch.nn as nn
import mathclass  PositionalEncoding(nn.Module):def __init__(self,max_seq_len=1e3, d_model=512):super(PositionalEncoding,self).__init__()pe = torch.zeros((max_seq_len,d_model))div_even =torch.pow(1e4,torch.arange(0, 512, 2)/d_model)div_odd = torch.pow(1e4,torch.arange(1, 512, 2)/d_model)position = torch.arange(0, max_seq_len).unsqueeze(1)pe[:,0::2]= torch.sin(position/div_even)pe[:,1::2]= torch.cos(position/div_odd)pe=pe.unsqueeze(0)self.register_buffer('pe', pe)def forward(self, x):batch_size, seq_len,embedding_size = x.shapex =x +self.pe[:,:seq_len,:].clone().detach()return xclass ScaledDotProduct_Attention(nn.Module):def __init__(self):super(ScaledDotProduct_Attention,self).__init__()self.softMax = nn.Softmax(dim=2)def forward(self, Q=None, K=None, V=None, attn_fill = None):batch_size, n_heads, seq_len,d_k = Q.shapescale = torch.matmul(Q,K.transpose(2,3))score = scale/math.sqrt(d_k**0.5)if attn_fill  is not None:score = scale.mask_fill(score,-1e9)attn_score = self.softMax(score)out = torch.matmul(attn_score,V)return outclass FFN(nn.Module):def __init__(self,input_size=512):super(FFN, self).__init__()self.net = nn.Sequential(nn.Linear(in_features=input_size, out_features=input_size*2),nn.ReLU(),nn.Linear(in_features=input_size*2, out_features=input_size))def forward(self,x):out = self.net(x)return outclass BlockAttention(nn.Module):def __init__(self, embedding_size, d_k,head_size):super(BlockAttention, self).__init__()self.layer_attention = MultiHeadAttention(embedding_size=512, d_k=64, head_size=8)self.layer_normal = nn.LayerNorm(embedding_size)def forward(self, x):x_residual = self.layer_attention(x,None)out = x_residual+xy = self.layer_normal(out)return yclass BlockFFN(nn.Module):def __init__(self, embedding_size):super(BlockFFN, self).__init__()self.layer_ffn = FFN()self.layer_normal = nn.LayerNorm(embedding_size)def forward(self, x):x_residual = self.layer_ffn(x)out = x_residual+xy = self.layer_normal(out)return yclass Encoder(nn.Module):def __init__(self,n=5,max_seq_len=1000,embedding_size=512,head_size=8):super(Encoder,self).__init__()d_k = int(embedding_size/head_size)self.layer_pe = PositionalEncoding(seq_len,embedding_size)layer = nn.Sequential(BlockAttention(embedding_size, d_k,head_size),BlockFFN(embedding_size))self.layers = nn.Sequential(*[layer for _ in range(n)])def forward(self, x):y = self.layers(x)return yclass MultiHeadAttention(nn.Module):def __init__(self,embedding_size=512, d_k=64, head_size=8):super(MultiHeadAttention,self).__init__()#[batch,seq_len, embedding_size]self.W_Q = nn.Linear(embedding_size, embedding_size)self.W_k = nn.Linear(embedding_size, embedding_size)self.W_V = nn.Linear(embedding_size, embedding_size)self.attention_layer = ScaledDotProduct_Attention()self.linear_layer = nn.Linear(in_features=embedding_size, out_features=embedding_size)self.head_size = head_sizeself.d_model = embedding_sizeself.d_k = d_kdef forward(self, inputs, attn_mask):#inputs.shape  [batch, seq_len, embedding_size]batch_size, seq_num, embedding_size = inputs.shapeQ = self.W_Q(inputs)K = self.W_k(inputs)V = self.W_V(inputs)#[batch,seq_num,nheads, d_k]->[batch,head_size, seq_num,d_k]subQ = Q.view(batch_size, -1,self.head_size,self.d_k).transpose(1,2)subK = K.view(batch_size, -1,self.head_size,self.d_k).transpose(1,2)subV = V.view(batch_size, -1,self.head_size,self.d_k).transpose(1,2)#[batch,head_size, seq_len, d_k]Z =self.attention_layer(subQ,subK, subV)#[batch, seq_len, d_k*n_heads]Z= Z.transpose(1,2).contiguous().view(batch_size,-1, self.d_model)print(Z.shape)out = self.linear_layer(Z)return outif __name__ == "__main__":max_seq_len =int(1e3)batch_size = 2embedding_size = 512head_size = 8d_k = int(embedding_size/head_size)seq_len = 3N = 5inputs = torch.rand(batch_size, seq_len, embedding_size)encoder = Encoder(N,max_seq_len,embedding_size,head_size)print(encoder)out = encoder(inputs)

参考:

3.【李宏毅机器学习2021】Transformer (上)_哔哩哔哩_bilibili

这篇关于【PyTorch][chapter 27][李宏毅深度学习][transformer-1]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1118155

相关文章

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Python中文件读取操作漏洞深度解析与防护指南

《Python中文件读取操作漏洞深度解析与防护指南》在Web应用开发中,文件操作是最基础也最危险的功能之一,这篇文章将全面剖析Python环境中常见的文件读取漏洞类型,成因及防护方案,感兴趣的小伙伴可... 目录引言一、静态资源处理中的路径穿越漏洞1.1 典型漏洞场景1.2 os.path.join()的陷

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Pytorch介绍与安装过程

《Pytorch介绍与安装过程》PyTorch因其直观的设计、卓越的灵活性以及强大的动态计算图功能,迅速在学术界和工业界获得了广泛认可,成为当前深度学习研究和开发的主流工具之一,本文给大家介绍Pyto... 目录1、Pytorch介绍1.1、核心理念1.2、核心组件与功能1.3、适用场景与优势总结1.4、优