1.1 什么是 HuggingFace
| 概念名称 | 说明 | 注意事项 |
|---|
| HuggingFace | 一家开源人工智能公司,致力于推动自然语言处理(NLP)和机器学习的民主化。提供 Transformers、Datasets、Tokenizers、Accelerate、Optimum、Hub 等一系列开源库和平台。 | HuggingFace 不是一个单一工具,而是一个生态系统,涵盖模型、数据、训练、部署全流程。 |
| Transformers 库 | HuggingFace 开发的核心 Python 库,提供数千种预训练模型(如 BERT、GPT、T5 等)的接口,支持 PyTorch、TensorFlow 和 JAX。 | 主要用于自然语言处理任务,但也逐步支持多模态任务(如视觉、语音)。 |
| Model Hub | HuggingFace 提供的在线平台(huggingface.co/models),用户可上传、分享、下载预训练模型。支持版本控制、模型卡片、评估指标展示。 | 所有公开模型均可通过 from_pretrained() 直接加载,极大简化模型复用流程。 |
| 社区与开源文化 | HuggingFace 拥有活跃的开源社区,鼓励用户贡献模型、数据集和代码。GitHub 上项目星标数超 10 万,文档完善,教程丰富。 | 建议积极参与社区(如论坛、Discord、GitHub Issues)以获取最新支持与最佳实践。 |
| 功能名称 | 说明 | 注意事项 |
|---|
| 预训练模型加载 | 支持从 Model Hub 或本地加载数千种预训练模型,兼容 PyTorch、TensorFlow。 | 使用 AutoModel 和 AutoTokenizer 可自动匹配模型类型,提高代码通用性。 |
| 多框架支持 | 同一模型可在 PyTorch(torch)、TensorFlow(tf)和 JAX(flax)间切换。 | 需安装对应后端库(如 torch 或 tensorflow),否则加载会失败。 |
| Pipeline API | 高层接口,封装常见 NLP 任务(如分类、问答、生成),无需手动编写推理逻辑。 | 适合快速原型开发,生产环境可进一步优化性能。 |
| Tokenizer 集成 | 提供与模型匹配的分词器,支持子词(subword)编码、批处理、截断、填充等。 | 分词器必须与模型对应,否则可能导致输入错误或性能下降。 |
| 自动配置管理 | AutoConfig 可自动加载模型配置(如隐藏层大小、注意力头数等)。 | 配置决定模型结构,修改需谨慎,避免与预训练权重不匹配。 |
| 可扩展性与自定义模型 | 支持用户继承基类定义自定义模型结构,并与库无缝集成。 | 需遵循库的模块命名和接口规范,确保兼容性。 |
1.3 模型中心(Model Hub)概览
| 概念名称 | 说明 | 注意事项 |
|---|
| Model Hub | HuggingFace 的在线模型仓库,包含超过 50 万个预训练模型。 | 可通过网页搜索、筛选(任务、语言、框架等)快速找到所需模型。 |
| 模型卡片(Model Card) | 每个模型附带的说明文档,包含训练方法、用途、限制、伦理考虑等信息。 | 使用模型前务必阅读模型卡片,了解其适用场景与潜在偏见。 |
| 模型版本控制 | 支持 Git 式版本管理,可回退到历史版本或比较不同版本差异。 | 推荐在生产环境中固定模型版本,避免因更新导致行为变化。 |
| 社区贡献模型 | 用户可上传自己的微调模型,供他人使用。 | 上传时建议提供清晰的 README 和示例代码,提升可用性。 |
| 评估指标集成 | 部分模型在 Hub 上展示在标准数据集上的评估结果(如 GLUE、SQuAD)。 | 评估结果仅供参考,实际性能取决于具体任务和数据分布。 |
1.4 开源与社区生态
| 概念名称 | 说明 | 注意事项 |
|---|
| 开源许可证 | Transformers 库采用 Apache 2.0 许可证,允许商业使用、修改和分发。 | 使用时无需付费,但建议在项目中注明依赖库来源。 |
| GitHub 仓库 | 主仓库地址:https://github.com/huggingface/transformers | 问题反馈、功能请求、代码贡献均通过 GitHub 进行。 |
| 文档与教程 | 官方文档详尽,包含 API 参考、快速入门、进阶教程、示例脚本等。 | 推荐优先查阅官方文档(https://huggingface.co/docs/transformers)。 |
| Discord 与论坛 | 提供实时交流平台,开发者可提问、分享经验。 | 社区响应迅速,但提问前建议先搜索已有讨论。 |
| 合作项目 | 与学术界(如 AllenNLP)、工业界(如 AWS、Google、NVIDIA)广泛合作。 | 支持主流云平台和硬件加速器,便于部署。 |
第二章:安装与环境配置
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
| pip 安装(稳定版) | pip install transformers | 安装最新稳定版本 | pip install transformers | 适用于大多数用户,版本经过测试,稳定性高。 |
| pip 安装(指定版本) | pip install transformers==4.35.0 | 安装特定版本以保证兼容性 | pip install transformers==4.30.0 | 在团队协作或生产环境中推荐固定版本。 |
| pip 安装(开发版) | pip install git+https://github.com/huggingface/transformers | 安装 GitHub 主分支最新代码 | pip install git+https://github.com/huggingface/transformers | 包含最新功能,但可能存在未修复的 bug,不推荐用于生产环境。 |
| conda 安装 | conda install -c conda-forge transformers | 使用 conda 包管理器安装 | conda install -c conda-forge transformers | 适合使用 Anaconda 或 Miniconda 的用户,依赖管理更统一。 |
2.2 依赖库
| 依赖库 | 语法(安装命令) | 用途 | 代码示例(导入) | 注意事项 |
|---|
| tokenizers | pip install tokenizers | 高性能分词库,由 Rust 实现,支持 BPE、WordPiece 等算法。 | from tokenizers import Tokenizer | Transformers 库默认使用此库进行分词,建议单独安装以获得最佳性能。 |
| torch(PyTorch) | pip install torch | PyTorch 深度学习框架,支持 GPU 加速。 | import torch | 若使用 PyTorch 模型,必须安装。推荐使用 torch==2.0.0 或更高版本。 |
| tensorflow | pip install tensorflow | TensorFlow 深度学习框架,支持 Keras。 | import tensorflow as tf | 若使用 TensorFlow 模型,必须安装。推荐使用 tensorflow==2.12 或更高版本。 |
| jax | pip install jax jaxlib | Google 开发的 Autograd 和 XLA 数值计算库。 | import jax | 用于 Flax 框架模型,适用于高性能计算场景。 |
| datasets | pip install datasets | 加载和处理大规模数据集的库。 | from datasets import load_dataset | 与 Transformers 深度集成,推荐用于模型微调任务。 |
2.3 验证安装与版本检查
| 操作名称 | 操作细节 | 注意事项 |
|---|
| 检查 transformers 版本 | 运行 import transformers; print(transformers.__version__) | 确保版本符合项目要求,避免因版本不兼容导致错误。 |
| 检查 PyTorch 安装 | 运行 import torch; print(torch.__version__); print(torch.cuda.is_available()) | 若使用 GPU,cuda.is_available() 应返回 True。 |
| 检查 TensorFlow 安装 | 运行 import tensorflow as tf; print(tf.__version__); print(tf.config.list_physical_devices('GPU')) | 确认 TensorFlow 能识别 GPU 设备。 |
| 导入测试 | 运行 from transformers import pipeline | 若无报错,说明库安装成功且依赖完整。 |
| 查看库信息 | 运行 transformers.utils.version.get_versions() | 输出详细版本信息,包括 transformers、torch、tensorflow 等。 |
第三章:快速上手:Pipeline API
3.1 Pipeline 概述
| 概念名称 | 说明 | 注意事项 |
|---|
| Pipeline | Transformers 提供的高层 API,封装了模型加载、分词、推理、后处理全流程。 | 适合快速原型开发和简单任务,屏蔽底层复杂性。 |
| 任务自动化 | 根据任务类型自动选择默认模型和分词器。 | 例如 pipeline("text-classification") 默认使用 distilbert-base-uncased-finetuned-sst-2-english。 |
| 支持的任务类型 | 包括文本分类、NER、问答、文本生成、翻译、摘要、掩码填充等。 | 完整列表见 transformers.pipelines.SUPPORTED_TASKS。 |
| 返回格式统一 | 输出为字典或字典列表,包含标签、分数、答案文本等结构化信息。 | 便于后续处理和展示。 |
3.2 常见任务类型与默认模型
| 任务类型(task) | 默认模型名称 | 用途示例 | 注意事项 |
|---|
text-classification | distilbert-base-uncased-finetuned-sst-2-english | 情感分析、垃圾邮件检测 | 输出情感标签(如”POSITIVE”/“NEGATIVE”)及置信度。 |
token-classification | dslim/bert-base-NER | 命名实体识别(人名、地名、组织等) | 使用 BIO 标注体系,输出实体及其位置。 |
question-answering | distilbert-base-cased-distilled-squad | 从文本中抽取答案 | 需提供问题和上下文,返回答案文本和起始位置。 |
fill-mask | bert-base-uncased | 掩码语言建模(完形填空) | 将 [MASK] 替换为最可能的词,可用于语言理解测试。 |
summarization | sshleifer/distilbart-cnn-12-6 | 文本摘要生成 | 输入长文本,输出简洁摘要。 |
translation_xx_to_yy | 如 Helsinki-NLP/opus-mt-en-zh(en→zh) | 机器翻译 | 需指定源语言和目标语言,如 translation_en_to_fr。 |
text-generation | gpt2 | 自回归文本生成 | 可生成故事、代码、对话等,支持控制生成长度和多样性。 |
zero-shot-classification | facebook/bart-large-mnli | 零样本分类(无需训练) | 提供候选标签,模型判断输入属于哪一类。 |
3.3 基本使用流程
| 步骤名称 | 操作细节 | 注意事项 |
|---|
| 导入 pipeline | from transformers import pipeline | 所有任务均通过此接口调用。 |
| 创建 pipeline 实例 | classifier = pipeline(task="text-classification") | 第一次运行会自动下载模型和分词器,耗时较长。 |
| 执行推理 | result = classifier("I love using HuggingFace!") | 输入可为字符串或字符串列表,支持批量处理。 |
| 查看输出结果 | print(result) → [{'label': 'POSITIVE', 'score': 0.9998}] | 输出为列表,每个元素对应一个输入样本。 |
| 指定自定义模型 | classifier = pipeline(task="text-classification", model="my_model") | 可替换默认模型为本地或 Hub 上的其他模型。 |
| 控制推理参数 | classifier("...", top_k=3) | 不同任务支持不同参数,如 top_k(返回前 k 个结果)、max_length 等。 |
第四章:Tokenizer(分词器)
4.1 分词的基本原理
| 概念名称 | 说明 | 注意事项 |
|---|
| 分词(Tokenization) | 将原始文本拆分为模型可处理的基本单元(token),如单词、子词或字符。 | 模型无法直接处理字符串,必须转换为数字 ID。 |
| 子词分词(Subword Tokenization) | 将词拆分为更小的子单元(如 “unfriendly” → “un”, “friend”, “ly”),平衡词汇表大小与未登录词处理。 | 常见算法:BPE(Byte-Pair Encoding)、WordPiece、Unigram。 |
| 词汇表(Vocabulary) | 分词器所支持的所有 token 的集合,每个 token 对应一个唯一 ID。 | 词汇表大小影响模型容量和内存占用,典型值为 30,000–100,000。 |
| 编码(Encoding) | 将文本转换为模型输入所需的数字 ID 序列(input_ids)、注意力掩码(attention_mask)等。 | 编码过程包括分词、映射到 ID、添加特殊标记、填充或截断。 |
| 解码(Decoding) | 将模型输出的 ID 序列转换回可读文本。 | 可选择是否移除特殊标记或保留控制符号。 |
4.2 AutoTokenizer 与具体 Tokenizer 类
| 方法 / 类名 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
AutoTokenizer.from_pretrained | AutoTokenizer.from_pretrained(pretrained_model_name_or_path) | 自动根据模型名称加载匹配的分词器 | tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") | 推荐使用,无需手动指定具体类名,提高代码通用性。 |
BertTokenizer | BertTokenizer.from_pretrained(...) | 专用于 BERT 及其变体的 WordPiece 分词器 | from transformers import BertTokenizer; tokenizer = BertTokenizer.from_pretrained("bert-base-uncased") | 仅在需要显式控制时使用,一般优先用 AutoTokenizer。 |
GPT2Tokenizer | GPT2Tokenizer.from_pretrained(...) | 用于 GPT 系列模型的 BPE 分词器 | from transformers import GPT2Tokenizer; tokenizer = GPT2Tokenizer.from_pretrained("gpt2") | GPT 类模型使用字节级 BPE(Byte-level BPE)。 |
T5Tokenizer | T5Tokenizer.from_pretrained(...) | 用于 T5 模型的 SentencePiece 分词器 | from transformers import T5Tokenizer; tokenizer = T5Tokenizer.from_pretrained("t5-small") | T5 使用基于 Unigram 的 SentencePiece。 |
save_pretrained | tokenizer.save_pretrained(save_directory) | 保存分词器配置和词汇表到本地 | tokenizer.save_pretrained("./my_tokenizer") | 与 from_pretrained 配合使用,便于模型共享和离线加载。 |
4.3 编码与解码方法
| 方法名称 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
call / encode | tokenizer(text, ...) 或 tokenizer.encode(text) | 编码单个或批量文本,返回字典格式输出 | encoded = tokenizer("Hello, world!", return_tensors="pt") | 推荐使用 __call__,支持更多参数(如 padding、truncation)。 |
encode | tokenizer.encode(text) | 仅返回 input_ids 列表 | input_ids = tokenizer.encode("Hello") → [101, 7592, 102] | 不包含 attention_mask 等辅助张量,适用于简单场景。 |
batch_encode_plus | tokenizer.batch_encode_plus(batch_text, ...) | 批量编码,支持不同长度序列的填充和截断 | encoded = tokenizer.batch_encode_plus(["Hi", "Hello"], padding=True) | 已被 __call__ 取代,建议使用新接口。 |
decode | tokenizer.decode(token_ids, ...) | 将 ID 序列解码为原始文本 | text = tokenizer.decode([101, 7592, 102]) → "Hello World" | 可设置 skip_special_tokens=True 忽略 [CLS]、[SEP] 等标记。 |
convert_ids_to_tokens | tokenizer.convert_ids_to_tokens(ids) | 将 ID 转换为对应的 token 字符串 | tokens = tokenizer.convert_ids_to_tokens([7592]) → ["hello"] | 用于调试和可视化分词结果。 |
convert_tokens_to_ids | tokenizer.convert_tokens_to_ids(tokens) | 将 token 字符串转换为对应 ID | ids = tokenizer.convert_tokens_to_ids(["hello"]) → [7592] | 支持单个 token 或 token 列表。 |
4.4 特殊标记(Special Tokens)管理
| 特殊标记 | 说明 | 获取方法 | 注意事项 |
|---|
[CLS] | 分类标记,通常用于句子级别任务的聚合表示 | tokenizer.cls_token、tokenizer.cls_token_id | BERT 类模型使用,位于序列开头。 |
[SEP] | 分隔标记,用于分隔两个句子(如问答任务中的问题与上下文) | tokenizer.sep_token、tokenizer.sep_token_id | 在句子对任务中必需。 |
[PAD] | 填充标记,用于将序列补齐到相同长度 | tokenizer.pad_token、tokenizer.pad_token_id | 批处理时必需,注意 attention_mask 应忽略 PAD 位置。 |
[MASK] | 掩码标记,用于 MLM 任务中被遮蔽的词 | tokenizer.mask_token、tokenizer.mask_token_id | 仅在训练或 fill-mask 任务中使用。 |
[UNK] | 未知标记,表示词汇表中不存在的 token | tokenizer.unk_token、tokenizer.unk_token_id | 出现在分词失败时,应尽量减少其出现频率。 |
| 添加自定义标记 | 手动添加新标记到词汇表 | tokenizer.add_special_tokens({'bos_token': '<BOS>'}) | 添加后需调整模型嵌入层维度(model.resize_token_embeddings())。 |
第五章:Model(模型)
5.1 AutoModel 与模型架构类
| 类名 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
AutoModel.from_pretrained | AutoModel.from_pretrained(pretrained_model_name_or_path) | 自动加载匹配的模型架构和权重 | model = AutoModel.from_pretrained("bert-base-uncased") | 推荐使用,无需关心具体模型类。 |
AutoModelForSequenceClassification | AutoModelForSequenceClassification.from_pretrained(...) | 加载用于文本分类的模型(带分类头) | model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=2) | 自动添加分类层,支持自定义标签数量。 |
AutoModelForTokenClassification | AutoModelForTokenClassification.from_pretrained(...) | 加载用于 NER 等序列标注任务的模型 | model = AutoModelForTokenClassification.from_pretrained("bert-base-NER", num_labels=9) | 输出每个 token 的类别概率。 |
AutoModelForQuestionAnswering | AutoModelForQuestionAnswering.from_pretrained(...) | 加载用于问答任务的模型 | model = AutoModelForQuestionAnswering.from_pretrained("bert-large-uncased-whole-word-masking-finetuned-squad") | 输出起始和结束位置的概率分布。 |
AutoModelForCausalLM | AutoModelForCausalLM.from_pretrained(...) | 加载用于自回归生成的模型(如 GPT) | model = AutoModelForCausalLM.from_pretrained("gpt2") | 用于文本生成任务。 |
AutoModelForMaskedLM | AutoModelForMaskedLM.from_pretrained(...) | 加载用于掩码语言建模的模型 | model = AutoModelForMaskedLM.from_pretrained("bert-base-uncased") | 用于 fill-mask 任务或 MLM 微调。 |
save_pretrained | model.save_pretrained(save_directory) | 保存模型权重和配置 | model.save_pretrained("./my_model") | 与 from_pretrained 配合使用,支持本地加载。 |
5.2 前向传播输出结构
| 输出字段 | 说明 | 获取方式 | 注意事项 |
|---|
last_hidden_state | 最后一层的隐藏状态,形状为 (batch_size, sequence_length, hidden_size) | outputs.last_hidden_state | 用于 token 级任务(如 NER)。 |
pooler_output | 池化输出(通常为 [CLS] 的表示),用于句子级任务 | outputs.pooler_output | BERT 类模型特有,可用于分类任务。 |
hidden_states | 所有层的隐藏状态(若 output_hidden_states=True) | outputs.hidden_states | 元组形式,索引 0 为嵌入层,1~n 为各层输出。 |
attentions | 注意力权重(若 output_attentions=True) | outputs.attentions | 用于可视化注意力机制,调试模型行为。 |
logits | 未归一化的预测分数(分类、生成等任务) | outputs.logits | 通常接 softmax 或 argmax 得到最终预测。 |
loss | 计算的损失值(训练时提供标签) | outputs.loss | 仅当输入包含 labels 时返回。 |
5.3 预训练模型加载方式
| 方法 / 参数 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
from_pretrained | AutoModel.from_pretrained("model_name") | 从 HuggingFace Hub 加载模型 | model = AutoModel.from_pretrained("bert-base-uncased") | 首次加载会下载缓存,后续从本地读取。 |
local_files_only | from_pretrained(..., local_files_only=True) | 仅从本地加载,不访问网络 | model = AutoModel.from_pretrained("./local_model", local_files_only=True) | 确保本地路径存在且完整。 |
cache_dir | from_pretrained(..., cache_dir="/path") | 指定模型缓存目录 | model = AutoModel.from_pretrained("bert-base-uncased", cache_dir="./cache") | 避免默认缓存路径空间不足。 |
revision | from_pretrained(..., revision="v2.0") | 加载特定版本的模型 | model = AutoModel.from_pretrained("bert-base-uncased", revision="main") | 适用于 Hub 上有多个版本的模型。 |
force_download | from_pretrained(..., force_download=True) | 强制重新下载模型 | model = AutoModel.from_pretrained("bert-base-uncased", force_download=True) | 用于更新损坏的缓存。 |
resume_download | from_pretrained(..., resume_download=True) | 恢复中断的下载 | model = AutoModel.from_pretrained("bert-base-uncased", resume_download=True) | 网络不稳定时有用。 |
5.4 模型配置(Config)管理
| 方法 / 属性 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
AutoConfig.from_pretrained | AutoConfig.from_pretrained("model_name") | 加载模型配置文件 | config = AutoConfig.from_pretrained("bert-base-uncased") | 包含 hidden_size、num_attention_heads 等超参数。 |
config.hidden_size | config.hidden_size | 获取隐藏层维度 | print(config.hidden_size) → 768 | 用于构建下游任务模块。 |
config.num_labels | config.num_labels = 3 | 设置分类任务的标签数量 | config = AutoConfig.from_pretrained("bert-base-uncased", num_labels=3) | 必须在加载模型前设置,否则分类头维度错误。 |
config.output_attentions | config.output_attentions = True | 启用注意力权重输出 | config = AutoConfig.from_pretrained("bert-base-uncased", output_attentions=True) | 增加内存消耗,仅在需要时开启。 |
config.save_pretrained | config.save_pretrained(save_directory) | 保存配置到本地 | config.save_pretrained("./my_config") | 与模型和分词器一起保存,确保完整性。 |
config.from_dict | BertConfig.from_dict(dict) | 从字典创建配置 | config = BertConfig.from_dict({"hidden_size": 512, "num_hidden_layers": 6}) | 用于完全自定义模型结构。 |
config.to_dict | config.to_dict() | 将配置转换为字典 | config_dict = config.to_dict() | 便于序列化或日志记录。 |
6.1 图像、语音等多模态处理组件
| 组件名称 | 说明 | 适用模型示例 | 注意事项 |
|---|
AutoFeatureExtractor | 自动加载图像或语音特征提取器,用于预处理原始信号 | ViT、Wav2Vec2、CLIP | 与 AutoProcessor 配合使用更方便。 |
AutoImageProcessor | 专用于图像处理的自动加载器(新版本推荐) | ViT、DETR、CLIP | 支持归一化、调整大小、中心裁剪等操作。 |
AutoProcessor | 多模态统一处理器,自动组合 tokenizer 和 feature extractor | LayoutLM、SpeechT5、OWL-ViT | 简化多模态输入处理流程。 |
Wav2Vec2FeatureExtractor | 用于 Wav2Vec2 模型的语音特征提取 | facebook/wav2vec2-base-960h | 处理 raw audio waveform,提取特征向量。 |
ViTImageProcessor | 用于 Vision Transformer 的图像预处理 | google/vit-base-patch16-224 | 将图像转换为模型输入的像素值张量。 |
6.2 Processor 的统一接口
| 方法 / 类名 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
AutoProcessor.from_pretrained | AutoProcessor.from_pretrained("model_name") | 自动加载多模态处理器 | processor = AutoProcessor.from_pretrained("microsoft/layoutlmv3-base") | 根据模型自动组合 tokenizer 和 image processor。 |
call | processor(text=text, images=image, ...) | 统一处理文本和图像输入 | inputs = processor(text="Hello", images=img, return_tensors="pt") | 支持混合输入,返回统一格式的张量。 |
apply_ocr | processor(image, apply_ocr=True) | 对图像自动执行 OCR 提取文本 | inputs = processor(images=img, apply_ocr=True) | 适用于文档理解模型(如 LayoutLM)。 |
decode_ocr | processor.decode_ocr(result) | 解码 OCR 识别结果 | text = processor.decode_ocr(inputs) | 获取图像中的文本内容。 |
6.3 特征提取器使用场景
| 使用场景 | 操作细节 | 注意事项 |
|---|
| 图像分类 | 使用 ViTImageProcessor 将图像调整为固定大小并归一化 | 输入需为 PIL.Image 或 numpy 数组。 |
| 语音识别 | 使用 Wav2Vec2FeatureExtractor 处理音频波形,提取特征向量 | 音频需为 16kHz 采样率的单声道。 |
| 视觉-语言任务(如 VQA) | 使用 AutoProcessor 同时处理问题文本和图像输入 | 确保模型支持多模态输入(如 CLIP、BLIP)。 |
| 文档理解 | 使用 LayoutLMv3Processor 处理带有布局信息的文档图像 | 可结合 bounding box 和 OCR 结果进行结构化信息提取。 |
| 零样本图像分类 | 使用 CLIPProcessor 编码图像和候选标签文本,计算相似度 | 实现跨模态检索和分类。 |
第七章:文本分类
7.1 使用 pipeline 进行分类
| 方法 / 参数 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
pipeline | pipeline(task, model) | 快速构建指定任务的推理管道 | classifier = pipeline("text-classification", model="bert-base-uncased") | 支持自动加载模型和分词器,适合快速原型开发。 |
| 推理调用 | classifier(text) | 对单个或批量文本进行分类 | result = classifier("I love this movie!") → [{'label': 'POSITIVE', 'score': 0.99}] | 输入可为字符串或字符串列表。 |
| 多标签分类 | pipeline("zero-shot-classification") | 零样本分类,无需训练 | classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli") | 提供候选标签,模型计算文本与每个标签的匹配度。 |
| 返回字段 | result['label']、result['score'] | 获取预测标签和置信度 | print(result[0]['label']) | score 范围为 0~1,表示模型置信度。 |
7.2 自定义模型微调流程
| 步骤 | 操作细节 | 工具 / 方法 | 注意事项 |
|---|
| 1. 数据加载 | 读取数据集(CSV、JSON、Dataset) | datasets.load_dataset、pandas.read_csv | 确保文本和标签字段清晰。 |
| 2. 标签映射 | 将文本标签转换为数字 ID | label2id = {"negative": 0, "positive": 1}、id2label | 构建 label2id 和 id2label 字典供模型使用。 |
| 3. 分词与编码 | 使用 tokenizer 编码文本 | tokenizer(text, padding=True, truncation=True, return_tensors="pt") | 设置 max_length 防止 OOM。 |
| 4. 模型定义 | 加载预训练模型并添加分类头 | AutoModelForSequenceClassification.from_pretrained(..., num_labels=2) | 根据任务类别数设置 num_labels。 |
| 5. 训练配置 | 定义训练参数(学习率、epoch、batch size) | TrainingArguments | 使用 Trainer 简化训练流程。 |
| 6. 训练执行 | 使用 Trainer 进行训练 | trainer = Trainer(model, args, train_dataset, eval_dataset, tokenizer) | 支持自动评估、保存、日志记录。 |
| 7. 模型评估 | 在验证集上计算准确率、F1 等指标 | compute_metrics 函数 | 自定义评估函数以适配任务需求。 |
| 8. 模型保存 | 保存微调后的模型 | model.save_pretrained("./finetuned_model") | 同时保存 tokenizer 和 config。 |
7.3 数据预处理与标签映射
| 操作 | 方法 | 示例 | 注意事项 |
|---|
| 文本清洗 | 去除特殊字符、HTML 标签、标准化大小写 | text = re.sub(r'<[^>]+>', '', text).lower() | 提高模型泛化能力。 |
| 标签编码 | 使用 LabelEncoder 或手动映射 | labels = [label2id[l] for l in raw_labels] | 确保训练和推理时标签一致。 |
| 数据集划分 | 划分训练集、验证集 | train_test_split from sklearn | 验证集用于监控过拟合。 |
| 使用 Dataset 映射 | 使用 datasets.Dataset 的 map() 函数 | dataset = dataset.map(lambda x: tokenizer(x['text'], ...), batched=True) | 批量处理提升效率。 |
第八章:命名实体识别(NER)
8.1 输出解码与标签对齐
| 问题 | 解决方案 | 示例 | 注意事项 |
|---|
| 子词拆分导致标签错位 | 将标签对齐到原始 token,通常只保留第一个子词的标签,其余设为”O” | "unfriendly" → ["un", "##friend", "##ly"],标签 [B-PER] → [B-PER, O, O] | 防止重复实体识别。 |
使用 is_split_into_words | tokenizer 传参 is_split_into_words=True 并配合 word_ids() 方法 | word_ids = encoded.word_ids(batch_index) | 精确追踪每个 token 对应的原始词位置。 |
| 解码预测结果 | 将模型输出的 token 级标签映射回原始文本 | 遍历 word_ids,合并相同词的预测标签 | 结合 BIO 规则进行后处理。 |
8.2 BIO 标注体系处理
| 标签类型 | 含义 | 示例 | 说明 |
|---|
B-XXX | 实体开始(Begin) | B-PER | 标记一个实体的起始 token。 |
I-XXX | 实体内部(Inside) | I-PER | 标记实体的后续 token。 |
O | 非实体(Outside) | O | 不属于任何命名实体。 |
B-LOC | 地点实体开始 | B-LOC | 如 “New York” → [B-LOC, I-LOC] |
B-ORG | 组织实体开始 | B-ORG | 如 “Google” → [B-ORG] |
| 合法性校验 | 检查标签序列是否符合规则 | I-PER 前必须是 B-PER 或 I-PER | 避免出现 I-PER 开头的非法序列。 |
8.3 序列标注评估指标
| 指标 | 计算方式 | 库支持 | 注意事项 |
|---|
| 准确率(Accuracy) | 正确预测的 token 数 / 总 token 数 | sklearn.metrics.accuracy_score | 忽略”O”类时可能高估性能。 |
| 精确率(Precision) | TP / (TP + FP) | seqeval 库 | 按实体级别计算更合理。 |
| 召回率(Recall) | TP / (TP + FN) | from seqeval.metrics import classification_report | 推荐使用 seqeval,支持 BIO 标注的实体级评估。 |
| F1 分数 | 2 * (Precision * Recall) / (Precision + Recall) | seqeval.metrics.f1_score | 综合衡量模型性能,是 NER 主要指标。 |
| 实体级评估 | 将连续的 B/I 标签视为一个实体,完全匹配才算正确 | classification_report(y_true, y_pred) | 比 token 级评估更严格。 |
第九章:问答系统(Question Answering)
| 概念 | 说明 | 示例 | 注意事项 |
|---|
| 抽取式问答 | 从给定上下文中直接抽取一段连续文本作为答案 | 问题:“谁写了《红楼梦》?” 上下文:“曹雪芹创作了《红楼梦》。” → 答案:“曹雪芹” | 不生成新文本,仅定位答案片段。 |
| 模型输出 | 模型预测答案在上下文中的起始(start)和结束(end)位置 | start_logits、end_logits | 通过 argmax 找到最可能的位置。 |
| 输入格式 | 将问题和上下文拼接,中间用 [SEP] 分隔 | "[CLS] question [SEP] context [SEP]" | 确保模型理解任务结构。 |
9.2 处理长文本的分段策略
| 策略 | 方法 | 优点 | 缺点 |
|---|
| 滑动窗口 | 将长文本切分为多个固定长度的窗口,重叠部分防止答案被截断 | 保证答案不被遗漏 | 增加计算量,需合并多个窗口的预测结果。 |
| 最大长度截断 | 直接截取前 max_length 个 token | 简单高效 | 可能丢失关键信息,尤其当答案在末尾时。 |
| 段落级过滤 | 先用简单模型或关键词筛选相关段落,再在候选段落中进行 QA | 减少计算量 | 可能误删包含答案的段落。 |
| 层次化处理 | 先定位答案所在段落,再在段落内精确定位 | 平衡效率与准确性 | 需要两个模型或两阶段推理。 |
9.3 答案提取与偏移映射
| 步骤 | 操作 | 工具 / 方法 | 注意事项 |
|---|
| 获取预测位置 | start_index = torch.argmax(start_logits)、end_index = torch.argmax(end_logits) | 确保 start_index <= end_index 且在有效范围内 | 可设置最大答案长度限制。 |
| 解码答案文本 | 使用 tokenizer 的 decode() 方法提取对应 token | answer = tokenizer.decode(input_ids[start_index:end_index+1]) | 可能包含多余空格或子词标记。 |
| 原始文本偏移 | 使用 token.offset_mapping 获取每个 token 在原始文本中的字符位置 | offsets = encoded['offset_mapping'] | 用于精确提取答案字符串,避免 tokenizer 引入的噪声。 |
| 过滤无效答案 | 排除全为空格或特殊标记的答案 | if answer.strip() == "" or answer == "[CLS]": ... | 提高输出质量。 |
第十章:文本生成(Text Generation)
10.1 自回归生成机制
| 概念 | 说明 | 示例 | 注意事项 |
|---|
| 自回归(Autoregressive) | 模型逐个生成 token,每一步依赖之前已生成的序列 | 输入 [BOS] → 预测下一个 → 拼接 → 继续预测 | 生成过程串行,无法并行化。 |
| 起始标记 | 使用 <BOS> 或 <s> 作为生成起点 | input_ids = tokenizer.encode("<s>", return_tensors="pt") | 不同模型起始标记不同。 |
| 结束条件 | 遇到 <EOS> 标记或达到最大长度时停止 | max_length=50、eos_token_id=tokenizer.eos_token_id | 防止无限生成。 |
10.2 生成参数控制
| 参数 | 作用 | 推荐值 | 影响 |
|---|
temperature | 控制输出随机性,值越低越确定 | 0.71.0(创造性),0.10.5(确定性) | 高温 → 分布平滑,多样性高;低温 → 分布尖锐,倾向于高概率词。 |
top_k | 仅从概率最高的 k 个词中采样 | 10~50 | 限制候选集,减少低概率词出现。 |
top_p(nucleus) | 从累积概率超过 p 的最小词集中采样 | 0.9~0.95 | 动态调整候选集大小,比 top_k 更灵活。 |
do_sample | 是否启用采样(False 时为贪婪搜索) | True(采样),False(贪婪) | 贪婪搜索常生成重复文本。 |
num_beams | Beam Search 的束宽 | 1(禁用),4~8(平衡质量与速度) | 值越大生成质量越高,但更慢。 |
repetition_penalty | 对重复 token 施加惩罚 | 1.0(无惩罚),1.2~2.0(抑制重复) | 防止模型陷入循环。 |
10.3 Beam Search 与采样策略
| 策略 | 原理 | 优点 | 缺点 |
|---|
| 贪婪搜索(Greedy) | 每步选择概率最高的 token | 简单快速 | 易陷入局部最优,生成重复或平凡文本。 |
| Beam Search | 保留 top-k 条候选序列,最终选择总分最高的序列 | 生成质量高,广泛用于机器翻译 | 无法生成多样性文本,k 大时计算开销高。 |
| 随机采样(Sampling) | 按概率分布随机选择下一个 token | 生成多样性好 | 可能生成低质量或无意义文本。 |
| Top-k 采样 | 从概率最高的 k 个词中按比例采样 | 平衡质量与多样性 | k 过小可能遗漏合理候选。 |
| Top-p 采样 | 从累积概率达 p 的最小集合中采样 | 动态适应分布形状 | 实现稍复杂。 |
第十一章:掩码语言建模(Masked Language Modeling, MLM)
11.1 MLM 任务原理
| 概念 | 说明 | 示例 | 注意事项 |
|---|
| MLM 任务 | 随机遮蔽输入中的部分 token,模型预测被遮蔽的内容 | "The cat sat on the [MASK]." → 预测 "mat" | BERT 的预训练任务之一。 |
| 遮蔽策略 | 通常遮蔽 15% 的 token,其中 80% 替换为 [MASK],10% 替换为随机词,10% 保留原词 | 提高模型鲁棒性 | 防止模型只在 [MASK] 出现时才预测。 |
| 输出形式 | 模型输出每个 [MASK] 位置的 logits,用于计算预测概率 | logits = model(input_ids).logits | 通过 argmax 或 top-k 获取预测词。 |
11.2 使用 pipeline 填空
| 方法 | 语法 | 示例 | 注意事项 |
|---|
fill-mask pipeline | pipeline("fill-mask", model="bert-base-uncased") | unmasker = pipeline("fill-mask", model="bert-base-uncased") | 自动处理遮蔽 token 的预测。 |
| 推理调用 | unmasker("The capital of France is [MASK].") | → [{'token_str': 'Paris', 'score': 0.99}, ...] | 返回按概率排序的候选词列表。 |
多个 [MASK] | 支持多个遮蔽位置 | "The [MASK] eats the [MASK]." | 分别预测每个位置。 |
11.3 模型预测结果解析
| 操作 | 方法 | 示例 | 注意事项 |
|---|
| 获取预测 ID | pred_ids = torch.argmax(logits, dim=-1) | 针对 [MASK] 位置 | 仅对遮蔽位置有效。 |
| 解码为文本 | predicted_token = tokenizer.decode(pred_id) | → "Paris" | 可能包含子词,需注意拼接。 |
| 获取 top-k 结果 | probs = logits.softmax(dim=-1)、topk = torch.topk(probs, k=5) | 获取前 5 个最可能的词及其概率 | 用于分析模型置信度。 |
| 跨词预测 | 多个子词共同构成一个完整词 | [MASK] → "un"、"##belie"、"##vable" → "unbelievable" | 需合并子词以获得完整单词。 |
第十二章:句子相似度与嵌入表示
| 方法 | 说明 | 示例 | 注意事项 |
|---|
| Sentence-Transformers 库 | 专用于生成高质量句子嵌入的库,基于 Transformer 微调 | from sentence_transformers import SentenceTransformer | 比直接取 [CLS] 向量效果更好。 |
| 模型选择 | 使用专为语义相似度训练的模型 | "all-MiniLM-L6-v2"、"paraphrase-multilingual-MiniLM-L12-v2" | 多语言模型支持跨语言相似度计算。 |
12.2 获取句子向量
| 步骤 | 操作 | 代码示例 | 注意事项 |
|---|
| 加载模型 | 实例化 SentenceTransformer 模型 | model = SentenceTransformer('all-MiniLM-L6-v2') | 首次运行会自动下载。 |
| 编码句子 | 输入文本列表,输出向量矩阵 | embeddings = model.encode(["Hello world", "How are you?"]) | 输出形状 (n_sentences, embedding_dim),如 (2, 384)。 |
| 向量归一化 | 可选:将向量归一化以简化相似度计算 | embeddings = embeddings / np.linalg.norm(embeddings, axis=1, keepdims=True) | 归一化后余弦相似度 = 向量点积。 |
12.3 余弦相似度计算
| 方法 | 公式 / 代码 | 示例 | 注意事项 |
|---|
| 余弦相似度 | `cos_sim = (A · B) / ( | | A |
| 使用 sklearn | from sklearn.metrics.pairwise import cosine_similarity | sim = cosine_similarity([emb1], [emb2]) → [[0.85]] | 输入为二维数组。 |
| 手动计算 | np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) | sim = np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2)) | 注意数值稳定性。 |
| 批量计算 | 计算多个句子间的相似度矩阵 | cosine_similarity(embeddings) | 用于聚类、检索等任务。 |
第十三章:数据集准备:Dataset 与 Dataloader
13.1 使用 datasets 库加载公开数据集
| 操作 | 方法 / 函数 | 说明 | 示例 | 注意事项 |
|---|
| 加载数据集 | load_dataset(path, name=None, split='train') | 从 Hugging Face Hub 或本地加载数据集 | dataset = load_dataset("glue", "mrpc", split="train") | name 用于指定子集(如 SQuAD 的 "plain_text") |
| 查看数据结构 | dataset.features、dataset[0] | 检查字段类型与单条样本 | print(dataset.features) → {'sentence1': Value('string'), ...} | 支持索引和切片访问 |
| 数据集拆分 | load_dataset(..., split='train[:80%]') | 按比例或数量划分 | train_ds = load_dataset("imdb", split="train[:80%]") | 支持 'train+validation' 合并 |
| 推送至 Hub | dataset.push_to_hub("your-name/dataset-name") | 共享自定义数据集 | 需登录 huggingface-cli login | 适合团队协作 |
| 流式加载 | load_dataset(..., streaming=True) | 适用于超大数据集,避免内存溢出 | streamed_ds = load_dataset("wikipedia", "20200501.en", streaming=True) | 不支持随机访问,需迭代处理 |
13.2 数据预处理与 tokenize 映射
| 步骤 | 方法 | 说明 | 示例 | 注意事项 |
|---|
| 初始化 tokenizer | AutoTokenizer.from_pretrained("bert-base-uncased") | 加载对应模型的分词器 | tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese") | 确保与模型版本一致 |
| 单样本编码 | tokenizer(text, max_length=512, truncation=True, padding=False) | 编码单个文本 | encoded = tokenizer("Hello world", return_tensors="pt") | 默认不填充,适合批处理前 |
| 批量映射 | dataset.map(tokenize_function, batched=True) | 高效批量处理整个数据集 | def tokenize_function(examples): return tokenizer(examples["text"], truncation=True, padding=True) | batched=True 显著提升速度 |
| 多字段处理 | tokenizer(examples["q1"], examples["q2"], ..., padding="max_length") | 处理句对任务(如 NLI) | 用于 MNLI、QQP 等任务 | 注意 max_length 设置 |
| 返回类型控制 | return_special_tokens_mask=True | 返回特殊 token 掩码,用于 MLM | 在预训练时有用 | 通常用于自定义 MLM 任务 |
| 缓存处理结果 | map(..., load_from_cache_file=True) | 自动缓存,避免重复处理 | 第二次运行会跳过 | 可手动清除缓存 |
13.3 构建 PyTorch/TensorFlow DataLoader
| 框架 | 方法 | 说明 | 示例 | 注意事项 |
|---|
| PyTorch | DataLoader(dataset, batch_size=16, shuffle=True, collate_fn=collate_fn) | 使用 torch.utils.data.DataLoader | from torch.utils.data import DataLoader | collate_fn 用于动态填充 |
| | | loader = DataLoader(ds, batch_size=8, collate_fn=tokenizer.pad) | |
| TensorFlow | tf.data.Dataset.from_generator() 或 from_tensor_slices | 构建高效输入管道 | tf_ds = dataset.to_tf_dataset(columns=["input_ids", "attention_mask"], label_cols=["labels"], batch_size=8) | 推荐使用 to_tf_dataset 封装方法 |
| 动态填充 | DataCollatorWithPadding | 自动对 batch 内样本填充到相同长度 | from transformers import DataCollatorWithPadding | 减少填充冗余,提升效率 |
| | | collator = DataCollatorWithPadding(tokenizer) | |
| GPU 预加载 | DataLoader(..., num_workers=4, pin_memory=True) | 加速数据传输到 GPU | 适合大 batch 训练 | num_workers > 0 可能引发多进程问题(Windows) |
| TF 数据流水线 | tf_ds = tf_ds.map(...).batch(8).prefetch(tf.data.AUTOTUNE) | 构建高性能流水线 | prefetch 重叠数据加载与训练 | 显著提升训练吞吐量 |
第十四章:Trainer API(PyTorch)
14.1 Trainer 类初始化参数
| 参数 | 类型 | 说明 | 示例 | 注意事项 |
|---|
model | PreTrainedModel | 要训练的模型 | model = AutoModelForSequenceClassification.from_pretrained(...) | 必须是 Hugging Face 模型 |
args | TrainingArguments | 训练配置对象 | args = TrainingArguments(output_dir="./output", ...) | 核心配置入口 |
train_dataset | Dataset | 训练数据集 | train_dataset=tokenized_datasets["train"] | 必须为 datasets.Dataset 类型 |
eval_dataset | Dataset | 验证数据集 | eval_dataset=tokenized_datasets["validation"] | 可选,用于监控性能 |
tokenizer | PreTrainedTokenizer | 分词器 | tokenizer=tokenizer | 用于保存和日志记录 |
data_collator | DataCollator | 批处理策略 | data_collator=DataCollatorWithPadding(tokenizer) | 默认使用 DefaultDataCollator |
compute_metrics | function | 自定义评估函数 | def compute_metrics(pred): return {"acc": accuracy_score(...)} | 输入为 EvalPrediction 对象 |
callbacks | List[TrainerCallback] | 回调函数列表 | [EarlyStoppingCallback(early_stopping_patience=3)] | 用于早停、日志等 |
14.2 TrainingArguments 配置详解
| 参数 | 默认值 | 说明 | 推荐值 | 影响 |
|---|
output_dir | 必填 | 模型和日志输出目录 | "./results" | 必须指定 |
num_train_epochs | 3.0 | 训练轮数 | 3~10 | 控制训练时间 |
per_device_train_batch_size | 8 | 每设备训练 batch size | 16~32(根据 GPU 显存) | 显存不足时降低 |
per_device_eval_batch_size | 8 | 每设备评估 batch size | 可略大于训练 batch | 评估不更新梯度,可更大 |
learning_rate | 5e-5 | 优化器学习率 | 2e-5 ~ 5e-5(BERT 类) | 太高易震荡,太低收敛慢 |
weight_decay | 0.0 | 权重衰减(L2 正则) | 0.01 | 防止过拟合 |
evaluation_strategy | "no" | 评估策略 | "steps"、"epoch" | 设为 "steps" 可定期验证 |
save_strategy | 与 evaluation_strategy 一致 | 保存策略 | "steps" | 定期保存检查点 |
logging_steps | 500 | 日志记录步数 | 100~500 | 频繁记录便于监控 |
eval_steps | None | 评估步数 | 500 | 与 logging_steps 一致 |
warmup_steps | 0 | 学习率预热步数 | 500~1000 | 平滑学习率变化,提升稳定性 |
max_grad_norm | 1.0 | 梯度裁剪阈值 | 1.0 | 防止梯度爆炸 |
fp16 | False | 是否使用混合精度 | True(支持 Tensor Cores 的 GPU) | 显存减半,速度提升 |
push_to_hub | False | 是否推送至 Hugging Face Hub | True | 便于分享模型 |
14.3 自定义训练循环简化
Trainer 隐藏了训练循环细节,但可通过继承 Trainer 并重写 training_step 或 compute_loss 实现定制。
| 场景 | 方法 | 说明 |
|---|
| 自定义损失函数 | 重写 compute_loss 方法 | 例如加入对比损失、标签平滑 |
| 梯度累积 | 设置 gradient_accumulation_steps=N | 在 TrainingArguments 中配置,模拟大 batch 训练 |
| 多任务学习 | 自定义 data_collator 和 compute_loss | 混合不同任务数据,加权损失 |
| 特殊优化策略 | 使用 TrainerCallback | 如动态调整学习率、早停 |
第十五章:TensorFlow 中的 Keras 训练流程
15.1 使用 compile() 与 fit()
| 步骤 | 方法 | 说明 | 示例 |
|---|
| 模型编译 | model.compile(optimizer, loss, metrics) | 配置训练参数 | 见下方代码块 |
| 数据准备 | to_tf_dataset() 或 from_generator | 转换为 tf.data.Dataset | tf_train_ds = train_ds.to_tf_dataset(..., batch_size=16) |
| 模型训练 | model.fit(tf_train_ds, validation_data=tf_eval_ds, epochs=3) | 执行训练 | 支持 callbacks 如 EarlyStopping、ModelCheckpoint |
| 自定义训练步 | 使用 @tf.function 装饰训练步 | 提升训练速度 | @tf.function 可编译为图模式,减少开销 |
模型编译示例:
optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5)
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
model.compile(optimizer=optimizer, loss=loss, metrics=['accuracy'])
15.2 TFTrainer 与原生 Keras 对比
| 特性 | TFTrainer | 原生 Keras |
|---|
| 易用性 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 灵活性 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 日志与监控 | 集成 TensorBoard、WandbCallback | 需手动配置 |
| 检查点管理 | 自动保存最佳模型、定期检查点 | 需 ModelCheckpoint 回调 |
| 分布式训练 | 支持 TPU、多 GPU | 支持,但配置稍复杂 |
| 自定义损失 | 需重写 compute_loss | 可直接在 compile 中传入函数 |
| 学习率调度 | 支持 WarmUp、PolynomialDecay | 支持所有 Keras 调度器 |
| 推荐场景 | 快速原型、标准任务 | 复杂模型、研究实验 |
第十六章:检查点保存与恢复
| 框架 | 保存方法 | 恢复方法 | 说明 |
|---|
| PyTorch(Trainer) | trainer.save_model("./checkpoint") | model = AutoModel.from_pretrained("./checkpoint") | 自动保存 pytorch_model.bin、config.json、tokenizer |
| TensorFlow(Keras) | model.save_weights("./ckpt") 或 model.save("./full_model") | model.load_weights("./ckpt") 或 tf.keras.models.load_model("./full_model") | save() 保存完整模型(含结构),save_weights 仅权重 |
| 手动保存 | torch.save(model.state_dict(), "model.pt") | model.load_state_dict(torch.load("model.pt")) | 需先定义相同结构的模型 |
| 恢复训练 | Trainer(..., args=TrainingArguments(resume_from_checkpoint=True)) | 从上次中断处继续训练 | 检查点需包含优化器状态 |
| 跨框架加载 | 不推荐 | 可通过 from_pt=True 加载 PyTorch 模型到 TF | TFAutoModel.from_pretrained("bert-base-uncased", from_pt=True) |
第十七章:自定义训练循环
17.1 手动实现训练步骤(PyTorch / TensorFlow)
PyTorch 示例:
model.train()
optimizer = AdamW(model.parameters(), lr=5e-5)
for epoch in range(epochs):
for batch in dataloader:
optimizer.zero_grad()
outputs = model(**batch)
loss = outputs.loss
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm=1.0)
optimizer.step()
TensorFlow 示例:
@tf.function
def train_step(batch):
with tf.GradientTape() as tape:
outputs = model(batch, training=True)
loss = loss_fn(batch["labels"], outputs.logits)
gradients = tape.gradient(loss, model.trainable_variables)
gradients = [tf.clip_by_norm(g, 1.0) for g in gradients] # 梯度裁剪
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
return loss
17.2 梯度裁剪与优化器设置
| 框架 | 方法 | 说明 |
|---|
| PyTorch | torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm) | 防止梯度爆炸,推荐 max_norm=1.0 |
| TensorFlow | tf.clip_by_norm(gradients, clip_norm) | 在 train_step 中对每个梯度张量裁剪 |
| 优化器选择 | AdamW(推荐) | 带权重衰减修正的 Adam,Hugging Face 默认 |
| 学习率调度 | get_linear_schedule_with_warmup | 预热后线性衰减,提升训练稳定性 |
第十八章:多卡训练基础
| 方法 | 框架 | 说明 | 命令 / 配置 |
|---|
| Data Parallel(DP) | PyTorch | 单进程,多线程,主卡聚合梯度 | model = torch.nn.DataParallel(model) |
| Distributed Data Parallel(DDP) | PyTorch | 多进程,每卡独立梯度同步 | torchrun --nproc_per_node=2 train.py |
| Trainer 多卡 | PyTorch | 自动检测 GPU,支持 DDP | 设置 TrainingArguments(..., n_gpu=2) |
| TensorFlow MirroredStrategy | TensorFlow | 多 GPU 同步训练 | strategy = tf.distribute.MirroredStrategy(),with strategy.scope(): model = create_model() |
| 适合单机多卡混合精度训练 | PyTorch(fp16=True),TF(dtype="mixed_float16") | 利用 Tensor Cores 加速 | 显存减半,速度提升 2~3x |
提示:使用 Accelerate 库可编写与硬件无关的训练脚本,自动处理多卡、混合精度等配置。
第十九章:模型配置(Configuration)管理
19.1 模型超参数设置
| 参数 | 说明 | 示例 | 影响 |
|---|
vocab_size | 词汇表大小 | 30522(BERT-base) | 决定嵌入层规模 |
hidden_size | 隐藏层维度 | 768 | 模型容量,影响计算量 |
num_hidden_layers | Transformer 层数 | 12 | 深度决定模型表达能力 |
num_attention_heads | 注意力头数 | 12 | 并行关注不同特征子空间 |
intermediate_size | FFN 中间层维度 | 3072 | 前馈网络宽度 |
hidden_act | 隐层激活函数 | "gelu" | 非线性变换 |
max_position_embeddings | 最大序列长度 | 512 | 支持输入文本长度 |
type_vocab_size | 句对任务类型数 | 2(NSP 任务) | 如 Segment A/B |
initializer_range | 权重初始化范围 | 0.02 | 影响训练稳定性 |
layer_norm_eps | LayerNorm 小常数 | 1e-12 | 数值稳定性 |
提示:可通过 config.update({"num_hidden_layers": 6}) 动态修改。
19.2 从配置创建模型
from transformers import AutoConfig, AutoModel
# 方法1:加载预设配置
config = AutoConfig.from_pretrained("bert-base-uncased")
model = AutoModel.from_config(config) # 随机初始化权重
# 方法2:自定义配置
from transformers import BertConfig
config = BertConfig(
vocab_size=30000,
hidden_size=512,
num_hidden_layers=6,
num_attention_heads=8,
intermediate_size=2048
)
model = AutoModel.from_config(config)
用途:用于从头训练模型(Pretraining)、轻量化定制。
19.3 配置保存与加载
| 操作 | 方法 | 说明 |
|---|
| 保存配置 | config.save_pretrained("./my_config/") | 生成 config.json |
| 加载配置 | config = AutoConfig.from_pretrained("./my_config/") | 与模型无关,仅结构参数 |
| 查看配置 | print(config) 或 config.to_dict() | 调试与验证 |
注意:config.json 是模型结构的”蓝图”,不包含权重。
第二十章:模型保存与加载
20.1 save_pretrained() 与 from_pretrained()
| 框架 | 保存 | 加载 | 说明 |
|---|
| PyTorch | model.save_pretrained("./pt_model") | model = AutoModel.from_pretrained("./pt_model") | 保存 pytorch_model.bin |
| TensorFlow | model.save_pretrained("./tf_model") | model = TFAutoModel.from_pretrained("./tf_model") | 保存 tf_model.h5 |
| 配置文件 | 自动保存 config.json | 自动加载 | 所有框架通用 |
通用性:.from_pretrained() 是 Hugging Face 模型加载的标准接口。
20.2 仅保存权重或完整模型
| 类型 | 方法 | 文件 | 说明 |
|---|
| 仅权重 | model.save_pretrained(..., save_config=False) | pytorch_model.bin 或 tf_model.h5 | 不保存结构,需手动定义模型 |
| 完整模型 | model.save_pretrained(...) | config.json + 权重 + tokenizer(可选) | 推荐,便于复现 |
| PyTorch 完整保存 | torch.save(model, "full.pt") | full.pt | 包含结构,但不推荐(依赖代码结构) |
| TensorFlow SavedModel | model.save("saved_model/") | SavedModel 格式 | 支持 TF Serving |
最佳实践:使用 save_pretrained() 保证跨环境兼容。
20.3 跨框架兼容性(PyTorch ↔ TensorFlow)
| 方向 | 方法 | 说明 |
|---|
| PyTorch → TensorFlow | TFAutoModel.from_pretrained("bert-base-uncased", from_pt=True) | 自动转换权重 |
| TensorFlow → PyTorch | AutoModel.from_pretrained("bert-base-uncased", from_tf=True) | 加载 .ckpt 文件 |
| 限制 | 层命名、精度差异 | 大多数模型支持,但自定义头可能失败 |
| 格式识别 | 自动检测文件后缀 | .bin → PT,.ckpt → TF,pytorch_model.bin → 可转 TF |
用途:在 PyTorch 训练后,导出为 TF 用于生产部署。
第二十一章:量化与模型压缩
21.1 动态量化支持
| 框架 | 支持情况 | 方法 | 说明 |
|---|
| PyTorch | ✅ 原生支持 | torch.quantization.quantize_dynamic() | 将权重转为 int8,推理时动态反量化 |
| TensorFlow | ✅ 支持 | tf.lite.TFLiteConverter + 动态范围量化 | 用于 TFLite 推理 |
| Transformers | ⚠️ 有限支持 | 需手动应用 | 适合 CPU 推理,加速 2-3x |
# PyTorch 动态量化示例
model_quantized = torch.quantization.quantize_dynamic(
model, {torch.nn.Linear}, dtype=torch.qint8
)
优点:减少模型大小,降低内存占用,适合边缘设备。
21.2 使用 Optimum 库进行优化
| 功能 | 方法 | 说明 |
|---|
| 量化(INT8/FP16) | optimum.onnxruntime.ORTModelForCausalLM | 结合 ONNX Runtime |
| 剪枝 | optimum.pruning | 移除不重要权重 |
| 知识蒸馏 | optimum.distillation | 小模型学习大模型输出 |
| Intel CPU 优化 | optimum.intel | 基于 Neural Compressor |
| NVIDIA GPU 优化 | optimum.nvidia | 使用 TensorRT |
安装:pip install optimum[onnxruntime] 或 optimum[intel]
21.3 减少推理内存占用
| 方法 | 说明 | 工具 / 技术 |
|---|
| 量化 | 权重从 FP32 → INT8 | torch.quantization、ONNX Runtime |
| 混合精度 | 使用 FP16 推理 | model.half()(PyTorch) |
| 模型剪枝 | 移除冗余连接 | torch.nn.utils.prune |
| 梯度检查点 | 训练时减少显存 | model.gradient_checkpointing_enable() |
| 模型分片 | 大模型拆分到多卡 | device_map="auto"(accelerate) |
| 使用 bigscience/bloom 风格分片 | 适合 >10B 模型 | from_pretrained(..., device_map="auto") |
第二十二章:多GPU与分布式训练
22.1 DataParallel 与 DistributedDataParallel
| 特性 | DataParallel(DP) | DistributedDataParallel(DDP) |
|---|
| 进程模型 | 单进程,多线程 | 多进程,每卡一个进程 |
| 梯度同步 | 主卡(GPU 0)聚合 | 所有卡对等通信(NCCL) |
| 效率 | 较低,主卡瓶颈 | 高,推荐使用 |
| 显存占用 | 不均衡 | 均衡 |
| 启动方式 | 代码内调用 | torchrun --nproc_per_node=N train.py |
| 适用场景 | 快速原型 | 生产训练 |
# DP(不推荐)
model = torch.nn.DataParallel(model, device_ids=[0, 1])
# DDP(推荐)
# torchrun --nproc_per_node=2 train.py
# 在代码中:torch.nn.parallel.DistributedDataParallel(model)
22.2 使用 Accelerate 库简化分布式训练
| 功能 | 说明 | 示例 |
|---|
| 自动设备管理 | 检测 GPU/TPU,分配 device_map | from accelerate import Accelerator
accelerator = Accelerator() |
| 梯度同步 | 自动处理 DDP | model, optimizer, dataloader = accelerator.prepare(model, optim, dl) |
| 混合精度 | 自动启用 FP16/BF16 | 在 Accelerator 初始化时配置 |
| 多机训练 | 支持多节点 | 配置 deepspeed 或 fsdp |
| 零冗余优化器(ZeRO) | 分片优化器状态 | 通过 deepspeed_config 启用 |
优势:编写单卡代码,自动扩展到多卡/多机。
22.3 梯度累积与批处理优化
| 概念 | 说明 | 实现 |
|---|
| 梯度累积 | 模拟大 batch,解决显存不足 | 在 TrainingArguments 中设置 gradient_accumulation_steps=4 |
| 等效 batch size | per_device_train_batch_size * num_devices * gradient_accumulation_steps | 如 8 * 2 * 4 = 64 |
| 手动实现 | 多步 loss.backward() 后 optimizer.step() | 需手动控制 step 和 zero_grad |
| 优化策略 | 结合 DynamicPadding + MaxLength 调整 | 减少填充,提升吞吐 |
注意:梯度累积后才更新参数,等效于大 batch 训练。
第二十三章:ONNX 导出与部署
23.1 将模型导出为 ONNX 格式
# 使用 CLI
transformers-cli convert --model bert-base-uncased --to onnx --output ./onnx/bert.onnx
# 或使用 optimum
from optimum.onnxruntime import ORTModelForSequenceClassification
model = ORTModelForSequenceClassification.from_pretrained("bert-base-uncased", from_transformers=True)
model.save_pretrained("./onnx/bert-onnx/")
| 概念 | 说明 | 实现 |
|---|
| 支持模型 | BERT、GPT-2、RoBERTa、DistilBert 等 | 查看 optimum 文档 |
| 输入 | 需提供示例输入(dummy_input) | 用于追踪动态维度 |
23.2 使用 ONNX Runtime 推理
from onnxruntime import InferenceSession
session = InferenceSession("./onnx/bert.onnx")
inputs = {
"input_ids": input_ids.numpy(),
"attention_mask": attention_mask.numpy(),
"token_type_ids": token_type_ids.numpy()
}
outputs = session.run(None, inputs)
| 概念 | 说明 | 实现 |
|---|
| 优势 | 跨平台、高性能、支持 GPU(CUDA、DirectML) | 适合生产环境 |
| 量化支持 | INT8、FP16 推理 | 进一步加速 |
23.3 性能对比与兼容性说明
| 运行时 | 推理速度 | 兼容性 | 适用场景 |
|---|
| PyTorch | 基准 | 高(支持所有模型) | 研究、开发 |
| TensorFlow | 快于 PT(优化后) | 高 | TF 生态部署 |
| ONNX Runtime | ⚡ 最快(尤其 CPU) | 中(部分模型需转换) | 生产、边缘设备 |
| TensorRT | 极快(NVIDIA GPU) | 低(仅 NVIDIA) | 高性能 GPU 推理 |
| TorchScript | 快(图模式) | 中(需脚本化) | C++ 部署 |
建议:
- CPU 推理:ONNX Runtime + 量化
- GPU 推理:TensorRT 或 FP16 PyTorch
- 快速部署:optimum + onnxruntime
第二十四章:PEFT:参数高效微调(Parameter-Efficient Fine-Tuning)
24.1 LoRA、Adapter、Prefix Tuning 原理
| 方法 | 核心思想 | 参数更新量 | 适用场景 | 优点 | 缺点 |
|---|
| LoRA(Low-Rank Adaptation) | 冻结原模型权重,在注意力层的 W_q、W_v 上注入低秩矩阵 A 和 B,使得增量 ΔW = A × B | <1% 总参数(如 7B 模型仅 4MB) | 大模型微调(LLaMA、Bloom) | 显存低、训练快、可组合多个适配器 | 需推理时合并权重或支持 LoRA 的运行时 |
| Adapter | 在 Transformer 层间插入小型 MLP 网络(bottleneck 结构),仅训练 adapter 模块 | ~3-5% 总参数 | 中小模型微调 | 模块化、易于插拔 | 增加推理延迟(额外计算) |
| Prefix Tuning | 向输入前缀添加可学习的连续向量(soft prompts),冻结主干模型 | 极少(仅 prefix embeddings) | 生成任务(摘要、对话) | 完全冻结模型,极省显存 | 效果依赖任务和长度,难解释 |
| BitFit | 仅微调模型中的 bias 项,其余冻结 | <0.1% 参数 | 资源极度受限场景 | 极简配置 | 性能提升有限 |
关键优势:在不修改原始大模型的前提下,实现快速、低成本的领域适配。
24.2 使用 PeftModel 进行轻量微调
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM
# 1. 加载基础模型
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
# 2. 配置 LoRA
lora_config = LoraConfig(
r=8, # 低秩矩阵秩
lora_alpha=32, # 缩放因子
target_modules=["q_proj", "v_proj"], # 应用模块
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 3. 包装为 PeftModel
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 输出:trainable params: 2,097,152 || all params: 6,738,415,616 || trainable: 0.03%
# 4. 训练(仅更新 LoRA 权重)
trainer.train()
注意:target_modules 需根据具体模型结构确定(可通过 model.config 查看)。
24.3 保存与合并适配器权重
| 操作 | 方法 | 说明 |
|---|
| 保存适配器 | model.save_pretrained("./lora-adapter") | 仅保存 adapter_config.json、adapter_model.bin |
| 加载适配器 | model = PeftModel.from_pretrained(model, "./lora-adapter") | 可叠加多个适配器 |
| 推理时合并 | model = model.merge_and_unload() | 将 LoRA 权重合并回原模型,生成标准 PreTrainedModel |
| 多适配器切换 | model.load_adapter("path/to/adapter", "name") + model.set_adapter("name") | 实现”模型多专家”(Multi-Expert)模式 |
| 导出完整模型 | merged_model.save_pretrained("./merged-model") | 合并后无需 PEFT 库即可推理 |
最佳实践:开发阶段保存适配器,部署前合并以提升推理速度。
第二十五章:Optimum:高性能推理与硬件加速
25.1 支持 Intel、NVIDIA、AWS 等后端
| 后端 | 子库 | 支持功能 |
|---|
| Intel CPU/GPU | optimum.intel | 基于 OpenVINO™ 的量化、编译优化 |
| NVIDIA GPU | optimum.nvidia | TensorRT 加速,FP16/INT8 推理 |
| AWS Inferentia | optimum.neuron | 编译为 Neuron IR,部署在 Inf1 实例 |
| AWS Trainium | optimum.neuronx | 分布式训练支持 |
| ONNX Runtime | optimum.onnxruntime | 跨平台推理(CPU/GPU/DirectML) |
| Graphcore IPUs | optimum.graphcore | 大规模模型加速 |
统一接口:ORTModelForSequenceClassification、TensorRTModelForCausalLM 等。
25.2 量化、编译、图优化
| 技术 | 方法 | 效果 |
|---|
| 动态量化 | model.quantize(quantization_config=DynamicQuantizationConfig()) | CPU 推理提速 2-3x,模型减半 |
| 静态量化(INT8) | 使用校准数据集量化激活值 | 更高精度保持,适合边缘设备 |
| 编译优化 | model.compile()(OpenVINO/TensorRT) | 生成优化执行图,减少调度开销 |
| 算子融合 | 自动融合 LayerNorm + Linear 等 | 减少 kernel 启动次数 |
| KV Cache 优化 | 在生成任务中缓存 key/value | 显著提升长文本生成速度 |
# 示例:使用 ONNX Runtime 推理
from optimum.onnxruntime import ORTModelForQuestionAnswering
model = ORTModelForQuestionAnswering.from_pretrained("./onnx-model/", use_io_binding=True)
25.3 与 HuggingFace 生态集成
| 功能 | 集成方式 | 说明 |
|---|
| AutoModel 扩展 | from_pretrained(..., export=True) | 自动导出并加载优化模型 |
| pipeline() 支持 | pipeline("text-generation", model=model) | 使用优化后的模型构建 pipeline |
| Trainer 兼容 | 结合 TrainingArguments | 在训练后直接导出为 TensorRT/ONNX |
| Hub 模型标签 | 添加 optimum、accelerated 标签 | 便于搜索高性能模型 |
提示:许多 Hub 上的模型已提供 Optimum 优化版本(如 optimum/onnxruntime-large-qa)。
第二十六章:模型上传与共享
26.1 创建 Hugging Face 账号与仓库
- 访问 huggingface.co 注册账号
- 创建新模型仓库:点击”New Model” → 设置名称、许可、标签
- 选择私有(Private)或公开(Public)
26.2 使用 huggingface-cli 登录与推送
# 登录
huggingface-cli login
# 输入 token(来自 https://huggingface.co/settings/tokens)
# 推送模型
model.push_to_hub("your-username/my-lora-adapter")
# 推送 tokenizer
tokenizer.push_to_hub("your-username/my-lora-adapter")
# 推送整个目录
huggingface-cli upload your-username/my-model ./local-folder/ .
Token 权限:选择 write 权限以允许推送。
26.3 模型卡片(Model Card)编写规范
README.md 文件应包含:
---
license: apache-2.0
tags:
- bert
- question-answering
- peft
- lora
---
# Model Card: fine-tuned-bert-squad-lora
## Model Details
- **Architecture**: BERT base
- **Task**: Question Answering
- **Dataset**: SQuAD v2.0
- **PEFT Method**: LoRA (r=8, alpha=16)
## Training Information
- Epochs: 3
- LR: 3e-4
- Batch Size: 16
- Metrics: EM=85.2%, F1=92.1%
## Intended Use
用于英文问答系统,不适合医疗/法律等专业领域。
## Bias & Fairness
可能存在性别/种族偏见,建议在部署前进行公平性评估。
模板参考:Hugging Face Model Card 指南
第二十七章:安全与隐私注意事项
27.1 模型偏见与公平性
| 风险 | 示例 | 缓解措施 |
|---|
| 刻板印象 | ”护士” → 女性,“工程师” → 男性 | 使用去偏数据集(如 WinoBias)、公平性评估工具(Fairlearn) |
| 歧视性输出 | 对少数群体生成负面内容 | 在训练中加入对抗去偏(Adversarial Debiasing) |
| 文化偏差 | 仅反映主流文化价值观 | 多语言/多文化数据混合训练 |
| 评估指标 | 使用 regard、toxicity 分数评估生成内容 | transformers.pipelines.Pipeline 支持内置检测 |
工具推荐:
datasets:bias_bias、hate_speech 数据集
fairlearn:公平性指标计算
perspectiveapi:内容毒性检测
27.2 输入过滤与内容审核
| 层级 | 方法 | 工具 |
|---|
| 输入层 | 过滤敏感词、正则匹配 | regex、flashtext |
| 预处理 | 检测仇恨言论、PII(个人身份信息) | detoxify、presidio |
| 模型层 | 使用安全分类器拦截有害请求 | unitary/toxic-bert、Salesforce/safety-flan-t5 |
| 输出层 | 审核生成内容再返回 | 同上 + 关键词黑名单 |
from transformers import pipeline
safety_checker = pipeline("text-classification", model="unitary/toxic-bert")
def safe_generate(prompt):
if safety_checker(prompt)[0]["label"] == "toxic":
return "输入内容不安全,已拒绝。"
return model.generate(prompt)
27.3 推理服务中的安全实践
| 实践 | 说明 |
|---|
| 最小权限原则 | API 服务仅开放必要端点,限制请求频率 |
| HTTPS 加密 | 所有通信启用 TLS |
| 输入长度限制 | 防止 DoS 攻击(如超长 prompt) |
| 沙箱环境 | 在隔离环境中运行模型推理 |
| 日志审计 | 记录所有请求用于安全审查(匿名化处理 PII) |
| 模型水印 | 在生成文本中嵌入隐形标识,追踪滥用来源 |
| 定期更新 | 及时修复依赖库漏洞(如 transformers、pytorch) |
生产建议:使用 TextAttack 或 Counterfit 进行红队测试(Red Teaming)。