Hugging Face NLP Course 第 3-5 模块中英对照¶
课程: Hugging Face NLP Course
原链接: https://huggingface.co/learn/nlp-course
版本: transformers >= 4.40.0
翻译时间: 2026-06-01
状态: 中英对照编译版
前续: 第 1 模块, 第 2 模块
📚 目录 (Table of Contents)¶
Module 3: Fine-tuning for Specific Tasks¶
模块 3: 特定任务的微调¶
- Chapter 3/1: Fine-tuning for Text Classification (文本分类微调)
- Chapter 3/2: Fine-tuning for Question Answering (问答微调)
- Chapter 3/3: Fine-tuning for Named Entity Recognition (命名实体识别微调)
Module 4: Building and Sharing Models¶
模块 4: 构建和共享模型¶
- Chapter 4/1: The Hugging Face Hub (Hugging Face Hub)
- Chapter 4/2: Sharing Models and Datasets (共享模型和数据集)
- Chapter 4/3: Creating Model Cards (创建模型卡片)
Module 5: Deployment and Production¶
模块 5: 部署和生产¶
- Chapter 5/1: Model Optimization (模型优化)
- Chapter 5/2: Deployment with Inference APIs (使用推理 API 部署)
- Chapter 5/3: Production Best Practices (生产最佳实践)
Module 3: Fine-tuning for Specific Tasks¶
模块 3: 特定任务的微调¶
Chapter 3/1: Fine-tuning for Text Classification¶
第 3/1 章:文本分类微调¶
English:
Text classification is one of the most common NLP tasks. It involves assigning a label or category to a given text. Examples include sentiment analysis, topic classification, and spam detection.
中文:
文本分类是最常见的 NLP 任务之一。它涉及为给定文本分配标签或类别。示例包括情感分析、主题分类和垃圾邮件检测。
完整微调示例 (Complete Fine-tuning Example):
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import TrainingArguments, Trainer
import numpy as np
from sklearn.metrics import accuracy_score, f1_score
# 1. 加载数据集
dataset = load_dataset("imdb")
# 2. 加载预训练模型和 tokenizer
model_name = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
model_name,
num_labels=2, # 二分类:正面/负面
id2label={0: "NEGATIVE", 1: "POSITIVE"},
label2id={"NEGATIVE": 0, "POSITIVE": 1}
)
# 3. 预处理数据
def tokenize_function(examples):
return tokenizer(
examples["text"],
padding="max_length",
truncation=True,
max_length=512
)
tokenized_datasets = dataset.map(
tokenize_function,
batched=True,
remove_columns=["text"]
)
# 4. 数据整理器
from transformers import DataCollatorWithPadding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
# 5. 评估指标
def compute_metrics(eval_pred):
logits, labels = eval_pred
predictions = np.argmax(logits, axis=-1)
return {
"accuracy": accuracy_score(labels, predictions),
"f1_macro": f1_score(labels, predictions, average="macro"),
"f1_weighted": f1_score(labels, predictions, average="weighted")
}
# 6. 训练参数
training_args = TrainingArguments(
output_dir="./text-classification",
learning_rate=2e-5,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
num_train_epochs=3,
weight_decay=0.01,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
logging_steps=100,
push_to_hub=False, # 设置为 True 可上传到 Hub
)
# 7. 创建 Trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["test"],
tokenizer=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
# 8. 开始训练
trainer.train()
# 9. 评估
results = trainer.evaluate()
print(f"Evaluation results: {results}")
# 10. 保存模型
trainer.save_model("./text-classification-model")
Chapter 3/2: Fine-tuning for Question Answering¶
第 3/2 章:问答微调¶
English:
Question answering (QA) models take a question and a context, and return the answer as a span of text from the context.
中文:
问答 (QA) 模型接受问题和上下文,返回上下文中文本片段作为答案。
SQuAD 数据集微调示例 (SQuAD Fine-tuning Example):
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForQuestionAnswering
from transformers import TrainingArguments, Trainer
import collections
# 1. 加载 SQuAD 数据集
datasets = load_dataset("squad")
# 2. 加载模型和 tokenizer
model_name = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForQuestionAnswering.from_pretrained(model_name)
# 3. 预处理函数
max_length = 384
doc_stride = 128
def preprocess_function(examples):
# 截断过长的问题
questions = [q.strip() for q in examples["question"]]
# Tokenize
inputs = tokenizer(
questions,
examples["context"],
max_length=max_length,
truncation="only_second",
return_overflowing_tokens=True,
stride=doc_stride,
return_offsets_mapping=True,
padding="max_length",
)
# 映射答案
offset_mapping = inputs.pop("offset_mapping")
sample_map = inputs.pop("overflow_to_sample_mapping")
start_positions = []
end_positions = []
for i, offsets in enumerate(offset_mapping):
input_ids = inputs["input_ids"][i]
cls_index = input_ids.index(tokenizer.cls_token_id)
# 获取样本信息
sequence_ids = inputs.sequence_ids(i)
sample_index = sample_map[i]
answers = examples["answers"][sample_index]
# 如果没有答案
if len(answers["answer_start"]) == 0:
start_positions.append(cls_index)
end_positions.append(cls_index)
else:
start_char = answers["answer_start"][0]
end_char = answers["answer_start"][0] + len(answers["text"][0])
# 找到 token 范围
token_start_index = 0
while sequence_ids[token_start_index] != 1:
token_start_index += 1
token_end_index = len(input_ids) - 1
while sequence_ids[token_end_index] != 1:
token_end_index -= 1
# 检查答案是否在上下文中
if not (offsets[token_start_index][0] <= start_char and
offsets[token_end_index][1] >= end_char):
start_positions.append(cls_index)
end_positions.append(cls_index)
else:
while token_start_index < len(offsets) and \
offsets[token_start_index][0] <= start_char:
token_start_index += 1
start_positions.append(token_start_index - 1)
while offsets[token_end_index][1] >= end_char:
token_end_index -= 1
end_positions.append(token_end_index + 1)
inputs["start_positions"] = start_positions
inputs["end_positions"] = end_positions
return inputs
# 4. 处理数据集
tokenized_datasets = datasets.map(
preprocess_function,
batched=True,
remove_columns=datasets["train"].column_names
)
# 5. 训练参数
training_args = TrainingArguments(
output_dir="./question-answering",
learning_rate=3e-5,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
num_train_epochs=3,
weight_decay=0.01,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
)
# 6. 创建 Trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["validation"],
tokenizer=tokenizer,
)
# 7. 训练
trainer.train()
# 8. 保存
trainer.save_model("./qa-model")
使用微调后的 QA 模型 (Using Fine-tuned QA Model):
from transformers import pipeline
# 加载微调后的模型
qa_pipeline = pipeline(
"question-answering",
model="./qa-model",
tokenizer="./qa-model"
)
# 使用示例
context = """
Hugging Face is a technology company that builds natural language processing tools.
It is known for its Transformers library which provides pre-trained models for various NLP tasks.
The company was founded in 2016 and is based in New York.
"""
question = "When was Hugging Face founded?"
result = qa_pipeline(question=question, context=context)
print(f"Answer: {result['answer']}")
print(f"Confidence: {result['score']:.2f}")
# 输出:Answer: 2016
# Confidence: 0.95
Chapter 3/3: Fine-tuning for Named Entity Recognition¶
第 3/3 章:命名实体识别微调¶
English:
Named Entity Recognition (NER) is the task of identifying and classifying named entities in text into predefined categories such as person, organization, location, etc.
中文:
命名实体识别 (NER) 是识别文本中的命名实体并将其分类为预定义类别(如人物、组织、地点等)的任务。
NER 微调完整示例 (Complete NER Fine-tuning Example):
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForTokenClassification
from transformers import TrainingArguments, Trainer
import numpy as np
from seqeval.metrics import accuracy_score, f1_score
# 1. 加载数据集 (ConLL 2003)
dataset = load_dataset("conll2003")
# 2. 标签映射
label_list = dataset["train"].features["ner_tags"].feature.names
print(f"Labels: {label_list}")
# ['O', 'B-PER', 'I-PER', 'B-ORG', 'I-ORG', 'B-LOC', 'I-LOC', 'B-MISC', 'I-MISC']
# 3. 加载模型和 tokenizer
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForTokenClassification.from_pretrained(
model_name,
num_labels=len(label_list),
id2label={i: label for i, label in enumerate(label_list)},
label2id={label: i for i, label in enumerate(label_list)}
)
# 4. 预处理函数
def tokenize_and_align_labels(examples):
tokenized_inputs = tokenizer(
examples["tokens"],
is_split_into_words=True,
padding="max_length",
truncation=True,
max_length=128
)
labels = []
for i, label in enumerate(examples["ner_tags"]):
word_ids = tokenized_inputs.word_ids(batch_index=i)
previous_word_idx = None
label_ids = []
for word_idx in word_ids:
if word_idx is None:
label_ids.append(-100) # 特殊 token 的标签设为 -100
elif word_idx != previous_word_idx:
label_ids.append(label[word_idx])
else:
label_ids.append(-100) # 同一词的后续 token 设为 -100
previous_word_idx = word_idx
labels.append(label_ids)
tokenized_inputs["labels"] = labels
return tokenized_inputs
# 5. 处理数据集
tokenized_datasets = dataset.map(
tokenize_and_align_labels,
batched=True,
remove_columns=dataset["train"].column_names
)
# 6. 数据整理器
from transformers import DataCollatorForTokenClassification
data_collator = DataCollatorForTokenClassification(tokenizer)
# 7. 评估指标
def compute_metrics(eval_pred):
logits, labels = eval_pred
predictions = np.argmax(logits, axis=-1)
# 移除 -100 标签
true_predictions = [
[label_list[p] for (p, l) in zip(prediction, label) if l != -100]
for prediction, label in zip(predictions, labels)
]
true_labels = [
[label_list[l] for (p, l) in zip(prediction, label) if l != -100]
for prediction, label in zip(predictions, labels)
]
return {
"accuracy": accuracy_score(true_labels, true_predictions),
"f1": f1_score(true_labels, true_predictions),
}
# 8. 训练参数
training_args = TrainingArguments(
output_dir="./ner-model",
learning_rate=2e-5,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
num_train_epochs=5,
weight_decay=0.01,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
)
# 9. 创建 Trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["validation"],
tokenizer=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
# 10. 训练
trainer.train()
# 11. 保存
trainer.save_model("./ner-model")
使用 NER 模型 (Using NER Model):
from transformers import pipeline
# 加载 NER 模型
ner_pipeline = pipeline(
"token-classification",
model="./ner-model",
aggregation_strategy="simple" # 聚合子词为完整实体
)
# 使用示例
text = """
Apple Inc. is headquartered in Cupertino, California.
Tim Cook is the CEO of Apple.
"""
entities = ner_pipeline(text)
for entity in entities:
print(f"{entity['entity_group']}: {entity['word']} "
f"(confidence: {entity['score']:.2f})")
# 输出:
# ORG: Apple Inc. (confidence: 0.99)
# LOC: Cupertino (confidence: 0.95)
# LOC: California (confidence: 0.96)
# PER: Tim Cook (confidence: 0.98)
# ORG: Apple (confidence: 0.97)
Module 4: Building and Sharing Models¶
模块 4: 构建和共享模型¶
Chapter 4/1: The Hugging Face Hub¶
第 4/1 章:Hugging Face Hub¶
English:
The Hugging Face Hub is a platform for sharing and discovering machine learning models, datasets, and demos. It hosts over 500,000 models and 100,000 datasets.
中文:
Hugging Face Hub 是一个共享和发现机器学习模型、数据集和演示的平台。它托管了超过 500,000 个模型和 100,000 个数据集。
Hub 功能 (Hub Features):
| 功能 | 英文 | 中文 | 说明 |
|---|---|---|---|
| Models | Models | 模型 | 预训练和微调模型 |
| Datasets | Datasets | 数据集 | 训练和评估数据 |
| Spaces | Spaces | 空间 | 交互式演示应用 |
| Organizations | Organizations | 组织 | 团队协作空间 |
| Discussions | Discussions | 讨论 | 模型卡片评论 |
上传模型到 Hub (Uploading Models to Hub):
from huggingface_hub import HfApi, login
# 1. 登录(使用 API token)
login(token="your_hf_token")
# 2. 创建仓库
api = HfApi()
api.create_repo(
repo_id="my-awesome-model",
repo_type="model",
exist_ok=True
)
# 3. 上传模型
api.upload_folder(
folder_path="./text-classification-model",
repo_id="my-awesome-model",
repo_type="model"
)
print("Model uploaded successfully!")
使用 Trainer 直接上传 (Direct Upload with Trainer):
# 在 TrainingArguments 中设置 push_to_hub=True
training_args = TrainingArguments(
output_dir="./model",
push_to_hub=True, # 训练完成后自动上传
hub_model_id="my-username/my-awesome-model",
hub_strategy="every_save", # 每次保存都上传
# ... 其他参数
)
# 训练后自动上传
trainer.train()
trainer.push_to_hub() # 或手动推送
Chapter 4/2: Sharing Models and Datasets¶
第 4/2 章:共享模型和数据集¶
English:
Sharing your models and datasets on the Hub enables collaboration and reproducibility. It also allows others to build upon your work.
中文:
在 Hub 上共享你的模型和数据集可以促进协作和可重复性。它还允许他人在你的工作基础上构建。
创建模型卡片 (Creating a Model Card):
---
language:
- en
- zh
tags:
- text-classification
- sentiment-analysis
- distilbert
license: mit
datasets:
- imdb
metrics:
- accuracy
- f1
---
# Model Card for My Sentiment Analysis Model
## Model Description
This is a fine-tuned DistilBERT model for sentiment analysis on movie reviews.
## Training Data
- Dataset: IMDb Movie Reviews
- Size: 50,000 reviews
- Languages: English
## Training Procedure
- Base model: distilbert-base-uncased
- Epochs: 3
- Batch size: 16
- Learning rate: 2e-5
## Evaluation Results
| Metric | Value |
|--------|-------|
| Accuracy | 0.91 |
| F1 (macro) | 0.91 |
## How to Use
```python
from transformers import pipeline
classifier = pipeline("sentiment-analysis",
model="username/my-awesome-model")
result = classifier("I love this movie!")
Limitations¶
- Only trained on English movie reviews
- May not generalize well to other domains
**共享数据集 (Sharing Datasets)**: ```python from datasets import Dataset from huggingface_hub import HfApi # 1. 准备数据集 data = { "text": ["Great product!", "Terrible service."], "label": [1, 0] } dataset = Dataset.from_dict(data) # 2. 推送到 Hub dataset.push_to_hub("my-username/my-dataset") # 3. 其他人可以加载 from datasets import load_dataset loaded_dataset = load_dataset("my-username/my-dataset")
Chapter 4/3: Creating Model Cards¶
第 4/3 章:创建模型卡片¶
English:
Model cards provide documentation for machine learning models. They should include information about the model's intended use, training data, evaluation results, and limitations.
中文:
模型卡片为机器学习模型提供文档。它们应包括有关模型的预期用途、训练数据、评估结果和局限性的信息。
模型卡片必备要素 (Essential Model Card Elements):
| 部分 | 英文 | 中文 | 重要性 |
|---|---|---|---|
| Model Details | Model Details | 模型详情 | ⭐⭐⭐⭐⭐ |
| Intended Use | Intended Use | 预期用途 | ⭐⭐⭐⭐⭐ |
| Training Data | Training Data | 训练数据 | ⭐⭐⭐⭐⭐ |
| Evaluation | Evaluation | 评估结果 | ⭐⭐⭐⭐⭐ |
| Limitations | Limitations | 局限性 | ⭐⭐⭐⭐ |
| Ethical Considerations | Ethical Considerations | 伦理考虑 | ⭐⭐⭐⭐ |
| Citation | Citation | 引用 | ⭐⭐⭐ |
Module 5: Deployment and Production¶
模块 5: 部署和生产¶
Chapter 5/1: Model Optimization¶
第 5/1 章:模型优化¶
English:
Model optimization techniques reduce model size and improve inference speed, making deployment more efficient.
中文:
模型优化技术减少模型大小并提高推理速度,使部署更高效。
优化技术对比 (Optimization Techniques Comparison):
| 技术 | 英文 | 压缩比 | 速度提升 | 精度损失 |
|---|---|---|---|---|
| 量化 | Quantization | 4x | 2-3x | <1% |
| 剪枝 | Pruning | 2-3x | 1.5-2x | 1-3% |
| 知识蒸馏 | Knowledge Distillation | 5-10x | 3-5x | 2-5% |
| ONNX | ONNX | 1-2x | 2-3x | <1% |
动态量化 (Dynamic Quantization):
from transformers import AutoModelForSequenceClassification
import torch
# 加载模型
model = AutoModelForSequenceClassification.from_pretrained(
"distilbert-base-uncased"
)
# 动态量化
quantized_model = torch.quantization.quantize_dynamic(
model,
{torch.nn.Linear},
dtype=torch.qint8
)
# 保存量化模型
torch.save(quantized_model.state_dict(), "quantized_model.pt")
# 检查大小
import os
original_size = os.path.getsize("original_model.pt")
quantized_size = os.path.getsize("quantized_model.pt")
print(f"Original: {original_size / 1e6:.2f} MB")
print(f"Quantized: {quantized_size / 1e6:.2f} MB")
print(f"Compression: {original_size / quantized_size:.2f}x")
ONNX 导出 (ONNX Export):
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
# 加载模型
model_name = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)
model.eval()
# 创建示例输入
dummy_input = tokenizer(
"Example input for ONNX export",
return_tensors="pt",
padding="max_length",
max_length=128
)
# 导出为 ONNX
torch.onnx.export(
model,
(dummy_input["input_ids"], dummy_input["attention_mask"]),
"model.onnx",
opset_version=11,
input_names=["input_ids", "attention_mask"],
output_names=["logits"],
dynamic_axes={
"input_ids": {0: "batch_size", 1: "sequence_length"},
"attention_mask": {0: "batch_size", 1: "sequence_length"},
"logits": {0: "batch_size"}
}
)
print("Model exported to ONNX format!")
Chapter 5/2: Deployment with Inference APIs¶
第 5/2 章:使用推理 API 部署¶
English:
Hugging Face Inference API provides a simple way to deploy and serve models without managing infrastructure.
中文:
Hugging Face 推理 API 提供了一种简单的方法来部署和服务模型,而无需管理基础设施。
使用 Inference API (Using Inference API):
from huggingface_hub import InferenceClient
# 1. 创建客户端
client = InferenceClient(token="your_hf_token")
# 2. 文本分类
result = client.text_classification(
"I love using Hugging Face!",
model="distilbert-base-uncased-finetuned-sst-2-english"
)
print(result)
# 3. 问答
result = client.question_answering(
question="What is NLP?",
context="NLP stands for Natural Language Processing.",
model="deepset/roberta-base-squad2"
)
print(result)
# 4. 文本生成
result = client.text_generation(
"Once upon a time",
model="gpt2",
max_new_tokens=50
)
print(result)
部署自定义模型 (Deploying Custom Models):
# 在模型仓库中添加 inference-api 配置
# config.json 中添加:
{
"architectures": ["AutoModelForSequenceClassification"],
"custom_headers": {},
"custom_parameters": {}
}
Chapter 5/3: Production Best Practices¶
第 5/3 章:生产最佳实践¶
English:
Deploying models to production requires careful consideration of performance, monitoring, and maintenance.
中文:
将模型部署到生产环境需要仔细考虑性能、监控和维护。
生产部署检查清单 (Production Deployment Checklist):
| 方面 | 检查项 | 重要性 |
|---|---|---|
| 性能 | 延迟 < 100ms | ⭐⭐⭐⭐⭐ |
| 性能 | 吞吐量 > 100 QPS | ⭐⭐⭐⭐ |
| 性能 | 模型量化/优化 | ⭐⭐⭐⭐ |
| 监控 | 日志记录 | ⭐⭐⭐⭐⭐ |
| 监控 | 指标收集 | ⭐⭐⭐⭐⭐ |
| 监控 | 异常检测 | ⭐⭐⭐⭐ |
| 安全 | 访问控制 | ⭐⭐⭐⭐⭐ |
| 安全 | 输入验证 | ⭐⭐⭐⭐⭐ |
| 维护 | 版本控制 | ⭐⭐⭐⭐⭐ |
| 维护 | A/B 测试能力 | ⭐⭐⭐⭐ |
| 维护 | 回滚机制 | ⭐⭐⭐⭐⭐ |
监控示例 (Monitoring Example):
import time
import logging
from prometheus_client import Counter, Histogram, start_http_server
# 定义指标
REQUEST_COUNT = Counter('model_requests_total', 'Total requests')
REQUEST_LATENCY = Histogram('model_request_latency_seconds', 'Request latency')
ERROR_COUNT = Counter('model_errors_total', 'Total errors')
# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class MonitoredPipeline:
def __init__(self, pipeline):
self.pipeline = pipeline
def __call__(self, input_data):
start_time = time.time()
REQUEST_COUNT.inc()
try:
result = self.pipeline(input_data)
latency = time.time() - start_time
REQUEST_LATENCY.observe(latency)
logger.info(f"Request processed in {latency:.3f}s")
return result
except Exception as e:
ERROR_COUNT.inc()
logger.error(f"Error processing request: {e}")
raise
# 启动监控服务器
start_http_server(8000)
print("Monitoring server started on port 8000")
🛠️ 实践练习 (Hands-on Exercises)¶
练习 1: 完整微调流程 (Exercise 1: Complete Fine-tuning Pipeline)¶
# TODO: 完成以下任务
# 1. 选择一个 Hugging Face 数据集
# 2. 选择一个预训练模型
# 3. 微调模型完成特定任务
# 4. 评估模型性能
# 5. 将模型上传到 Hub
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import TrainingArguments, Trainer
# 你的代码在这里
练习 2: 模型优化 (Exercise 2: Model Optimization)¶
# TODO: 对微调后的模型进行优化
# 1. 应用动态量化
# 2. 导出为 ONNX 格式
# 3. 比较优化前后的大小和推理速度
import torch
import time
# 你的代码在这里
练习 3: 创建模型卡片 (Exercise 3: Create a Model Card)¶
# TODO: 为你的模型创建完整的模型卡片
# 包括:模型描述、训练数据、评估结果、局限性、使用示例
---
language:
- <your-languages>
tags:
- <your-tags>
license: <your-license>
---
# Model Card for <Your Model Name>
...
翻译完成时间: 2026-06-01
原课程模块: Module 3-5
前续: 第 1 模块, 第 2 模块
后续: 高级主题 (待创建)