1. 理解Transformer微调中的核心投影层
在大型语言模型(LLM)微调过程中,我们经常会遇到q_proj、k_proj、v_proj、o_proj等模块名称。这些看似神秘的缩写其实对应着Transformer架构中最核心的线性变换层。我第一次接触这些概念时也是一头雾水,直到真正动手微调模型后才恍然大悟——这些投影层实际上是控制模型注意力机制和FFN(前馈网络)行为的"调节旋钮"。
以Llama 2模型为例,当我们查看其模型结构时,会发现每个Transformer层包含以下关键投影模块:
- 注意力机制部分:q_proj、k_proj、v_proj、o_proj
- 前馈网络部分:gate_proj、up_proj、down_proj
这些投影层本质上都是全连接层(线性层),负责将输入向量映射到不同的特征空间。它们的命名遵循了非常直观的规则:"q"代表Query,"k"代表Key,"v"代表Value,这些都是注意力机制中的核心概念;而"o"代表Output,是注意力机制的最终输出。
提示:在微调时选择性地调整这些投影层,可以显著影响模型在不同任务上的表现。比如只微调q_proj和v_proj能在保持模型泛化能力的同时,有效降低显存消耗。
1.1 注意力机制中的四大投影层
在标准的自注意力机制中,输入序列会经过四个关键的线性变换:
-
q_proj (Query投影):
- 将输入向量映射为查询向量(Query)
- 维度通常为[hidden_size, num_heads * head_dim]
- 决定了模型"寻找什么信息"
-
k_proj (Key投影):
- 将输入向量映射为键向量(Key)
- 维度与q_proj相同
- 决定了模型"用什么特征来匹配"
-
v_proj (Value投影):
- 将输入向量映射为值向量(Value)
- 维度通常为[hidden_size, num_heads * head_dim]
- 包含了实际要传递的信息内容
-
o_proj (Output投影):
- 将多头注意力的输出映射回模型维度
- 维度通常为[num_heads * head_dim, hidden_size]
- 对注意力结果进行最后的整合
在实际应用中,我们经常会看到这样的配置代码:
python复制self.q_proj = nn.Linear(hidden_size, num_heads * head_dim, bias=False)
self.k_proj = nn.Linear(hidden_size, num_heads * head_dim, bias=False)
self.v_proj = nn.Linear(hidden_size, num_heads * head_dim, bias=False)
self.o_proj = nn.Linear(num_heads * head_dim, hidden_size, bias=False)
1.2 前馈网络中的三重投影
Transformer中的前馈网络(FFN)部分同样包含几个重要的投影层,特别是在Llama等模型采用的SwiGLU结构中:
-
gate_proj:
- 控制信息流动的"门控"投影
- 维度通常为[hidden_size, intermediate_size]
- 与up_proj共同决定哪些信息可以通过
-
up_proj:
- 向上扩展特征的投影
- 维度通常为[hidden_size, intermediate_size]
- 将特征映射到更高维空间
-
down_proj:
- 将扩展后的特征压缩回原维度
- 维度通常为[intermediate_size, hidden_size]
- 完成特征的最终整合
典型的实现代码如下:
python复制self.gate_proj = nn.Linear(hidden_size,
