第 3 章 模型加载与保存
学习目标
- 掌握
from_pretrained/save_pretrained与本地缓存机制 - 认识
config.json、model.safetensors等文件的作用 - 会用
from_config随机初始化模型,理解「结构」与「权重」的分离 - 会用
dtype参数控制加载精度 - 会解读 transformers v5 的 LOAD REPORT
3.1 from_pretrained:从 Hub 或本地加载
from_pretrained 是 transformers 最重要的方法:传入一个模型 id 或本地目录,它会自动下载(若在 Hub)并加载配置、分词器或权重。
from transformers import AutoModel
model = AutoModel.from_pretrained("google-bert/bert-base-uncased")
print(type(model).__name__, "参数总数:", sum(p.numel() for p in model.parameters()))输出:
BertModel 参数总数: 109482240BERT-base 有约 1.09 亿参数。第一次运行时,transformers 会逐文件下载并打印进度条;文件缓存到本机(默认 ~/.cache/huggingface/hub),第二次加载直接读缓存。
3.2 模型目录里有什么
把模型保存到本地,看看文件清单:
from transformers import AutoModel, AutoTokenizer
model = AutoModel.from_pretrained("google-bert/bert-base-uncased")
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
model.save_pretrained("./my-bert")
tokenizer.save_pretrained("./my-bert")目录内容:
my-bert/
├── config.json # 结构配置:层数、维度、词表等
├── model.safetensors # 模型权重
├── tokenizer.json # 分词器(序列化格式,fast tokenizer)
└── tokenizer_config.json # 分词器配置(特殊 token 等)逐项说明:
- config.json:描述「模型长什么样」。同一个目录,模型权重可以换,config 定义了每层的大小。
- model.safetensors:权重文件,采用 safetensors 格式(安全、快、无 pickle 风险)。旧格式是
pytorch_model.bin。 - tokenizer.json / tokenizer_config.json:分词器本体与配置。
保存后重新加载:
reloaded = AutoModel.from_pretrained("./my-bert")
print(type(reloaded).__name__)输出:
BertModelfrom_pretrained 的入参可以是 Hub 模型 id,也可以是本地目录——两处对调用方完全透明,这就是第 2 章说的「统一接口」。
3.3 结构与权重分离:随机初始化
有时你不想用预训练权重,而是按结构随机初始化一个新模型。用 AutoConfig 或具体 Config 类描述结构,再传给模型类:
from transformers import BertConfig, BertModel
config = BertConfig(hidden_size=64,
num_hidden_layers=2,
num_attention_heads=2,
intermediate_size=128,
vocab_size=1000)
model = BertModel(config)
print("随机初始化模型参数:", sum(p.numel() for p in model.parameters()))输出:
随机初始化模型参数: 168128因为结构由 config 决定、权重随机生成,所以「加载」与「初始化」在 transformers 里是两件不同的事:
| 操作 | 代码 | 结果 |
|---|---|---|
| 加载预训练权重 | AutoModel.from_pretrained(id) | 结构与权重都来自 checkpoint |
| 随机初始化 | BertModel(config) / from_config(config) | 结构来自 config,权重随机 |
3.4 控制加载精度:dtype
大模型按 fp32 加载占显存大,常用半精度(bf16/fp16)加载。v5 用 dtype 参数(旧写法 torch_dtype 已弃用):
import torch
from transformers import AutoModel
model = AutoModel.from_pretrained("google-bert/bert-base-uncased",
dtype=torch.bfloat16)
print(next(model.parameters()).dtype)输出:
torch.bfloat16要点:
torch.bfloat16:范围大、精度低,现代 GPU(NVIDIA Ampere 及以后)友好,训练常用。torch.float16:范围小,可能出现溢出,推理常用。- 加载后仍可
.to("cuda")移动设备。
3.5 解读 LOAD REPORT
transformers v5 在加载权重时会打印一份报告。以「用 BERT 主干加载分类头」为例:
[transformers] BertForSequenceClassification LOAD REPORT from: prajjwal1/bert-tiny
Key | Status |
--------------------------+------------+-
cls.predictions.bias | UNEXPECTED |
cls.seq_relationship.bias | UNEXPECTED |
classifier.weight | MISSING |
classifier.bias | MISSING |
Notes:
- UNEXPECTED: can be ignored when loading from different task/architecture
- MISSING: those params were newly initialized because missing from the checkpoint两类状态的含义:
- UNEXPECTED:checkpoint 里有、但当前模型结构用不上的权重(这里是预训练 MLM 头的权重)。加载「不同任务/架构」时出现属正常,可忽略。
- MISSING:当前模型结构需要、但 checkpoint 里没有的权重——被随机初始化了。微调前看到分类头 MISSING 是正常的,这正是你要训练的部分。
训练前先看一遍 LOAD REPORT,能立刻发现「模型头选错」或「权重没加载上」的问题。
动手实践
- 下载一个模型(如
prajjwal1/bert-tiny),打印 LOAD REPORT,解释每个 MISSING/UNEXPECTED 来自哪里。 - 用
BertConfig自定义一个hidden_size=32, num_hidden_layers=1的迷你 BERT,保存到本地,再加载回来,对比两次打印的参数数量。 - 用
dtype=torch.float16加载 bert-tiny,统计模型一半以上参数是否为 fp16。
常见错误
错误 1:模型 id 拼错或模型 config 缺字段。
transformers v5 的 AutoConfig 要求 config.json 里有 model_type。某些老仓库(如 prajjwal1/bert-tiny)缺少该字段,AutoModel.from_pretrained 直接报:
ValueError: Unrecognized model in prajjwal1/bert-tiny. Should have a `model_type` key in its config.json.解决:用显式类 + 显式 config 加载:
from transformers import BertConfig, BertForSequenceClassification
config = BertConfig.from_pretrained("prajjwal1/bert-tiny", num_labels=2)
model = BertForSequenceClassification.from_pretrained("prajjwal1/bert-tiny", config=config)错误 2:用 torch_dtype=(旧参数)。
[transformers] `torch_dtype` is deprecated! Use `dtype` instead!v5 中改为 dtype=。
错误 3:以为保存目录可以删掉 config.json。
没有 config.json,from_pretrained 无法重建结构,加载必然失败。config 与权重都要保存。
章末练习
基础
- 保存
bert-tiny到本地目录,列出目录所有文件,并说明每个文件的作用。 - 用
BertConfig(hidden_size=32, num_hidden_layers=1, num_attention_heads=2, intermediate_size=64, vocab_size=500)随机初始化模型,打印参数量。
提高
- 分别用
AutoModel与AutoModelForSequenceClassification加载prajjwal1/bert-tiny,对比两次 LOAD REPORT 的差异,写出解释。 - 用
dtype=torch.bfloat16加载 bert-tiny,把模型移到 GPU(如果可用),做一次前向并打印输出 dtype。
挑战
- 实现函数
load_or_init(model_id, config):AutoConfig.from_pretrained成功则从 checkpoint 加载,失败则用传入的 config 随机初始化,并打印提示。
章末自测
model.safetensors文件里存的是什么?from_pretrained能接受哪两类路径?- LOAD REPORT 中
MISSING状态意味着什么? - v5 中控制加载精度的参数是
torch_dtype还是dtype? - 随机初始化模型时,结构由谁决定?
- 判断:没有 config.json 也能用 from_pretrained 加载模型。
