当前位置:   article > 正文

Transformer模型编码器部分实现2(全连接+规范化+子层连接+编码器层+整体连接代码)_transformer的全连接层

transformer的全连接层

部分内容来自于网络教程,如有侵权请联系本人删除相关内容:

教程链接:https://www.bilibili.com/video/BV17Y4y1j7cf?p=22&spm_id_from=pageDriver&vd_source=eca88088d891c6950b5aea556143b41c2.3.5规范化层-part1_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV17Y4y1j7cf?p=22&spm_id_from=pageDriver&vd_source=eca88088d891c6950b5aea556143b41c

1.前馈全连接层

Transformer中前馈全连接层就是具有两层线性层的全连接网络。

作用:注意力记住可能对复杂过程的拟合程度不够,通过增加两层网络来增强模型的能力。

前馈全连接层的代码分析

  1. # 前馈全连接网络
  2. class PositionwiseFeedForward(nn.Module):
  3. def __init__(self, d_model, d_ff, dropout=0.1):
  4. # d_model: 词嵌入的维度,同时也是全连接层的输入输出维度
  5. # d_ff: 第一个线性层的输入维度,第二个线性层的输出维度
  6. super(PositionwiseFeedForward,self).__init__()
  7. self.fc1 = nn.Linear(d_model, d_ff)
  8. self.fc2 = nn.Linear(d_ff, d_model)
  9. self.dropout = nn.Dropout(p = dropout)
  10. def forward(self,x):
  11. # x:上一层的输出
  12. return self.fc2(self.dropout(F.relu(self.fc1(x))))

2.规范化层

随着网络层数的加深,通过多层的计算后参数可能开始出现过大或过小的情况,这样可能会导致学习过程出现异常,模型可能收敛非常慢。因此都会一定层数之后接规范化层进行数值的规范化,使特征数值在合理范围内。

规范化层代码实现:

  1. class LayerNorm(nn.Module):
  2. def __init__(self, features, eps=1e-6):
  3. '''
  4. features:词嵌入维度
  5. eps:足够小的数,在规范化公式的分母出现,防止分母为0,
  6. '''
  7. super(LayerNorm, self).__init__()
  8. self.a2 = nn.Parameter(torch.ones(features))
  9. self.b2 = nn.Parameter(torch.zeros(features))
  10. self.eps = eps
  11. def forward(self, x):
  12. # 输入x为上一层的输出
  13. # 对x的最后一个维度求均值,保持输出维度和输入一样
  14. mean = x.mean(-1,keepdim=True)
  15. # 对x的最后一个维度求标准差,保持输出维度和输入一样
  16. std = x.std(-1,keepdim=True)
  17. return self.a2*(x - mean)/(std + self.eps)+self.b2

3.子层连接结构

基于以上的模块代码,我们要实现带有残差链接的子层链接结果。一共有两个子层,如图所示:

  1. class SublayerConnection(nn.Module):
  2. def __init__(self, size, dropout=0.1):
  3. # size: 词嵌入维度
  4. super(SublayerConnection,self).__init__()
  5. self.norm = LayerNorm(size)
  6. self.dropout = nn.Dropout(p=dropout)
  7. self.size = size
  8. def forward(self, x, sublayer):
  9. # 上一层输出x作为输入
  10. # 第二个参数为子层函数
  11. return x + self.dropout(sublayer(self.norm(x)))

4.编码器子层

在学完以上结构后,我们将编码器的所有部分进行连接,构成整个编码器子层。

编码器层的作用:作为编码器的组成单元,每个编码器层完成一次对输入的提取特征过程,即编码过程。

编码器层示意图:

  1. class EncoderLayer(nn.Module):
  2. def __init__(self, size, self_attn, feed_forward, dropout):
  3. # size: 词嵌入维度
  4. # self_attn: 多头自注意力子层实例化对象
  5. # feed_forward: 前馈全连接实例化对象
  6. super(EncoderLayer,self).__init__()
  7. self.self_attn = self_attn
  8. self.feed_forward = feed_forward
  9. self.size = size
  10. self.sublayer = clones(SublayerConnection(size, dropout),2)
  11. def forward(self, x, mask):
  12. # x: 上一层输出张量
  13. # mask: 掩码张量
  14. # 输出为经过整个编码器层的特征表示
  15. x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, mask))
  16. return self.sublayer[1](x, self.feed_forward)

5.编码器

编码器用于对输入进行指定的特征提取过程,也称为编码,由N个编码器层堆叠而成。

编码器的输出是Transformer中编码器的特征提取表示,他将成为解码器输入的一部分。

  1. class Encoder(nn.Module):
  2. def __init__(self, layer, N):
  3. # layer: 编码器层
  4. # N: 编码器层数
  5. super(Encoder, self).__init__()
  6. # 首先使用clone函数克隆N个编码器层
  7. self.layers = clones(layer, N)
  8. # 初始化规范化层
  9. self.norm = LayerNorm(layer.size)
  10. def forward(self, x, mask):
  11. # x: 上一层的输出
  12. # mask: 掩码张量
  13. # 让x依次经过N个编码器处理,最后经过规范化层
  14. for layer in self.layers:
  15. x = layer(x, mask)
  16. return self.norm(x)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/354164
推荐阅读
相关标签
  

闽ICP备14008679号