模型篇(Bert llama deepseek)
Bert相关
BERT的核心在于双向编码器的设计,主要在预训练阶段设计了两种任务:
Masked Language Model (MLM):随机遮蔽输入句子中的一些单词(15%),然后预测这些单词。
Next Sentence Prediction (NSP):预测两个句子是否是连续的句子。这有助于模型理解句子之间的关系。
Bert的变体
RoBERTa (A Robustly Optimized BERT Pretraining Approach):
RoBERTa通过更大的数据集、更长的训练时间以及动态掩码等策略对BERT的预训练过程进行了优化。
取消了NSP任务
ALBERT (A Lite BERT):
ALBERT通过共享层间的参数来减少模型大小,同时保持了BERT的性能。
DistilBERT:
DistilBERT是一个更小、更快的BERT模型,通过知识蒸馏的方法从BERT中学习而来。
DeBERTa (Decoding-enhanced BERT with disEntangled attention):
DeBERTa通过对BERT的注意力机制进行改进,提高了模型的表示能力。
MobileBERT:
MobileBERT是为移动和边缘设备优化的BERT模型,具有较小的模型大小和高效的计算性能。
SqueezeBERT:
SqueezeBERT通过结构化剪枝和知识蒸馏技术减小了模型大小,同时保持了性能。
ERNIE (Enhanced Representation through kNowledge Integration):
ERNIE是由百度开发的一系列模型,它通过知识图谱的融合来增强语言表示。
RoBERTa为什么要取消NSP任务
NSP 对下游任务的贡献有限,尤其是在一些主要依赖于单句上下文的任务中。
MLM 任务本身已经能够有效捕捉上下文表示,并且训练时的优化方法(如增加数据量和训练时间)也进一步提升了模型的性能。
去除 NSP 后,RoBERTa 通过更高效的预训练策略,获得了更强的语言理解能力,在多个基准上超过了 BERT。
llama系列
llama1(2023)
模型架构
基础架构: 基于标准的 Transformer 架构,但进行了优化:
使用 RMSNorm(Root Mean Square Layer Normalization)替代传统 LayerNorm,提升训练稳定性。
SwiGLU 激活函数取代 ReLU,增强非线性表达能力。
RoPE(Rotary Positional Embedding) 位置编码,在注意力层中动态生成位置信息。
参数规模: 提供 7B、13B、33B、65B 四个版本,其中 65B 模型参数量最大,推理能力最强。
训练数据
数据量: 约 1.4T tokens,主要来自公开数据集(如 CommonCrawl、Wikipedia、书籍、代码库等),但排除了专有数据(如社交媒体内容)。
数据多样性: 包含多语言文本(英语为主),但未专门针对代码优化。
训练方法
目标函数: 标准的自回归语言模型目标(预测下一个 token)。
优化器: 使用 AdamW,结合余弦学习率调度和权重衰减。
训练效率: 通过高效的并行策略(数据并行+模型并行)在 GPU 集群上训练。
llama2(2023)
模型架构
改进点:
上下文长度提升至4K tokens(后续扩展至 16K)。
引入了 Grouped Query Attention (GQA)(仅限 34B 和 70B 版本),降低显存占用并加速推理。
使用更高效的预归一化(Pre-LayerNorm)结构。
参数规模: 7B、13B、34B、70B,其中 70B 版本性能接近 GPT-3.5。
训练数据
数据量: 约 2T tokens,数据源与 LLaMA 1 类似,但进行了更严格的质量过滤和去重。
新增内容: 包含更多对话数据(用于微调对话模型),支持多轮交互能力。
训练方法
预训练: 延续自回归训练,但优化了数据混合比例(代码和学术文本占比更高)。
微调:
监督微调(SFT): 使用人工标注的对话数据。
RLHF(基于人类反馈的强化学习): 对齐人类偏好,提升安全性和有用性。
安全机制: 引入安全分类器,减少有害输出。
llama3(2024)
模型架构
重大升级:
支持 8K 上下文窗口(可扩展至更长),优化长文本处理能力。
全面采用 Grouped Query Attention (GQA),不同参数版本分组策略不同(如 8B 用 MHA,70B 用 GQA)。
改进的 Tokenization,词汇表扩展至 128K,支持多语言和代码符号。
参数规模: 开源 8B 和 70B 版本,另有未开源的 400B+ 版本。
训练数据
数据量: 约 15T tokens,覆盖 30+ 种语言,代码数据占比显著提升。英文语料95%,其它语言5%
数据质量: 引入更复杂的数据清洗管道(去重、毒性过滤、多模态数据筛选)。(启发式过滤器、NSFW过滤器、语义重复删除技术等)
训练方法
高效训练:
使用 3D 并行(数据并行+流水线并行+张量并行)和 ZeRO 优化。
混合精度训练(BF16/FP16)结合梯度检查点。
SFT、拒绝采样、PPO、DPO
多阶段训练: 先预训练基础模型,再针对不同任务(对话、代码、数学)分阶段微调。
llama3和llama2的区别
在架构上,Llama 系列模型采用了仅decoder-only结构,用于多种配置下的下一个标记预测,参数规模从 8B到 70B到405B不等。Llama3是MetaAI发布的最新一代开源大语言模型,与Llama2相比,Llama3在多个方面进行了显著的升级和改进:
模型输出:Llama2的模型输出仅限于文本,而Llama3能够生成文本和代码,增强了模型的多功能性。此外,Llama3.1进一步增加了工具调用功能 。
上下文窗口大小:Llama3将上下文窗口大小从4k标记增加到了8k标记,而Llama3.1的上下文窗口大小更是扩展到了148K 。
Tokenizer和词汇表:Llama3采用了新的Tokenizer,将词汇表大小从32K扩展至128K,这不仅提高了编码效率,也为处理更多语言提供了基础。Llama3的Token数量从2T增加到了15T+,而Llama3.1的token数量也达到了15T+ 。
训练数据和时长:Llama3使用了超过15万亿Token的训练数据,这是Llama2训练数据量的7倍以上。同时,Llama3的训练时长也显著增加,例如Llama3-70B模型的训练时长达到了640万个GPU小时,显示出训练成本的大幅增长 。
模型架构:Llama3保持了与Llama2相似的基于解码器的Transformer架构,但进行了一些调整,如采用Group Query Attention(分组查询注意力)技术以加速推理。此外,Llama3的8B和70B版本都采用了GQA,上下文长度也扩展到了8k 。
性能提升:在各项评测基准中,Llama3相比Llama2展现出了显著的性能提升,例如在综合理解评测基准MMLU、数学推理GSM8K以及代码能力HumanEval的评测结果上都有大幅提高 。
指令跟随能力:Llama3在指令跟随能力上进行了优化,特别是在复杂逻辑推理问题上,能够更准确地选择最合适的答案 。
许可证变更:Llama3的许可证中新增了明确归属的要求,衍生模型需要在其名称开头包含“Llama 3”,并且在衍生作品或服务中需注明“基于 Meta Llama 3 构建” 。
qwen系列
qwen1
模型结构:基于Transformer改进,类似LLaMa结构
Tiktoken BPE,选择词汇表cl100k base作为起点扩充词汇表,将数字拆分为单个数字,最终词汇表大小约为152k
Untied Embedding:Input embedding和Output embedding不进行共享,是单独的两个权重矩阵,但是代价是增加了内存消耗,不过可以显著提升模型的性能
RoPE位置编码、Pre-RMSNorm、SwiGLU激活函数
在大多数层移除偏置bias,但在注意力的QKV层中保留,以增强模型的外推能力。通过添加偏差项,可以更好地捕捉输入数据的特征,从而提升模型在处理未知或未见数据时的表现。这种增强外推能力的做法对于处理复杂任务和应对多样化的数据输入非常重要。
模型训练
采用标准的自回归语言模型训练目标
训练时上下文长度为2048,为了构建批次数据,对文本内容进行随机打乱及合并,再将其截断到指定长度
注意力模块采用Flash attention,以提高计算效率并减少内存使用
使用BF16混合精度加速训练
优化器采用AdamW,超参数β1、β2和ε分别为0.9、0.95和1e-8
采用余弦学习率计划,学习率会衰减到峰值的10%
上下文长度(外推能力)扩展
通过动态NTK插值、LogN-Scaling和分层窗口Self-Attention等技术,有效地扩展了模型的上下文长度,同时保持了性能
动态NTK插值:核心思想 高频外推,低频内插
LogN -Scaling:根据熵不变性以及一些合理的假设,可以得到一个新的缩放因子,从而得到一种Scaled Dot-Product Attention,LogN-Scaling可以根据上下文长度与训练长度的比值,对Q和V的点积进行重新缩放,确保注意力值的熵随着上下文长度的增长而保持稳定
分层窗口Self-Attention:使用分层窗口Self-Attention,将注意力限制在一个上下文窗口内,防止模型关注到太远的内容;在不同层采用不同的窗口大小,较低的层使用较短的窗口,而较高的层使用较长的窗口 综合上述技术,Qwen预训练长度2048,推理的时候可以处理8192
Reward Model训练
预训练偏好模型(preference model pretraining):奖励模型由同等大小Qwen模型+池化层得来,用特殊的句子结束标记经过池化层的映射值作为模型奖励值
微调奖励模型:
分类系统:为确保prompt具备一定的多样性和复杂性,创建了一个包含约6600详细标签的分类系统
平衡采样:并采用了一种平衡采样算法,以在选择提示时兼顾多样性和复杂性
多样性采样:为了生成多样的回复,实验过程使用了不同规模和采样策略的Qwen模型,因为多样化的回复有助于降低标注难度并提高奖励模型的性能
介绍下Qwen3
三阶段预训练
通用基座:4 096 token 上下文,累积 30 万亿 token,构建语言与常识能力。
推理强化:继续在 4 096 token 长度下追加 5 万亿 高质量 STEM/Code 样本,加速学习率衰减。
长上下文扩容:采用ABF+ YARN + DCA,将窗口扩展至 32 768 token,训练数千亿 token。
长 CoT 冷启动:先用 Qwen2.5‑72B-Instruct进行用户query筛选 提升样本质量与多样性,再用QwQ-32B生成候选响应。
推理 RL(GRPO):选取多样且困难的问题,使用GRPO,大 batch + off-policy训练,只需170步即可让Qwen3-235B-A22B模型在 AIME’24 分数从 70 提升到 85+。
思维链显/隐控制:在词表注入专用 special token,并在 prompt 中使用 /think 与 /no_think 标签实现显式模式切换;训练结果显示,模型还能自发学会 短 CoT,兼顾低延迟与准确度。还可通过 thinking budget 截断思考 token,动态平衡速度与准确率。
奖励模型(RM)设计:覆盖 20 + 任务域(指令遵循、格式一致、偏好对齐、Agent 工具调用、RAG 等),为每个子任务定制评分规则,结合基于规则的Reward、参考答案评分、无参考的偏好模型评分三种信号,保证 RL 阶段反馈精准且稳定。
轻量蒸馏:
off-policy蒸馏(教师多模式输出)。
on-policy蒸馏(学生自行 roll‑out,再按 KL 对齐教师),仅 1/10 GPU‑hours 即把双模式推理能力下迁到 14B / 8B / 30B‑A3B 等小模型,效果显著优于纯 SFT。
deepseek系列
1.24年1.5日,DeepSeek LLM发布,没太多创新类似llama那一套(llama1的RoPE/RMSNorm/SwiGLU+llama270B或llama3的GQA)
2.24年1.11日,DeepSeekMoE,开启创新之路提出细粒度专家分割和共享专家隔离,以及一系列负载均衡
3.24年1.25,发布DeepSeek-Coder24年2月,发布DeepSeekMath提出了Group Relative Policy Optimization(简称GRPO),以替代PPO--舍弃critic模型
4.24年5.7日,DeepSeek-V2
提出多头潜在注意力MLA且改进MOE
其中的MLA是整个deepseek系列最大的几个创新之一,且由此引发了各大厂商百万token的大幅降价
5.24年12.26日,DeepSeek-V3发布在MOE、GRPO、MLA基础上提出Multi-Token预测,且含FP8训练
大家纷纷把它和Llama3.1405B对比,V3以极低的训练成本造就超强的效果,再度出圈
6.25年1.20日,DeepSeek R1发布
一方面,提出舍弃SFT、纯RL训练大模型的范式,且效果不错
二方面,性能比肩o1甚至略微超越
占三方面,直接公布思维链且免费,不像o1那样藏着掖着,对用户极度友好
Deepseek r1
在dpsk r1的这篇报告里,提到了2个模型,分别是 DeepSeek-R1-Zero
和 DeepSeek-R1
,总结来看:
强化学习取代SFT:zero算是一个实验性质的模型,在zero上不通过任何sft的方式,仅使用RL + 规则RM,就能激发模型产出带反思的long cot。这里使用的RL是GRPO:从一个好的模型开始,并根据正确性和风格结果给予奖励,没有PRM,没有MCTS,没有花哨的奖励模型。基本上检查答案是否正确。
涌现时刻(Aha Moment):在训练过程中,DeepSeek-R1-Zero展现了复杂行为的自发涌现,如反思和探索替代方法,这些行为并非通过明确编程实现,而是模型与强化学习环境交互的自然产物,显著增强了其推理能力。
r1是受到zero RL相关的实验结果启发,而新训的最终版的模型。zero所采用的RL方法(即什么样的RL能激发模型主动产出long cot,甚至是反思)将被 r1 参考。r1的训练流程包含四阶段:
冷启动:通过few shot prompting、直接生成、收集r1-zero的输出等,来收集少量数据长CoT数据来微调模型。
针对推理型问题的强化学习:也使用GRPO,同时为了缓解COT中有时会出现语言混合现象,因此在训练时还引入了语言一致性奖励。
拒绝采样和监督微调:对于推理型数据,从强化学习checkpoint进行拒绝采样生成推理轨迹;对于非推理型数据,使用了来自 DeepSeek-V3 的 SFT 数据集。
针对所有场景的强化学习:为了使输出更符合人类偏好,引入一个辅助强化学习阶段,结合奖励信号(reward signals)和多样化的提示分布(diverse prompt distributions)来训练模型,以确保其在不同场景下都能表现出色。
蒸馏技术的应用:DeepSeek通过R1模型的输出,蒸馏出多个小模型,适配市面上对模型尺寸的主流需求。其中,32B和70B模型在多项能力上实现了对标OpenAI o1-mini的效果,展现了蒸馏技术在传递大模型推理模式方面的优势。
MLA原理
Multi-Head Latent Attention (MLA) 是 DeepSeek-V3 模型中用于高效推理的核心注意力机制。MLA 通过低秩联合压缩技术,减少了推理时的键值(KV)缓存,从而在保持性能的同时显著降低了内存占用。具体来说,MLA使用下投影矩阵将键和值压缩成潜在向量,然后通过上投影矩阵将其还原。这种方式显著减少了KV缓存的大小,同时保持了与标准多头注意力(MHA)相当的性能。
GRPO
GRPO(Group Relative Policy Optimization)算法是一种强化学习算法,通过组内相对奖励机制来优化策略模型。与传统的PPO算法不同,GRPO通过组内相对奖励机制来优化策略模型,避免了使用额外的价值函数模型(critic model),这种方法不仅简化了训练流程,显著减少了内存和计算资源的消耗。
组内相对奖励:GRPO的核心思想是通过组内相对奖励来估计基线(baseline),从而避免使用额外的价值函数模型。具体来说,对于每个问题 q,GRPO从旧策略 $$\pi_{\theta_{old}}$$ 中采样一组输出 {o1,o2,…,oG},然后对每个输出 oi 进行奖励打分 ri。通过计算组内奖励的均值和标准差,将奖励归一化为组内相对奖励。
优化目标:GRPO的优化目标是最大化一个带有比例的目标函数,该函数考虑了当前策略和旧策略之间的比例关系,并通过裁剪超参数 ϵ 来限制策略更新的幅度。
Deepseek R1 训练流程
冷启动:通过few shot prompting、直接生成、收集r1-zero的输出等,来收集少量数据长CoT数据来微调模型。
针对推理型问题的强化学习:也使用GRPO,同时为了缓解COT中有时会出现语言混合现象,因此在训练时还引入了语言一致性奖励。
拒绝采样和监督微调:对于推理型数据,从强化学习checkpoint进行拒绝采样生成推理轨迹;对于非推理型数据,使用了来自 DeepSeek-V3 的 SFT 数据集。
针对所有场景的强化学习:为了使输出更符合人类偏好,引入一个辅助强化学习阶段,结合奖励信号(reward signals)和多样化的提示分布(diverse prompt distributions)来训练模型,以确保其在不同场景下都能表现出色。
DeepSeekMOE
MoE借鉴集成学习的思想,可以替换transformer模型中的FFN层,包含一个门控网络和多个路由专家网络。将FFN分割成多个专家,这些专家可以根据其特定的功能被设计成处理不同类型的输入或特征,构建门控网络决定对每个输入使用哪些专家。
DeepSeekMoE中采用了共享专家和路由专家两种,共享专家也就是所有问题都会参与计算的专家,路由专家则是由门控网络计算觉得是否参与训练。
针对MoE模型面临的负载不均衡问题,采用了无辅助损失的负载均衡策略,在门控网络计算每个专家的亲和力时,加入偏置量,在训练过程中持续监控每个专家的负载,每个训练步骤结束的时候,如果某个专家过载,则按照某一特定比例减少其偏置量;如果某个专家负载不足,则相应的按照同一比例增加其偏置量。
手撕
多头注意力
import torch.nn as nn
import numpy as np
import torch
import mathclass MHA(nn.Module):def __init__(self, num_head, dimension_k, dimension_v, d_k, d_v, d_o):# d_k表示head dimension,d_k * num_head 就是embedding的长度super().__init__()self.num_head = num_headself.d_k = d_kself.d_v = d_vself.d_o = d_oself.fc_q = nn.Linear(dimension_k, num_head * d_k)self.fc_k = nn.Linear(dimension_k, num_head * d_k)self.fc_v = nn.Linear(dimension_v, num_head * d_v)self.fc_o = nn.Linear(num_head * d_v, d_o)self.softmax = nn.Softmax(dim=2)def forward(self, q, k, v, mask):batch, n_q, dimension_q = q.size()batch, n_k, dimension_k = k.size()batch, n_v, dimension_v = v.size()q = self.fc_q(q)k = self.fc_k(k)v = self.fc_v(v)q = q.view(batch, n_q, self.num_head, self.d_k).permute(2, 0, 1, 3).contiguous().view(-1, n_q, self.d_k)k = k.view(batch, n_k, self.num_head, self.d_k).permute(2, 0, 1, 3).contiguous().view(-1, n_k, self.d_k)v = v.view(batch, n_v, self.num_head, self.d_v).permute(2, 0, 1, 3).contiguous().view(-1, n_v, self.d_v)attention = torch.matmul(q, k.transpose(-1, -2)) / math.sqrt(self.d_k)mask = mask.repeat(self.num_head, 1, 1)attention = attention + maskattention = self.softmax(attention)output = torch.matmul(attention, v)output = output.view(self.num_head, batch, n_q, self.d_v).permute(1, 2, 0, 3).contiguous().view(batch, n_q, -1)output = self.fc_o(output)return attention, outputclass MQA(nn.Module):def __init__(self, num_head, dimension_k, dimension_v, d_k, d_v, d_o):super().__init__()self.num_head = num_headself.d_k = d_kself.d_v = d_vself.d_o = d_oself.fc_q = nn.Linear(dimension_k, num_head * d_k)self.fc_k = nn.Linear(dimension_k, d_k)
交叉熵损失计算
pytorch实现
#使用torch计算交叉熵
ce_loss = nn.CrossEntropyLoss()
#假设有3个样本,每个都在做3分类
pred = torch.FloatTensor([[0.3, 0.1, 0.3],[0.9, 0.2, 0.9],[0.5, 0.4, 0.2]]) #n*class_num
#正确的类别分别为1,2,0
target = torch.LongTensor([1,2,0]) #nloss = ce_loss(pred, target)
print(loss, "torch输出交叉熵")#实现softmax函数
def softmax(matrix):return np.exp(matrix) / np.sum(np.exp(matrix), axis=1, keepdims=True)#验证softmax函数
# print(torch.softmax(pred, dim=1))
# print(softmax(pred.numpy()))#将输入转化为onehot矩阵
def to_one_hot(target, shape):one_hot_target = np.zeros(shape)for i, t in enumerate(target):one_hot_target[i][t] = 1return one_hot_target#手动实现交叉熵
def cross_entropy(pred, target):batch_size, class_num = pred.shapepred = softmax(pred)target = to_one_hot(target, pred.shape)entropy = - np.sum(target * np.log(pred), axis=1)return sum(entropy) / batch_sizeprint(cross_entropy(pred.numpy(), target.numpy()), "手动实现交叉熵")
numpy实现
import numpy as np# 定义 softmax 函数
def softmax(x):x_exp = np.exp(x - np.max(x, axis=1, keepdims=True)) # 防止数值溢出return x_exp / np.sum(x_exp, axis=1, keepdims=True)# 定义交叉熵损失函数
def cross_entropy(logits, labels):probs = softmax(logits)m = labels.shape[0]log_probs = -np.log(probs[np.arange(m), labels] + 1e-8) # 避免 log(0)return np.sum(log_probs) / m# 示例数据
logits = np.array([[0.3, 0.1, 0.3],[0.9, 0.2, 0.9],[0.5, 0.4, 0.2]])
labels = np.array([1, 2, 0])# 计算交叉熵损失
loss = cross_entropy(logits, labels)
print("交叉熵损失(NumPy 实现):", loss)