赞
踩
Transformer是由编码器和解码器组成。Transformer的编码器和解码器是基于自注意力的模块叠加而成的,源(输入)序列和目标(输出)序列的嵌入(embedding)表示将加上位置编码(positional encoding),再分别输入到编码器和解码器中。
在此之前已经描述并实现了基于缩放点积多头注意力和位置编码。接下来将实现Transformer模型的剩余部分。
- import math
- import pandas as pd
- from mxnet import autograd, np, npx
- from mxnet.gluon import nn
- from d2l import mxnet as d2l
-
- npx.set_np()
基于位置的前馈网络对序列中的所有位置的表示进行变换时使用的是同一个多层感知机(MLP),这就是称前馈网络是基于位置的(positionwise)的原因。在下面的实现中,输入X的形状(批量大小,时间步数或序列长度,隐单元数或特征维度)将被一个两层的感知机转换成形状为(批量大小,时间步数,ffn_num_outputs)的输出张量。
- #@save
- class PositionWiseFFN(nn.Block):
- """基于位置的前馈网络"""
- def __init__(self, ffn_num_hiddens, ffn_num_outputs, **kwargs):
- super(PositionWiseFFN, self).__init__(**kwargs)
- self.dense1 = nn.Dense(ffn_num_hiddens, flatten=False,
- activation='relu')
- self.dense2 = nn.Dense(ffn_num_outputs, flatten=False)
-
- def forward(self, X):
- return self.dense2(self.dense1(X))
下面的例子显示,改变张量的最里层维度的尺寸,会改变成基于位置的前馈网络的输出尺寸。因为用同一个多层感知机对所有位置上的输入进行变换,所以当所有这些位置的输入相同时,它们的输出也是相同的。
- ffn = PositionWiseFFN(4, 8)
- ffn.initialize()
- ffn(np.ones((2, 3, 4)))[0]
层规范化和批量规范化的目标相同,但层规范化是基于特征维度进行规范化。尽管批量规范化在计算机视觉中被广泛应用,但在自然语言处理任务中(输入通常是变长序列)批量规范化通常不如层规范化的效果好。
以下代码对比不同维度的层规范化和批量规范化的效果。
- ln = nn.LayerNorm()
- ln.initialize()
- bn = nn.BatchNorm()
- bn.initialize()
- X = np.array([[1, 2], [2, 3]])
- # 在训练模式下计算X的均值和方差
- with autograd.record():
- print('层规范化:', ln(X), '\n批量规范化:', bn(X))
现在可以使用残差连接和层规范化来实现AddNorm类。暂退法也被作为正则化方法使用。
- #@save
- class AddNorm(nn.Block):
- """残差连接后进行层规范化"""
- def __init__(self, dropout, **kwargs):
- super(AddNorm, self).__init__(**kwargs)
- self.dropout = nn.Dropout(dropout)
- self.ln = nn.LayerNorm()
-
- def forward(self, X, Y):
- return self.ln(self.dropout(Y) + X)
残差连接要求两个输入的形状相同,以便加法操作后输出张量的形状相同。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。