关键词:LLaMA
,Transformer
,GLU
,SwiGLU
前言
SwiGLU激活函数在PaLM,LLaMA等大模型中有广泛应用,在大部分测评中相较于Transformer FFN中所使用的ReLU函数都有提升。本篇先介绍LLaMA中SwiGLU的实现形式,再追溯到GLU门控线性单元,以及介绍GLU的变种,Swish激活函数等内容。
内容摘要
- LLaMA中SwiGLU的实现形式
- GLU门控线性单元原理简述
- 通过GLU的变种改进Transformer
- Swish和SiLU激活函数
LLaMA中SwiGLU的实现形式
SwiGLU本质上是对Transformer的FFN前馈传播层的第一层全连接
和ReLU
进行了替换,在原生的FFN中采用两层全连接,第一层升维,第二层降维回归到输入维度,两层之间使用ReLE激活函数,计算流程图如下(省略LayerNorm模块)
![](https://img.haomeiwen.com/i22206660/015f61ac48687997.png)
SwiGLU也是全连接配合激活函数的形式,不同的是SwiGLU采用两个权重矩阵和输入分别变换,再配合Swish激活函数做哈达马积的操作,因为FFN本身还有第二层全连接,所以带有SwiGLU激活函数的FFN模块一共有三个权重矩阵,用公式表达如下
![](https://img.haomeiwen.com/i22206660/2e62e2ea371545d7.png)
其中W1,V为SwiGLU模块的两个权重矩阵,W2为原始FFN的第二层全连接权重矩阵,⊗代表哈达玛积逐位相乘,Swish为激活函数,其中β为Swish激活函数的一个参数,一般β=1此时等同于SiLU激活函数,可视化计算流程图如下
![](https://img.haomeiwen.com/i22206660/cab538f62107d300.png)
在HuggingFace LLaMA的源码实现中,在Decoder模块LlamaDecoderLayer中的LlamaMLP引入SwiGLU改造了FFN层,实现如下
class LlamaDecoderLayer(nn.Module):
def __init__(self, config: LlamaConfig):
...
# TODO 门控线性单元
self.mlp = LlamaMLP(
hidden_size=self.hidden_size,
intermediate_size=config.intermediate_size, # 11008
hidden_act=config.hidden_act, # silu
)
LlamaMLP的实现了SwiGLU逻辑,代码和公式完全对应
class LlamaMLP(nn.Module):
def __init__(
self,
hidden_size: int, # 4096
intermediate_size: int, # 11008
hidden_act: str, # silu
):
super().__init__()
self.gate_proj = nn.Linear(hidden_size, intermediate_size, bias=False)
self.down_proj = nn.Linear(intermediate_size, hidden_size, bias=False)
self.up_proj = nn.Linear(hidden_size, intermediate_size, bias=False)
self.act_fn = ACT2FN[hidden_act]
def forward(self, x):
return self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
在LLaMA2-7B中,FFN的原始输入维度为4096,一般而言中间层是输入维度的4倍等于16384,由于SwiGLU的原因FFN从2个矩阵变成3个矩阵,为了使得模型的参数量大体保持不变,中间层维度做了缩减,缩减为原来的2/3即10922,进一步为了使得中间层是256的整数倍,有做了取模再还原的操作,最终中间层维度为11008,计算公式如下
![](https://img.haomeiwen.com/i22206660/13c4dc9c9cd7e0f1.png)
GLU门控线性单元原理简述
SwiGLU是GLU门控线性单元的变种,了解SwiGLU必须从GLU入手,GLU提出于2016年发表的论文《nguage modeling with gated convolutional networks》中,GLU是一种类似LSTM带有门机制
的网络结构,同时它类似Transformer一样具有可堆叠性
和残差连接
,它的作用是完成对输入文本的表征,通过门机制控制信息通过的比例
,来让模型自适应地选择哪些单词和特征对预测下一个词有帮助
,通过堆叠来挖掘高阶语义,通过残差连接来缓解堆叠的梯度消失和爆炸。
堆叠的每一层就是门控GLU门控线性单元,通过Sigmoid激活函数和哈达玛积实现门控机制,公式如下
![](https://img.haomeiwen.com/i22206660/27c121cf14385582.png)
其中W和V两个卷积操作,当卷积patch size=1时等同于两个全连接层,GLU对输入文本的计算流程示意图如下
![](https://img.haomeiwen.com/i22206660/7cec8fddb70f844d.png)
相比于LSTM,GLU不需要复杂的门机制,不需要遗忘门,仅有一个输入门,因此计算更加高效,同时作者提出在他的实验中,基于GLU的GCNN门控卷积神经网络和LSTM相比,在相同参数数量和训练环境下,GCNN的预测困惑度更低,表现优于LSTM。
通过GLU的变种改进Transformer
2017年随着Transformer的提出和成功,促进了后续对Transformer结构的改进的研究,比如在2020年发表的论文《GLU Variants Improve Transformer》中,提出使用GLU的变种来改进Transformer的FFN层,作者提出的变种就是将GLU中原始的Sigmoid激活函数替换为其他的激活函数,作者列举了替换为ReLU,GELU和SwiGLU的三种变体,公式如下
![](https://img.haomeiwen.com/i22206660/f32c7bb00ac4493a.png)
本质上就是将Sigmoid激活函数替换为其他激活函数,命名上将激活函数的缩写加在GLU前面作为前缀。进一步作者将这种GLU变体替换FFN中的第一层全连接和激活函数,并且去除了GLU中偏置项bias,以SwiGLU为例,结合FFN它的计算公式为
![](https://img.haomeiwen.com/i22206660/6ab8f8fc00475c2c.png)
由于这种方式使得FFN中的权重矩阵从2变为了3,为了使得模型的参数大体不变,因此中间层的向量维度需要削减为原始维度的三分之二。
在论文的实验模块,作者通过数据证明通过GLU变体改造后的Transformer在大多数NLP任务上都比FFN的评价得分明显更高,其中ReGLU在实验中获得了最高的平均分,其次是SwiGLU。
![](https://img.haomeiwen.com/i22206660/762939b53ee3adae.png)
Swish和SiLU激活函数
Swish激活函数由Google团队在2017年提出,被证明在更深的模型上表现出比ReLU更好的性能,Swish的公式如下
![](https://img.haomeiwen.com/i22206660/b8a8261fd8a7905b.png)
其中σ为激活函数Sigmoid,β为Swish的一个参数,通常为一个常数或者让模型自适应学习得到。输入x和Sigmoid相乘使得它类似LSTM中的门机制,因此Swish也被成为self-gated激活函数,只需要一个标量输入即可完成门控操作。
当β=0时,Swish退化为一个线性函数,当β趋近于无穷大时,Swish就变成了ReLU,不同β下Swish的图形如下
![](https://img.haomeiwen.com/i22206660/256e32f852cb9edd.png)
Swish函数的曲线是平滑的,并且函数在所有点上都是可微的。这在模型优化过程中很有帮助,被认为是 swish 优于 ReLU 的原因之一。在LLaMA中采用常数β=1,此时Swish也叫SiLU激活函数。
全文完毕。
网友评论