这是 Transformer 中使用的位置前馈网络的 PyTorch 实现。
FFN 由两个全连接层组成。隐藏层中的维度数_%5e_0_%5e_通常设置为标记嵌入维度_%5e_1_%5e_的四倍左右。因此,它有时也被称为扩张-压缩网络。
隐藏层有一个激活函数,通常设置为 ReLU (Rectified Linear Unit) 激活函数,_%5e_2_%5e_
在此基础上, FFN 函数可以写作:_%5e_3_%5e_其中_%5e_4_%5e__%5e_5_%5e_、_%5e_6_%5e_和_%5e_7_%5e_是可学习的参数。
有时还会使用 GELU (Gaussian Error Linear Unit) 激活函数来代替 ReLU 。_%5e_8_%5e_其中_%5e_9_%5e_
这是一个通用实现,支持包括门控线性单元(GLU) 在内的不同变体。我们还对这些进行了实验:
38import torch
39from torch import nn as nn
40
41from labml_helpers.module import Module
44class FeedForward(Module):
d_model
是标记嵌入中的特征数量d_ff
是 FFN 隐藏层中的特征数量dropout
是隐藏层的 Dropout 率is_gated
指定了隐藏层是否为门控层bias1
指定了第一个全连接层是否应该具有可学习的偏置bias2
指定第二个全连接层是否应具有可学习的偏置bias_gate
指定门控的全连接层是否应具有可学习的偏置49 def __init__(self, d_model: int, d_ff: int,
50 dropout: float = 0.1,
51 activation=nn.ReLU(),
52 is_gated: bool = False,
53 bias1: bool = True,
54 bias2: bool = True,
55 bias_gate: bool = True):
65 super().__init__()
第一层由权重和偏差进行参数化
67 self.layer1 = nn.Linear(d_model, d_ff, bias=bias1)
第一层由权重和偏差进行参数化
69 self.layer2 = nn.Linear(d_ff, d_model, bias=bias2)
隐藏层 Dropout
71 self.dropout = nn.Dropout(dropout)
激活函数
73 self.activation = activation
是否存在门控
75 self.is_gated = is_gated
76 if is_gated:
如果存在门控,则通过线性层将输入值与门相乘,并由权重 和偏置进行参数化
79 self.linear_v = nn.Linear(d_model, d_ff, bias=bias_gate)
81 def forward(self, x: torch.Tensor):
83 g = self.activation(self.layer1(x))
如果进行门控,
85 if self.is_gated:
86 x = g * self.linear_v(x)
否则
88 else:
89 x = g
使用 Dropout
91 x = self.dropout(x)
根据是否进行门控,返回或者
94 return self.layer2(x)