大模型

1 前言

1.1 huggingface

Hugging Face 是一个人工智能公司,提供的transformer库十分好用,以及社区:https://huggingface.co,类似于github。

1.1.1 应用

以nlp为例,典型使用流程:

from transformers import AutoTokenizer, AutoModelForSequenceClassification
# 加载 tokenizer 和模型
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased")
# 编码输入
inputs = tokenizer("I love Hugging Face!", return_tensors="pt")
# 模型前向推理
outputs = model(**inputs)
# 输出 logits(未归一化的类别分数)
print(outputs.logits)

1.1.2 主要组件

1.1.2.1 AutoTokenizer, AutoModel

自动适配你加载的模型类型,不用手动选类。

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
model = AutoModel.from_pretrained("bert-base-cased")

1.1.2.2 pipeline

封装常见任务,适合快速测试:

from transformers import pipeline
classifier = pipeline("sentiment-analysis")
result = classifier("I love this library!")
print(result)

1.1.2.2 datasets

统一的数据集管理工具,支持自动下载 + 分词 + token 化.

from datasets import load_dataset
dataset = load_dataset("imdb")  # 加载 IMDB 数据集

2 tokens和embedding

2.1 tokens

tokens是词元。按照某种形式进行切分得到的子词。

2.1.1 切分方式

例如:"ChatGPT is awesome!"

  1. 单词级别(空格划分)

["ChatGPT", "is", "awesome", "!"]

  1. 字符级别(直接split)

["C", "h", "a", "t", "G", "P", "T", " ", "i", "s", ...]

  1. 子词级别

["Chat", "G", "PT", " is", " awe", "some", "!"]

大多数现代大模型(包括 GPT)使用 子词分词法(比如 BPE、WordPiece、SentencePiece),因为它能很好平衡 词汇覆盖率 和 模型大小。

你可以用 OpenAI 提供的工具 tiktoken 查看分词情况(适用于 GPT 模型):

import tiktoken
enc = tiktoken.encoding_for_model("gpt-4")
tokens = enc.encode("ChatGPT is awesome!")
print(tokens)             # 输出 token 的 ID
print(len(tokens))        # 输出 token 的数量

2.2 embedding

2.2.1 one-hot编码

One-hot 是一种最基础的表示离散符号的方法。
对于["apple", "banana", "cat", "dog"],

每个词都可以表示为一个全 0 向量,只有对应词的位置是 1:

apple	[1, 0, 0, 0]
banana	[0, 1, 0, 0]
cat	[0, 0, 1, 0]
dog	[0, 0, 0, 1]

独热编码简单直观,适合离散分类;但维度高且稀疏(大多数元素是0),不包含词与词之间的任何“语义信息”。

比如 “apple” 和 “banana” 实际上语义很接近,但它们的 one-hot 向量之间没有任何关系。

2.2.2 embedding是什么

我们可以把 embedding 理解成是 “低维的、可学习的、语义丰富的 one-hot 替代品”。

从数学角度讲,embedding 就是:

把 one-hot 向量(维度 = 词表大小)通过一个权重矩阵投影(投影矩阵)到一个低维空间(比如 128、256、768 维)。

简化理解:

one-hot(大小 V) × W(V × D)= embedding(大小 D)

V 是词表大小(vocab size), D 是嵌入维度(embedding dim), W 是一个 embedding 矩阵,是模型的参数,会随着训练更新。

2.2.3 上下文embedding

上下文 embedding 是指词或子词的向量表示,它的数值不仅取决于词本身,还取决于它在句子中的上下文语境。这是与传统词向量(如 word2vec、GloVe)最大的区别。

例如:"He sat on the bank of the river." vs "He deposited money in the bank."

代码:

from transformers import AutoTokenizer, AutoModel
import torch
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")
sentence = "He sat on the bank of the river"
inputs = tokenizer(sentence, return_tensors="pt")
outputs = model(**inputs)
embeddings = outputs.last_hidden_state  # shape: [batch_size, seq_len, hidden_dim]

“词表 + embedding table”看作 Transformer 模型的输入入口,它把词的符号转成初始向量,而后续的上下文 embedding 才是“理解”阶段。

2.2.4 文本embedding

将一句话/一段文本转化为embedding。

示例代码:

from transformers import AutoTokenizer, AutoModel
import torch
model_name = "sentence-transformers/all-MiniLM-L6-v2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
sentence = "I love deep learning"
inputs = tokenizer(sentence, return_tensors="pt", padding=True, truncation=True)
with torch.no_grad():
    outputs = model(**inputs)
# 提取句子 embedding(平均池化)
embedding = outputs.last_hidden_state.mean(dim=1)

就得到了一个维度为 [1, hidden_dim] 的句子向量,可以用于文本分类、检索、聚类等任务。

应用场景:

场景 使用说明
语义搜索 将 query 和文档编码为向量,计算余弦相似度
聚类 文本转向量后做 KMeans、DBSCAN 等
可视化 降维到 2D 展示文本语义分布(如 TSNE)
文本分类 把 embedding 喂入分类器(SVM、MLP)
问答 / RAG 检索相似文本片段辅助生成答案

2.3 tokenizer

2.3.1 概念

Tokenizer(分词器)是将自然语言文本(如句子、段落)转换成模型可处理的token序列的工具,也可以逆向转换。
这些token是数字编号,最终会作为模型的输入。

例如:

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
text = "Transformers are amazing!"
# 编码为 token id
encoded = tokenizer.encode(text)
print("Token IDs:", encoded)
# 解码回字符串
decoded = tokenizer.decode(encoded)
print("Decoded:", decoded)

不同tokenizer有自己不同的词表,词表是token <-> id的映射字典,每个 tokenizer 都有词表的正向和反向映射。

查看tokenizer的词表:

tokenizer = AutoTokenizer.from_pretrained("gpt2")
vocab = tokenizer.get_vocab()  # 返回 dict
print(list(vocab.items())[:10])  # 打印前十个 token 与 id

2.3.2 应用

现代大模型使用的 tokenizer 通常是 子词级别(subword level),这里列出最主流的几种:

名称 常用于模型 算法思想 特点
BPE(Byte Pair Encoding) GPT 系列(GPT-2/3/4)、RoBERTa、CLIP、Qwen 基于频率的合并规则 高压缩率,性能好
WordPiece BERT 系列 类似 BPE,控制词表大小 可控性好,语义稳健
Unigram Language Model ALBERT、T5、XLNet 概率模型,选最优子词集合 压缩率和泛化较好
SentencePiece(库) T5、mBART、BLOOM 支持 BPE/Unigram,支持生僻字符、空格编码 脱离空格,原生支持多语言
Byte-Level BPE GPT-2、GPT-Neo、OPT 每个字节都是 token,支持任意文本 无需预处理,更健壮
TokenizerFast(基于 Rust) Huggingface 中统一接口 性能极快,提供一致 API 封装了各种算法

3 对话格式和RRMNorm以及KVCache

3.1 ChatML

ChatML 是一种“对话格式的标注协议”,用于告诉大语言模型:一段输入是“谁说的什么话”,以结构化的方式进行对话信息建模。

Chat:表示这是用于“多轮对话”的上下文格式。
ML:代表 “Markup Language(标记语言)”,像 XML/HTML 一样使用标签来表示结构。

3.2 Alpaca

Alpaca 对话格式是一种 轻量级的指令微调格式,最早由斯坦福大学在Alpaca项目中提出,用于训练类ChatGPT的语言模型。该格式是基于 “指令-输入-输出”三元组的结构,非常适合用于单轮问答或伪多轮指令模拟训练。

{
  "instruction": "根据输入的关键词写一篇短文",
  "input": "人工智能,未来",
  "output": "人工智能是未来技术发展的关键......"
}

3.1.1 基本格式

<|im_start|>system
你是一个智能助手。<|im_end|>
<|im_start|>user
请解释一下牛顿第一定律。<|im_end|>
<|im_start|>assistant
牛顿第一定律,也称惯性定律,是指......<|im_end|>

或者

[
  {"role": "system", "content": "You are a helpful assistant."},
  {"role": "user", "content": "Tell me a joke."},
  {"role": "assistant", "content": "Why did the chicken cross the road? To get to the other side!"}
]

常见角色包括:

  • system: 设定初始角色和风格(如“你是法律顾问”)
  • user: 用户输入内容
  • assistant: 模型输出内容
  • tool: 工具调用(如函数调用、插件)

3.2 RMSNorm(Root Mean Square Layer Normalization)

2.2.1 定义:

RMSNorm 是一种 简化的 LayerNorm(层归一化),最早由 Zhang & Sennrich (2019) 提出。与 LayerNorm 不同,它只归一化输入的均方根值(Root Mean Square),不减去均值。

3.2.2 公式:

设输入为 \(x \in \mathbb{R}^d\),RMSNorm 计算方式为:

\[\text{RMSNorm}(x) = \frac{x}{\text{RMS}(x)} \cdot \gamma \]

其中:

\[\text{RMS}(x) = \sqrt{\frac{1}{d} \sum_{i=1}^{d} x_i^2 + \epsilon} \]

  • \(\gamma\):可训练的缩放参数(和 LayerNorm 一样)
  • \(\epsilon\):防止除零的小常数

3.2.3 与 LayerNorm 区别:

项目 LayerNorm RMSNorm
是否减均值 ✅ 是 ❌ 否
计算复杂度 稍高 更低
表现差距 相近 相近甚至更好(在 LLM 中)
使用情况 GPT-2, BERT 等 LLaMA, BLOOM, RWKV 等

为什么 LLaMA 用 RMSNorm?

  • 更快、内存更低
  • 更适合深层网络
  • 更稳定(尤其在 fp16/bfloat16 精度下)

3.3 KVCache(Key-Value Cache)

3.3.1 定义:

KVCache 是 Transformer 推理(尤其是解码阶段)中缓存 注意力机制中的 Key 和 Value 的技术,从而避免每一步都重复计算前面所有 token 的 Key 和 Value。

3.3.2 背景:注意力计算

在自回归模型中,decoder 的每一步都要做如下注意力计算:

\[\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\top}{\sqrt{d}}\right)V \]

其中:

  • Q: 当前 token 的 Query
  • K: 所有历史 token 的 Key
  • V: 所有历史 token 的 Value

如果每生成一个 token 就重新计算 K 和 V,会非常浪费时间!


KVCache 做了什么?

在第一次生成 token 时:

  1. 模型保存每个 token 的 Key 和 Value

    kv_cache["key"] = [K₁, K₂, ..., K_t]
    kv_cache["value"] = [V₁, V₂, ..., V_t]
    
  2. 后续每一步:

    • 只计算当前 token 的 Query(Q)
    • 与缓存的 K、V 做注意力
    • 避免重复计算

3.3.3 优点:

优势 说明
快速推理 缓存 K/V 避免重复计算,提高解码速度
节省显存 对于 fp16 或量化模型,缓存非常高效
解码更稳定 连续对话、长文本生成时稳定性更好

3.3.4 KVCache 举例(推理过程):

for step in range(max_length):
    q = model.compute_query(new_token)
    k, v = model.compute_kv(new_token)
    kv_cache.append(k, v)

    output = attention(q, kv_cache.k, kv_cache.v)
    new_token = decode(output)

KVCache 是必须理解的加速机制;而如果你想自定义模型架构,RMSNorm 是比 LayerNorm 更适合深层 Transformer 的选择。

4 SFT

4.1 大模型训练流程

SFT 是 Supervised Fine-Tuning(监督微调)的缩写,是大语言模型训练中的一个关键阶段。

4.1.1 预训练Pretraining

数据来自海量无标注文本:书籍、网页、论文、代码、对话、社交平台等。

数据量百 GB ~ 数 TB。

让模型掌握语言基础能力,例如语法、常识、词义联想、上下文理解。

训练任务:
自回归语言建模(Causal LM):如 GPT 系列,给定前文预测下一个 token(用左侧上下文)

掩码语言建模(Masked LM):如 BERT,随机遮盖词,让模型填空

4.1.2 监督微调SFT (Supervised Fine-Tuning)

让模型具备“指令跟随能力”,即根据任务需求做问答、翻译、摘要、代码生成等。

人工构造或过滤出的 高质量指令-响应对。

数据格式:

{
  "instruction": "请总结下面的文章",
  "input": "这是一篇关于……",
  "output": "这篇文章主要讲了……"
}

参数高效微调(PEFT)技术,可用来SFT:

  • LoRA
  • Prefix Tuning
  • P-Tuning
  • adapter tuning
  • prompt tuning

4.1.3 对齐训练

这一步是让模型变得“更像助手”,不仅要 正确,还要 有礼貌、安全、不胡说八道。

这个步骤分为几个方法:

4.1.3.1 人类反馈强化学习(RLHF)

训练三步走:

  1. 收集回答对比(模型 A vs 模型 B,哪个更好?)

  2. 训练奖励模型(学习人类偏好)

  3. 强化学习优化(PPO 等方法优化原模型)

代表:ChatGPT、Claude、InstructGPT

4.1.3.2 DPO(Direct Preference Optimization)

一种更简单、直接替代 RLHF 的新方法,不需要复杂的 RL 过程。

4.1.4 后训练(Post-training)和工具增强

这一步可选,有些有,有些没有。

多模态扩展:引入图像、音频、视频(如 GPT-4V、Gemini)

工具增强:引入计算器、搜索引擎、数据库调用等(如 Toolformer, ChatGPT Plugins)

领域适配(Domain Adaptation):金融、医疗、法律等定制模型(如 BloombergGPT)

5 Transformer

5.1 自注意力

为什么除以\(\sqrt{d_k}\)

5.2 FFN

一句话定义:在Transformer模型中,FFN(Feed-Forward Network,前馈神经网络)是每个编码器和解码器层的重要组成部分,位于自注意力机制之后。它的主要作用是对自注意力层输出的特征进行非线性变换和增强,进一步提升模型的表达能力。​

FFN,或者说是 MLP(多层感知机,也就是全连接层加激活函数的堆叠),是注意力之后的非线性处理器,它帮助模型在局部空间重新塑形信息。

为什么 Transformer 的 FFN 具有扩展维度(通常 4 倍隐藏层维度)?

注意力层(Attention)处理的是token 间的交互,而 FFN 则对每个 token 独立地做非线性变换。换句话说:Attention 是“交流”,FFN 是“思考”。为了让每个 token “思考得更深”,FFN 提供了一个更高维的中间特征空间。扩展维度就是为了在这个空间中能进行更丰富的非线性组合。

5.3 层归一化

  1. 为什么Transformer选择LayerNorm而非BatchNorm?
    Transformer 输入的是序列(文本 token、图像 patch、语音帧……),长度不固定。BatchNorm 要在同一 batch 内统计所有样本的均值方差,但不同样本序列长度不同 → 无法统一统计。

  2. 层归一化在 Transformer 中的作用是什么?
    在 Transformer 中,LayerNorm 是数值稳定器:控制每层输入的尺度;保持梯度健康;减少分布漂移;稳定收敛并提高泛化。Self-Attention 和 FFN 各自都可能让特征爆炸或塌陷,LayerNorm 则让整个网络始终“温度适中”。

所以 Transformer 的 LayerNorm 虽然名字叫“归一化”,但实际上做的是标准化操作(零均值 + 单位方差)。

关于归一化以及标准化的说法

层归一化实现
nn.LayerNorm只针对于最后一个维度起作用。减去均值,除以标准差。

x = torch.randn(batch_size, seq_len, d_model)
layer_norm = nn.LayerNorm(d_model)
normalized_x = layer_norm(x)

RMSNorm不减均值,并且除以的是每一项平方和(比方差少了减均值的操作)然后开根。

5.4 残差链接

5.5 位置编码

两种方法

  1. 绝对位置编码
    正弦/余弦函数结合位置pos和维度i获取独特的值。
  2. 可学习的位置编码(如BERT)
    方法:随机初始化一个位置嵌入矩阵,形状为[max_seq_len, d_model],通过训练学习。

长度外推

长度外推(Length Extrapolation)指模型在训练时只见过固定长度的序列,在推理时能否正确处理更长的序列。
产生原因:可学习位置编码只对训练长度有效;长序列输入可能导致模型捕捉不到远程依赖。
解决:函数式位置编码(如正弦、RoPE);相对位置编码(Relative Position Bias);分层或递归结构,压缩上下文层级建模。

6 大模型预训练

一句话定义:预训练(Pre-training) 是指在大规模无标注数据上训练模型,使其学习通用的语言表示(如词、句子的语义和语法规律),再通过微调(Fine-tuning) 适配到具体任务(如文本分类、问答)。​核心思想:先“通识教育”,再“专业训练”。

6.1 自监督学习

6.2 继续预训练

7 大模型微调

一句话定义:微调是指在一个大模型已经通过大规模数据集(如通用文本、图像数据集等)进行预训练之后,在一个相对较小且专用的任务数据集上进行进一步的训练。这一过程的目的是让模型在新的任务中得到优化,通常涉及调整模型的部分参数,或者根据新数据集的特征进行适当的修改。

posted @ 2025-06-07 22:17  saulstavo  阅读(82)  评论(0)    收藏  举报