HuggingFace 快速上手
本节定位
很多新人第一次接触 HuggingFace 时,会被这些名字绕晕:
AutoTokenizerAutoModelpipelineconfigforward
看起来像很多 API,
但如果把核心流程抽出来,其实非常稳定:
文本 -> tokenizer -> input ids / mask -> model.forward -> hidden states / logits
这节课的目标,就是把这条链讲清楚。
学习目标
- 理解 HuggingFace 最常见的输入到输出流程
- 分清 tokenizer、config、model、batch 分别负责什么
- 看懂一个不依赖在线下载的最小
transformers示例 - 建立以后读官方示例和仓库代码时的第一层熟悉感
一、HuggingFace 到底在帮我们做什么?
1.1 它不是一个“模型”,而是一整套生态
很多人会把 HuggingFace 误解成:
- 一个很强的模型平台
更准确地说,它是一整套围绕模型开发的工具生态,常见包括:
transformersdatasetstokenizerspeft
其中你最常接触的是:
- tokenizer
- model
- config
1.2 最常见的工作流只有几步
无论是做分类、生成还是抽特征,
最核心的调用路径通常都长这样:
- 用 tokenizer 把文本转成
input_ids - 准备
attention_mask - 把 batch 喂给 model
- 从输出里拿到 hidden states、logits 或生成结果
如果这条链在脑子里顺了,
很多例子就不会再显得乱。
1.3 一个类比:像组装标准化实验台
你可以把 HuggingFace 想成实验台标准件:
- tokenizer 像样本预处理器
- config 像模型蓝图
- model 像真正执行计算的机器
- batch 像一次送进去的一盘样本
它的价值就在于:
- 统一接口
- 降低重复劳动
- 让你更快试模型和任务
二、先把几个最常见对象分清楚
2.1 Tokenizer:把文本变成模型输入
它通常负责:
- 分词
- token -> id
- padding
- truncation
输出里最常见的字段是:
input_idsattention_mask
2.2 Config:模型结构蓝图
config 主要描述:
- hidden size
- 层数
- 头数
- 词表大小
你可以把它理解成“模型长什么样”的说明书。
2.3 Model:真正执行 forward 的部分
model 会根据 config 建出神经网络,
然后接受张量输入,输出:
last_hidden_statepooler_outputlogits
不同任务模型输出会不太一样,
但核心思路一致。
2.4 Batch:为什么总要做 padding
因为一批文本长度不同。
模型通常要求输入张量形状统一,
所以要:
- 把短句补齐
- 用 mask 告诉模型哪些位置是真实 token
三、先看一个零下载、可直接运行的 transformers 示例
这段代码有几个特别重要的特点:
- 不依赖联网下载模型
- 直接用本地
BertConfig随机初始化一个小模型 - 自己准备一份超小词表
- 把两条句子编码成 batch 喂给模型
也就是说,它能让你把 HuggingFace 的主干流程完整跑通。
运行提示
pip install torch transformers
import torch
from transformers import BertConfig, BertModel
vocab = {
"[PAD]": 0,
"[CLS]": 1,
"[SEP]": 2,
"[UNK]": 3,
"reset": 4,
"password": 5,
"refund": 6,
"order": 7,
"please": 8,
"help": 9,
}
def tokenize(text):
return text.lower().split()
def encode(text, max_length=6):
tokens = ["[CLS]"] + tokenize(text) + ["[SEP]"]
input_ids = [vocab.get(token, vocab["[UNK]"]) for token in tokens][:max_length]
attention_mask = [1] * len(input_ids)
if len(input_ids) < max_length:
pad_count = max_length - len(input_ids)
input_ids += [vocab["[PAD]"]] * pad_count
attention_mask += [0] * pad_count
return input_ids, attention_mask
texts = [
"please help reset password",
"refund order",
]
encoded = [encode(text) for text in texts]
input_ids = torch.tensor([item[0] for item in encoded], dtype=torch.long)
attention_mask = torch.tensor([item[1] for item in encoded], dtype=torch.long)
config = BertConfig(
vocab_size=len(vocab),
hidden_size=32,
num_hidden_layers=2,
num_attention_heads=4,
intermediate_size=64,
)
model = BertModel(config)
outputs = model(input_ids=input_ids, attention_mask=attention_mask)
print("input_ids shape :", tuple(input_ids.shape))
print("attention_mask shape :", tuple(attention_mask.shape))
print("last_hidden_state shape:", tuple(outputs.last_hidden_state.shape))
print("pooler_output shape :", tuple(outputs.pooler_output.shape))
3.1 这段代码最该按什么顺序读?
最推荐的顺序是:
- 先看
encode,弄清文本是怎么变成input_ids的 - 再看
BertConfig,知道模型结构是怎样定义的 - 最后看
model(...)的输出 shape
这样你会很快把:
- 文本格式
- 模型结构
- 前向输出
这三件事串起来。
3.2 为什么这里不用 from_pretrained?
因为 from_pretrained 常常需要联网下载权重。
为了保证示例可以离线直接跑,这里故意采用:
BertConfig(...)BertModel(config)
也就是说:
- 模型是随机初始化的
它不能拿来做真实任务预测,
但非常适合拿来理解 HuggingFace 的基础调用流程。