transformer架构解析{前馈全连接层,规范化层,子层(残差)连接结构}(含代码)-4

目录

前言

前馈全连接层

学习目标

 什么是前馈全连接层

前馈全连接层的作用

 前馈全连接层代码实现

规范化层

学习目标

规范化层的作用

 规范化层的代码实现

子层(残差)连接结构

学习目标

什么是子层(残差)连接结构

子层连接结构代码实现 


前言

        我们之前学习了输入层(词嵌入层(经过词向量编码),位置编码(通过词位置信息向量和词特征矩阵得到))。注意力机制(注意力计算规则,自注意力和注意力区别,注意力机制,多头注意力机制)

前馈全连接层

学习目标

        了解什么是前馈全连接层及其作用

        掌握前馈全连接层的实现过程

 什么是前馈全连接层

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

前馈全连接层的作用

        考虑到注意力机制可能对复杂过程的拟合程度不够,通过增加两层网络来增强模型能力

 前馈全连接层代码实现

#前馈全连接层的代码分析
class PositionwiseFeedForward(nn.Module):
    def __init__(self, d_model,d_ff, dropout = 0.1):
        #输入的参数分别是:d_model词嵌入的维度,d_ff全连接网络的中间层维度,dropout=0.1置零比率
        super(PositionwiseFeedForward,self).__init__()

        #首先先使用nn实例化两个线性层对象self.w1,self.w2
        #参数是d_mdoel,d_ff,d_model
        self.w1 = nn.Linear(d_model,d_ff)
        self.w2 = nn.Linear(d_ff,d_model)
        #然后使用nn实例化dropout对象
        self.dropout = nn.Dropout(p=dropout)

    def forward(self,x):
        #输入参数x表示上一层的输出
        #首先经过第一个线性层,然后使用Funtional中的relu函数激活
        #之后在使用dropout进行随即处置0,最后经过第二个线性层w2,返回结果
        return self.w2(self.dropout(F.relu(self.w1(x))))
#实例化参数
d_model = 512
d_ff = 128
dropout = 0.2
x = mha_result
pwf = PositionwiseFeedForward(d_model,d_ff,dropout=dropout)
pwf_result = pwf(x)
print(pwf_result)
print(pwf_result.shape)

规范化层

学习目标

        了解规范化层的作用

        掌握规范化层的实现过程

规范化层的作用

        它是所有深层网络模型都需要的标准网络层,因为随着网络层数的增加,通过多层计算后的参数可能开始出现过大的或者过小的情况,这样会导致模型收敛的非常慢,因此都会在一定层数后接入规范化层进行数值规范化,使其数值特征在合理范围内。

 规范化层的代码实现

#规范化层的代码实现
#通过layerNorm实现规范化操作的类
class LayerNorm(nn.Module):
    def __init__(self, features,eps=1e-6):
        #初始化参数:features表示词嵌入的维度,eps表示一个足够小的数,在规范化公式分母出现,防止分母为0
        super(LayerNorm,self).__init__()

        #根据features初始化两个张量a2,b2,第一个初始化张量为1张量。就是说里面所有元素都是1,第二个初始化为0张量
        #里面所有元素都为0,这两张张量就是规范化层的参数。
        #因为直接对上一层得到的结果做规范化计算,将改变的结果正常表征,因此就需要有参数作为调节因子,
        #使其既能满足规范化要求,又不能改变针对目标的表征。最后使用nn.parameter封装,代表他们是模型的参数
        self.a2 = nn.Parameter(torch.ones(features))
        self.b2 = nn.Parameter(torch.zeros(features))

        #把eps传入类中
        self.eps = eps

    def forward(self,x):
        #输入的参数来自上一层的输出
        #在函数中,首先对输入变量x求其最后一个维度的均值,并保持如输入维度一致
        #接着再求最后一个维度的标准差,然后就是根据规范化公式,用x减去均值除以标准差获得规范化的结果
        #最后对结果乘以缩放系数,即a2,加上位移参数b2

        mean = x.mean(-1,keepdim=True) #-1表示最后一个维度
        std = x.std(-1,keepdim = True)
        return self.a2 *(x - mean) / (std + self.eps) + self.b2
features = d_model = 512
eps = 1e-6

#x是前馈全连接层的输出
x = pwf_result
ln = LayerNorm(features,eps=eps)
ln_result = ln(x)
print(ln_result)
print(ln_result.shape)

子层(残差)连接结构

学习目标

        了解什么是子层连接结构

        掌握子层连接结构的实现过程

什么是子层(残差)连接结构

        输入到每个子层以及规范化层的过程中,还使用了残差链接(跳跃链接),我们把这一部分结构叫做子层连接结构(代表子层及其链接结构),在每个编码器层,都有两个子层,这两个子层加上周围的链接结构形成了两个子层链接结构

        子层链接结构图:

子层连接结构代码实现 

#子层连接结构
#使用SublayerConnection来实现子层连接结构的类
class SublayerConnection(nn.Module):
    def __init__(self, size,dropout=0.1):
        #输入两个参数size表示词嵌入的维度,dropout对输出矩阵的随机置0
        super(SublayerConnection,self).__init__()

        #实例化规范化层
        self.norm = LayerNorm(size)
        #使用nn中预定义的dropout实例化一个self.dropout对象
        self.dropout = nn.Dropout(p=dropout)

    def forward(self,x,sublayer):
        #该逻辑函数中,接收上一个子层或者子层的输入作为第一个参数
        #将该子层连接中的子层函数作为第二个参数

        #我们首先对输入做规范化处理,然后将结果传入子层做处理,之后在再对子层进行dropout操作
        #随机停止一些网络中的神经元的作用,防止过拟合,最后还有一个add的操作
        #因为存在跳跃连接,所以将输入x与dropout后的子层输出结果相加作为最终子层的连接输出

        return x + self.dropout(sublayer(self.norm(x)))
#实例化参数
size = 512
dropout = 0.2
head = 8
d_model = 512
#输入参数
#令x为编码器的输出
x = pe_result
#print(x)
mask = Variable(torch.zeros(2,4,4))

#假设子层中装的是多层注意力层,实例化
self_attn = MutiHeadedAttention(head,d_model)

#使用lambda获得一个函数类型的子层
sublayer = lambda x: self_attn(x,x,x,mask)

sc = SublayerConnection(size=size,dropout=dropout)
sc_result = sc(x,sublayer)
print(sc_result)
print(sc_result.shape)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值