补短
对于模型训练过程中,如果出现样本标签数据分布极其不均衡,通常会采取什么方法来解决问题
问题本质
loss会被多数类主导,会使得模型只要学会猜多数类就能得高分
所以核心目的是:让模型在训练时多关心少数类
解决方式
数据层面
1.过采样(oversampling)
重复采样少数类样本或用数据增强制造新样本
缺点:重复样本容易导致过拟合,增强不合理会引入噪声
2.欠采样(Undersampling)
随机丢弃多数类样本
只适用于数据量极大时
3.合成样本(例如SMOTE算法,即Synthetic Minority Oversampling Technique合成少数过采样算法)
在特征空间用特殊算法合成少数类样本
比直接复制好,对比之下也能缓解过拟合,但仍然有过拟合的可能
如果少数类样本和多数类样本在特征空间中存在大量重叠,SMOTE合成的新样本可能会落入多数类样本呢区域,反而加剧了样本的混淆
损失函数层面
1.类别加权(Class weighting)
在loss里给少数类更大的权重
例如L=-w_y log{p(y)}
让w_y和1/freq(y)成比例
常用,但权重过大容易造成训练不稳定,需要调参
2.Focal loss
L = -(1-p_y)^γ log{p(y)}
难样本权重大,易样本自动降权
但会多一个超参并且对概率校准有影响
采样策略层面
1.Balanced mini-batch
每个batch强制类别均衡
2.两阶段训练 (coarse->fine)
stage 1:均衡采样,学区分能力
stage 2:按真实分布微调
高风险任务常见,但训练流程与调参复杂度较高
self-attention
假设我有一串tokens
X = [x1,x2,x3,x4,…,xN]
每个xi代表模型当前层的token表示,包含内容信息和位置编码
X通过对应的投影矩阵,即W_Q,W_K,W_V相乘得到三种线性变换视角Q、K、V
Q(Query,查询),站在当前token的视角,表示“我关心什么样的信息”
K(Key),站在被查询token的视角,表示“我具备什么样的特征”
V(Value),真正被聚合/加权的信息,表示“如果你选我,我给你什么”
例如(QK^T)_{ij} = (q_i)^T k_j含义为:
token i问:token j和我关心的东西有多相关?
之后对这样的权重按行用softmax后与V矩阵相乘给每个token生成一个新的表示向量(分配注意力)
transformer的感受野encoder中是可以看到所有的token的,你认为感受野越大越好还是越小越好
感受野太大的问题
1.self-attn本质是加权平均,在噪声很大的早期(高时间步)就用的话会导致细节被大量无关token稀释,模型会更倾向于整体统计而不是局部几何
2.token多->attention成本爆炸
可能会:被迫用更大patch,减少层数
3.噪声环境下,全局attention会把噪声彼此传播
感受野太小的问题
1.学不到全局一致性,例如人脸五官不错但比例和位置怪
2.类别、关系、结构一致性等高层语义需要全局属性
解决措施
分层、分尺度、分阶段
1.底层小,高层大
2.高分辨率局部,低分辨率全局
3.diffusion不同时间步不同感受野
位置编码:sin cos,正余弦,bert可学习位置编码,rope相比于正余弦编码的优势
正余弦位置编码
为每个token的每个维度按公式计算一个cos/sin值,每个token都能得到一个和维度数量相同的向量来表达位置。本质是绝对位置,每个token都带着自己是第几位的标签,不能显式表示token之间的相对位置关系,需要模型从绝对位置向量间接学习。
我认为这种绝对位置编码对超出训练长度的长上下文泛化往往不稳定,上下文超过训练长度会出问题,绝对位置表示可能很难让模型理解超出训练长度的位置
bert的可学习位置编码
同样是绝对位置,不过会为每一个位置pos直接学一个向量,这个向量在模型里会学习会更新
RoPE(Rotary Positional Embedding,旋转位置编码)
RoPE把位置变成一种几何变换:位置越靠后,向量在某些二维子空间里旋转得越多
对Q和K做“按位置旋转”,让注意力的点积天然带上相对位置信息
优势:
1.相对位置信息天然进入注意力,结果会依赖相对距离i-j,模型会更容易学到近的/远的相关、周期性结构等相对模式
2.长上下文泛化通常更强,因为用的相对关系,比绝对位置的可迁移性强很多
3.不需要额外的可学习参数
4.相加式位置会改变每个token的表示本身,RoPE 通过对 Q/K 做旋转来影响相似度计算,而不改变 token 的模长,更贴合 attention 基于几何相似度的本质
补充 相对位置编码ALiBi
对logits做距离越大就衰减越多的bias,softmax 之后,这个线性惩罚会变成 指数级的衰减
欠拟合和过拟合定义,通常如何解决?
欠拟合
模型无法充分学习训练数据中的模式,本身能力不足
核心思路:增强模型的学习能力
增大模型容量(更深/更宽)
使用更强的特征表示(更好的 embedding、引入 attention)
训练更久(增加 epoch)
减弱正则化(降低 dropout、weight decay)
调大学习率(在合理范围内)
过拟合
模型过度拟合训练数据,学习了噪声和偶然性,泛化能力差
核心思路:限制模型记忆噪声,提升泛化
增加数据量或做数据增强
加强正则化(dropout、L2、label smoothing)
使用 early stopping
减小模型容量
使用 ensemble(模型集成)
合理划分训练/验证集,避免数据泄漏
transformer的位置编码的基底是10000为什么设置10000
10000的作用就是让波长从几步覆盖到大约几万步的量级
Transformer的典型设计d=512,序列长度常见在几百几千,用10000作为基底刚刚好,低维(高频)负责局部结构,高维(低频)负责长距离结构
10000不是必须的,只是默认基底,换别的也可以工作
基底变小,比如1000,整体更偏高频,更敏感短距离,但长距离表示能力变差
基底变大,比如100000,整体更偏低频,更强调长聚集,近距离分辨率可能变弱
所以10000只是一个在常见序列长度范围内经验上稳定、实现上方便的选择。
讲一下 FlashAttention 的思想和做法
原始attention的瓶颈
在GPU上,真正拖慢的是内存访问
在标准实现中:
显式构造QK^T后写进HBM(显存)
从HBM读出来QK^T做softmax再写进HBM
从HBM读出来结果再乘V
中间结果大且短命、又反复进出显存
Flash-attn的改进
不存下QK^T,而是边算边softmax边乘V,加速主要来自更少的显存读写
Attention可以分块并且结果依然严格等价,因为softmax可以在线计算
最终计算需要维护的有:
按行:QK^T/根号d_k最大值(e^x中的x最大值),用于在计算时在指数位被减去,维持范围可控
分子 and 分母累计(分子是一个向量,分母是标量)
在分块时如果发现了更大的x,那么之前累计的分子/分母必须整体乘一个比例因子,这个用数学计算推一下很简单就能算出来
分子除以分母得到分配了注意力的一个token
对每行进行相同操作得到最终结果
补充
causal mask:在未来区/不合法的地方当作-∞,得到的e^x即为0
反向传播:反向时局部分块重算P,算完就用掉
RAG和GraphRAG
RAG(Retrieval-Augmented Generation,检索增强生成)
在生成之前,从外部知识源检索信息,并把检索结果作为上下文交给模型生成
比较擅长回答局部问题,但如果问比较全局的问题比如“这堆文档主要讨论了什么主题”,它通常会embedding检索几段相关chunk->拼到prompt->生成,导致漏掉多样性
GraphRAG就是针对这种问题提出的
GraphRAG
1.把文本变成一种可被结构化检索/汇总的主题摘要+图结构:
GraphRAG用LLM从文档里抽取:实体(entity)和关系(relation),形成一个实体-关系图
然后对图做社区划分(community detection),把联系紧密的实体分成社区
接着为每个社区预生成community summary
2.用“社区摘要”做Map-Reduce式回答(global全局搜索):
Map:对于每个社区摘要,让LLM生成“针对该问题的部分回答”
Reduce:把所有部分回答汇总/再总结成最终答案
在GraphRAG的官方文档里还有局部搜索/DRIFT搜索
局部(local)搜索和RAG有点像,但GraphRAG还会扩展到其邻居和相关概念来对特定实体进行推理,适用于谁负责、发生了什么,这样的具体实体/关系的事实与推理问题
DRIFT搜索则是在局部搜索的基础上增加了社区上下文搜索,补充上下文理解/用于解释等
注意点
值得注意的是,GraphRAG虽然是RAG的扩展版,但应根据应用场景不同选择使用对象,而不是单纯认为GraphRAG就比RAG好。
GraphRAG离线构建成本高,图质量依赖于抽取准确率。在问简单事实问题时不如RAG
RAG最爱用的Top-K 向量搜索是“相似度驱动”,GraphRAG 是“结构驱动”。前者回答“哪段话最像问题”,后者回答“哪些对象和关系与问题有关”
为什么现在 Decoder - only 成为大模型的主流架构
不同的架构主要都是在做什么
Encoder-only适用于学习/理解语义,如将擅长对文本内容进行分析、分类,包括情感分析,更偏判别和表示,不适合自由生成等
Encoder-Decoder适用于条件生成,主要用于NLP,擅长处理输入和输出序列之前存在复杂映射关系的任务,比如翻译、摘要
Decoder-only在位置position上使用到了mask(保证自回归),相当于去掉encoder和cross attn,保留decoder block的Encoder-Decoder架构
为什么“Decoder-only”成为了主流
Encoder-Decoder最早解决的是:明确 输入->输出,这么一条路
后来发现Decoder-only把输入也当成要生成的一部分即可,于是prompt token和answer token就统一成了一条序列,满足自回归的生成方式
介于decoder什么都能统一成next-token prediction的特性,其泛用面广,可以将多种任务统一成一种格式,如翻译、问答、对话 等。虽然encoder-decoder也能做,但天然具有局限性。
世界上最多的数据不是QA对也不是翻译对,而是连续文本,decoder-only的预训练不需要任何标注就能做到,并且自回归和kv cache十分契合。
所以decoder-only赢的不是结构,而是范式,不过它只是通用大模型的目前最优解。在翻译、检索、表示学习等领域另外两种架构依然健在。
trade-off:Decoder-only 在条件生成和对齐复杂输入时,结构表达不如 Encoder–Decoder 直接,但工程统一性更重要
了解过哪些模型训练优化的方法
模型训练优化本质是在算力、显存、通信开销和数值稳定性之间做取舍,不同的并行和显存优化策略,实际上是在这四个维度上移动瓶颈
并行与切分
数据并行(DP):最基础,多卡分batch,同步梯度
张量并行(TP):把矩阵乘按维度切到多卡(如QKV,FFN的线性层分片)
流水线并行(PP):按层切,像装配线一样跑micro-batch
ZeRO:把optimizer state/gradients/parameters分片,显存降很多
3D并行:DP+TP+PP组合,大模型训练标配思路
训练时在省什么内存
Parameter(参数),模型权重W
Gradient(梯度),▽W
Optimizer states(优化器状态),比如Adam的一阶/二阶矩m,v
Activations(激活/中间结果):前向为了反向要保存的中间张量
不同并行策略主要在这四类上做取舍
显存优化:主要对付激活和optimizer states
Activation checkpointing:不存中间激活,反向时重算,省显存换算力(看到这里的时候在想,我去,这不就是flash-attn的做法么,实际上不然,flash-attn是只保留少量统计量在需要时局部算P;这里这个方法是保存一个检查点,反向需要的时候从检查点开始前向重新算一遍,是用计算换显存)
Offload:把optimizer state或参数挪到CPU/SSD,吞吐会受影响但能训更大的模型
序列并行(sequence parallel):在TP下一步把B×S×H的激活沿着序列维S分片到不同GPU,从而降低activation memory峰值,常见于Megatron-LM
算子/数值:提升吞吐
混合精度训练
梯度累积:把大batch拆成k个micro-batch,先不更新参数,梯度先加起来,累积k次做一次更新
梯度裁剪:梯度太大时把它按比例缩小
loss scaling:FP16 会出现问题:梯度太小会下溢变成 0
做法:先把 loss 乘一个大系数 S,让梯度也按比例变大;反向完再把梯度除回去
fused kernels:把多个小算子合成为一次大操作
Attention的训练优化
FlashAttention/memory-efficient attention
长上下文训练技巧:RoPE scaling、位置插值、chunked attention等
了解过哪些模型推理优化的方法
瓶颈
算力、显存、显存带宽、调度效率
量化
weight-only量化:最稳,改动小,省显存,提cache命中率
weight+activation量化:更省但更容易数值不稳
KV cache量化:对长上下文关键
结构层面优化
MQA(Multi-QueryAttention):每个head的Query共享K和V矩阵,k v只有一头
GQA(Grouped-QueryAttention):每个head的Query共享K和V矩阵中的n头,k v有若干头(< head头)
蒸馏:大模型教小模型,少层少参数
MoE:每token只激活部分专家(算量低但系统复杂)
剪枝/稀疏化
算子级加速
FlashAttn
参考标准
第一类是 减少重复计算:自回归生成基本都会用 KV cache,避免每个 token 反复算历史注意力;在服务端会进一步做 prefix cache / KV 复用,对重复前缀的请求能明显降 TTFT 和成本。
第二类是 提升 GPU 利用率和显存效率:比如 continuous batching 把不同长度请求持续拼 batch;配合 paged KV / PagedAttention 这类分页管理 KV cache,减少显存碎片、提高吞吐,长上下文并发更稳。
第三类是 算子级加速:注意力通常是瓶颈,会用 FlashAttention 这种 memory-efficient attention 来降低显存读写、提升速度;线性层会靠更好的 GEMM/kernels 和算子融合。
第四类是 降低精度/压缩:比如 INT8/INT4 量化(权重量化、甚至 KV cache 量化)来降显存和带宽,从而提升并发、降低成本,同时要关注精度回归。
另外还有 speculative decoding 这种解码加速:用小模型先草拟 token,大模型验证,能减少大模型前向次数,在输出较长时收益明显。
实际落地我会看目标:如果追吞吐就是 batching+paged KV+flash attention;如果追首 token 延迟就优先 prefix cache、减少 prefill 成本;如果显存紧就量化和 GQA/MQA 这类减少 KV 占用的结构。”
如果要提升大模型的多轮对话能力,你有哪些可以改进的点
主线
让模型在长对话里持续保持目标、记住关键事实、少跑题、少出幻觉、能纠错
数据层面
数据里加目标/偏好/已知事实/待确认点等结构化字段,添加负样本和对比数据、让模型对比学习,构造需要引用第N轮信息才能答对的样本,避免模型指挥就近记忆
训练目标是让模型学会对话管理而不是只答题
多任务训练,不知训练next-token,还有关键信息抽取、对话状态跟你更新、引用对话证据
偏好对齐(DPO/RLHF类)
自我纠错训练,让模型学会道歉、回滚,修正并解释原因。如果直接用‘用户说你错了 → 道歉并改答案’的数据做训练,会明显放大幻觉。实际需要把纠错拆成两步:先验证是否真的错了,再决定是修正、澄清还是坚持原结论,而且修正必须绑定明确证据,否则只是两次自由生成
记忆机制
短期工作记忆:对最近几轮做结构化摘要,每轮更新一次,作为系统级隐藏上下文
长期记忆:偏好/背景等存成可检索条目,每次对话先检索再注入
记忆写入策略:稳定性高+未来复用价值高+用户明确期望
冲突处理:新信息与旧记忆冲突,优先触发澄清而非覆盖
实际系统中,过度写入长期记忆会放大早期错误,导致模型在后续对话中持续基于错误前提推理,因此记忆管理比记忆容量更重要
上下文管理
分层上下文:系统/策略;结构化摘要;近邻原文对话
引用式回答
话题切换检测
工具检索
RAG针对多轮等
为什么有了 SFT 之后还需要 RLHF
SFT(Supervised Fine-Tuning,监督微调)
给定输入和输出,模型来学习从输入到输出的这种映射关系。在SFT中,做的是next token prediction,目标是最大化下一个token的准确率
RLHF(Reinforcement Learning from Human Feedback)
会先训练一个reward model,让reward model去学习什么要的回复是更符合人类偏好,再让这个reward model去指导大模型进行学习,从而引导大模型输出更符合人类标注的回复
结论
SFT的目标是模仿,更倾向于复刻数据分布,会被示范数据限制:数据中可能会有隐性坏习惯,比如过于啰嗦、迎合用户等;也可能不同标注者风格不同导致示例数据不一致
RLHF的目标是偏好优化,会把这种偏好变成一个可优化的奖励,RLHF可以用偏好比较把坏行为/风格压下去
很多关键质量维度并不是 对/错 二分类,而是需要:更礼貌、更简洁、更遵循指令等。这些很难用一条标准答案概括
在事实不确定时,SFT往往倾向于给出一个看起来像答案的答案。人类更加偏好不确定就说明不确定、或给出可验证步骤,这种保守且尽量没有幻觉的偏好,用RLHF正好
SFT可以打底学习指令跟随和基本对话能力,RLHF对齐偏好、安全、语气等,是不同的分工
即使 SFT 数据足够干净,SFT 仍然只能拟合条件分布 P(y∣x),而无法显式表达在多个可行解中更偏好哪一个,这也是偏好学习RLHF不可替代的原因。
PPO 和 DPO 的主要思想是什么
PPO(Proximal Policy Optimization)
用人类偏好训练出一个reward model(RM)
用PPO在RM给的reward下,把大模型当作策略优化
PPO关键思想是:限制每次更新,别离策略太远
首先PPO不允许新策略在某个token上的概率涨/跌太多,用一个clip区间超出就不给更多奖励
在RLHF中,Reward通常会= RMscore-βKL(πθ∥πref) 防止语言能力塌陷的生命线
πθ:当前正在被训练、会不断变化的模型策略(new / updated policy)
πref:一个固定的参考策略(reference policy),通常是 SFT 后冻结的大模型
PPO 通过裁剪更新幅度和 KL 正则,在保证训练稳定的前提下,用强化学习最大化人类偏好奖励
DPO(Direct Preference Optimization)
DPO把人类偏好建模为:在同一个prompt偏好下,人类更偏好回答A,而不是B,然后直接优化在当前prompt前提下提高A的概率,降低B的概率
通过直接优化偏好对的概率差,在无需显式强化学习的情况下完成偏好对齐,本质上是把 PPO 的最优解转成一个对比式的监督目标,工程更简单、训练更稳定
大模型的灾难性遗忘问题怎么解决
保留关键参数
代表思路EWC、SI、MAS
只适合小模型/少任务,因为重要性估计不稳定,并且任务多了之后所有参数都很重要
复习
保存旧任务样本,训练时和新任务样本混着来
用模型自己生成旧任务数据进行训练,但这样噪音会被放大,轮数过多记忆会变形
结构隔离
lora/MoE/Adapter/Progressive Networks
代价:参数量膨胀/推理复杂度上升
idea
有限容量系统在没有外部记忆的情况下同时保持所有过去最优解是不可能的,值得思考的是,什么应该被忘掉和什么值得被记住
了解 KV cache 吗, GQA 的思想是什么
KV cache
把“历史 token 的 K/V”当作推理的外部记忆,避免重复计算
GQA(Grouped-Query Attention)
之前在上面提到过,就是MQA和MHA的折中方案,比MHA占用显存少,比MQA精度高,原理是让多个 Q heads 共享更少套 K/V
transformer和llama的LN有什么区别,手写RMSNorm
transformer的是LayNorm
对每个 token 的隐藏向量做
减均值 + 除标准差,然后再做可学习的缩放/平移
llama的LN实际上是RMSNorm
不减均值,只用均方根做尺度归一化,通常没有 β
对比
LayerNorm:稳、全能、代价稍高
RMSNorm:简、快、在现代 Transformer 里“刚好够用”
LLaMA 的选择不是因为 LN 不好,而是因为它“用不着那么多”
FFN有什么不同,写Relu和SwiGLU
在 Transformer 里,FFN(Feed-Forward Network)是逐 token 的 MLP,不做 token 间交互,只在 hidden 维度上“拉伸 → 非线性 → 压回”。
ReLU FFN
SwiGLU,LLaMA的核心FFN
a = w1(x) # 内容
g = F.silu(w2(x)) # 门
out = w3(a * g) # 门控后投影回 dim
表达力主要来自:门随输入变化,让同一个 FFN 在不同 token 上表现得像“不同的函数”。