听诊器的发明,让医生第一次能听见心肺的内部声音。 Transformer 的诞生,则让机器第一次真正理解了语言的上下文。对医疗人来说,这不只是技术的突破,它意味着我们可以重新思考如何让 AI 在临床、科研和患者服务中发挥作用。
作为医疗从业者,我们每天都要处理庞杂的信息:病历、科研文献……而 Transformer 正是当下所有大语言模型(LLM)的核心。理解它,等于理解了 ChatGPT、医学辅助诊断系统、自动科研写作工具的根基。
所以,接下来我希望带你一步步走入 Transformer 学习课程,用通俗的方式来理解复杂的技术。
需要课程代码以及问题咨询通过留言
在路上的蟹老板(pqjrkwem@gmail.com)
课程简介
本课程将教你如何使用 Transformaer 生态系统的库进行自然语言处理(NLP)。
涵盖的库
- Transformers - 核心模型库
- Datasets - 数据集处理
- Tokenizers - 文本分词
- Accelerate - 训练加速
- Hugging Face Hub - 模型共享平台
课程结构
第 1-4 章:Transformers 基础
介绍 Transformers 库的主要概念。完成后你将:
- 了解 Transformer 模型的工作原理
- 使用 Transformer 模型
- 微调一个预训练模型
- 分享模型和标记器
第 5-8 章:拥有一个自己的模型
- Datasets库
- Tokenizers库
- 主要的 NLP 任务
- 构建和分享你的模型
学习要求
具备:
良好的 Python 知识, 要是熟悉 深度学习和机器学习就更好了, 对于tensorflow 或者 pytorch 熟悉更更更加分
Tokenizer 详解
Tokenization 算法
基于单词(Word-based)
tokenized_text = "Jim Henson was a puppeteer".split()
# ['Jim', 'Henson', 'was', 'a', 'puppeteer']
基于单词的分词示例:
┌─────────────────────────────────────────────────┐
│ 原始文本: "Jim Henson was a puppeteer" │
│ ↓ │
│ 分词结果: [Jim] [Henson] [was] [a] [puppeteer] │
│ ↓ │
│ Token IDs: [5234] [6721] [1098] [23] [9876] │
└─────────────────────────────────────────────────┘
优点:简单易用
缺点:词汇表很大,相似词被视为不同(如 “dog” 和 “dogs”)
基于字符(Character-based)
基于字符的分词示例:
┌──────────────────────────────────────────────────┐
│ 原始文本: "Hello" │
│ ↓ │
│ 分词结果: [H] [e] [l] [l] [o] │
│ ↓ │
│ Token IDs: [72] [101] [108] [108] [111] │
└──────────────────────────────────────────────────┘
优点:词汇表小,未知 token 少
缺点:单个字符语义信息少,序列长度大幅增加
基于子词(Subword)
结合两种方法的优点,常用词保持完整,罕见词分解为子词。
基于子词的分词示例:
┌──────────────────────────────────────────────────────┐
│ 原始文本: "Let's do tokenization!" │
│ ↓ │
│ 分词结果: [Let] ['s] [do] [token] [ization] [!] │
│ ↓ │
│ Token IDs: [2421] [188] [342] [19204] [2734] [999] │
└──────────────────────────────────────────────────────┘
例如:"annoyingly" → "annoying" + "ly""tokenization" → "token" + "ization"
常见算法:
- Byte-level BPE(GPT-2)
- WordPiece(BERT)
- SentencePiece/Unigram(多语言模型)
加载和保存 Tokenizer
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
# 使用
tokenizer("Using a Transformer network is simple")
# 保存
tokenizer.save_pretrained("directory_on_my_computer")
编码过程
编码分两步:分词 → 转换为 ID
分词
sequence = "Using a Transformer network is simple"
tokens = tokenizer.tokenize(sequence)
print(tokens)
# ['Using', 'a', 'transform', '##er', 'network', 'is', 'simple']
转换为 ID
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)
# [7993, 170, 11303, 1200, 2443, 1110, 3014]
解码
decoded_string = tokenizer.decode([7993, 170, 11303, 1200, 2443, 1110, 3014])
print(decoded_string)
# 'Using a Transformer network is simple'
综合应用
Tokenizer 的高级功能:
from transformers import AutoTokenizer
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
# 单个句子
sequence = "I've been waiting for a HuggingFace course my whole life."
model_inputs = tokenizer(sequence)
# 多个句子
sequences = [
"I've been waiting for a HuggingFace course my whole life.",
"So have I!"
]
model_inputs = tokenizer(sequences)
# 填充
model_inputs = tokenizer(sequences, padding="longest")
model_inputs = tokenizer(sequences, padding="max_length")
model_inputs = tokenizer(sequences, padding="max_length", max_length=8)
# 截断
model_inputs = tokenizer(sequences, truncation=True)
model_inputs = tokenizer(sequences, max_length=8, truncation=True)
# 返回特定框架的张量
model_inputs = tokenizer(sequences, padding=True, return_tensors="pt") # PyTorch
model_inputs = tokenizer(sequences, padding=True, return_tensors="tf") # TensorFlow
model_inputs = tokenizer(sequences, padding=True, return_tensors="np") # NumPy
特殊 Token
Tokenizer 会自动添加特殊 token:
sequence = "I've been waiting for a HuggingFace course my whole life."
model_inputs = tokenizer(sequence)
print(tokenizer.decode(model_inputs["input_ids"]))
# "[CLS] i've been waiting for a huggingface course my whole life. [SEP]"
完整流程
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = [
"I've been waiting for a HuggingFace course my whole life.",
"So have I!"
]
tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")
output = model(**tokens)
章末小测验
1. 自然语言处理流程的顺序是什么?
❌ 首先是模型它处理文本并返回原始预测。然后 tokenizer 会对这些预测进行解释,并在将它们转换回文本
❌ 首先 Tokenizer 处理文本并返回 id。模型根据这些 id 并输出预测,可以是一些文本。
✅ Tokenizer 处理文本并返回 ID。模型处理这些 ID 并输出预测。然后可以再次使用 tokenizer 将这些预测转换回文本。
2. Transformer 模型输出张量的维度是?
❌ 2 个维度:序列长度(Sequence Length)和批次大小(Batch Size)
❌ 2 个维度:序列长度(Sequence Length)和隐藏层大小(Hidden Size)
✅ 3 个维度:序列长度(Sequence Length)、批次大小(Batch Size)和隐藏层大小(Hidden Size)
3. 下列哪些是子词分词的例子?
✅ WordPiece
❌ 基于单个字符的分词
❌ 基于空格和标点符号的分割
✅ BPE (Byte Pair Encoding)
✅ Unigram
❌ 以上都不是
4. 什么是模型头(Head)?
❌ 原始 Transformer 网络的一种组件,直接将张量输入到正确的层
❌ 也称为自注意力(self-attention)机制,它会根据序列的其他 tokens 调整一个 token 的表示
✅ 一个附加组件,通常由一个或几个层组成,用于将 Transformer 的预测转换为特定任务的输出
5. 什么是 AutoModel?
❌ 根据你的数据自动进行训练的模型
✅ 一个根据 checkpoint 返回模型体系结构的对象
❌ 一种可以自动检测输入语言来加载正确权重的模型
6. 批处理不同长度的句子需要哪些处理?
✅ 截断
❌ 直接将 Tensors 返回
✅ 填充
✅ 注意力掩码(Attention masking)
7. 对 logits 使用 SoftMax 的意义?
❌ 它软化了 logits 输出,使结果更可靠
❌ 它限定了上下界,使模型的输出结果可以被解释
✅ 输出的和是 1,从而产生概率解释
8. Tokenizer API 的核心方法是?
❌ encode
因为它可以将文本编码为 ID,将预测的 ID 解码为文本
✅ 直接调用 Tokenizer 对象
❌ pad
(填充)
❌ tokenize
9. tokenizer.tokenize("Hello!")
返回什么?
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
result = tokenizer.tokenize("Hello!")
✅ 字符串列表,每个字符串都是一个 token
❌ 一个 ID 的列表
❌ 包含所有分词后的字符串
10. 以下代码有什么错误?
from transformers import AutoTokenizer, AutoModel
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
model = AutoModel.from_pretrained("gpt2")
encoded = tokenizer("Hey!", return_tensors="pt")
result = model(**encoded)
❌ 不,看起来是对的
✅ Tokenizer 和模型应该来自相同的 checkpoint
❌ 由于模型输入需要是一个 Batch,因此可以使用 tokenizer 对其进行截断或填充来改进这段代码
总结
恭喜完成本章学习!你已经掌握:
- Transformer 模型的基本构造
- Tokenizer 管道的组成
- 如何使用 Transformers 模型
- 如何利用 tokenizer 转换文本
- Input IDs 的局限性和注意力掩码
- 灵活可配置的 Tokenizer 方法