关于transformer的学习2

transformer 框架(根据李宏毅老师的视频整理的笔记)
在这里插入图片描述
左边的是encoder编码器,右边是decoder解码器,解码器在之前时刻的输出作为 预测的输入
Embedding就是从原始数据提取出来的Feature

Lawer norm(是把行样本标准化)
Batch norm (是把某一列向量标准化)

残差链接
Add指 X+MultiHeadAttention(X),是一种残差连接,可以跨层向上传递信息
在这里插入图片描述

Norm指 Layer Normalization,通常用于 RNN 结构,Layer Normalization 会将每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛

Key words: blue mlp 残差连接 正交基

傅里叶 变换(通俗易懂的理解傅里叶变换(一)[收藏] - 知乎 (zhihu.com)):
我把sin(3x)+sin(5x)的曲线给你,但是前提是你不知道这个曲线的方程式,现在需要你把sin(5x)给我从图里拿出去,看看剩下的是什么。这基本是不可能做到的。
但是在频域呢?则简单的很,无非就是几条竖线而已。
所以很多在时域看似不可能做到的数学操作,在频域相反很容易。这就是需要傅里叶变换的地方。尤其是从某条曲线中去除一些特定的频率成分,这在工程上称为滤波,是信号处理最重要的概念之一,只有在频域才能轻松的做到。
再说一个更重要,但是稍微复杂一点的用途——求解微分方程。(这段有点难度,看不懂的可以直接跳过这段)微分方程的重要性不用我过多介绍了。各行各业都用的到。但是求解微分方程却是一件相当麻烦的事情。因为除了要计算加减乘除,还要计算微分积分。而傅里叶变换则可以让微分和积分在频域中变为乘法和除法,大学数学瞬间变小学算术有没有。

#######李宏毅 transformer模型
Issure: issure
总结:
是什么? 基于seq2seq架构的transformer模型可以完成NLP领域研究的典型任务,如机器翻译,文本生成,同时还可以构建预训练模型,用于不同任务的迁移学习。

基本组成
输入:源语言文本和目标文本,包含源文本嵌入层及位置编码,目标文本嵌入层及其位置编码
编码器
解码器
输出 包含linear(得到outputsize), softmax(求最大的值)

编码器部分
• 由N个编码器层堆叠而成
• 每个编码器由2个子层连接结构组成
• 第一个包括一个多头自注意力子层和规范化层以及一个残差连接
• 第二个子层连接结构包括一个前馈全连接子层和规范化层和一个残差连接

解码器部分
• 由N个解码器层堆叠而成
• 每个解码器由三个子层连接结构组成
• 第一个包括一个多头自注意力子层(masked)和规范化层以及一个残差连接
• 第二个子层包括一个多头注意力子层和规范化层以及一个残差连接
• 第三个子层连接结构包括一个前馈全连接子层和规范化层和一个残差连接

2.2 输入部分实现
○ 源文本嵌入层及位置编码
○ 目标文本嵌入层及其位置编码

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/5ba3d1fb9d444b13849acbd33eef37e2.png)
     ○ 文本嵌入层的作用,都是为了将文本中的词汇的数字表示转变为向量表示,希望在这样高维的空间  中捕捉词汇间的关系。

最简单的方法是 one-hot(将每个单词表示成0,1元素组成的向量),文本转变向量的几种常用的方法(one-hot,TF-IDF,word2vec)_文件转向量-CSDN博客
One-hot 编码():
将每个单词表示为一个独热向量,向量维度为词汇表大小,其中只有一个元素为1,其余为0。将所有单词的独热向量拼接起来,得到文本的向量表示
在这里插入图片描述

词转化为向量方法_通过词嵌入将单词转为向量-CSDN博客
文本嵌入层的代码分析

#构建Emberdding类来实现文本嵌入层
class Embedings(nn.Module):
    def __init__(self, d_model, vocab_size):
        #vocab_size:词典大小
        #d_model:词向量维度
        #定义Embedding层
        super(Embedings, self).__init__()
        self.embed = nn.Embedding(vocab_size, d_model)
        self.d_model = d_model
    def forward(self, x):

        #x 代表输入进模型的文本通过词汇映射后的数字张量
        return self.embed(x) * math.sqrt(self.d_model)
d_model = 512
vocab_size = 1000

input = Variable(torch.LongTensor([[100, 2, 421, 508], [491, 998, 1, 221]]))
emb = Embedings(d_model,vocab_size)
embr = emb(input)
# print(embed(input).shape)
print("embr:",embr)
print(embr.shape)

: • 位置编码器的作用
○ 因为在transformer的编码器结构中,并没有针对词汇位置信息的处理,因此需要在Embedding层后加入位置编码器,将词汇位置的不同可能会产生不同的语义的信息引入到词嵌入张量中,以弥补位置信息的缺失
○ Dropout:置0比率(置0比率就是以百分之多少的比率让神经网络中的某些神经元失效),max_length:每个句子的最大长度
• 位置编码器的代码分析
```
#定义位置编码

 class PositionalEncoding(nn.Module):
    def __init__(self, d_model, dropout, max_len=5000):
        #d_model:词向量维度
        #dropout:dropout比率,置0的概率
        #max_len:最大序列长度,每个句子的最大长度
        super(PositionalEncoding, self).__init__()
        #实例化nn中预定义的dropout层,将dropout传入层中,获得对象self.dropout
        self.dropout =nn.Dropout(p=dropout)
        #初始化一个位置编码矩阵,它是一个θ阵,矩阵大小是max_len*d_model,形状很重要
        pe = torch.zeros(max_len, d_model)
        #初始化一个绝对位置矩阵,在这,词汇的位置矩阵就是他的索引
        position = torch.arange(0, max_len).unsqueeze(1) # (1,max_lenth)convert to (max_lenth,1)
        #接下里考虑的是如何将位置信息加入到位置编码矩阵中,即positional 如何加入到pe中?

        # 计算位置编码
        
        #div_term是一个变形矩阵,它的维度是d_model/2,每个元素是一个常数,这个常数是一个很大的数,这个数是一个固定值,这个值是10000的负数除以d_model
        #为什么要变形矩阵,是因为positional 到pe差一个1*d_model的矩阵
        div_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model))
        pe[:, 0::2] = torch.sin(position * div_term)#给偶数位置加入d_model/2个sin值
        pe[:, 1::2] = torch.cos(position * div_term)#给奇数位置加入d_model/2个cos值
        #pe现在是一个二维的矩阵
        #输入是三维的,所以需要扩展一下
        pe=pe.unsqueeze(0)
        #把pe注册成一个模型buffer,相当于一个常量,不会变化,训练的时候重新加载时,模型结构与参数一同被加载
        self.register_buffer('pe', pe)
    def forward(self, x):
        # x代表文本序列的词嵌入向量表示,是一个三维的张量,维度是batch_size*seq_len*d_model
        #把pe的维度扩展成x的维度,维度是batch_size*seq_len*d_model
        #pe的编码太长了,所以需要截取一下,截取成和x一样的维度,也就是max_length对应的维度缩减到x的维度,这样才能相加
        #这个也可以说名,transformer可以处理变长的序列
        #requires_grad=False表示不需要计算梯度
        #x.size(1) 确实是指 x 张量的第二维的大小,即 x 的列数,x.size(0)是指x张量的第一维的大小,即x的行数 

        x = x + Variable(self.pe[:, :x.size(1)], requires_grad=False)
        return self.dropout(x)
```

学习中。。。

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值