第三章:模型加载与基础使用

好,咱们进入实战环节了。模型微调的第一步是什么?不是调参数,不是写训练循环——而是先把模型请进来,让它能跑起来。这一步看似简单,但坑不少。我见过太多同学卡在模型加载这一步,一卡就是半天。

今天我们就来聊聊:怎么把 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_HOMETRANSFORMERS_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)
核心要点: 训练和推理时,tokenizer 的参数要保持一致。特别是 max_lengthtruncation 策略,变了就会出问题。

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。

一个小习惯: 每次加载新模型,我都会先跑一次推理测试。确认输出形状和数值范围都正常,再开始微调。这能帮你提前发现 90% 的配置问题。

3.5 本章知识体系

下面这张图总结了模型加载与基础使用的完整流程:

模型加载与基础使用流程 1. 模型下载 snapshot_download 2. 模型加载 AutoModel.from_pretrained 3. Tokenizer配置 AutoTokenizer 4. 推理 测试 关键配置项 • torch_dtype: float16 / float32 — 影响显存占用 • device_map: "auto" — 自动分配到 GPU/CPU • max_length: 128 / 512 / 2048 — 根据模型和任务调整 • padding: "max_length" / "longest" — 批次训练时必设 💡 每次加载新模型,先跑推理测试,再开始微调

整个流程其实就四步:下载 → 加载 → 配 Tokenizer → 跑推理。每一步都有坑,但只要你按这个顺序来,基本不会出大问题。

我个人习惯把这四步写成一个脚本,每次换模型就改一行模型名。这样既省时间,又不容易漏掉配置。


公众号:蓝海资料掘金营,微信deep3321