第四章:大模型(LLM)
第九部分:最强开源大模型:Llama3 原理介绍与实现
第五节:SwiGLU Activation function
这一节我们来讲解 SwiGLU 激活函数,这是 Llama3 在前馈网络(Feed Forward Network, FFN)中采用的激活方式。
1️⃣ 背景:为什么要引入 SwiGLU?
在 Transformer 中,前馈网络(FFN) 占据了很大一部分计算量与参数量。
传统的激活函数(如 ReLU, GELU)虽然表现稳定,但在超大规模语言模型中,研究发现 门控型激活函数(Gated Activation Functions) 可以提升表达能力与训练稳定性。
代表性方法是 GLU(Gated Linear Unit)系列。
-
通过引入一个 门控机制(Gate),让输入在流入非线性函数之前被“选择性放大/抑制”。
-
对语言建模尤其有效。
2️⃣ GLU 系列激活函数
(1) 基本 GLU
提出于 2016 年:
-
σ 是 Sigmoid 激活函数。
-
第一个线性层
产生“主分支”。
-
第二个线性层
产生“门控信号”,控制信息流。
(2) GELU-based GLU(GEGLU)
-
用 GELU 替代 Sigmoid,提升了性能。
(3) Swish-based GLU(SwiGLU) —— Llama3 采用
其中 Swish 函数为:
相比 ReLU/GELU,Swish 具有更好的平滑性,梯度传播更稳定。
3️⃣ SwiGLU 的形式化定义
给定输入向量 ,
-
经过两组线性变换:
-
其中 U 是主分支,V 是门控分支。
SwiGLU 公式:
其中 ⊗ 表示逐元素乘法。
4️⃣ Llama3 中的前馈网络结构(FFN with SwiGLU)
在 Llama3 的 Transformer Block 中,FFN 采用如下结构:
特点:
-
仍然是 双分支结构(主分支 + 门控分支)。
-
SwiGLU 替代传统的 GELU/ReLU,提升表达能力。
-
输出再经过第三个线性投影
回到模型维度。
PyTorch 实现(简化版)
import torch
import torch.nn as nn
import torch.nn.functional as F
class SwiGLU(nn.Module):
def __init__(self, dim, hidden_dim):
super().__init__()
self.W1 = nn.Linear(dim, hidden_dim, bias=False)
self.W2 = nn.Linear(dim, hidden_dim, bias=False)
self.W3 = nn.Linear(hidden_dim, dim, bias=False)
def forward(self, x):
u = self.W1(x)
v = self.W2(x)
# Swish 激活:v * sigmoid(v)
swish_v = v * torch.sigmoid(v)
return self.W3(u * swish_v)
5️⃣ SwiGLU 的优势
-
更强的表达能力
-
通过门控机制,允许 FFN 学习更复杂的非线性关系。
-
-
梯度更平滑
-
相比 ReLU,Swish 避免了硬截断(ReLU 的 0 区域)。
-
相比 GELU,Swish 在大规模训练中表现更稳定。
-
-
计算效率高
-
只引入了一次额外的逐元素乘法,计算开销低。
-
-
实验效果
-
Meta 的实验表明,SwiGLU 在语言建模任务上优于 ReLU/GELU。
-
成为了 Llama2/3 的默认选择。
-
6️⃣ 总结
-
传统 FFN:两层 MLP + ReLU/GELU
-
Llama3 FFN:三层 MLP + SwiGLU
-
SwiGLU 的核心:门控机制 + Swish 激活
-
收益:更高效的训练、更好的收敛、更强的表达能力