Hugging Face Transformers 实战
Pipeline 工厂、Trainer API 训练循环、Hub 模型上传下载、Datasets / Tokenizers
Hugging Face 生态概览
Hugging Face 生态以 Transformers 库为核心,围绕深度学习全流程构建了五个关键库,覆盖模型加载、数据处理、训练加速和模型分发等环节。下表总结了各库的定位与核心功能:
| 库名称 | 定位 | 核心功能 |
|---|---|---|
| Transformers | 模型加载与推理 | 提供统一的 from_pretrained() API,支持 BERT、GPT、T5 等 10 万+ 预训练模型 |
| Datasets | 数据集管理 | 高效加载、预处理、流式读取 Hugging Face Hub 上的数千个公开数据集 |
| Tokenizers | 高性能分词 | 实现 BPE / WordPiece / Unigram 三种算法,Rust 后端极速分词 |
| Accelerate | 训练加速 | 零代码修改支持 GPU / TPU / 混合精度 / 分布式训练 |
| Hub | 模型共享平台 | push_to_hub() / from_pretrained() 实现模型上传与下载,支持版本管理 |
五个库彼此独立又可无缝协作,构成了从数据到模型再到部署的完整工具链。
Pipeline 工厂模式
pipeline() 是 Transformers 库最高层的 API,采用工厂模式设计:用户只需传入任务名称,pipeline 自动推断任务类型、加载对应的模型和 Tokenizer,封装预处理与后处理逻辑。
支持的 20+ 任务
pipeline 支持以下常见 NLP 任务以及部分 CV / 多模态任务:
- 文本分类(
text-classification) - 情感分析(
sentiment-analysis) - 问答(
question-answering) - 文本生成(
text-generation) - 摘要(
summarization) - 翻译(
translation) - 命名实体识别(
ner/token-classification) - 文本填充(
fill-mask) - 特征提取(
feature-extraction) - 零样本分类(
zero-shot-classification) - 表格问答(
table-question-answering) - 视觉问答(
visual-question-answering) - 图像分类(
image-classification) - 图像分割(
image-segmentation) - 目标检测(
object-detection) - 语音识别(
automatic-speech-recognition) - 音频分类(
audio-classification) - 文本转语音(
text-to-speech) - 文档问答(
document-question-answering)
自定义 pipeline
除了使用默认模型,用户可显式指定 model、tokenizer、device 等参数实现定制:
from transformers import pipeline
# 指定模型和 GPU 设备
classifier = pipeline(
"text-classification",
model="distilbert-base-uncased-finetuned-sst-2-english",
tokenizer="distilbert-base-uncased",
device=0 # 使用 GPU,-1 为 CPU
)
result = classifier("Hugging Face is amazing!")
print(result)
# [{'label': 'POSITIVE', 'score': 0.9998}]代码示例:三种典型 pipeline
from transformers import pipeline
# 1. 文本分类(情感分析)
sentiment = pipeline("sentiment-analysis")
print(sentiment("I love using Transformers!"))
# [{'label': 'POSITIVE', 'score': 0.9998}]
# 2. 问答
qa = pipeline("question-answering")
result = qa(
question="Hugging Face 是什么?",
context="Hugging Face 是一家专注于自然语言处理的 AI 公司,创建了 Transformers 库。"
)
print(f"答案: {result['answer']}, 置信度: {result['score']:.4f}")
# 答案: AI 公司, 置信度: 0.9821
# 3. 文本生成
generator = pipeline("text-generation", model="gpt2")
output = generator("Deep learning is", max_length=30, num_return_sequences=1)
print(output[0]["generated_text"])
# Deep learning is a branch of machine learning that uses neural networks...pipeline 内部自动完成 tokenize -> model forward -> decode 的完整链路,是快速验证模型效果的最佳入口。
Trainer API 训练循环
对于需要微调模型的场景,Transformers 提供了 Trainer API,封装了训练循环、日志记录、评估和模型保存等逻辑,用户只需配置 TrainingArguments 并提供数据集。
TrainingArguments 配置
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./results", # 输出目录
learning_rate=2e-5, # 学习率
per_device_train_batch_size=16, # 每设备训练批次大小
per_device_eval_batch_size=64, # 每设备评估批次大小
num_train_epochs=3, # 训练轮数
weight_decay=0.01, # 权重衰减
gradient_accumulation_steps=2, # 梯度累积步数
fp16=True, # 混合精度训练(FP16)
evaluation_strategy="epoch", # 每轮评估
save_strategy="epoch", # 每轮保存
logging_steps=100, # 日志步数间隔
save_total_limit=2, # 最多保留 2 个检查点
load_best_model_at_end=True, # 训练结束加载最佳模型
push_to_hub=False, # 是否自动推送至 Hub
)Trainer 类
from transformers import (
AutoTokenizer,
AutoModelForSequenceClassification,
Trainer
)
# 加载模型和分词器
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
model_name, num_labels=2
)
# 数据集预处理(以 Datasets 加载的数据为例)
def tokenize_function(examples):
return tokenizer(
examples["text"], truncation=True, padding="max_length", max_length=128
)
# 假设已通过 Datasets 库加载 train_dataset 和 eval_dataset
# tokenized_train = train_dataset.map(tokenize_function, batched=True)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_train,
eval_dataset=tokenized_eval,
tokenizer=tokenizer,
)
# 训练与评估
trainer.train()
trainer.evaluate()完整微调训练代码
以下展示从加载模型到微调完成的完整流程:
from datasets import load_dataset
from transformers import (
AutoTokenizer,
AutoModelForSequenceClassification,
Trainer,
TrainingArguments
)
# 1. 加载数据集
dataset = load_dataset("imdb")
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
# 2. 数据预处理
def preprocess(batch):
return tokenizer(
batch["text"], truncation=True, padding="max_length", max_length=256
)
tokenized = dataset.map(preprocess, batched=True)
# 3. 配置训练参数
args = TrainingArguments(
output_dir="./finetuned-model",
num_train_epochs=1,
per_device_train_batch_size=8,
fp16=True,
save_strategy="no",
report_to="none"
)
# 4. 加载模型
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased", num_labels=2
)
# 5. 初始化 Trainer 并训练
trainer = Trainer(
model=model,
args=args,
train_dataset=tokenized["train"].select(range(800)),
eval_dataset=tokenized["test"].select(range(200)),
tokenizer=tokenizer,
)
trainer.train()
# 6. 评估
metrics = trainer.evaluate()
print(f"评估结果: {metrics}")Seq2SeqTrainer 用于生成式任务
对于 T5、BART 等序列到序列模型,使用 Seq2SeqTrainer 配合 Seq2SeqTrainingArguments:
from transformers import (
AutoModelForSeq2SeqLM,
Seq2SeqTrainer,
Seq2SeqTrainingArguments
)
model = AutoModelForSeq2SeqLM.from_pretrained("t5-small")
training_args = Seq2SeqTrainingArguments(
output_dir="./t5-finetuned",
predict_with_generate=True, # 使用 generate() 进行生成
generation_max_length=128, # 最大生成长度
per_device_train_batch_size=8,
)
trainer = Seq2SeqTrainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
tokenizer=tokenizer,
)
trainer.train()Trainer API 极大减少了训练模版代码,同时保留了通过自定义 compute_metrics 和 DataCollator 进行扩展的能力。
Hub 模型上传下载
Hugging Face Hub 托管了超过 10 万个预训练模型,通过 from_pretrained() 和 push_to_hub() 实现无缝上传和下载。
下载模型
from transformers import AutoModel, AutoTokenizer
# 从 Hub 加载,自动缓存至 ~/.cache/huggingface/
model = AutoModel.from_pretrained("bert-base-uncased")
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# 指定版本(分支 / tag / commit hash)
model = AutoModel.from_pretrained("bert-base-uncased", revision="v1.0.0")上传模型
from huggingface_hub import login
# 登录(需先在 huggingface.co 创建 token)
login(token="your_hf_token")
# 推送模型和 tokenizer 至 Hub
model.push_to_hub("your-username/your-model")
tokenizer.push_to_hub("your-username/your-model")
# 私有仓库
model.push_to_hub("your-username/private-model", private=True)模型在 Hub 上以 Git 仓库管理,支持版本标签(tag)、分支(branch)和 commit 级别的回滚,便于团队协作与模型迭代。
Datasets 库
Datasets 库提供了高效的数据加载与处理能力,支持内存映射(memory-mapping)和流式加载,可处理 GB 甚至 TB 级别的数据集。
加载常用数据集
from datasets import load_dataset
# 加载完整数据集(默认全部下载)
dataset = load_dataset("imdb")
print(dataset)
# DatasetDict({
# train: Dataset({ features: ['text', 'label'], num_rows: 25000 })
# test: Dataset({ features: ['text', 'label'], num_rows: 25000 })
# })
# 流式加载:不下载全部数据,适合超大数据集
stream_dataset = load_dataset("c4", "en", streaming=True)
for i, example in enumerate(stream_dataset["train"]):
if i >= 5:
break
print(example["text"][:100])数据集处理
# map:批量预处理
def add_prefix(example):
example["text"] = "[CLS] " + example["text"]
return example
dataset = dataset.map(add_prefix)
# filter:过滤数据
dataset = dataset.filter(lambda x: len(x["text"]) > 50)
# select:选取子集
small_train = dataset["train"].select(range(1000))
# 支持多进程加速
dataset = dataset.map(tokenize_function, batched=True, num_proc=4)流式加载的优势
对于 GB 级以上的数据集,流式加载无需将全部数据读入内存:
# 流式模式下的处理与完整模式 API 一致
stream_dataset = load_dataset("oscar", "unshuffled_deduplicated_en", streaming=True)
tokenized_stream = stream_dataset.map(tokenize_function, batched=True)
for batch in tokenized_stream["train"].take(100):
# 逐批处理,内存占用恒定
passTokenizers 库
Tokenizers 库采用 Rust 后端实现,分词速度远超 Python 原生实现,支持三种主流算法。
三种 Tokenizer 类型
| Tokenizer 类型 | 算法原理 | 代表模型 | 特点 |
|---|---|---|---|
| BPE (Byte-Pair Encoding) | 从字符级别开始,逐步合并最频繁的字节对 | GPT-2、RoBERTa | 词表大小可控,处理未登录词能力强 |
| WordPiece | 贪心最长匹配 + 基于概率的切分 | BERT、DistilBERT | 对常见单词保留完整形式 |
| Unigram | 基于语言模型概率,逐 token 去除最低分片段 | XLNet、ALBERT | 可生成多个分词候选 |
训练自定义 Tokenizer
from tokenizers import Tokenizer, models, trainers, pre_tokenizers
# 从 BPE 模型初始化
tokenizer = Tokenizer(models.BPE())
# 设置预分词器(按空格和标点切分)
tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=True)
# 配置训练器
trainer = trainers.BpeTrainer(
vocab_size=30000,
special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"],
min_frequency=2
)
# 训练(传入文本文件列表)
files = ["./data/corpus1.txt", "./data/corpus2.txt"]
tokenizer.train(files, trainer)
# 保存与加载
tokenizer.save("./my-tokenizer.json")
loaded_tokenizer = Tokenizer.from_file("./my-tokenizer.json")
# 与 Transformers 整合使用
from transformers import PreTrainedTokenizerFast
fast_tokenizer = PreTrainedTokenizerFast(tokenizer_object=loaded_tokenizer)
fast_tokenizer.save_pretrained("./my-tokenizer")实际示例:从数据到模型的完整工作流
以下展示一个完整的实践流程:加载预训练模型 -> Tokenizer -> Dataset 预处理 -> Trainer 微调 -> 推送至 Hub。
from datasets import load_dataset
from transformers import (
AutoTokenizer,
AutoModelForSequenceClassification,
Trainer,
TrainingArguments
)
from huggingface_hub import login
# 1. 登录 Hub
login(token="your_hf_token")
# 2. 加载数据集
dataset = load_dataset("imdb")
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
# 3. Tokenizer 预处理
def tokenize(batch):
return tokenizer(batch["text"], truncation=True, padding=True, max_length=256)
tokenized = dataset.map(tokenize, batched=True)
# 4. 配置训练参数
args = TrainingArguments(
output_dir="./imdb-finetuned",
num_train_epochs=2,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
evaluation_strategy="epoch",
save_strategy="epoch",
fp16=True,
logging_steps=50,
push_to_hub=True, # 训练结束后自动推送
hub_model_id="your-username/imdb-distilbert"
)
# 5. 加载预训练模型
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased", num_labels=2
)
# 6. 初始化 Trainer 并微调
trainer = Trainer(
model=model,
args=args,
train_dataset=tokenized["train"].select(range(2000)),
eval_dataset=tokenized["test"].select(range(500)),
tokenizer=tokenizer,
)
trainer.train()
# 7. 评估与推送
eval_result = trainer.evaluate()
trainer.push_to_hub()
print(f"训练完成,评估准确率: {eval_result}")以上流程覆盖了 Hugging Face 生态的核心环节。实际项目中可根据需要替换为不同的模型架构(BERT、GPT、T5、LLaMA 等)和数据集(GLUE、SQuAD、CNN/DailyMail 等),各组件之间的接口保持高度一致,这也是 Hugging Face 生态的设计哲学之一。