LLM 基础知识
大模型核心技术点在于训练资源、数据清洗和数据配比等,其难点或许不在于模型训练和模型结构搭建
【变形金刚之神!Bless Me】
- 相较于 RNN,Transformer 直接将句子中任意两个单词的联系通过一个计算步骤直接联系起来,远距离依赖特征之间的距离被极大缩短,有利于有效地利用这些特征;
- Self Attention 大大提升了计算的并行,通过上三角mask可以同时训练一句话中的所有token;
NLP 任务:情感分析、文本生成、命名体识别、阅读理解、掩码填充、文本摘要、机器翻译、特征提取、对话机器人。
NLP 数据集大多是未标注的文档,因此采用自监督学习的方式训练模型,如预测下一个词 LM、完形填空 MLM。早些年,流行的是词嵌入 Word Embedding,目标是采用向量的形式表示词元,采用一组向量表示一段话,可以用于计算词/句子相似度。
现阶段,Transformer 的出现促使三种类型的模型的出现:前缀语言模型 Encoder-Decoder(prefix-lm);掩码语言模型/自编码模型 Encoder-Only;因果语言模型/自回归模型 Decoder-Only。Encoder-only 适用于机器翻译、句子分类、命名体识别和问答(大概);Decoder-only 适用于文本预测;Encoder-Decoder 适用于文本压缩。
基础知识
预训练显存占用
样例:大小为 n B的模型,Adam 优化器,混合精度 fp16, b(batch_size),s(sequence len),h(hidden size)
- 输入输出:sbh*2 byte
- 模型大小:n*2 GB
- 梯度大小:n*2 GB
- 优化器大小:(4+4+4) *n GB。模型更新时,梯度很小,学习率也很小,精度丢失会影响模型收敛效果,所以优化器中的数据全都是 fp32 精度。
- 激活值大小:sbh(34+5*a*s/h)*L byte 分析
数据获取和清洗
少量高质量数据优于大量低质量数据
Tokenizer
特殊 Token
- [PAD] 填充至固定长度
- [CLS] 分类任务
- [SEP] 分隔符
- [MASK] 自监督任务,序列填空
- [BOS] / [EOS] 自回归任务,约束文本生成的边界
- [UNK] 无法识别的词
- [SPE] 词汇表预留的标志
[Q] Tokenizer 是选左 Padding 还是右 Padding?
训练和推理阶段的 <PAD> 标记是填充在左边还是右边都可以
- 训练阶段,每一轮的 batch 都是独立的,
attention mask
会把与有效序列无关的部分都屏蔽了,因此两者都行; - 推理阶段,存在自回归的推理过程,当并发
batch infer
时,左 padding 可以直接将推理得到的下一跳 Token 合并到input_ids
尾部,简化编码过程;
优化器
在石器时代,人们直接使用 loss.backward()
计算梯度,乘以固定的学习率,得到所有参数更新的幅度。然而,使用固定的学习率,在梯度变化剧烈的地方,会导致更新不稳定或收敛慢。
为提高收敛效果,出现了很多优化器,它们被收藏在 torch.optim
里面,最出名的应该是 Adam
、AdamW
、SGD
三大天王,待我娓娓道来。
Adam
自适应学习率: Adam 通过计算一阶和二阶矩估计来为每个参数自适应地调整学习率;
偏差校正: 初始阶段梯度估计可能偏低,通过偏差校正可以加速初期的学习速率;
适应性强: Adam 在很多不同的模型和数据集上都表现出了良好的性能;
减少显存占用
混合精度训练:FP16 速度快,占用小,适合前向传播、反向传播、矩阵计算;FP32 精度高,适合梯度累积、权重更新、归一化、softmax(可以通过动态损失缩放减少精度损失)
梯度累积: loss = loss / self.args.gradient_accumulation_steps
,更稳定的梯度估计
梯度检查点:gradient_checkpointing=True
只保存计算代价大且显存占用少的中间激活值,在反向传播时重新计算未保存的激活值
采样
top_k (int):每次保留概率最大的几个序列,再按照概率选择保留的序列(不适用于概率分布平滑的情况)
top_p (float: 0~1):保留前n个概率和大于 p 的序列,再按照概率选择保留的序列(适用于概率分布平滑的情况,按照概率采样,提高响应多样性)
temperature:优化了 Softmax 函数改为 $p(x_i)=\frac{e{\frac{x_i}t}}{\sum_{j=1}ne^{\frac{x_j}t}}$,温度越小 softmax 的概率分配越尖锐(确定性),反之越平滑(随机性)
num_beams:每次保留概率最大的几个序列,最后输出概率最大的值(上面三个方法已足够,束搜索未包含在 OpenAI API 中)
嵌入模型
提示词在嵌入模型中扮演着关键角色,提供上下文、指导生成的格式、增强模型效果、适应不同任务并减少噪声。通过使用合适的提示词,可以提高嵌入模型的性能和实用性。
bge-large-zh-v1.5
嵌入模型的架构:
- BertEmbeddings
- word_embeddings
- position_embeddings
- token_type_embeddings
- LayerNorm + dropout
- BertEncoder
- attention
- MLP
- LayerNorm + dropout
- BertPooler
- dense + activation
相对位置编码
相对位置编码具有外推性(extrapolation ability)的原因在于它不是将位置信息编码为与序列中的绝对位置直接相关的固定模式,而是将注意力权重或其他模型组件与元素之间的相对距离联系起来。
编程
Transformers及相关库
Transformers:核心库,模型加载、模型训练、流水线并行等
Tokenizer:分词器,对数据进行预处理,文本到token序列的互相转换。具体工作包括:分词、索引、填充截断、attention_mask、token_type
Datasets:数据集库,提供了数据集的加载、处理等方法
Evaluate:评估函数,提供各种评价指标的计算函数
Trainer:将模型训练流程打包,包括:创建优化器、创建DataLoader、tensor转移到CUDA上
PEFT:高效微调模型的库,提供了几种高效微调的方法,小参数量动大模型
Accelerate:分布式训练,提供了分布式训练解决方案,包括大模型的加载与推理解决方案
Optimum:优化加速库,支持多种后端,如Onnxruntime、OpenVino等
Gradio:可视化部署库,几行代码快速实现基于Web交互的算法演示系统
分布式训练
Accelerate 包,融合了 Deepspeed、DDP、FSDP;
LLaMA-Factory 源码
trainargs.main_process_first() 内的代码只在主进程里面运行,适用于数据处理;
为实现高效打包,替换 transformers 包内模型的 _get_unpad_data
方法,实现4Dmask,以区分每个 batch 中的不同序列;