# Summary # Cues # Notes # 飞书云文档 --- ## 代码熊的大模型知识库 * **企业公开** * **搜索** * **目录(暂无内容)** * **与我分享** --- ## 📚 目录 * **🎯 从0到∞: 大语言模型知识面试一本通** * 1. 大语言模型基础 * 1.1 Transformer * 1.2 模型参数量计算 * 1.3 面试考点解析 * 2. 大语言模型架构 * 3. 大语言模型预训练 * 3.1 预训练相关概念 * 3.2 预训练数据相关 * 3.3 Tokenizer训练 * 3.4 大模型训练侧优化 * 3.5 训练/推理显存占用分析 * 3.6 LoRA训练显存占用分析 * 3.7 大模型训练节约显存的方法? * 3.8 面试考点解析 * 4. 大模型监督微调 * 4.1 微调基础概念 * 4.2 Prompt Tuning * 4.3 Instruction Tuning * 4.4 参数高效微调PEFT * 4.5 面试考点解析 * 5. 大语言模型强化学习 * 5.1 强化学习基础概念 * 5.2 RLHF与近端策略优化PPO * 5.3 直接偏好优化DPO * 5.4 o1相关技术 * 5.5 面试考点解析 * 5.6 从概率模型上看SFT和RL的区别 * 6. 提示工程与RAG * 7. 大模型推理侧优化 * 8. 大语言模型评测 * 9. 多模态笔记 * 10. 大模型项目实践 * **2025年最好的大模型学习路线** * **缓冲区:论文笔记** * **补充篇:笔试、面试技巧** * **新鲜面经** * **互联网提前批入口总结** * **手撕合集(更新中)** --- <small>代码熊的大模型知识库 > 🎯从0到∞: 大语言模型知识面试一本通 > 1. 大语言模型基础 > **1.3 面试考点解析**</small> # 1.3 面试考点解析 * **Authors:** 古希腊掌管代码的神, 飞猪环游记THU * **Last Modified:** 7月12日 21:15 > ### 🤖 AI 速览 > > 本文讨论了面试中关于Transformer相关知识的考点解析,涵盖手撕代码、原理问答、参数量计算、解码方法等多个方面。关键要点包括: > > 1. **手撕Transformer模块**:给出了MHA、FFN、Positional Embedding、Encoder、Decoder等模块的代码实现,还给出了Transformer整体的代码及测试代码。 > 2. **手撕Attention**:提供了使用`np.einsum`和`np.matmul`两种方式实现Multi-Head Attention的代码及测试脚本。 > 3. **K、Q、V使用问题**:K和Q使用不同的投影矩阵计算,能增加表达能力和泛化能力;若K和Q相同,attention score矩阵是对称矩阵,泛化能力差。 > 4. **Decoder的Cross Attn Mask**:使用padding mask屏蔽来自encoder的padding token,不用融合casual mask也不会出现attn信息泄漏问题。 > 5. **大模型输出解码方法**:有Greedy、Random Sampling、Top-K、Top-P、BeamSearch、Blockwise Parallel Decoding、Speculative Sampling、Contrastive Decoding等方法,各方法在解码速度、质量和多样性上各有优劣。 > 6. **扩充词表**:优点是提高编解码效率、上下文长度和中文能力(存疑),步骤为扩充词表(去重)和Embedding初始化(随机或用原词表均值扩充)。 > 7. **Prenorm与Postnorm区别**:Pre-Norm结构往往更容易训练,但最终效果通常不如Post-Norm,在transfomer layers较多时,Pre-Norm会造成退化,Post-Norm训练任务更难但更不易收敛。 ## Q1: 手撕Transformer中的各个模块 **A1: 参考代码** 主要几个部分:MHA、FFN、Positional Embedding、Encoder & Decoder ### MHA (Multi-Head Attention) ```python import torch import torch.nn as nn import torch.nn.functional as F import math class MultiHeadAttention(nn.Module): def __init__(self, embed_size, heads): super(MultiHeadAttention, self).__init__() self.embed_size = embed_size self.heads = heads self.head_dim = embed_size // heads assert (self.head_dim * self.heads == self.embed_size), "embed_dim needs to be divisible by heads" self.k = nn.Linear(self.embed_size, self.embed_size, bias=False) self.q = nn.Linear(self.embed_size, self.embed_size, bias=False) self.v = nn.Linear(self.embed_size, self.embed_size, bias=False) self.fc_out = nn.Linear(self.heads * self.head_dim, self.embed_size) def forward(self, value, key, query, mask): b = query.shape[0] value_len, key_len, query_len = value.shape[1], key.shape[1], query.shape[1] q, k, v = self.q(query), self.k(key), self.v(value) # Split the embedding into self.heads different pieces q = q.reshape(b, query_len, self.heads, self.head_dim) k = k.reshape(b, key_len, self.heads, self.head_dim) v = v.reshape(b, value_len, self.heads, self.head_dim) # Einsum does matrix multiplication for query*keys for each training example # with every other key, then scale, mask, and apply softmax attention = torch.einsum("bqhd,bkhd->bhqk", [q, k]) if mask is not None: attention = attention.masked_fill(mask == 0, float("-1e20")) attention = F.softmax(attention / math.sqrt(self.head_dim), dim=3) out = torch.einsum("bhqk,bkhd->bqhd", [attention, v]).reshape(b, query_len, self.heads * self.head_dim) out = self.fc_out(out) return out ``` ### Transformer Block ```python class TransformerBlock(nn.Module): def __init__(self, embed_size, heads, dropout, inner_dim): super(TransformerBlock, self).__init__() self.attention = MultiHeadAttention(embed_size, heads) self.norm1 = nn.LayerNorm(embed_size) self.norm2 = nn.LayerNorm(embed_size) self.feed_forward = nn.Sequential( nn.Linear(embed_size, inner_dim), nn.ReLU(), nn.Linear(inner_dim, embed_size) ) self.dropout = nn.Dropout(dropout) def forward(self, value, key, query, mask): attention = self.attention(value, key, query, mask) x = self.dropout(self.norm1(attention + query)) forward = self.feed_forward(x) out = self.dropout(self.norm2(forward + x)) return out ```