HuggingFace Transformers 完全指南
HuggingFace Transformers 是目前最主流的预训练模型工具库,提供数千个在 Hugging Face Hub 上发布的预训练模型,覆盖 NLP、计算机视觉、语音、多模态等任务。它的核心价值在于:一套统一 API 驯服从 BERT 到 LLaMA 的所有主流架构,无需了解每种架构的内部细节。 对比主要替代方案: 适合场景:需要在本地运行开源模型(Llama、Mistral、Qwen)、Fine-tuning 已有模型、使用 BERT 类模型做文本分类 / NER / 问答。不适合场景:只需调用 GPT-4 等闭源 API(用 OpenA
官方文档:https://huggingface.co/docs/transformers/
适用版本:5.8.0(2026-05-07 核实)
概述
HuggingFace Transformers 是目前最主流的预训练模型工具库,提供数千个在 Hugging Face Hub 上发布的预训练模型,覆盖 NLP、计算机视觉、语音、多模态等任务。它的核心价值在于:一套统一 API 驯服从 BERT 到 LLaMA 的所有主流架构,无需了解每种架构的内部细节。
对比主要替代方案:
- OpenAI Python SDK:只能调用 OpenAI 闭源模型,无法在本地运行开源模型
- sentence-transformers:专注于 Embedding,不覆盖生成、分类等宽泛任务
- LiteLLM:聚合各厂商 API,依赖外部服务,不支持本地推理
适合场景:需要在本地运行开源模型(Llama、Mistral、Qwen)、Fine-tuning 已有模型、使用 BERT 类模型做文本分类 / NER / 问答。不适合场景:只需调用 GPT-4 等闭源 API(用 OpenAI SDK 更简单)。
安装
pip install transformers torch # CPU / CUDA
pip install transformers torch --index-url https://download.pytorch.org/whl/cu118 # CUDA 11.8
pip install accelerate datasets # 训练与数据处理
pip install bitsandbytes # 4/8-bit 量化
pipeline — 一行完成推理
pipeline() 是 Transformers 最简洁的推理接口,屏蔽了 tokenize → forward → decode 的细节。
pipeline()
transformers.pipeline(
task: str,
model: str | PreTrainedModel = None,
config: str | PreTrainedConfig = None,
tokenizer: str | PreTrainedTokenizer = None,
feature_extractor: str | FeatureExtractionMixin = None,
image_processor: str | BaseImageProcessor = None,
processor: str | ProcessorMixin = None,
revision: str = "main",
use_fast: bool = True,
token: str | bool = None,
device: int | str | torch.device = None,
device_map: str | dict = None,
dtype: str | torch.dtype = None,
trust_remote_code: bool = False,
model_kwargs: dict[str, Any] = None,
**kwargs
) -> Pipeline
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
task |
str |
必须 | 任务字符串,见下表;决定返回哪种 Pipeline 实例 |
model |
str | PreTrainedModel |
None |
Hub 模型 ID、本地路径或已加载的模型实例;None 时使用各任务默认模型 |
config |
str | PreTrainedConfig |
None |
模型配置;None 时从 model 自动推断 |
tokenizer |
str | PreTrainedTokenizer |
None |
分词器;None 时自动加载 |
feature_extractor |
str | FeatureExtractionMixin |
None |
语音 / 视觉任务的特征提取器 |
image_processor |
str | BaseImageProcessor |
None |
视觉 / 多模态任务的图像处理器 |
processor |
str | ProcessorMixin |
None |
多模态任务的统一处理器 |
revision |
str |
"main" |
Hub 上的分支、tag 或 commit id |
use_fast |
bool |
True |
优先使用 Rust 实现的快速分词器(PreTrainedTokenizerFast) |
token |
str | bool |
None |
HuggingFace Hub 访问 token;True 则使用 hf_auth_login 已存储的 token |
device |
int | str | torch.device |
None |
推理设备;"cpu" / "cuda" / "cuda:1" / "mps";与 device_map 互斥 |
device_map |
str | dict |
None |
设备映射,"auto" 自动跨 GPU / CPU 分片(依赖 accelerate);与 device 互斥 |
dtype |
str | torch.dtype |
None |
模型精度;torch.float16 / torch.bfloat16 / "auto" |
trust_remote_code |
bool |
False |
允许执行 Hub 上的自定义建模代码,仅对可信仓库开启 |
model_kwargs |
dict |
None |
透传给 model.from_pretrained() 的额外参数(如 load_in_8bit=True) |
支持的任务字符串
语音(Audio)
| task 字符串 | Pipeline 类 |
|---|---|
"audio-classification" |
AudioClassificationPipeline |
"automatic-speech-recognition" |
AutomaticSpeechRecognitionPipeline |
"text-to-audio" / "text-to-speech" |
TextToAudioPipeline |
"zero-shot-audio-classification" |
ZeroShotAudioClassificationPipeline |
计算机视觉(Vision)
| task 字符串 | Pipeline 类 |
|---|---|
"depth-estimation" |
DepthEstimationPipeline |
"image-classification" |
ImageClassificationPipeline |
"image-feature-extraction" |
ImageFeatureExtractionPipeline |
"image-segmentation" |
ImageSegmentationPipeline |
"image-text-to-text" |
ImageTextToTextPipeline |
"keypoint-matching" |
KeypointMatchingPipeline |
"mask-generation" |
MaskGenerationPipeline |
"object-detection" |
ObjectDetectionPipeline |
"video-classification" |
VideoClassificationPipeline |
"zero-shot-image-classification" |
ZeroShotImageClassificationPipeline |
"zero-shot-object-detection" |
ZeroShotObjectDetectionPipeline |
自然语言处理(NLP)
| task 字符串 | Pipeline 类 |
|---|---|
"fill-mask" |
FillMaskPipeline |
"ner" / "token-classification" |
TokenClassificationPipeline |
"sentiment-analysis" / "text-classification" |
TextClassificationPipeline |
"text-generation" |
TextGenerationPipeline |
"summarization" |
SummarizationPipeline |
"translation" |
TranslationPipeline |
"question-answering" |
QuestionAnsweringPipeline |
"table-question-answering" |
TableQuestionAnsweringPipeline |
"document-question-answering" |
DocumentQuestionAnsweringPipeline |
"feature-extraction" |
FeatureExtractionPipeline |
"zero-shot-classification" |
ZeroShotClassificationPipeline |
示例
from transformers import pipeline
# 最小示例:情感分析
clf = pipeline("sentiment-analysis")
result = clf("This movie is fantastic!")
# [{'label': 'POSITIVE', 'score': 0.9998}]
# 指定模型 + GPU + 半精度
gen = pipeline(
"text-generation",
model="meta-llama/Llama-3.2-1B-Instruct",
device=0,
dtype="auto",
token=True, # 需要 HF 访问 token
trust_remote_code=True,
)
output = gen("Once upon a time", max_new_tokens=100)
# 批量处理(传入列表)
ner = pipeline("ner", model="dslim/bert-base-NER")
results = ner(["Alice lives in Paris", "Bob works at Google"])
# 语音识别
asr = pipeline("automatic-speech-recognition", model="openai/whisper-base")
transcription = asr("audio.wav")
# {'text': '...'}
# 零样本分类(不需要重新训练)
classifier = pipeline("zero-shot-classification")
classifier(
"I need to cancel my subscription",
candidate_labels=["billing", "technical support", "account management"],
)
Auto 类 — 自动加载模型与分词器
Auto 类根据模型名称或本地路径自动选择正确的架构类,是加载预训练模型的推荐方式。
AutoTokenizer.from_pretrained()
AutoTokenizer.from_pretrained(pretrained_model_name_or_path, **kwargs)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
pretrained_model_name_or_path |
str | PathLike |
必须 | Hub 模型 ID(如 "bert-base-uncased")或本地目录路径 |
cache_dir |
str | PathLike |
None |
缓存目录;默认 ~/.cache/huggingface/hub |
force_download |
bool |
False |
忽略缓存,强制重新下载 |
revision |
str |
"main" |
Hub 上的分支、tag 或 commit id |
trust_remote_code |
bool |
False |
允许执行仓库中的自定义分词器代码 |
use_fast |
bool |
True |
优先使用 Rust 快速实现(PreTrainedTokenizerFast) |
proxies |
dict[str, str] |
None |
代理配置,如 {'http': '127.0.0.1:7890'} |
token |
str | bool |
None |
Hub 访问 token,用于访问私有模型 |
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
# 编码文本
inputs = tokenizer("Hello, world!", return_tensors="pt")
# {'input_ids': tensor(...), 'attention_mask': tensor(...)}
# 批量编码(自动 padding)
inputs = tokenizer(
["Hello world", "How are you?"],
padding=True,
truncation=True,
max_length=128,
return_tensors="pt",
)
# 保存到本地(用于离线部署)
tokenizer.save_pretrained("./my_tokenizer")
AutoModel.from_pretrained()
AutoModel.from_pretrained(pretrained_model_name_or_path, **kwargs)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
pretrained_model_name_or_path |
str | PathLike |
必须 | Hub 模型 ID 或本地路径 |
cache_dir |
str | PathLike |
None |
缓存目录 |
force_download |
bool |
False |
强制重新下载 |
revision |
str |
"main" |
版本标识符 |
trust_remote_code |
bool |
False |
允许自定义建模代码 |
device_map |
str | dict |
None |
设备映射;"auto" 自动多 GPU 分片 |
return_unused_kwargs |
bool |
False |
返回未被模型使用的额外 kwargs |
low_cpu_mem_usage |
bool |
False |
减少 CPU 内存使用,加载大模型时建议开启 |
torch_dtype |
torch.dtype | str |
None |
加载精度;"auto" 使用模型原始精度 |
load_in_8bit |
bool |
False |
8-bit 量化加载(需要 bitsandbytes) |
load_in_4bit |
bool |
False |
4-bit NF4 量化加载(需要 bitsandbytes) |
from transformers import AutoModel, AutoModelForSequenceClassification, AutoModelForCausalLM
import torch
# 加载编码器(BERT 类)
model = AutoModel.from_pretrained("google-bert/bert-base-uncased")
# 分类任务:编码器 + 分类头
clf_model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased-finetuned-sst-2-english"
)
# 生成任务:解码器(LLM)
llm = AutoModelForCausalLM.from_pretrained(
"microsoft/phi-2",
torch_dtype=torch.float16,
device_map="auto", # 自动多 GPU 分片
low_cpu_mem_usage=True,
)
# 4-bit 量化(减少 ~75% 显存)
llm_4bit = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.2-8B-Instruct",
load_in_4bit=True,
device_map="auto",
token=True,
)
# 保存模型
model.save_pretrained("./saved_model")
常用 AutoModel 子类
| 类名 | 适用任务 | 代表模型 |
|---|---|---|
AutoModelForSequenceClassification |
文本分类、情感分析 | BERT, RoBERTa, DistilBERT |
AutoModelForTokenClassification |
NER、词性标注 | BERT, DeBERTa |
AutoModelForQuestionAnswering |
抽取式问答 | BERT, ELECTRA |
AutoModelForCausalLM |
文本生成(GPT 类) | GPT-2, LLaMA, Mistral, Qwen |
AutoModelForSeq2SeqLM |
翻译、摘要(编解码器) | T5, BART, mT5 |
AutoModelForMaskedLM |
Fill-mask、预训练 | BERT, RoBERTa |
AutoModelForImageClassification |
图像分类 | ViT, Swin Transformer |
Tokenizer 核心方法
编码与解码
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
# 编码:文本 → token id
encoding = tokenizer(
"Hello, world!",
add_special_tokens=True, # 添加 [CLS] / [SEP] 等特殊 token
max_length=128,
padding="max_length", # 填充到最大长度
truncation=True, # 超出截断
return_attention_mask=True,
return_tensors="pt", # 返回 torch.Tensor
)
# encoding.input_ids, encoding.attention_mask, encoding.token_type_ids
# 批量编码(自动对齐 padding)
batch = tokenizer(
["sentence one", "sentence two"],
padding=True, # 同批次内对齐
truncation=True,
return_tensors="pt",
)
# 解码:token id → 文本
ids = [101, 7592, 1010, 2088, 999, 102]
text = tokenizer.decode(ids, skip_special_tokens=True)
# "hello , world !"
# 批量解码
texts = tokenizer.batch_decode(batch.input_ids, skip_special_tokens=True)
推理流程(手动)
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
model_name = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)
model.eval()
texts = ["I love this movie!", "This was a waste of time."]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
# outputs.logits: shape [batch_size, num_labels]
probs = torch.softmax(outputs.logits, dim=-1)
labels = model.config.id2label
for i, prob in enumerate(probs):
pred = labels[prob.argmax().item()]
print(f"{texts[i]!r}: {pred} ({prob.max():.4f})")
文本生成
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
model_name = "microsoft/phi-2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float16, device_map="auto")
inputs = tokenizer("Explain quantum computing in simple terms:", return_tensors="pt").to(model.device)
# generate() 核心参数
outputs = model.generate(
**inputs,
max_new_tokens=200, # 最多新生成 200 个 token
temperature=0.7, # 采样温度;越高越随机,越低越确定
top_p=0.9, # nucleus sampling;累计概率阈值
top_k=50, # top-k 采样
do_sample=True, # 开启采样(否则贪心解码)
repetition_penalty=1.1, # 惩罚重复 token
pad_token_id=tokenizer.eos_token_id,
)
# 解码时只保留新生成的 token
new_tokens = outputs[0][inputs.input_ids.shape[1]:]
print(tokenizer.decode(new_tokens, skip_special_tokens=True))
generate() 主要参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
max_new_tokens |
int |
None |
最多生成的新 token 数(推荐用此参数替代 max_length) |
max_length |
int |
20 |
输入 + 输出总 token 上限 |
do_sample |
bool |
False |
是否采样;False 为贪心解码 |
temperature |
float |
1.0 |
温度系数;< 1 更确定,> 1 更随机 |
top_p |
float |
1.0 |
Nucleus sampling 阈值;0.9 表示从累计 90% 概率的 token 中采样 |
top_k |
int |
50 |
Top-k 采样;每步只从概率最高的 k 个 token 中采样 |
repetition_penalty |
float |
1.0 |
重复惩罚;> 1 惩罚已出现的 token |
num_beams |
int |
1 |
Beam search 的束宽;1 关闭 beam search |
num_return_sequences |
int |
1 |
返回的候选序列数;需 num_beams >= num_return_sequences |
pad_token_id |
int |
None |
Padding token id;批量生成时必须设置 |
eos_token_id |
int | list |
None |
结束 token id;遇到此 token 停止生成 |
Trainer — Fine-tuning 训练器
Trainer 封装了训练循环、梯度累积、混合精度、分布式训练等,是 Fine-tuning 的标准工具。
TrainingArguments
from transformers import TrainingArguments
args = TrainingArguments(
output_dir="./results", # 检查点保存路径
num_train_epochs=3,
per_device_train_batch_size=16, # 每张 GPU 的批次大小
per_device_eval_batch_size=64,
warmup_steps=500, # 学习率预热步数
weight_decay=0.01, # L2 正则化系数
logging_dir="./logs",
logging_steps=100,
eval_strategy="epoch", # 每个 epoch 评估一次
save_strategy="epoch",
load_best_model_at_end=True, # 训练结束加载最优检查点
fp16=True, # 开启混合精度(需要 CUDA)
dataloader_num_workers=4,
report_to="tensorboard",
)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
output_dir |
str |
必须 | 模型检查点和输出的保存路径 |
num_train_epochs |
float |
3.0 |
训练轮次 |
per_device_train_batch_size |
int |
8 |
每张设备的训练批次大小 |
per_device_eval_batch_size |
int |
8 |
每张设备的评估批次大小 |
learning_rate |
float |
5e-5 |
AdamW 优化器初始学习率 |
weight_decay |
float |
0.0 |
L2 正则化系数(AdamW 的权重衰减) |
warmup_steps |
int |
0 |
学习率线性预热步数 |
warmup_ratio |
float |
0.0 |
以训练总步数的比例设置预热(与 warmup_steps 二选一) |
fp16 |
bool |
False |
开启 FP16 混合精度训练(CUDA) |
bf16 |
bool |
False |
开启 BF16 混合精度训练(Ampere+ GPU) |
gradient_accumulation_steps |
int |
1 |
梯度累积步数;有效批次 = per_device_train_batch_size × gradient_accumulation_steps |
eval_strategy |
str |
"no" |
评估策略:"no" / "steps" / "epoch" |
save_strategy |
str |
"steps" |
保存策略:"no" / "steps" / "epoch" |
load_best_model_at_end |
bool |
False |
训练结束时加载验证集最优检查点 |
report_to |
str | list |
"none" |
实验追踪平台:"tensorboard" / "wandb" / "none" |
dataloader_num_workers |
int |
0 |
DataLoader 工作进程数 |
Trainer 完整示例
from transformers import (
AutoTokenizer, AutoModelForSequenceClassification,
TrainingArguments, Trainer
)
from datasets import load_dataset
import numpy as np
from sklearn.metrics import accuracy_score, f1_score
# 加载数据集
dataset = load_dataset("imdb")
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
def tokenize(examples):
return tokenizer(examples["text"], truncation=True, max_length=512)
tokenized = dataset.map(tokenize, batched=True, remove_columns=["text"])
tokenized = tokenized.rename_column("label", "labels")
# 加载模型
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased", num_labels=2
)
# 定义评估指标
def compute_metrics(eval_pred):
logits, labels = eval_pred
preds = np.argmax(logits, axis=-1)
return {
"accuracy": accuracy_score(labels, preds),
"f1": f1_score(labels, preds, average="weighted"),
}
training_args = TrainingArguments(
output_dir="./imdb-distilbert",
num_train_epochs=3,
per_device_train_batch_size=32,
per_device_eval_batch_size=64,
warmup_ratio=0.1,
weight_decay=0.01,
eval_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
fp16=True,
report_to="tensorboard",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized["train"],
eval_dataset=tokenized["test"],
tokenizer=tokenizer,
compute_metrics=compute_metrics,
)
trainer.train()
trainer.save_model("./best-imdb-distilbert")
模型保存与加载
# 保存(本地)
model.save_pretrained("./my_model")
tokenizer.save_pretrained("./my_model")
# 加载本地
model = AutoModelForSequenceClassification.from_pretrained("./my_model")
tokenizer = AutoTokenizer.from_pretrained("./my_model")
# 推送到 Hub(需要登录)
# huggingface-cli login
model.push_to_hub("my-username/my-model-name")
tokenizer.push_to_hub("my-username/my-model-name")
最佳实践
在生产环境中复用 pipeline 实例:每次调用 pipeline() 都会重新加载模型权重,开销极大。应在应用启动时初始化一次,后续复用同一个实例。
# 正确:全局单例
_clf = None
def get_classifier():
global _clf
if _clf is None:
_clf = pipeline("text-classification", model="...", device=0)
return _clf
# 错误:每次请求都重新创建
def classify(text):
clf = pipeline("text-classification") # 重新加载模型,极慢
return clf(text)
用 torch.no_grad() 和 model.eval() 推理:不添加这两个上下文时,PyTorch 会构建计算图并保留梯度,推理时浪费约 30% 内存。
model.eval()
with torch.no_grad():
outputs = model(**inputs)
量化大模型降低显存门槛:70B 参数模型全精度需约 140GB 显存,4-bit 量化后约 35GB,可在单张 A100 80G 上运行。推理精度损失通常在 1–2% 以内。
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.2-70B",
load_in_4bit=True,
device_map="auto",
bnb_4bit_compute_dtype=torch.bfloat16,
)
使用 datasets 库处理大规模数据集:datasets 支持内存映射(Arrow 格式),100GB 数据集无需全量载入内存,配合 .map(batched=True) 并行处理可显著加速预处理。
from datasets import load_dataset
dataset = load_dataset("json", data_files="data.jsonl", split="train")
tokenized = dataset.map(
lambda x: tokenizer(x["text"], truncation=True),
batched=True,
num_proc=4, # 4 进程并行
remove_columns=["text"],
)
通过 revision 锁定模型版本:Hub 上的模型权重可能随时更新,生产环境应固定到特定 commit id,避免模型漂移。
model = AutoModel.from_pretrained(
"google-bert/bert-base-uncased",
revision="7f56ae30", # 锁定到具体 commit
)
批量推理优于逐条推理:逐条调用 pipeline 时 GPU 利用率通常不足 10%,传入列表可以触发批量矩阵乘法,吞吐量提升 5–20 倍。
# 正确:批量传入
results = clf(["text1", "text2", "text3", ..., "text64"])
# 低效:逐条处理
results = [clf(text) for text in texts]
常见陷阱
陷阱:设备不一致导致 RuntimeError
现象: RuntimeError: Expected all tensors to be on the same device
原因: 模型在 GPU,但 input tensor 在 CPU;或者反过来。
解决: 调用 .to(model.device) 将输入移到与模型相同的设备。
model = model.to("cuda")
inputs = tokenizer(text, return_tensors="pt")
inputs = {k: v.to(model.device) for k, v in inputs.items()} # 正确
# inputs = inputs.to("cuda") # 错误:dict 没有 .to() 方法
陷阱:生成时不设置 pad_token_id
现象: 批量调用 generate() 时警告 Setting pad_token_id to eos_token_id,结果截断或质量下降。
原因: GPT 类模型(LLaMA、Mistral 等)没有 pad_token 设计,批量生成时长度不一致需要 padding。
解决: 显式设置 pad_token_id,并将 tokenizer 的 padding 方向改为左侧。
tokenizer.padding_side = "left" # 生成任务用左侧 padding
outputs = model.generate(
**inputs,
pad_token_id=tokenizer.eos_token_id,
max_new_tokens=100,
)
陷阱:Fine-tuning 时忘记 num_labels
现象: 训练文本分类时 loss 异常高,模型不收敛。
原因: from_pretrained 时若不指定 num_labels,分类头的输出维度默认为 2(二分类),多分类任务下计算 loss 时维度不匹配。
解决: 加载模型时传入正确的 num_labels。
# 错误:5 分类任务用默认 num_labels=2
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased")
# 正确:明确指定类别数
model = AutoModelForSequenceClassification.from_pretrained(
"bert-base-uncased",
num_labels=5,
id2label={0: "1-star", 1: "2-star", 2: "3-star", 3: "4-star", 4: "5-star"},
label2id={"1-star": 0, "2-star": 1, "3-star": 2, "4-star": 3, "5-star": 4},
)
陷阱:在训练循环中保留计算图耗尽内存
现象: 训练过程中 GPU 内存持续增长,最终 OOM。
原因: loss.item() 之前调用了 loss.detach() 或在日志记录时直接存储 loss tensor,导致整个计算图被保留在内存中。
解决: 使用 .item() 将标量提取为 Python float,释放计算图。
# 错误:保留了 tensor(及其完整计算图)
train_losses.append(loss)
# 正确:提取 Python float
train_losses.append(loss.item())