保存时间:2026/3/29 16:22:22
7168×2048 矩阵,把Attention传来的7168维特征,压缩到2048维(目的是减少计算量,聚焦核心特征);2048×7168 矩阵,把加工后的2048维特征,再恢复成7168维(因为下一层Attention还需要7168维的输入,维度得匹配)。| 激活函数 | 核心公式 | 关键特点 | 适用场景 |
|---|---|---|---|
| GeLU | GELU(x)=0.5x[1+erf(2x)] | 平滑概率性激活,对中间值响应细腻,梯度传递稳定,无神经元死亡问题 | 通用场景首选,适合Kimi K2等需平衡精度与效率的MoE模型,适配多数语义加工需求 |
| ReLU | ReLU(x)=max(0,x) | 计算极快,结构简单;但负输入直接归零,易出现“神经元死亡” | 少单独用于MoE,可搭配变体使用,适合对速度要求极高、特征较简单的场景 |
| Swish | Swish(x)=x⋅σ(βx)(σ为sigmoid,β为可学习参数) | 自门控机制,自适应保留弱特征,对复杂语义关联捕捉能力强 | MoE中处理多义词、长句逻辑等复杂语义场景,需微调β提升效果 |
| Mish | Mish(x)=x⋅tanh(softplus(x)) | 激活曲线更平滑,梯度衰减慢,深层特征加工能力优于Swish | 长序列处理、多专家协同场景,适合对深层语义精度要求高的MoE模型 |
| SiLU | SiLU(x)=x⋅σ(x)(β=1时与Swish等价) | 计算效率比Swish略高,PyTorch等框架内置,部署成本低 | 需简化部署、兼顾效率与效果的MoE模型,可替代Swish使用 |
| FastGELU | FastGELU(x)=0.5x(1+tanh(xπ2)) | GeLU的近似简化版,计算速度更快,精度仅轻微下降 | 对推理效率要求高的MoE模型,如大批次token处理场景 |
| ApproxGELU | ApproxGELU(x)=x⋅σ(1.702x) | 进一步简化的GeLU变体,速度最快,精度略低于FastGELU | 极致追求推理速度的MoE场景,允许轻微精度损耗 |
import torch.nn as nn
# 定义一个专家的 FFN 层,激活函数用 GeLU
class ExpertFFN(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(7168, 2048) # 降维矩阵
self.activation = nn.GELU() # 激活函数:直接调用框架内置的 GeLU 类
self.fc2 = nn.Linear(2048, 7168) # 升维矩阵
def forward(self, x):
x = self.fc1(x)
x = self.activation(x) # 执行激活运算
x = self.fc2(x)
return x
self.activation = nn.GELU() 这行代码,直接识别出“这一层用的是 GeLU 激活”,无需额外标志——函数的“名字”就是框架内置的类名/方法名。| 激活函数 | PyTorch 内置名称 | TensorFlow 内置名称 |
|---|---|---|
| GeLU | nn.GELU() | tf.keras.activations.gelu |
| ReLU | nn.ReLU() | tf.keras.activations.relu |
| Swish | nn.Swish() | tf.keras.activations.swish |
| Mish | 需安装 torch_mish 库 | tf.keras.activations.mish |
| SiLU | nn.SiLU() | 同 Swish(TensorFlow 中 SiLU 等价于 Swish(β=1)) |
| FastGELU | 无内置,需自定义 | 无内置,需自定义 |
self.activation = nn.GELU(),你哪怕自己写一个简化版的GeLU函数(只要计算逻辑一致),再按“降维→激活→升维”的顺序组织参数,也能正常运行模型。但如果不知道结构(比如不知道用GeLU还是ReLU,不知道专家矩阵的维度),就算拿到参数,也无法正确加载和运算——相当于拿到一堆乐高积木,却没有说明书,不知道该怎么拼。| 维度 | ReLU | GeLU |
|---|---|---|
| 计算逻辑 | 阈值筛选(非负则留,负则归零) | 概率加权(按正态分布概率调整) |
| 处理风格 | 激进、简单 | 温和、细腻 |
| 核心特点 | 计算极快,但易“神经元死亡” | 梯度稳定,但计算略复杂 |
import torch
import torch.nn as nn
# 定义一个完整的MoE专家FFN模块(含辅助优化模块)
class ExpertFFN(nn.Module):
def __init__(self, input_dim=7168, hidden_dim=2048, dropout_rate=0.1):
super().__init__()
# 1. 第一段线性变换:降维(7168→2048)
self.fc1 = nn.Linear(input_dim, hidden_dim)
# 2. 归一化(LayerNorm):稳定特征数值,避免梯度爆炸
self.norm = nn.LayerNorm(hidden_dim)
# 3. 非线性激活:用GeLU(大模型常用)
self.activation = nn.GELU()
# 4. Dropout:训练时随机关闭部分神经元,防止过拟合
self.dropout = nn.Dropout(dropout_rate)
# 5. 第二段线性变换:升维(2048→7168)
self.fc2 = nn.Linear(hidden_dim, input_dim)
# 6. 残差连接的缩放系数(可选,优化深层训练)
self.scale = nn.Parameter(torch.ones(1))
def forward(self, x):
# 保存原始输入(用于残差连接)
residual = x # residual: [batch_size, seq_len, 7168]
# 第一步:降维线性变换
x = self.fc1(x) # x: [batch_size, seq_len, 2048]
# 第二步:归一化(稳定数值分布)
x = self.norm(x) # x: [batch_size, seq_len, 2048]
# 第三步:非线性激活(核心特征加工)
x = self.activation(x) # x: [batch_size, seq_len, 2048]
# 第四步:Dropout(训练时生效,测试时关闭)
x = self.dropout(x) # x: [batch_size, seq_len, 2048]
# 第五步:升维线性变换(适配下一层输入)
x = self.fc2(x) # x: [batch_size, seq_len, 7168]
# 第六步:残差连接(保留原始特征,缓解深层梯度消失)
x = residual + self.scale * x # x: [batch_size, seq_len, 7168]
return x
# 测试模块:模拟一个token序列输入
if __name__ == "__main__":
# 模拟输入:batch_size=2(2个句子),seq_len=5(每个句子5个token),input_dim=7168
batch_input = torch.randn(2, 5, 7168)
# 初始化专家FFN
expert = ExpertFFN()
# 前向传播
output = expert(batch_input)
# 输出结果形状:和输入一致(7168维),说明维度适配正常
print(f"输入形状: {batch_input.shape}")
print(f"输出形状: {output.shape}")
fc1和fc2的矩阵权重不是固定的,会通过训练不断调整,比如让fc1更精准地筛选核心特征,fc2更合理地还原特征维度。| x(弧度) | 0 | 1.256 | 2.512 | 3.14 | 6.283 |
|---|---|---|---|---|---|
| sin(x) | 0 | 0.951 | 0.598 | 0 | 0 |
| f₁(x) | 0 | 0 | 0.456 | 0.77 | 2.341 |
| x(弧度) | 0 | 1.256 | 2.512 | 3.14 | 6.283 |
|---|---|---|---|---|---|
| sin(x) | 0 | 0.951 | 0.598 | 0 | 0 |
| f₂(x) | 2.0 | 1.623 | 1.246 | 1.058 | 0 |
| x(弧度) | 0 | 1.256 | 2.512 | 3.14 | 6.283 |
|---|---|---|---|---|---|
| sin(x) | 0 | 0.951 | 0.598 | 0 | 0 |
| 叠加结果 | 0.8 | 0.649 | 0.847 | 0.622 | 1.873 |
| x(弧度) | 0 | 1.256 | 2.512 | 3.14 | 6.283 |
|---|---|---|---|---|---|
| sin(x) | 0 | 0.951 | 0.598 | 0 | 0 |
| f₃(x) | 0 | 0 | 0.002 | 0.128 | 0.757 |
| x(弧度) | 0 | 1.256 | 2.512 | 3.14 | 6.283 |
|---|---|---|---|---|---|
| sin(x) | 0 | 0.951 | 0.598 | 0 | 0 |
| 最终结果 | 0.8 | 0.649 | 0.846 | 0.583 | 1.646 |
| 维度 | 幂级数展开(多阶导数) | 深度学习(多层激活叠加) |
|---|---|---|
| 核心逻辑 | 靠曲线的“局部导数信息”(1阶、2阶…),用多项式无限逼近曲线 | 靠“简单非线性模块的全局组合”,用多层网络无限逼近曲线 |
| 依赖条件 | 曲线必须“无限可导”(比如sin(x)),否则无法展开 | 无需求导,哪怕曲线不光滑(比如分段函数)也能逼近 |
| 逼近方式 | 从“单个点”的导数出发,全局拟合曲线 | 从“整体特征”出发,分层提炼曲线规律 |
| 场景 | 视觉Token的连续特性体现 | 幂级数(泰勒展开)的适配逻辑 |
|---|---|---|
| 输入变化 | 亮度从50→51,Token向量平滑增减 | 泰勒展开的“小增量 x−x0=1”,导数项可精准捕捉这种微小变化 |
| 特征渐变 | “猫眼睛→猫耳朵”的Token向量连续过渡 | 多阶导数项叠加,可拟合这种“渐变曲线”的曲率变化 |
| 无离散字典 | 无需固定字典,Token向量随像素连续生成 | 幂级数无需“离散点匹配”,直接对连续输入展开 |
import numpy as np
import matplotlib.pyplot as plt
# ---------------------- 1. 定义视觉Token的连续特征函数 ----------------------
# 模拟:视觉Token的某一特征维度y,随输入亮度x(0~100)的连续变化(光滑可导)
def visual_feature_func(x):
"""视觉Token的连续特征函数(模拟亮度x→特征y的映射)"""
return np.sin(0.1 * x) + 0.01 * x # 光滑曲线,模拟视觉特征渐变
# ---------------------- 2. 计算泰勒展开的各阶导数项 ----------------------
# 围绕中心点x0=50(亮度为50的视觉Token)展开
x0 = 50
# 0阶项:f(x0)
f_x0 = visual_feature_func(x0)
# 1阶导数:f'(x) = 0.1*cos(0.1x) + 0.01
f1_x0 = 0.1 * np.cos(0.1 * x0) + 0.01
# 2阶导数:f''(x) = -0.01*sin(0.1x)
f2_x0 = -0.01 * np.sin(0.1 * x0)
# 3阶导数:f'''(x) = -0.001*cos(0.1x)
f3_x0 = -0.001 * np.cos(0.1 * x0)
# 定义泰勒展开函数(1阶、3阶)
def taylor_1st(x):
"""1阶泰勒展开(直线逼近)"""
return f_x0 + f1_x0 * (x - x0)
def taylor_3rd(x):
"""3阶泰勒展开(曲线逼近)"""
return (f_x0
+ f1_x0 * (x - x0)
+ (f2_x0 / 2) * (x - x0)**2
+ (f3_x0 / 6) * (x - x0)**3)
# ---------------------- 3. 生成数据并可视化 ----------------------
# 生成连续的亮度输入x(0~100,模拟视觉Token的连续变化)
x = np.linspace(0, 100, 200) # 200个连续采样点,体现视觉Token的连续性
y_true = visual_feature_func(x) # 真实的视觉特征曲线
y_taylor1 = taylor_1st(x) # 1阶泰勒逼近
y_taylor3 = taylor_3rd(x) # 3阶泰勒逼近
# 绘图
plt.figure(figsize=(10, 6))
plt.plot(x, y_true, label='视觉Token真实特征曲线(连续)', linewidth=2.5, color='#2E86AB')
plt.plot(x, y_taylor1, label='1阶泰勒展开(直线逼近)', linewidth=2, linestyle='--', color='#A23B72')
plt.plot(x, y_taylor3, label='3阶泰勒展开(曲线逼近)', linewidth=2, linestyle='-.', color='#F18F01')
plt.scatter(x0, f_x0, color='red', s=100, zorder=5, label=f'展开中心点x0={x0}')
plt.xlabel('视觉Token的亮度(连续输入)', fontsize=12)
plt.ylabel('视觉Token的特征维度值(连续输出)', fontsize=12)
plt.title('视觉Token的连续性与泰勒展开逼近', fontsize=14, fontweight='bold')
plt.legend(fontsize=11)
plt.grid(alpha=0.3)
plt.show()
import numpy as np
import matplotlib.pyplot as plt
# ---------------------- 1. 视觉Token的连续特征函数(光滑可导) ----------------------
def visual_feature_func(x):
"""模拟视觉Token特征随亮度x的连续变化(光滑曲线)"""
return np.sin(0.1 * x) + 0.01 * x # 基础曲线:正弦波动+线性递增
# ---------------------- 2. 计算各阶泰勒展开的导数项(围绕x0=50展开) ----------------------
x0 = 50 # 展开中心点(亮度为50的视觉Token)
f_x0 = visual_feature_func(x0) # 0阶项:f(x0)
# 1阶导数及在x0处的值(特征变化率)
f1 = lambda x: 0.1 * np.cos(0.1 * x) + 0.01
f1_x0 = f1(x0)
# 2阶导数及在x0处的值(变化率的变化)
f2 = lambda x: -0.01 * np.sin(0.1 * x)
f2_x0 = f2(x0)
# 3阶导数及在x0处的值(曲率变化)
f3 = lambda x: -0.001 * np.cos(0.1 * x)
f3_x0 = f3(x0)
# 4阶导数及在x0处的值(曲率的变化率)
f4 = lambda x: 0.0001 * np.sin(0.1 * x)
f4_x0 = f4(x0)
# ---------------------- 3. 定义0~4阶泰勒展开函数 ----------------------
def taylor_0th(x):
"""0阶展开:仅常数项(完全不随x变化)"""
return f_x0
def taylor_1st(x):
"""1阶展开:常数项+1阶项(直线)"""
return f_x0 + f1_x0 * (x - x0)
def taylor_2nd(x):
"""2阶展开:1阶+2阶项(二次曲线)"""
return taylor_1st(x) + (f2_x0 / 2) * (x - x0)**2
def taylor_3rd(x):
"""3阶展开:2阶+3阶项(三次曲线)"""
return taylor_2nd(x) + (f3_x0 / 6) * (x - x0)**3
def taylor_4th(x):
"""4阶展开:3阶+4阶项(四次曲线)"""
return taylor_3rd(x) + (f4_x0 / 24) * (x - x0)**4 # 4! = 24
# ---------------------- 4. 生成数据并可视化多级逼近效果 ----------------------
x = np.linspace(0, 100, 500) # 更密集的采样点,体现连续性
y_true = visual_feature_func(x) # 真实特征曲线
# 计算各阶展开的结果
y0 = taylor_0th(x)
y1 = taylor_1st(x)
y2 = taylor_2nd(x)
y3 = taylor_3rd(x)
y4 = taylor_4th(x)
# 绘图
plt.figure(figsize=(12, 7))
plt.plot(x, y_true, label='真实视觉特征曲线', linewidth=3, color='#2E86AB')
plt.plot(x, y0, label='0阶展开(常数)', linestyle='-', color='#E63946', alpha=0.7)
plt.plot(x, y1, label='1阶展开(直线)', linestyle='--', color='#FFB703', alpha=0.8)
plt.plot(x, y2, label='2阶展开(二次曲线)', linestyle='-.', color='#FB8500', alpha=0.8)
plt.plot(x, y3, label='3阶展开(三次曲线)', linestyle=':', color='#1D3557', alpha=0.9)
plt.plot(x, y4, label='4阶展开(四次曲线)', linestyle=(0, (3, 1, 1, 1)), color='#457B9D', alpha=0.9)
plt.scatter(x0, f_x0, color='red', s=120, zorder=5, label=f'展开中心x0={x0}')
plt.xlabel('视觉Token亮度(连续输入)', fontsize=12)
plt.ylabel('特征维度值(连续输出)', fontsize=12)
plt.title('视觉Token特征的多级泰勒展开逼近(0~4阶对比)', fontsize=14, fontweight='bold')
plt.legend(fontsize=10, loc='upper left')
plt.grid(alpha=0.3)
plt.show()
ValueError: x and y must have same first dimension, but have shapes (500,) and (1,) 表明:在绘制0阶泰勒展开曲线时,x(长度为500的数组)和 y0(长度为1的标量)的维度不匹配。taylor_0th(x) 函数返回的是 f_x0(一个单一数值,即 visual_feature_func(50) 的计算结果),而 plt.plot(x, y0) 要求 x 和 y0 必须是长度相同的数组,因此导致维度不匹配错误。x 长度相同的数组(每个元素都等于 f_x0),确保 x 和 y0 维度一致。import numpy as np
import matplotlib.pyplot as plt
# ---------------------- 1. 视觉Token的连续特征函数(光滑可导) ----------------------
def visual_feature_func(x):
"""模拟视觉Token特征随亮度x的连续变化(光滑曲线)"""
return np.sin(0.1 * x) + 0.01 * x # 基础曲线:正弦波动+线性递增
# ---------------------- 2. 计算各阶泰勒展开的导数项(围绕x0=50展开) ----------------------
x0 = 50 # 展开中心点(亮度为50的视觉Token)
f_x0 = visual_feature_func(x0) # 0阶项:f(x0)
# 1阶导数及在x0处的值(特征变化率)
f1 = lambda x: 0.1 * np.cos(0.1 * x) + 0.01
f1_x0 = f1(x0)
# 2阶导数及在x0处的值(变化率的变化)
f2 = lambda x: -0.01 * np.sin(0.1 * x)
f2_x0 = f2(x0)
# 3阶导数及在x0处的值(曲率变化)
f3 = lambda x: -0.001 * np.cos(0.1 * x)
f3_x0 = f3(x0)
# 4阶导数及在x0处的值(曲率的变化率)
f4 = lambda x: 0.0001 * np.sin(0.1 * x)
f4_x0 = f4(x0)
# ---------------------- 3. 定义0~4阶泰勒展开函数 ----------------------
def taylor_0th(x):
"""0阶展开:仅常数项(完全不随x变化)"""
return np.full_like(x, f_x0) # 生成与x同形状的数组,元素均为f_x0
def taylor_1st(x):
"""1阶展开:常数项+1阶项(直线)"""
return f_x0 + f1_x0 * (x - x0)
def taylor_2nd(x):
"""2阶展开:1阶+2阶项(二次曲线)"""
return taylor_1st(x) + (f2_x0 / 2) * (x - x0)**2
def taylor_3rd(x):
"""3阶展开:2阶+3阶项(三次曲线)"""
return taylor_2nd(x) + (f3_x0 / 6) * (x - x0)**3
def taylor_4th(x):
"""4阶展开:3阶+4阶项(四次曲线)"""
return taylor_3rd(x) + (f4_x0 / 24) * (x - x0)**4 # 4! = 24
# ---------------------- 4. 生成数据并可视化多级逼近效果 ----------------------
x = np.linspace(0, 100, 500) # 更密集的采样点,体现连续性
y_true = visual_feature_func(x) # 真实特征曲线
# 计算各阶展开的结果
y0 = taylor_0th(x)
y1 = taylor_1st(x)
y2 = taylor_2nd(x)
y3 = taylor_3rd(x)
y4 = taylor_4th(x)
# 绘图
plt.figure(figsize=(12, 7))
plt.plot(x, y_true, label='真实视觉特征曲线', linewidth=3, color='#2E86AB')
plt.plot(x, y0, label='0阶展开(常数)', linestyle='-', color='#E63946', alpha=0.7)
plt.plot(x, y1, label='1阶展开(直线)', linestyle='--', color='#FFB703', alpha=0.8)
plt.plot(x, y2, label='2阶展开(二次曲线)', linestyle='-.', color='#FB8500', alpha=0.8)
plt.plot(x, y3, label='3阶展开(三次曲线)', linestyle=':', color='#1D3557', alpha=0.9)
plt.plot(x, y4, label='4阶展开(四次曲线)', linestyle=(0, (3, 1, 1, 1)), color='#457B9D', alpha=0.9)
plt.scatter(x0, f_x0, color='red', s=120, zorder=5, label=f'展开中心x0={x0}')
plt.xlabel('视觉Token亮度(连续输入)', fontsize=12)
plt.ylabel('特征维度值(连续输出)', fontsize=12)
plt.title('视觉Token特征的多级泰勒展开逼近(0~4阶对比)', fontsize=14, fontweight='bold')
plt.legend(fontsize=10, loc='upper left')
plt.grid(alpha=0.3)
plt.show()
taylor_0th(x) 函数中,将原本直接返回标量 f_x0 的逻辑,改为使用 np.full_like(x, f_x0) 生成与 x 形状完全相同的数组,数组中每个元素的值均为 f_x0,从而保证 x 和 y0 的维度一致,解决绘图时的维度不匹配问题。| 维度 | 多头注意力(多个头) | MoE的8个专家 |
|---|---|---|
| 核心逻辑 | 把Attention的“特征空间”分成多个子空间,每个头独立计算注意力,最后融合 | 把FFN的“特征处理”分成多个专属任务,每个专家独立运算,最后融合 |
| 并行方式 | 多个头并行计算注意力权重 | 8个专家并行执行“降维-激活-升维” |
| 目标 | 捕捉不同维度的语义关联(如语法、逻辑、情感) | 处理不同类型的特征(如政治语义、语法、实体) |
| 融合方式 | 多头输出拼接后线性变换 | 专家输出加权求和(权重由门控网络给出) |