Hugging Face 核心三件套:Transformers、Tokenizer 与 Datasets 从零到实战

Hugging Face 早已从一个简单的库,成长为整个 AI 开发的基础设施。截至 2026 年初,Hugging Face Hub 已经托管了超过 90 万个模型、20 万个数据集和 35 万个交互式应用(Spaces)。而在某些统计口径下,模型数量已超过 240 万个,数据集超过 91 万个。更值得关注的是,超过 1.5 万家企业客户依赖该平台,涵盖金融服务、医疗保健、汽车、法律科技和政府等多个行业。

如此庞大的生态,对于很多初学者来说可能有些眼花缭乱:我到底该从哪里开始?怎么把那些强大的模型用起来?

别担心,这篇保姆级教程,就是为你准备的。我们将抛开复杂的概念,从零开始,一步步拆解 Hugging Face 生态中三个最核心的库------TransformersTokenizerDatasets,并通过大量的代码示例和详细注释,带你理清一条从原始数据到模型部署的最短路径。读完本文,你不仅会懂得如何加载模型,更能掌握一套高效的 NLP 工作流。

官网地址为:https://huggingface.co/

国内镜像地址为:https://hf-mirror.com/


1. Hugging Face 生态:不只是模型下载站

很多朋友以为 Hugging Face 就是个下载模型的地方,就像 AI 界的"App Store"。但实际上,它已经发展成一个完整的全栈式 MLOps 平台,涵盖了 AI 开发的整个生命周期。

你可以把它想象成一座繁华的 AI 城市:

  • Hugging Face Hub(市中心广场)

    :最热闹的地方,上面有各种模型 (Models)、数据集 (Datasets)和交互式应用(Spaces)。你需要的任何资源,几乎都能在这里找到。每个模型和数据集都有专门的卡片页面,包含描述、预期用途、训练细节、评估结果和许可信息。

  • Transformers(核心工厂)

    :这个库负责将广场上的模型"图纸"和"零件"(权重和配置)组装成一个可以直接使用的 PyTorch 或 TensorFlow 模型。

  • Tokenizer(语言翻译官)

    :因为计算机只懂数字,不懂文字,所以 Tokenizer 的作用就是将我们写的句子,翻译成模型能理解的"数字密码"。

  • Datasets(高效的仓库管理员)

    :专门管理数据,无论你的数据是躺在本地硬盘的 CSV 文件里,还是在云端的数据库里,它都能帮你高效、有序地整理好,并以最快的速度送到模型"嘴边"。

值得一提的是,几乎每个开源权重模型------从 Meta 的 Llama 系列到 Mistral 的模型再到 Google 的 Gemma------都主要通过 Hub 分发。而 Transformers 库则提供了一个统一的 API,用于加载和运行数千种模型架构,消除了为每个模型家族编写自定义加载代码的需要。


2. 准备工作:镜像与安装

由于网络原因,直接从官网下载模型有时会比较慢。国内用户可以配置镜像站来加速。

2.1 配置国内镜像站(hf-mirror.com

在你的代码或终端中设置环境变量 HF_ENDPOINT,将其指向国内镜像站 https://hf-mirror.com,之后的下载就会快很多。

方法一:终端设置(临时生效)

复制代码
export HF_ENDPOINT=https://hf-mirror.com

方法二:在 Python 代码中设置

复制代码
import os
# 设置环境变量,让 Hugging Face 的下载请求指向国内镜像
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'

设置成功后,所有的 from_pretrained() 方法都会自动通过这个镜像站下载。

方法三:永久生效(写入配置文件)

复制代码
# 将以下内容添加到 ~/.bashrc 或 ~/.zshrc
echo 'export HF_ENDPOINT=https://hf-mirror.com' >> ~/.bashrc
source ~/.bashrc

2.2 安装必需的库

在开始之前,请确保你已经安装了 transformers 和 datasets 这两个核心库:

复制代码
pip install transformers datasets

如果要使用 PyTorch 进行模型训练,还需要安装 PyTorch:

复制代码
# 根据你的 CUDA 版本选择合适的安装命令
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

3. Transformers 库:模型加载的艺术

Transformers 库的核心,就是提供了一个统一的接口,让你能用一行代码加载成百上千种预训练模型。这个接口,就是我们今天的主角------from_pretrained()。

3.1 from_pretrained 底层到底发生了什么?

当你写下这行代码时------model = AutoModel.from_pretrained("bert-base-chinese")------背后究竟发生了什么?简单来说,from_pretrained 方法完成了一个从"模型描述"到"可运行模型实例"的完整构建过程。这个过程可以分解为五个核心步骤,它们环环相扣:

第一步:定位与获取

系统首先需要找到模型。它既可以接受 Hugging Face Hub 上的模型名称(如 "bert-base-chinese"),也可以接受本地硬盘上的文件夹路径。如果是 Hub 上的模型,它会检查本地缓存(默认路径 ~/.cache/huggingface/hub/),如果缓存不存在,则从 Hub 下载。

第二步:配置解析

接着,它会读取并解析模型的配置文件(通常是 config.json)。这个文件定义了模型的"蓝图"------有多少层、每层有多少神经元、用的是什么激活函数、注意力头的数量等关键参数。一个典型的 config.json 文件长这样:

复制代码
{
  "architectures": ["BertForMaskedLM"],
  "model_type": "bert",
  "hidden_size": 768,
  "num_hidden_layers": 12,
  "num_attention_heads": 12,
  "vocab_size": 21128
}

第三步:架构构建

根据配置文件中的蓝图,在内存中初始化一个空的模型架构。此时所有的权重都是随机值------这一步只是搭建了神经网络的"骨架"。

第四步:权重载入

这是最关键的一步。系统将预训练好的权重文件(通常是 pytorch_model.bin 或 model.safetensors)中的数值,精确地填充到刚刚建好的空架构的对应位置。这个过程涉及复杂的张量形状匹配和层名对应。

第五步:最终实例化

将已经"注入灵魂"的模型对象返回给你,你就可以用它进行推理、微调,完成你的下游任务了。

理解这些机制,不仅能让你在模型加载失败时快速定位问题(比如经典的 "Missing config.json" 错误),更能让你在需要自定义模型结构、进行模型剪枝或适配特殊硬件时,做到心中有数。

3.2 AutoModel vs AutoModelForXXX:到底该用哪个?

当你开始看文档时,可能会对 AutoModel 和 AutoModelForSequenceClassification 等一堆"变体"感到困惑。简单来说,它们的主要区别在于模型是否有"任务头"(Task Head)。

  • AutoModel:通用主干网络

    只加载模型的"骨架",输出的是隐藏状态(Hidden States),也就是文本经过模型编码后的高维向量。它像是一个"裸模型",适合进行特征提取或自定义任务。输出形状为 [batch_size, seq_len, hidden_dim]。

  • AutoModelForXXX:自带"武器"的专家

    在主干网络的基础上,为你自动添加了一个专门处理特定任务的"头",输出的是可以直接用于该任务的逻辑值(Logits)。例如,AutoModelForSequenceClassification(文本分类)在模型最后加了一个全连接层,可以直接输出每个类别的得分。

AutoModel 的自动识别机制

很多朋友会有这样的疑惑:加载模型时,我到底该用 AutoModel 还是像 BertModel 这样的具体模型类?实际上,它们最终会走向同一个终点,实现完全相同的效果。AutoModel 就像一个"智能导航"------你不需要知道目的地具体是什么车型,只需要告诉它地址,它自己会去查地图、找车型。

这个自动识别的魔法,来源于配置文件里的 architectures 字段。当 AutoModel 读取到 "architectures": ["BertModel"] 时,它就会去自己的注册表里查找,最终定位到 transformers.models.bert.modeling_bert.BertModel 这个类。所以,AutoModel 就像一个万能适配器,背后是一套复杂的自动发现机制。

常用 AutoModelForXXX 类型一览表

|------------------------------------|----------|----------------------------------------------|-----------------------|
| 模型类 | 任务头 | 输出内容 | 适用场景 |
| AutoModel | 无 | last_hidden_state (高维特征) | 特征提取、自定义下游任务 |
| AutoModelForSequenceClassification | 分类头 | logits [batch, num_labels] | 情感分析、主题分类、垃圾邮件检测 |
| AutoModelForTokenClassification | 词元分类头 | logits [batch, seq_len, num_labels] | 命名实体识别(NER)、词性标注(POS) |
| AutoModelForQuestionAnswering | 问答头 | start_logits , end_logits [batch, seq_len] | 抽取式问答(如 SQuAD) |
| AutoModelForMaskedLM | 掩码语言模型头 | logits [batch, seq_len, vocab_size] | 完形填空、BERT-style 预训练 |
| AutoModelForCausalLM | 自回归语言模型头 | logits [batch, seq_len, vocab_size] | 文本生成(GPT 系列) |
| AutoModelForSeq2SeqLM | 编码器-解码器头 | logits [batch, dec_seq_len, vocab_size] | 机器翻译、文本摘要(T5、BART) |

最佳实践:除非有特殊需求,否则始终优先使用 AutoModelForXXX 系列。这种方式可以实现代码解耦,支持任意兼容模型,让代码更具可移植性。

3.3 实战:加载一个用于中文文本分类的 BERT 模型

复制代码
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

# 1. 定义模型名称('google-bert/bert-base-chinese' 是 Google 发布的中文 BERT 模型)
model_name = "google-bert/bert-base-chinese"

# 2. 加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_name)

# 3. 加载用于序列分类(文本分类)的模型
# 设置 num_labels=2,因为我们假设这是一个二分类任务(例如:正面/负面)
# num_labels 参数的作用是告诉模型:"我们正在处理一个二分类任务"
# 模型的最后一层(分类器)会被初始化为一个输出维度为 2 的线性层[reference:20]
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    num_labels=2  # 告诉模型,我们需要一个输出 2 个类别的分类头
)

# 4. 准备输入文本
texts = ["这部电影太棒了,强烈推荐!", "剧情很无聊,浪费了两个小时。"]

# 5. 使用分词器将文本转换为模型输入
inputs = tokenizer(
    texts, 
    padding=True,      # 自动填充到 batch 内最长长度
    truncation=True,   # 超过最大长度时自动截断
    return_tensors="pt"  # return_tensors="pt" 表示返回 PyTorch 张量(tensor)
)
# inputs 是一个字典,包含三个键:
# - input_ids: token 对应的 ID 序列,形状为 (2, seq_len)
# - attention_mask: 注意力掩码,1 表示真实 token,0 表示填充 token
# - token_type_ids: 句子类型标记(BERT 特有,用于区分两个句子)

# 6. 进行推理
with torch.no_grad():  # 推理阶段不需要计算梯度,可以节省内存和加快速度
    outputs = model(**inputs)  # 使用 ** 将字典解包为关键字参数

# 7. 获取分类结果
logits = outputs.logits  # logits 的形状为 (batch_size, num_labels) = (2, 2)
# logits 是原始的模型输出分数,未经 softmax 归一化
predictions = torch.argmax(logits, dim=-1)  # 取分数最高的类别作为预测结果

print(predictions)  # 输出:tensor([0, 1]) 假设 0 代表正面,1 代表负面

# 8. 如果需要概率,可以对 logits 应用 softmax
probs = torch.softmax(logits, dim=-1)
print(probs)  # 输出每个类别的概率分布

代码解读:

  1. AutoTokenizer.from_pretrained(model_name):加载与 BERT 模型配套的分词器。Tokenizer 必须与模型在预训练时使用的分词器保持一致,也就是词表需要一致。

  2. AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2):加载模型,并覆盖其默认的分类头,指定我们的任务需要输出 2 个类别。重要提示:对于分类任务,必须显式指定 num_labels(类别数),否则模型会默认使用预训练时的类别数,可能与当前任务不符。

  3. tokenizer(texts, return_tensors="pt"):一次性对列表中的所有文本进行编码、填充和截断,并直接返回 PyTorch 张量。

  4. model(**inputs):将编码后的 input_ids、attention_mask 等参数传入模型,得到输出。

  5. outputs.logits:这是模型的核心输出,即分类的原始分数,形状为 [batch_size, num_labels]。注意这里是 logits 而非概率,因为模型最后一层没有应用 softmax------softmax 通常与损失函数(如 CrossEntropyLoss)结合使用,或者在推理时手动添加。

  6. torch.argmax(logits, dim=-1):找到分数最高的类别索引,作为最终的预测结果。

3.4 更多模型加载技巧

从本地路径加载:如果你已经下载好了模型,可以直接从本地文件夹加载,方便离线使用。

复制代码
model = AutoModelForSequenceClassification.from_pretrained("./my_local_model/")
tokenizer = AutoTokenizer.from_pretrained("./my_local_model/")

要求本地目录中必须包含 config.json 和模型权重文件(如 pytorch_model.bin 或 model.safetensors)。

多 GPU / 设备自动映射:当模型很大时,可以设置 device_map="auto",让 accelerate 库自动帮你把模型的不同层分配到可用的 GPU 或 CPU 上。

复制代码
model = AutoModelForSequenceClassification.from_pretrained(model_name, device_map="auto")

加载半精度模型(节省显存)

复制代码
model = AutoModelForSequenceClassification.from_pretrained(
    model_name, 
    torch_dtype=torch.float16  # 以 FP16 半精度加载,显存占用减半
).to("cuda")

忽略不匹配的权重(适用于微调时修改了模型结构)

复制代码
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    ignore_mismatched_sizes=True  # 如果权重形状与模型结构不匹配,跳过不匹配的层
)

4. Tokenizer:文本与数字的桥梁

我们辛苦加载的模型只认识数字,不认识文字。所以,在把文本喂给模型之前,必须先进行"翻译"。这个翻译官就是 Tokenizer

4.1 Tokenizer 的核心原理:主流分词算法

Tokenizer 将文本转换为模型可处理的数字序列,直接影响模型的性能和效率。目前主流的分词算法主要有三种:BPE、WordPiece 和 SentencePiece。

BPE(Byte Pair Encoding)

BPE 通过合并高频字符对来构建词汇表。它的优点是能有效处理未登录词(OOV,即 Out-Of-Vocabulary,指词表中不存在的词),词汇量可控,多语言支持较好。但缺点是对中文支持有限,可能产生不完整的词。GPT 系列模型使用的就是 BPE 算法。

WordPiece

WordPiece 由 Google 开发,专门用于 BERT 预训练。它基于最大似然估计逐步合并词片段,在词前添加 ## 标记子词。例如,"playing" 会被分词为 ["play", "##ing"]。WordPiece 更适合英文,此后很多基于 BERT 的 Transformer 模型都复用了这种方法。

SentencePiece

SentencePiece 将文本视为 Unicode 序列,不依赖空格分词,因此具有语言无关性,特别适合支持中文、日文等无空格语言。如果你需要处理中文文本,SentencePiece 是最佳选择。

算法对比表

|------|-------------|-----------------|-----------------|
| 特性 | BPE | WordPiece | SentencePiece |
| 分词粒度 | 子词 | 子词 | 子词/字符 |
| 语言支持 | 英文为主 | 英文为主 | 多语言(支持中文) |
| 空格处理 | 依赖空格 | 依赖空格 | 不依赖空格 |
| 训练速度 | 快 | 中等 | 慢 |
| 典型应用 | GPT、RoBERTa | BERT、DistilBERT | T5、XLNet、ALBERT |

4.2 Tokenizer 的工作流程

一个完整的 Tokenizer 工作流程包括以下几个步骤:

  1. 标准化(Normalization)

    :将文本统一为某种标准形式,如小写化、去除多余空格、Unicode 规范化等。

  2. 预分词(Pre-tokenization)

    :将文本初步切分成更小的单元(如单词),为子词分词做准备。

  3. 分词(Tokenization)

    :将预分词后的单元进一步切分成子词单元,并映射到词表中的 ID。

  4. 后处理(Post-processing)

    :添加特殊标记(如 BERT 的 [CLS] 和 [SEP])、生成 attention_mask 和 token_type_ids。

4.3 Tokenizer 常用 API 实战

复制代码
from transformers import AutoTokenizer

model_name = "google-bert/bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)

text = "我爱自然语言处理"

# 1. 分词(tokenize)------ 将文本切分为 token 字符串
tokens = tokenizer.tokenize(text)
print("分词结果:", tokens)  
# 输出: ['我', '爱', '自', '然', '语', '言', '处', '理']
# 注意:BERT 中文分词器采用字级别分词,每个汉字作为一个 token

# 2. token 转 ID(convert_tokens_to_ids)------ 将 token 映射到词表中的 ID
ids = tokenizer.convert_tokens_to_ids(tokens)
print("Token ID:", ids)  
# 输出: [2769, 4263, 5632, 4197, 6427, 6241, 1905, 4415]

# 3. ID 转 token(convert_ids_to_tokens)------ 反向映射
tokens_back = tokenizer.convert_ids_to_tokens(ids)
print("还原 token:", tokens_back)  
# 输出: ['我', '爱', '自', '然', '语', '言', '处', '理']

# 4. 编码(encode):直接得到带特殊标记的 ID 序列
# encode 方法相当于 tokenize + convert_tokens_to_ids + 添加特殊标记
ids_with_special = tokenizer.encode(text)
print("编码结果(含特殊标记):", ids_with_special)  
# 输出: [101, 2769, 4263, 5632, 4197, 6427, 6241, 1905, 4415, 102]
# 101 是 [CLS](分类标记),102 是 [SEP](分隔标记)

# 通过 add_special_tokens 参数控制是否添加特殊标记
ids_without_special = tokenizer.encode(text, add_special_tokens=False)
print("编码结果(不含特殊标记):", ids_without_special)
# 输出: [2769, 4263, 5632, 4197, 6427, 6241, 1905, 4415]

# 5. 解码(decode):将 ID 序列还原为文本
decoded_text = tokenizer.decode(ids_with_special)
print("解码结果:", decoded_text)  
# 输出: "[CLS] 我爱自然语言处理 [SEP]"

# 使用 skip_special_tokens=True 跳过特殊标记
decoded_clean = tokenizer.decode(ids_with_special, skip_special_tokens=True)
print("解码结果(跳过特殊标记):", decoded_clean)
# 输出: "我爱自然语言处理"

# 6. 推荐方式:tokenizer() 方法(即 __call__)
# 这是最全面的接口,自动完成所有步骤
inputs = tokenizer(
    text, 
    padding=True,       # 是否填充到统一长度
    truncation=True,    # 是否截断超长文本
    max_length=10,      # 最大长度
    return_tensors="pt" # 返回 PyTorch 张量
)
print("模型直接输入:", inputs)
# 输出一个字典,包含三个字段:
# - input_ids: token ID 序列,形状 (1, 10)
# - attention_mask: 注意力掩码,1 表示真实 token,0 表示填充 token
# - token_type_ids: 句子类型标记(BERT 专用),通常第一个句子为 0

打印结果:

复制代码
分词结果: ['我', '爱', '自', '然', '语', '言', '处', '理']
Token ID: [2769, 4263, 5632, 4197, 6427, 6241, 1905, 4415]
还原 token: ['我', '爱', '自', '然', '语', '言', '处', '理']
编码结果(含特殊标记): [101, 2769, 4263, 5632, 4197, 6427, 6241, 1905, 4415, 102]
编码结果(不含特殊标记): [2769, 4263, 5632, 4197, 6427, 6241, 1905, 4415]
解码结果: [CLS] 我 爱 自 然 语 言 处 理 [SEP]
解码结果(跳过特殊标记): 我 爱 自 然 语 言 处 理
模型直接输入: {'input_ids': tensor([[ 101, 2769, 4263, 5632, 4197, 6427, 6241, 1905, 4415,  102]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}

4.4 特殊标记详解

BERT 系列模型使用了一系列特殊标记,这些标记在分词和编码过程中会自动添加:

|----------|----------------|-------|------------------------|
| 特殊标记 | Token ID(BERT) | 含义 | 用途 |
| [PAD] | 0 | 填充标记 | 用于将 batch 内的序列填充到相同长度 |
| [UNK] | 100 | 未知词标记 | 词表中不存在的词会被映射为 [UNK] |
| [CLS] | 101 | 分类标记 | 放在序列开头,其输出向量常用于分类任务 |
| [SEP] | 102 | 分隔标记 | 用于分隔两个句子(如问答任务)或标记句子结束 |
| [MASK] | 103 | 掩码标记 | 用于掩码语言模型(MLM)预训练任务 |

4.5 批量处理与模型配合

在实际应用中,我们通常需要批量处理多条文本。Tokenizer 原生支持批量处理,而且效率极高。

复制代码
from transformers import AutoTokenizer, AutoModel
import torch

model_name = "google-bert/bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# 批量文本
texts = ["我爱自然语言处理", "我爱人工智能", "我们一起学习"]

# 批量编码
encoded = tokenizer(
    texts,
    padding="max_length",   # 填充到指定最大长度(而不是 batch 内最长长度)
    truncation=True,        # 超过长度则截断
    max_length=10,          # 统一长度
    return_tensors="pt"     # 返回 PyTorch 张量
)

# 查看编码结果
print("input_ids 形状:", encoded["input_ids"].shape)  # torch.Size([3, 10])
print("attention_mask 形状:", encoded["attention_mask"].shape)  # torch.Size([3, 10])
print("token_type_ids 形状:", encoded["token_type_ids"].shape)  # torch.Size([3, 10])

# 模型推理
with torch.no_grad():
    outputs = model(**encoded)

print("输出 keys:", outputs.keys())
print("last_hidden_state 形状:", outputs.last_hidden_state.shape)  # (3, 10, 768)
print("pooler_output 形状:", outputs.pooler_output.shape)          # (3, 768)

padding 参数的三种取值:

  • padding=True 或 padding="longest":将 batch 内所有序列填充到该 batch 中的最长长度。

  • padding="max_length":将所有序列填充到 max_length 指定的长度。

  • padding=False:不进行填充(不推荐用于批量输入)。

return_tensors 参数的取值:

  • return_tensors="pt":返回 PyTorch 张量

  • return_tensors="tf":返回 TensorFlow 张量

  • return_tensors="np":返回 NumPy 数组

  • 不指定则返回 Python 列表


5. Datasets 库:高效的数据管理

datasets 是 Hugging Face 提供的一个轻量级数据处理库,专为 NLP 任务设计,能够高效地支持模型训练过程中的数据加载与预处理操作。它的主要特点包括:

  • 加载方便

    :支持读取本地文件(如 CSV、JSON),也支持加载 Hugging Face Hub 上的公开数据集。

  • 结构清晰

    :数据集的内部结构类似表格,每条样本由若干字段组成。

  • 无缝协作

    :与 Tokenizer 等 Hugging Face 模块高度集成,可直接构造模型输入。

  • 功能丰富

    :支持常见的数据处理操作,如批量映射(.map())、字段筛选、训练/验证集划分等。

  • 内存高效

    :数据集默认以内存映射(memory-mapped)方式存储,不会一次性将所有数据加载到内存中。

5.1 安装与导入

复制代码
pip install datasets

5.2 加载本地数据

load_dataset() 是 datasets 库的核心函数,支持多种本地文件格式,如 CSV、JSON、Parquet、文本文件等,并允许一次加载一个或多个文件。它内部会根据数据文件的扩展名(json、csv、parquet、txt 等)自动推断如何加载数据。

支持的数据格式列表

|--------------------|---------|----------------------------------------------------|
| 数据格式 | 类型参数 | 加载示例 |
| CSV/TSV | csv | load_dataset('csv', data_files='data.csv') |
| JSON/JSON Lines | json | load_dataset('json', data_files='data.json') |
| Parquet | parquet | load_dataset('parquet', data_files='data.parquet') |
| 文本文件 | text | load_dataset('text', data_files='data.txt') |
| Pickled DataFrames | pandas | load_dataset('pandas', data_files='data.pkl') |

加载单个文件

复制代码
from datasets import load_dataset

# 加载单个 CSV 文件(返回 DatasetDict,默认 split 名为 "train")
dataset_dict = load_dataset('csv', data_files='./data/online_shopping.csv')

# 访问训练集
dataset = dataset_dict["train"]
print(dataset)
# 输出: Dataset({features: ['review', 'label', 'cat'], num_rows: 10000})

加载多个文件(训练集和测试集)

复制代码
# 使用字典将不同的 split 映射到不同的文件路径
dataset_dict = load_dataset('csv', data_files={
    'train': './data/train.csv',
    'test': './data/test.csv'
})

# 现在可以通过键名访问不同的 split
train_dataset = dataset_dict["train"]
test_dataset = dataset_dict["test"]

print(train_dataset)  # Dataset({features: [...], num_rows: 8000})
print(test_dataset)   # Dataset({features: [...], num_rows: 2000})

使用通配符批量加载

复制代码
# 加载所有符合模式的 CSV 文件
dataset = load_dataset("csv", data_files="data_*.csv")

# 加载特定模式的文件
dataset = load_dataset("json", data_files="data/*.json")

5.3 查看数据集内容

load_dataset() 返回的是一个 DatasetDict 对象,可以像字典一样通过键名(如 "train")访问具体的 Dataset 对象。

复制代码
from datasets import load_dataset

dataset_dict = load_dataset('csv', data_files='data/online_shopping.csv')
dataset = dataset_dict["train"]

# 获取第一条样本
print(dataset[0])
# 输出示例:{'review': '很喜欢的一本书', 'label': 1, 'cat': '书籍'}

# 获取前三条样本的某个字段
print(dataset[:3]['review'])
# 输出:['很喜欢的一本书', '内容丰富', '讲解清晰']

# 获取数据集信息
print(f"数据集大小: {len(dataset)}")
print(f"字段列表: {dataset.column_names}")
print(f"特征类型: {dataset.features}")

5.4 加载在线数据集

Hugging Face Hub 提供了大量开源数据集,涵盖文本分类、问答、翻译、摘要等任务。加载方式与本地数据几乎一致:

复制代码
# 加载 IMDB 情感分析数据集
dataset = load_dataset("imdb")

# 加载 GLUE 基准测试中的 MRPC 数据集
dataset = load_dataset("glue", "mrpc")

# 加载 SQuAD 问答数据集
dataset = load_dataset("squad")

执行上述代码时,数据集会自动从 Hugging Face Hub 下载,并缓存至本地用户目录,默认路径为 ~/.cache/huggingface/datasets/。后续再次使用时将自动从本地加载,无需联网或重复下载。

5.5 数据预处理常用操作

5.5.1 删除列

如果数据集中有些字段在训练中不需要,可以使用 remove_columns() 删除它们,这可以显著减少内存占用:

复制代码
# 删除不需要的字段
dataset = dataset.remove_columns(["cat", "reviewer_id", "timestamp"])

5.5.2 过滤行

使用 .filter() 方法可以筛选符合条件的样本。该方法接收一个返回布尔值的函数,只有返回 True 的样本会被保留:

复制代码
# 保留 review 非空、去除空格后不为空、且 label 为 0 或 1 的样本
dataset = dataset.filter(
    lambda x: x["review"] is not None 
    and x["review"].strip() != "" 
    and x["label"] in [0, 1]
)

.filter() 方法同样支持 batched 参数,可以批量处理以提高效率。

5.5.3 划分训练集和验证集

使用 .train_test_split() 方法可以将单一数据集划分为训练集和验证集:

复制代码
# 按 80/20 比例划分训练集和验证集
dataset_dict = dataset.train_test_split(test_size=0.2, seed=42)

train_dataset = dataset_dict["train"]
eval_dataset = dataset_dict["test"]

print(f"训练集大小: {len(train_dataset)}")
print(f"验证集大小: {len(eval_dataset)}")

seed 参数用于设置随机种子,确保划分结果可复现。

5.5.4 使用 map() 方法进行批量编码

.map() 是 datasets 中最核心的方法之一,可以对整个数据集中的每一条样本(或每一批样本)进行统一处理。这是 Hugging Face 推荐的数据预处理方式。

.map() 方法的基本语法如下:

复制代码
dataset = dataset.map(function, batched=False, remove_columns=None)

|----------------|-----------------------------------|
| 参数 | 说明 |
| function | 要应用到每条样本上的函数(或每批样本上的函数) |
| batched | 是否以"批"为单位处理样本;若为 True,则每次接收一个样本列表 |
| remove_columns | 是否删除原始列,常用于清理不再需要的字段 |

为什么使用 batched=True?

批处理映射的主要目标是加快处理速度。通常,处理批量数据比处理单个样本要快得多。特别是对于 Tokenizer,它在处理批量数据时速度更快,因为会并行处理批次中的所有样本的分词任务。例如,使用 batched=True 处理 1 万条数据可能只需要几秒钟,而逐条处理可能需要几分钟甚至更长时间。

实战:使用 map() 进行分词编码

复制代码
from transformers import AutoTokenizer
from datasets import load_dataset

# 加载模型对应的分词器
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-chinese")

# 定义编码函数
def tokenize_function(examples):
    """
    对每条样本的 review 字段进行编码
    注意:由于设置了 batched=True,examples 是一个字典,
    其中 examples["review"] 是一个列表,包含一批样本的 review 文本
    """
    return tokenizer(
        examples["review"],           # 一批文本
        padding="max_length",         # 填充到固定长度
        truncation=True,              # 自动截断超长文本
        max_length=128                # 最大序列长度
    )

# 加载数据集
dataset = load_dataset('csv', data_files='./data/reviews.csv')["train"]

# 使用 map() 批量处理数据集
# batched=True 让处理更高效,输入数据是批量列表,输出数据也应该是批量列表[reference:31]
encoded_dataset = dataset.map(tokenize_function, batched=True)

# 查看编码后的字段
print(encoded_dataset.column_names)
# 输出: ['review', 'label', 'cat', 'input_ids', 'attention_mask', 'token_type_ids']

.map() 方法的更多用法

复制代码
# 1. 格式化文本(添加前缀)
def add_prefix(examples):
    examples["review"] = ["Review: " + text for text in examples["review"]]
    return examples

dataset = dataset.map(add_prefix, batched=True)

# 2. 增加新字段(如计算文本长度)
def add_length_column(examples):
    examples["text_length"] = [len(text) for text in examples["review"]]
    return examples

dataset = dataset.map(add_length_column, batched=True)

# 3. 数据增强(生成多个改写版本)
def augment_text(examples):
    # 这里可以调用数据增强函数
    examples["augmented"] = [text + " (augmented)" for text in examples["review"]]
    return examples

# 4. 删除原始列,只保留编码后的字段
encoded_dataset = dataset.map(
    tokenize_function, 
    batched=True,
    remove_columns=["review", "cat"]  # 删除不再需要的原始列
)

5.6 保存与加载处理后的数据集

处理后的数据可以保存到本地,供后续训练或复用,避免重复预处理。Datasets 提供了多种保存方式。

5.6.1 保存为 Arrow 格式(推荐)

Arrow 格式是 Hugging Face 官方推荐的数据持久化方式,既支持单个 Dataset 也支持多个子集的 DatasetDict。Arrow 格式的优点是加载速度极快、内存占用低。

复制代码
# 保存 DatasetDict(包含多个 split)
dataset_dict.save_to_disk("./data/processed")

# 保存单个 Dataset
train_dataset.save_to_disk("./data/processed_train")

# 加载
from datasets import load_from_disk
dataset_dict = load_from_disk("./data/processed")
train_dataset = load_from_disk("./data/processed_train")

保存后的目录结构示例:

复制代码
processed/
├── dataset_dict.json
├── train/
│   ├── data-00000-of-00001.arrow
│   ├── dataset_info.json
│   └── state.json
└── test/
│   ├── data-00000-of-00001.arrow
│   ├── dataset_info.json
│   └── state.json

5.6.2 保存为 CSV 或 JSON

如果希望将数据导出为通用格式(如用于可视化或非 Hugging Face 工具使用),可以使用 .to_csv() 或 .to_json() 方法。但需注意,这些方法仅适用于单个 Dataset,不支持 DatasetDict。

复制代码
# 保存为 CSV
train_dataset.to_csv("./data/processed/train.csv")

# 保存为 JSON
train_dataset.to_json("./data/processed/train.json")

# 重新加载
from datasets import load_dataset
csv_dataset = load_dataset("csv", data_files="./data/processed/train.csv")["train"]
json_dataset = load_dataset("json", data_files="./data/processed/train.json")["train"]

5.7 集成 PyTorch DataLoader

经过预处理的 Dataset 对象可以直接与 PyTorch 的 DataLoader 配合使用。虽然它并非继承自 torch.utils.data.Dataset,但由于实现了 len() 和 getitem() 这两个核心接口,因此能够被 DataLoader 正确识别并进行批量迭代。

在使用前,需要通过 set_format() 方法将指定字段转换为张量格式以适配模型输入:

复制代码
from torch.utils.data import DataLoader

# 设置返回格式为 PyTorch 张量,并指定需要转换的字段
train_dataset.set_format(
    type="torch",                    # 指定输出为 PyTorch 张量
    columns=["input_ids", "attention_mask", "label"]  # 需要转换为张量的字段
)

# 需要注意的是:
# - 该方法仅改变通过 dataset[i] 访问样本时的返回格式,不会修改底层数据存储
# - 通过 columns 指定的字段会在访问时自动转换为 torch.Tensor 类型
# - 未通过 columns 指定的字段在访问时将被自动过滤

# 创建 DataLoader
train_dataloader = DataLoader(
    train_dataset, 
    batch_size=32,      # 批量大小
    shuffle=True        # 训练时打乱数据
)

# 迭代训练
for batch in train_dataloader:
    # batch 是一个字典,包含 input_ids, attention_mask, label 等张量
    # batch["input_ids"].shape = (32, max_length)
    # batch["attention_mask"].shape = (32, max_length)
    # batch["label"].shape = (32,)

    outputs = model(**batch)
    loss = outputs.loss
    loss.backward()
    # ... 优化器步骤等

6. 完整实战:从原始数据到模型训练

下面我们将前面学到的所有知识串联起来,完成一个完整的情感分析任务。

6.1 准备数据

复制代码
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import TrainingArguments, Trainer
import torch

# 配置国内镜像(可选)
import os
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'

# 1. 加载本地数据
dataset_dict = load_dataset('csv', data_files={
    'train': './data/train.csv',
    'test': './data/test.csv'
})

# 查看数据格式
print(dataset_dict["train"][0])
# 输出示例:{'review': '非常好用,物超所值', 'label': 1}

6.2 数据预处理

复制代码
# 2. 加载分词器
model_name = "google-bert/bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)

# 3. 定义预处理函数
def preprocess_function(examples):
    """
    对数据集中的每条样本进行分词编码
    """
    return tokenizer(
        examples["review"],           # 文本字段
        truncation=True,              # 自动截断
        padding="max_length",         # 填充到最大长度
        max_length=128                # 最大序列长度
    )

# 4. 对训练集和测试集进行编码
# batched=True 可以显著加快处理速度
encoded_dataset = dataset_dict.map(preprocess_function, batched=True)

# 5. 确认标签列名称正确(如果原始标签列名不是 'label',需要重命名)
# encoded_dataset = encoded_dataset.rename_column("sentiment", "label")

# 6. 设置输出格式为 PyTorch 张量
encoded_dataset.set_format("torch", columns=["input_ids", "attention_mask", "label"])

print("预处理完成!")
print(f"训练集大小: {len(encoded_dataset['train'])}")
print(f"测试集大小: {len(encoded_dataset['test'])}")

6.3 加载模型

复制代码
# 7. 加载预训练模型,添加分类头
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    num_labels=2  # 二分类任务(正面/负面)
)

# 如果有 GPU,将模型移动到 GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
print(f"模型运行设备: {device}")

6.4 配置训练参数并训练

复制代码
# 8. 配置训练参数
training_args = TrainingArguments(
    output_dir="./results",              # 模型保存目录
    evaluation_strategy="epoch",         # 每个 epoch 结束后进行评估
    learning_rate=2e-5,                  # 学习率(BERT 微调常用 2e-5 到 5e-5)
    per_device_train_batch_size=16,      # 训练 batch size(根据 GPU 显存调整)
    per_device_eval_batch_size=16,       # 评估 batch size
    num_train_epochs=3,                  # 训练轮数
    weight_decay=0.01,                   # 权重衰减,防止过拟合
    save_strategy="epoch",               # 每个 epoch 保存一次模型
    logging_dir="./logs",                # 日志目录
    logging_steps=10,                    # 每 10 步打印一次日志
    load_best_model_at_end=True,         # 训练结束后加载最佳模型
    metric_for_best_model="eval_loss",   # 选择最佳模型的指标
)

# 9. 创建 Trainer 并开始训练
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=encoded_dataset["train"],
    eval_dataset=encoded_dataset["test"],
    tokenizer=tokenizer,                 # 自动保存 tokenizer
)

# 开始训练
trainer.train()

# 10. 保存最终模型
trainer.save_model("./final_model")
tokenizer.save_pretrained("./final_model")
print("模型已保存到 ./final_model")

6.5 使用训练好的模型进行推理

复制代码
# 11. 加载训练好的模型进行推理
from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch

model = AutoModelForSequenceClassification.from_pretrained("./final_model")
tokenizer = AutoTokenizer.from_pretrained("./final_model")

# 移动到 GPU(如果有)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
model.eval()  # 切换到评估模式

# 12. 预测新文本
new_texts = [
    "这个产品质量非常好,值得购买!",
    "客服态度很差,再也不买了。",
    "性价比一般,凑合用吧。"
]

# 编码文本
inputs = tokenizer(
    new_texts, 
    padding=True, 
    truncation=True, 
    max_length=128,
    return_tensors="pt"
)

# 移动到相同设备
inputs = {k: v.to(device) for k, v in inputs.items()}

# 推理
with torch.no_grad():
    outputs = model(**inputs)
    logits = outputs.logits
    predictions = torch.argmax(logits, dim=-1)
    probabilities = torch.softmax(logits, dim=-1)

# 输出结果
label_map = {0: "正面", 1: "负面"}
for text, pred, probs in zip(new_texts, predictions, probabilities):
    print(f"文本: {text}")
    print(f"预测: {label_map[pred.item()]}")
    print(f"概率: 正面={probs[0].item():.4f}, 负面={probs[1].item():.4f}")
    print("-" * 50)

预期输出:

复制代码
文本: 这个产品质量非常好,值得购买!
预测: 正面
概率: 正面=0.9876, 负面=0.0124
--------------------------------------------------
文本: 客服态度很差,再也不买了。
预测: 负面
概率: 正面=0.0012, 负面=0.9988
--------------------------------------------------
文本: 性价比一般,凑合用吧。
预测: 正面  # 取决于模型训练数据
概率: 正面=0.6234, 负面=0.3766
--------------------------------------------------

7. 常见问题与解决方案

7.1 模型加载失败:"Missing config.json"

错误原因:指定的路径或模型名称不正确,或者模型文件不完整。

解决方案

复制代码
# 检查模型名称是否正确
model_name = "google-bert/bert-base-chinese"  # 正确格式

# 或者检查本地路径是否存在
import os
if os.path.exists("./my_model/config.json"):
    model = AutoModel.from_pretrained("./my_model")
else:
    print("config.json 不存在,请检查路径")

7.2 显存不足(CUDA Out of Memory)

解决方案

复制代码
# 1. 减小 batch size
training_args = TrainingArguments(
    per_device_train_batch_size=4,  # 从 16 减小到 4
    # ...
)

# 2. 使用梯度累积(等效于增大 batch size)
training_args = TrainingArguments(
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,  # 累积 4 步后更新一次,等效 batch size = 16
    # ...
)

# 3. 使用半精度训练
training_args = TrainingArguments(
    fp16=True,  # 使用 FP16 半精度训练,显存占用减半
    # ...
)

# 4. 减小序列长度
max_length = 64  # 从 128 减小到 64

7.3 分词器与模型不匹配

错误原因:使用的分词器与模型在预训练时使用的分词器不一致。

解决方案

复制代码
# 始终从同一个模型名称加载分词器
model_name = "google-bert/bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# 不要混合使用不同模型的分词器
# ❌ 错误做法
# tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# model = AutoModel.from_pretrained("google-bert/bert-base-chinese")

7.4 数据集加载中文乱码

解决方案

复制代码
# 指定编码格式
dataset = load_dataset('csv', data_files='data.csv', encoding='utf-8')

# 或者使用 pandas 作为中间层
import pandas as pd
df = pd.read_csv('data.csv', encoding='utf-8')
from datasets import Dataset
dataset = Dataset.from_pandas(df)

8. 总结

通过本文的详细讲解和大量代码示例,你应该已经掌握了 Hugging Face 生态中三个最核心的库的使用方法:

Transformers 库:提供了统一的 from_pretrained() 接口,可以轻松加载各种预训练模型。其底层包含五个核心步骤:定位与获取、配置解析、架构构建、权重载入和最终实例化。通过 AutoModelForXXX 系列类,可以快速适配不同的 NLP 任务,每个任务头都是针对特定任务设计的输出层。在加载分类模型时,必须显式指定 num_labels 参数,否则模型会默认使用预训练时的类别数。

Tokenizer 库:负责将原始文本转换为模型可理解的数字输入,支持分词、编码、填充、截断等全流程操作。主流的分词算法包括 BPE(用于 GPT)、WordPiece(用于 BERT)和 SentencePiece(多语言支持)。Tokenizer 与模型必须配套使用------你使用的 Tokenizer 必须跟对应的模型在预训练时的 Tokenizer 保持一致,也就是词表需要一致。推荐使用 tokenizer() 方法(即 call)进行批量编码,并设置 batched=True 以利用并行处理加速。

Datasets 库:提供高效的数据加载与预处理能力,支持本地文件和在线数据集。内置的 map() 方法可以批量处理整个数据集,配合 batched=True 可以显著加快处理速度。预处理后的数据集可以保存为 Arrow 格式(推荐)或 CSV/JSON 格式,并可以直接与 PyTorch DataLoader 无缝集成。Datasets 库的核心优势在于其内存映射机制,可以处理远大于内存的数据集。

这三个库组合在一起,形成了一套完整的 NLP 开发流水线:从数据准备(Datasets)到文本编码(Tokenizer),再到模型加载与训练(Transformers),每一步都有简洁而强大的 API 支持。无论你是做情感分析、命名实体识别、文本生成还是问答系统,这套工作流都能大幅提升开发效率。

最后,不要忘记配置国内镜像站 HF_ENDPOINT=https://hf-mirror.com,可以显著加快模型和数据集的下载速度。如果在使用过程中遇到问题,可以随时查阅 Hugging Face 官方文档或社区论坛。现在,就动手尝试一下吧!

相关推荐
谙弆悕博士3 分钟前
GPT-5.5 Instant 免费开放背后的技术跃迁与战略阳谋
人工智能·python·gpt·chatgpt·学习方法·业界资讯
Purple Coder6 分钟前
《电池储能系统全书:从电芯到电网的公用事业级储能指南》-3
人工智能
AI精钢7 分钟前
把 Markdown 笔记变成可问答的知识图谱:本地 Graph RAG 工具 Kwipu 实测
人工智能·笔记·python·aigc·知识图谱
kobesdu12 分钟前
【ROS2实战笔记-15】ros2bag 的深度应用:从数据回放到系统级离线分析
人工智能·笔记·移动机器人·ros2
AIDF202613 分钟前
第六篇:实战出击——深度学习的“减脂”与“提速”
人工智能·深度学习·框架·推理
AI工具测评与分析16 分钟前
2026年4月GitHub热门开源项目榜单:AI智能体正式迈入工业化协作时代
人工智能·开源·github
俊哥V30 分钟前
每日 AI 研究简报 · 2026-05-08
人工智能·ai
tanis_20771 小时前
学术论文 PDF 的版面自动还原:MinerU 对多栏排版、浮动图表与脚注区域的识别实战
人工智能·pdf·ocr
guo_xiao_xiao_1 小时前
YOLOv11室内果蔬展示苹果目标检测数据集-37张-apple-1_3
人工智能·yolo·目标检测
AI学长1 小时前
数据集|草莓成熟度目标检测数据集-3类530张图
人工智能·目标检测·草莓成熟度目标检测数据集