第三章:模型加载与基础使用
好,咱们进入实战环节了。模型微调的第一步是什么?不是调参数,不是写训练循环——而是先把模型请进来,让它能跑起来。这一步看似简单,但坑不少。我见过太多同学卡在模型加载这一步,一卡就是半天。
今天我们就来聊聊:怎么把 HuggingFace 上的预训练模型下载下来,怎么用 AutoModel 加载,Tokenizer 怎么配,最后跑一个推理测试验证一切正常。
3.1 HuggingFace 模型下载:别直接 git clone
很多人第一次接触 HuggingFace,习惯性就想 git clone。嗯,这确实能下载,但你会下载到一堆没用的文件。我个人习惯用 snapshot_download 或者直接用 from_pretrained 自动缓存。
为什么会这样?因为 HuggingFace 的仓库里除了模型权重,还有配置文件、tokenizer 文件、甚至一些训练日志。你全 clone 下来,一个 7B 模型可能就是 15GB,网络差一点直接崩溃。
我在项目中遇到过:团队里有人用 git clone 下载 LLaMA,结果下载到一半断网,重来。浪费了整整一个下午。后来我教他用 huggingface_hub 的断点续传功能,半小时搞定。
推荐做法:
from huggingface_hub import snapshot_download
# 只下载必要文件
snapshot_download(
repo_id="bert-base-uncased",
local_dir="./models/bert-base",
ignore_patterns=["*.h5", "*.ot", "*.msgpack"]
)
或者更简单,直接用 from_pretrained,它会自动缓存:
from transformers import AutoModel
model = AutoModel.from_pretrained("bert-base-uncased")
# 第一次下载,之后都在缓存里
HF_HOME 或 TRANSFORMERS_CACHE,可以指定缓存路径。我一般设到 SSD 上,加载速度快很多。
3.2 AutoModel 加载预训练模型:自动匹配架构
AutoModel 是 HuggingFace 里我最喜欢的类之一。你想想看,以前加载不同模型要记不同的类名:BertModel、GPT2Model、T5Model……现在只需要一个 AutoModel,它会根据你传的模型名称自动匹配。
它的原理其实很简单:读取模型目录下的 config.json,里面写了 model_type 字段,然后自动实例化对应的类。
from transformers import AutoModel, AutoConfig
# 加载配置
config = AutoConfig.from_pretrained("bert-base-uncased")
print(config.model_type) # 输出: bert
# 加载模型
model = AutoModel.from_pretrained("bert-base-uncased", config=config)
这里有个细节要注意:from_pretrained 默认会下载最新的权重。如果你想要特定版本,可以在模型名后面加 @v1.0.0 这样的 tag。
torch_dtype,默认 float32 加载,显存直接爆了。后来我习惯加上 torch_dtype=torch.float16 或者 device_map="auto"。
# 推荐写法:半精度 + 自动设备映射
model = AutoModel.from_pretrained(
"bert-base-uncased",
torch_dtype=torch.float16,
device_map="auto"
)
3.3 Tokenizer 配置:别小看这个步骤
Tokenizer 是什么?说白了就是把人类语言翻译成模型能理解的数字。你想想看,模型只认识数字,不认识汉字和英文。Tokenizer 就是那个翻译官。
我见过最离谱的错误:有人用 Bert 的 tokenizer 去处理 GPT 的输入。结果呢?分词结果完全不对,模型输出一堆乱码。嗯,这里要注意:Tokenizer 必须和模型匹配。
正确的做法:
from transformers import AutoTokenizer
# 加载与模型匹配的 tokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# 编码文本
inputs = tokenizer(
"Hello, I'm learning LoRA fine-tuning.",
padding="max_length",
truncation=True,
max_length=128,
return_tensors="pt" # 返回 PyTorch 张量
)
print(inputs["input_ids"].shape) # torch.Size([1, 128])
Tokenizer 返回的是一个字典,包含三个关键字段:
| 字段名 | 含义 | 形状 |
|---|---|---|
| input_ids | token 对应的数字 ID | (batch_size, seq_len) |
| attention_mask | 哪些位置是真实 token(1),哪些是 padding(0) | (batch_size, seq_len) |
| token_type_ids | 区分句子 A 和句子 B(仅部分模型) | (batch_size, seq_len) |
max_length 和 truncation 策略,变了就会出问题。
3.4 模型推理测试:验证一切正常
模型加载好了,tokenizer 也配好了,接下来就是跑一次推理。这一步不是为了得到什么结果,而是为了验证整个链路是通的。
我习惯写一个简单的测试函数:
import torch
def test_inference(model, tokenizer, text):
"""快速测试模型推理是否正常"""
model.eval() # 切换到评估模式
# 编码
inputs = tokenizer(text, return_tensors="pt")
inputs = {k: v.to(model.device) for k, v in inputs.items()}
# 推理
with torch.no_grad():
outputs = model(**inputs)
# 检查输出形状
print(f"输入文本: {text}")
print(f"输出形状: {outputs.last_hidden_state.shape}")
print(f"输出均值: {outputs.last_hidden_state.mean().item():.4f}")
return outputs
# 跑一次
text = "LoRA is a powerful fine-tuning method."
outputs = test_inference(model, tokenizer, text)
输出应该类似这样:
输入文本: LoRA is a powerful fine-tuning method.
输出形状: torch.Size([1, 10, 768])
输出均值: -0.0234
看到 768 这个数字了吗?这是 BERT-base 的隐藏层维度。如果你加载的是其他模型,这个数字会变。比如 LLaMA 是 4096。
3.5 本章知识体系
下面这张图总结了模型加载与基础使用的完整流程:
整个流程其实就四步:下载 → 加载 → 配 Tokenizer → 跑推理。每一步都有坑,但只要你按这个顺序来,基本不会出大问题。
我个人习惯把这四步写成一个脚本,每次换模型就改一行模型名。这样既省时间,又不容易漏掉配置。
公众号:蓝海资料掘金营,微信deep3321