LLMs 激活函数篇
来源:AI GC面试宝典 作者:宁静致远 日期:2023年09月29日
1. FFN(前馈神经网络)块
计算公式:
$$FFN(x) = f(xW_1 + b_1)W_2 + b_2$$
📝通俗解释:FFN是Transformer中每个注意力层后面的"加工车间"。它先把输入放大(通过$W_1$升维),经过激活函数处理,再压缩回来(通过$W_2$降维)。就像先把信息拆分成更多小碎片(升维),筛选处理后再组合成原来的样子(降维)。
2. GeLU(高斯误差线性单元)
计算公式:
$$GeLU(x) \approx 0.5x(1 + tanh(\sqrt{\frac{2}{\pi}}(x + 0.044715x^3)))$$
📝通俗解释:GeLU是一种"智能门控"的激活函数。它会根据输入值的大小来决定让多少信息通过:大的正值几乎完全通过,负值会被抑制,接近零的值会有选择性地通过。这比传统的ReLU更"平滑",能让模型学习更细腻的特征。
3. Swish
计算公式:
$$Swish_{\beta}(x) = x \cdot \sigma(\beta x)$$
其中 $\sigma$ 是Sigmoid函数,$\beta$ 是可训练参数。
📝通俗解释:Swish可以理解为"带参数的平滑门"。它把输入乘以一个经过Sigmoid处理的门控值 ($\beta x$)。$\beta$ 可以让模型自己学习门控的"松紧程度",比固定的门控更灵活。
4. GLU(线性门控单元)
计算公式:
$$GLU(x) = \sigma(xW + b) \otimes xV$$
使用GLU的FFN:
$$FFN_{GLU} = (f(xW_1) \otimes xV)W_2$$
📝通俗解释:GLU的核心思想是"用一部分信息控制另一部分信息的通过"。$\sigma(xW)$ 产生一个0~1之间的"门控值",然后用它来控制 $xV$ 的信息流量。这就像用一个开关来调节水流大小,比单一的非线性变换更有效。
5. GeGLU(GeLU + GLU)
计算公式:
$$GeGLU(x) = GeLU(xW) \otimes xV$$
📝通俗解释:GeGLU把GLU中的Sigmoid门控换成GeLU,让门控变得更"智能"。不再是简单的开/关,而是根据输入大小动态调整通过程度。
6. SwiGLU(Swish + GLU)
计算公式:
$$SwiGLU = Swish_{\beta}(xW) \otimes xV$$
📝通俗解释:SwiGLU结合了Swish的平滑特性和GLU的门控机制,是目前大语言模型中表现最好的激活函数之一。LLaMA系列模型就采用了这种设计。
7. 各LLM模型使用的激活函数
| 模型 | 激活函数 |
|---|---|
| GPT-3 | GeLU |
| LLaMA | SwiGLU |
| LLaMA2 | SwiGLU |
| Baichuan | SwiGLU |
| ChatGLM-6B | GeLU |
| ChatGLM2-6B | SwiGLU |
| Bloom | GeLU |
| Falcon | GeLU |
📝通俗解释:从表格可以看出,早期模型(如GPT-3、Bloom)倾向于使用GeLU,而较新的模型(如LLaMA、Baichuan)则选择SwiGLU。这反映了业界对激活函数认知的演进——SwiGLU的门控机制能带来更好的性能。
8. FFN中间维度的计算
以隐藏层维度 $h = 4096$ 为例:
- 标准FFN(4h): $4 \times 4096 = 16384$
- GLU类FFN(4h × 2/3): $\frac{2}{3} \times 4 \times 4096 \approx 10923$,向上取整到128的倍数得到 11008
📝通俗解释:FFN的中间层通常比输入大很多(通常是4倍),这样可以提供更大的"思考空间"。但GLU类FFN因为多了一个门控分支,中间层可以稍小一些(~2.67倍),减少计算量的同时保持类似性能。
9. 模型参数对比
LLaMA-7B
| 模块 | 参数形状 | 参数量 |
|---|---|---|
| model.embed_tokens.weight | [32000, 4096] | 131,072,000 |
| model.layers.0.self_attn.q_proj.weight | [4096, 4096] | 16,777,216 |
| model.layers.0.self_attn.k_proj.weight | [4096, 4096] | 16,777,216 |
| model.layers.0.self_attn.v_proj.weight | [4096, 4096] | 16,777,216 |
| model.layers.0.self_attn.o_proj.weight | [4096, 4096] | 16,777,216 |
| model.layers.0.mlp.gate_proj.weight | [11008, 4096] | 45,088,768 |
| model.layers.0.mlp.down_proj.weight | [4096, 11008] | 45,088,768 |
| model.layers.0.mlp.up_proj.weight | [11008, 4096] | 45,088,768 |
| model.layers.0.input_layernorm.weight | [4096] | 4,096 |
| model.layers.0.post_attention_layernorm.weight | [4096] | 4,096 |
📝通俗解释:LLaMA的FFN使用了3个投影矩阵(gate、up、down),这是SwiGLU的标准配置。相比传统的2个矩阵(up_proj、down_proj),多出来的gate_proj用于生成门控信号。
BLOOM-7B
| 模块 | 参数形状 | 参数量 |
|---|---|---|
| transformer.word_embeddings.weight | [250880, 4096] | 1,027,604,480 |
| transformer.word_embeddings_layernorm.weight | [4096] | 4,096 |
| transformer.word_embeddings_layernorm.bias | [4096] | 4,096 |
| transformer.h.0.input_layernorm.weight | [4096] | 4,096 |
| transformer.h.0.input_layernorm.bias | [4096] | 4,096 |
| transformer.h.0.self_attention.query_key_value.weight | [12288, 4096] | 50,331,648 |
| transformer.h.0.self_attention.query_key_value.bias | [12288] | 12,288 |
| transformer.h.0.self_attention.dense.weight | [4096, 4096] | 16,777,216 |
| transformer.h.0.self_attention.dense.bias | [4096] | 4,096 |
| transformer.h.0.post_attention_layernorm.weight | [4096] | 4,096 |
| transformer.h.0.post_attention_layernorm.bias | [4096] | 4,096 |
| transformer.h.0.mlp.dense_h_to_4h.weight | [16384, 4096] | 67,108,864 |
| transformer.h.0.mlp.dense_h_to_4h.bias | [16384] | 16,384 |
| transformer.h.0.mlp.dense_4h_to_h.weight | [4096, 16384] | 67,108,864 |
| transformer.h.0.mlp.dense_4h_to_h.bias | [4096] | 4,096 |
📝通俗解释:BLOOM使用的是标准的FFN结构(dense_h_to_4h和dense_4h_to_h),中间层维度是16384(4×4096),这与它使用GeLU激活函数的设计一致。相比LLaMA的SwiGLU,BLOOM的FFN只有2个投影矩阵。
参考来源: 知识星球 - AI GC面试宝典 整理日期: 2024年8月11日