Qwen整体介绍
Qwen的整体架构与Llama2类似,如下图所示:

其中:
tokenizer将文本转为词表里面的数值。- 数值经过
embedding得到一一对应的向量。 attention_mask是用来看见左边、右边,双向等等来设定。- 各类下游任务,
Casual,seqcls等,基本都是基础模型model后面接对应的Linear层,还有损失函数不一样。
1 Qwen2Config
Qwen2Config中包含一些自定义的超参数
- 设置了模型的两个属性:
padding_idx(用于指定填充标记的索引),vocab_size(词汇表的大小) - 初始化了模型的嵌入层、解码器层、归一化层
- 嵌入层(
nn.Embedding):模型使用嵌入层将输入的标记映射成密集的向量表示。 - 解码器层(
nn.ModuleList()):模型包含多个解码器层,这些层都是由 `Qwen2DecoderLayer`` 定义 - 归一化层
Qwen2RMSNorm:归一化层使用的是 Root Mean Square Layer Normalization - 设置了是否使用
gradient_checkpoint主要是用来节省显存 - 调用
post_init()完成一些初始化和准备检查的代码
class Qwen2Model(Qwen2PreTrainedModel):
def __init__(self, config: Qwen2Config):
super().__init__(config)
self.padding_idx = config.pad_token_id
self.vocab_size = config.vocab_size
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
self.layers = nn.ModuleList(
[Qwen2DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
)
self.norm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
self.gradient_checkpointing = False
# Initialize weights and apply final processing
self.post_init()
对于post_init函数:
主要是对参数进行初始化,以及初始化梯度检查点作用
def post_init(self):
"""
A method executed at the end of each Transformer model initialization, to execute code that needs the model's
modules properly initialized (such as weight initialization).
"""
self.init_weights()
self._backward_compatibility_gradient_checkpointing()
1.2 Qwen2DecoderLayer
1.2.1 初始化
layer三件套:attn+MLP+norm
QWEN2_ATTENTION_CLASSES = {
"eager": Qwen2Attention, # 一般情况下是这个
"flash_attention_2": Qwen2FlashAttention2,
"sdpa": Qwen2SdpaAttention,
}
class Qwen2DecoderLayer(nn.Module):
def __init__(self, config: Qwen2Config):
super().__init__()
self.hidden_size = config.hidden_size
self.self_attn = QWEN2_ATTENTION_CLASSES[config._attn_implementation](config, layer_idx)
self.mlp = Qwen2MLP(config)
self.input_layernorm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
self.post_attention_layernorm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
这里面的input_layernorm和post_attention_layernorm内容是一样的,只是应用的顺序不一样。
1.1.2 Forward
- 首先复制一份
hidden_states为residual,然后将hidden_states送入Norm,再送入attn模块。 - 得到
attn的输出后,再复制一份residual,再将hidden_states送入Norm,mlp,再与residual进行相加。最后输出的就是这个hidden_states啦。
residual = hidden_states
# 标准化后送入attn
hidden_states = self.input_layernorm(hidden_states) # RMSNorm标准化
# Self Attention
hidden_states, self_attn_weights, present_key_value = self.self_attn(
hidden_states=hidden_states,
attention_mask=attention_mask,
position_ids=position_ids,
past_key_value=past_key_value,
output_attentions=output_attentions,
use_cache=use_cache,
**kwargs,
)
# 残差与新的hidden_states相加
hidden_states = residual + hidden_states
# Fully Connected
residual = hidden_states
# 同样的RMSNorm标准化
hidden_states = self.post_attention_layernorm(hidden_states)
hidden_states = self.mlp(hidden_states)
hidden_states = residual + hidden_states
outputs = (hidden_states,)
return outputs
1.3 Qwen2Attention
1.3.1 初始化
核心参数解析:
num_key_value_heads:表示键值对的头数num_key_value_groups:表示键值对的组数,计算为num_heads//num_key_value_headsGQA的实现!!q_proj,k_proj,v_proj,o_proj四个Linear操作。后续LoRa也基本都对他动的刀子.
class Qwen2Attention(nn.Module):
"""Multi-headed attention from 'Attention Is All You Need' paper"""
def __init__(self, config: Qwen2Config):
super().__init__()
self.config = config
self.layer_idx = layer_idx
self.hidden_size = config.hidden_size
self.num_heads = config.num_attention_heads
self.head_dim = self.hidden_size // self.num_heads
self.num_key_value_heads = config.num_key_value_heads
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
self.max_position_embeddings = config.max_position_embeddings
self.rope_theta = config.rope_theta
self.is_causal = True
self.attention_dropout = config.attention_dropout
if (self.head_dim * self.num_heads) != self.hidden_size:
raise ValueError(
f"hidden_size must be divisible by num_heads (got `hidden_size`: {
self.hidden_size}"
f" and `num_heads`: {
self.num_heads})."
)
self.q_proj = nn.Linear(self.hidden_size, self.num_heads * self.head_dim, bias=config.attention_bias)
self.k_proj = nn.Linear(self.hidden_size, self.num_key_value_heads

7245

被折叠的 条评论
为什么被折叠?



