【LLM】qwen3.5-9b
一、总体架构(三大子系统)
Qwen3_5ForConditionalGeneration │ ┌───────────────────────────┼───────────────────────────┐ ▼ ▼ ▼ Qwen3_5VisionModel Qwen3_5TextModel (Backbone) LM Head (ViT 视觉编码器) (32 层 hybrid decoder) (投影到 vocab) depth=27 blocks full+linear attention tie_word_embed hidden=1152 hidden=4096 patch=16 heads=16输入数据流:
文本 tokens ──┐ │──► 词嵌入 embed_tokens (hidden=4096) ──┐ <image_pad> ──┘ │ ▼ Reference ──► Qwen3_5VisionModel (ViT) ──► out (4096d) Images / Video ├─ Conv3d patch_embed ├─ pos_embed (bilinear interp) ├─ 27 × VisionBlock (full attention) └─ PatchMerger (spatial_merge=2 → 4× 压缩) │ [文本 embed | 视觉 embed replaces <image_pad>] ◄──┘ │ ▼ Qwen3_5TextModel 32 × DecoderLayer (mixture of full & linear attention) │ ▼ RMSNorm → LM head关键点:视觉侧和文本侧的融合发生在嵌入层,不是 cross-attention。视觉 tokens 被投影到 4096 维后,替换文本序列里的<image_pad>占位 token,之后统一走文本 backbone 的 self-attention。
二、Vision Tower(视觉编码器)细节
Qwen3_5VisionModel(modeling_qwen3_5.pyL1018-1125):
| 组件 | 结构 | 输出 |
|---|---|---|
patch_embed | Conv3d(3, 1152, kernel=(2,16,16), stride=(2,16,16)) | (T/2, H/16, W/16) 网格,每 patch 1152d |
pos_embed | 双线性插值的可学习 2D 位置编码 (num_position_embeddings=2304 → 48×48) | 加到 patch embed 上 |
rotary_pos_emb | 2D RoPE,每 head_dim/2 = 36 维 | 送 attention |
blocks | 27 ×Qwen3_5VisionBlock每块含 Qwen3_5VisionAttention(full attention,16 heads,head_dim=72)+ MLP(GELU,4304 中间维) | (N_patch, 1152) |
merger | 空间 2×2 池化 →LayerNorm → Linear(4608, 4608) → GELU → Linear(4608, 4096) | (N_patch/4,4096) |
参数量估算:
- Conv3d patch_embed:~1.8M
- 27 层 vision block:每层 ≈ 15M,合计~405M
- pos_embed:2304 × 1152 ≈ 2.6M
- merger:≈ 39M
Vision tower 合计≈ 450M(占 9B 里的约 5%)。
核心事实:spatial_merge_size=2,temporal_patch_size=2→ 一张 448×448 图像会得到约(448/16/2)² = 196个视觉 token(送进文本 backbone 时)。视频每 2 帧合并一次时间。
三、Text Backbone(文本主干)——hybrid attention 是核心
Qwen3_5TextModel(modeling_qwen3_5.pyL1137):
input: [B, T, 4096] │ ├─ DecoderLayer 0 (linear_attention) ├─ DecoderLayer 1 (linear_attention) ├─ DecoderLayer 2 (linear_attention) ├─ DecoderLayer 3 (full_attention) ← 只有这 8 层能拿到标准 attention weights ├─ DecoderLayer 4 (linear_attention) ├─ DecoderLayer 5 (linear_attention) ├─ DecoderLayer 6 (linear_attention) ├─ DecoderLayer 7 (full_attention) ← ├─ ... ├─ DecoderLayer 31 (full_attention) ← │ └─ RMSNorm → hidden_statesFull attention 层的位置(full_attention_interval=4,从第 3 层开始):
[3, 7, 11, 15, 19, 23, 27, 31] 共 8 层其余24 层都是linear_attention(Qwen3_5GatedDeltaNet,一种 state-space 类似 Mamba 的机制)。
3.1 Full Attention 层(Qwen3_5Attention)
标准多头 self-attention:
- hidden_size = 4096
- num_attention_heads = 16
- head_dim = 256(注意:这里不是 4096/16=256,是显式配置的)
- 每 token 前向:
Q, K, V ∈ [T, 16, 256] - Attention weights 矩阵:
[16, T, T] - 输出:
(hidden_states, attention_weights)
这是我们能提取到 attention weight 的唯一入口。
3.2 Linear Attention 层(Qwen3_5GatedDeltaNet)
不是标准 QK^T 结构,而是状态空间模型——用 recurrent 累加的方式近似 attention,形式类似 Mamba / RetNet。特征:
- 显存 O(hidden × head_dim),与序列长度无关
- 没有明确的 attention weights 矩阵(数学上没有 softmax(QK^T))
- HuggingFace 里
output_attentions=True会静默丢弃这些层的返回值
这就是为什么我实验里out.attentions长度只有 8——只有 full_attention 层能提供 attention weights。
3.3 Decoder Layer 前向(Qwen3_5DecoderLayer.forward)
residual=hidden_states hidden_states=input_layernorm(hidden_states)# RMSNormiflayer_type=="linear_attention":hidden_states=linear_attn(hidden_states,...)# SSM-styleeliflayer_type=="full_attention":hidden_states,_=self_attn(hidden_states,...)# 标准 attentionhidden_states=residual+hidden_states# residualresidual=hidden_states hidden_states=post_attention_layernorm(hidden_states)hidden_states=mlp(hidden_states)# SwiGLU MLPhidden_states=residual+hidden_states# residual单层参数:
- attention (full):Q/K/V/O projection 各 ~4M,合计 ~16M;linear_attention 大致同量级
- MLP:
Linear(4096, 12288) + Linear(12288, 4096)= 50M(3 个 gate 结构,实际约150M) - 每层合计约170M,32 层 =~5.4B
四、总参数量核对
| 组件 | 参数量 |
|---|---|
| Vision tower(27 层 ViT) | ~450M |
| Text embed_tokens (248320 × 4096) | ~1.0B |
| Text backbone (32 层) | ~5.4B |
| LM head (tied with embed_tokens) | 0(复用) |
| RMSNorm 等 | ~1M |
| 总计 | ~7B ~ 9B(含 embedding 后是 9B) |
配置里的 “9B” 主要来自巨大的 vocabulary embedding(248K token)。
