Day 1: Hugging Face Transformers库
学习目标
- 了解Hugging Face生态系统及其在大模型开发中的重要性
- 掌握Transformers库的核心概念和基本组件
- 学习如何加载和使用预训练模型进行推理
- 理解模型、分词器和配置的关系
- 掌握不同任务类型的模型使用方法
1. Hugging Face生态系统概述
1.1 Hugging Face简介
Hugging Face是一家专注于自然语言处理(NLP)的AI公司,提供了一套完整的工具和平台,使开发者能够更容易地使用、微调和部署最先进的机器学习模型。
核心组件:
- Transformers:提供预训练模型的Python库
- Datasets:用于访问和共享数据集的库
- Tokenizers:高性能的分词库
- Hub:模型和数据集的共享平台
- Accelerate:分布式训练库
- PEFT:参数高效微调库
- Spaces:托管ML演示的平台
1.2 Hugging Face Hub
Hugging Face Hub是一个集中式平台,用于共享、发现和协作机器学习模型、数据集和演示。
主要特点:
- 超过100,000个公开可用的预训练模型
- 数千个公共数据集
- 模型卡片和文档
- 版本控制和模型历史
- 在线推理API
- 社区协作和讨论
常见模型类型:
- 语言模型(GPT、BERT、T5等)
- 图像模型(CLIP、ViT、Stable Diffusion等)
- 音频模型(Whisper、Wav2Vec等)
- 多模态模型(BLIP、LLaVA等)
1.3 与传统JAVA生态系统的对比
特性 | JAVA生态系统 | Hugging Face生态系统 |
---|---|---|
中央仓库 | Maven Central | Hugging Face Hub |
包管理 | Maven/Gradle | pip/conda |
依赖解析 | pom.xml | requirements.txt |
社区贡献 | GitHub/Pull Request | Hub/Pull Request |
文档 | Javadoc | Model Cards |
版本控制 | Semantic Versioning | Git-based |
部署方式 | JAR/WAR/Docker | API/Docker/ONNX |
2. Transformers库基础
2.1 安装和设置
bash
# 基本安装
pip install transformers
# 完整安装(包含所有可选依赖)
pip install transformers[all]
# 特定功能安装
pip install transformers[torch] # PyTorch版本
pip install transformers[tf] # TensorFlow版本
pip install transformers[flax] # JAX/Flax版本
验证安装:
python
import transformers
print(transformers.__version__)
2.2 核心概念
1. 模型(Model):
- 神经网络架构及其权重
- 负责实际的计算和预测
- 可以是编码器、解码器或编码器-解码器架构
2. 分词器(Tokenizer):
- 将文本转换为模型可以处理的数字表示
- 处理特殊标记、填充和截断
- 负责从模型输出转换回人类可读的文本
3. 配置(Configuration):
- 定义模型的架构参数
- 包含隐藏层大小、注意力头数量等信息
- 允许自定义模型行为
4. 流水线(Pipeline):
- 将分词、模型推理和后处理组合成一个简单的接口
- 提供开箱即用的解决方案
- 支持多种常见任务
2.3 基本架构
Transformers库采用统一的API设计,使不同模型可以通过相似的接口使用:
模型类层次结构:
- 基础类 :
PreTrainedModel
- 架构特定类 :
BertModel
,GPT2Model
,T5Model
等 - 任务特定类 :
BertForSequenceClassification
,GPT2LMHeadModel
等
分词器类层次结构:
- 基础类 :
PreTrainedTokenizer
,PreTrainedTokenizerFast
- 模型特定类 :
BertTokenizer
,GPT2Tokenizer
,T5Tokenizer
等
配置类层次结构:
- 基础类 :
PretrainedConfig
- 模型特定类 :
BertConfig
,GPT2Config
,T5Config
等
3. 使用预训练模型
3.1 模型加载
Transformers提供了多种加载预训练模型的方式:
1. 使用AutoClass(推荐):
python
from transformers import AutoModel, AutoTokenizer
# 加载模型和分词器
model_name = "bert-base-uncased"
model = AutoModel.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
2. 使用特定模型类:
python
from transformers import BertModel, BertTokenizer
model = BertModel.from_pretrained("bert-base-uncased")
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
3. 使用流水线:
python
from transformers import pipeline
# 创建文本分类流水线
classifier = pipeline("sentiment-analysis")
3.2 模型推理
基本推理流程:
- 使用分词器处理输入文本
- 将分词后的输入传递给模型
- 处理模型输出
python
# 使用分词器处理文本
text = "Hello, I'm a JAVA developer learning about large language models."
inputs = tokenizer(text, return_tensors="pt")
# 模型推理
outputs = model(**inputs)
# 处理输出
# 输出格式取决于模型类型和任务
使用流水线简化推理:
python
from transformers import pipeline
# 文本分类
classifier = pipeline("sentiment-analysis")
result = classifier("I love learning new technologies!")
print(result) # [{'label': 'POSITIVE', 'score': 0.9998}]
# 文本生成
generator = pipeline("text-generation")
result = generator("As a JAVA developer, I want to")
print(result)
# 问答
qa = pipeline("question-answering")
result = qa(
question="What is Hugging Face?",
context="Hugging Face is an AI company that develops tools for building applications using machine learning."
)
print(result)
3.3 常见模型系列
1. BERT及其变体:
- 双向编码器表示
- 适用于理解任务:分类、命名实体识别、问答等
- 变体:RoBERTa, DistilBERT, ALBERT等
python
from transformers import BertModel, BertTokenizer
model = BertModel.from_pretrained("bert-base-uncased")
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
inputs = tokenizer("Hello, my name is John", return_tensors="pt")
outputs = model(**inputs)
# 获取最后一层隐藏状态
last_hidden_states = outputs.last_hidden_state
2. GPT系列:
- 生成式预训练Transformer
- 适用于生成任务:文本生成、摘要、对话等
- 变体:GPT-2, GPT-Neo, GPT-J等
python
from transformers import GPT2LMHeadModel, GPT2Tokenizer
model = GPT2LMHeadModel.from_pretrained("gpt2")
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# 设置特殊标记
tokenizer.pad_token = tokenizer.eos_token
# 生成文本
input_text = "As a JAVA developer, I want to"
inputs = tokenizer(input_text, return_tensors="pt")
outputs = model.generate(
inputs["input_ids"],
max_length=50,
num_return_sequences=1,
no_repeat_ngram_size=2
)
# 解码输出
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(generated_text)
3. T5系列:
- Text-to-Text Transfer Transformer
- 将所有NLP任务统一为文本到文本的转换
- 适用于多种任务:翻译、摘要、问答、分类等
python
from transformers import T5ForConditionalGeneration, T5Tokenizer
model = T5ForConditionalGeneration.from_pretrained("t5-small")
tokenizer = T5Tokenizer.from_pretrained("t5-small")
# 翻译任务
input_text = "translate English to German: Hello, how are you?"
inputs = tokenizer(input_text, return_tensors="pt")
outputs = model.generate(inputs["input_ids"])
translated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(translated_text)
4. 多语言模型:
- 支持多种语言的模型
- 例如:mBERT, XLM-RoBERTa等
python
from transformers import XLMRobertaModel, XLMRobertaTokenizer
model = XLMRobertaModel.from_pretrained("xlm-roberta-base")
tokenizer = XLMRobertaTokenizer.from_pretrained("xlm-roberta-base")
# 处理不同语言的文本
texts = [
"Hello, how are you?", # 英语
"你好,最近怎么样?", # 中文
"Hola, ¿cómo estás?" # 西班牙语
]
for text in texts:
inputs = tokenizer(text, return_tensors="pt")
outputs = model(**inputs)
# 处理输出...
4. 分词器详解
4.1 分词器的作用
分词器是NLP模型处理文本的第一步,负责将原始文本转换为模型可以理解的数字序列。
主要功能:
- 将文本分割成标记(tokens)
- 将标记转换为ID
- 添加特殊标记(如[CLS], [SEP], [MASK]等)
- 处理序列长度(填充或截断)
- 创建注意力掩码(attention masks)
4.2 分词方法
1. 基于词的分词:
- 将文本分割成完整的词
- 优点:保留词的语义完整性
- 缺点:词表非常大,无法处理未知词
2. 基于字符的分词:
- 将文本分割成单个字符
- 优点:词表小,没有未知标记问题
- 缺点:失去了词级语义,序列长度增加
3. 子词分词(最常用):
- 介于词和字符之间的平衡
- 常见算法:BPE(字节对编码)、WordPiece、SentencePiece、Unigram
- 优点:词表大小适中,可以处理未知词
- 例如:"transforming" → "transform" + "##ing"
4.3 使用分词器
基本用法:
python
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
# 单个文本
encoded = tokenizer("Hello, how are you?")
print(encoded)
# 批量文本
batch_encoded = tokenizer(
["Hello, how are you?", "I'm a JAVA developer"],
padding=True, # 填充到最长序列
truncation=True, # 截断超长序列
max_length=10, # 最大长度
return_tensors="pt" # 返回PyTorch张量
)
print(batch_encoded)
查看分词结果:
python
text = "Hello, I'm a JAVA developer learning about transformers."
encoded = tokenizer(text)
# 获取标记ID
token_ids = encoded["input_ids"]
print(token_ids)
# 将ID转回标记
tokens = tokenizer.convert_ids_to_tokens(token_ids)
print(tokens)
# 将ID转回完整文本
decoded_text = tokenizer.decode(token_ids)
print(decoded_text)
特殊标记和填充:
python
# 查看特殊标记
print(f"CLS token: {tokenizer.cls_token}, ID: {tokenizer.cls_token_id}")
print(f"SEP token: {tokenizer.sep_token}, ID: {tokenizer.sep_token_id}")
print(f"PAD token: {tokenizer.pad_token}, ID: {tokenizer.pad_token_id}")
print(f"UNK token: {tokenizer.unk_token}, ID: {tokenizer.unk_token_id}")
# 手动添加特殊标记
tokens = tokenizer.tokenize("Hello, how are you?")
tokens = [tokenizer.cls_token] + tokens + [tokenizer.sep_token]
token_ids = tokenizer.convert_tokens_to_ids(tokens)
4.4 自定义分词器
从头训练分词器:
python
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace
# 创建一个新的BPE分词器
tokenizer = Tokenizer(BPE())
tokenizer.pre_tokenizer = Whitespace()
# 准备训练器
trainer = BpeTrainer(
special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"],
vocab_size=25000
)
# 从文件训练
files = ["path/to/file1.txt", "path/to/file2.txt"]
tokenizer.train(files, trainer)
# 保存分词器
tokenizer.save("my_tokenizer.json")
将自定义分词器与Transformers集成:
python
from transformers import PreTrainedTokenizerFast
# 从保存的文件加载
tokenizer = PreTrainedTokenizerFast(tokenizer_file="my_tokenizer.json")
# 设置特殊标记
tokenizer.cls_token = "[CLS]"
tokenizer.sep_token = "[SEP]"
tokenizer.pad_token = "[PAD]"
tokenizer.mask_token = "[MASK]"
tokenizer.unk_token = "[UNK]"
5. 任务特定模型使用
5.1 文本分类
文本分类是将文本分配到预定义类别的任务,如情感分析、主题分类等。
python
from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch
# 加载模型和分词器
model_name = "distilbert-base-uncased-finetuned-sst-2-english" # 情感分析模型
model = AutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 准备输入
text = "I really enjoyed the new movie. It was fantastic!"
inputs = tokenizer(text, return_tensors="pt")
# 模型推理
with torch.no_grad():
outputs = model(**inputs)
# 处理输出
logits = outputs.logits
predicted_class = torch.argmax(logits, dim=1).item()
print(f"Predicted class: {predicted_class}")
print(f"Class names: {model.config.id2label}")
使用流水线:
python
from transformers import pipeline
classifier = pipeline("sentiment-analysis")
result = classifier("I really enjoyed the new movie. It was fantastic!")
print(result) # [{'label': 'POSITIVE', 'score': 0.9998}]
5.2 文本生成
文本生成是根据提示或上下文生成连贯文本的任务。
python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# 加载模型和分词器
model_name = "gpt2"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 设置PAD标记
tokenizer.pad_token = tokenizer.eos_token
# 准备输入
text = "As a JAVA developer transitioning to AI, I want to"
inputs = tokenizer(text, return_tensors="pt")
# 生成文本
outputs = model.generate(
inputs["input_ids"],
max_length=100,
num_return_sequences=1,
temperature=0.7, # 控制随机性
top_k=50, # Top-K采样
top_p=0.95, # Top-P (nucleus) 采样
no_repeat_ngram_size=2, # 避免重复n-gram
do_sample=True # 使用采样而非贪婪解码
)
# 解码输出
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(generated_text)
使用流水线:
python
from transformers import pipeline
generator = pipeline("text-generation")
result = generator(
"As a JAVA developer transitioning to AI, I want to",
max_length=100,
num_return_sequences=1
)
print(result[0]["generated_text"])
5.3 问答
问答任务是从给定上下文中找出问题答案的任务。
python
from transformers import AutoModelForQuestionAnswering, AutoTokenizer
import torch
# 加载模型和分词器
model_name = "distilbert-base-cased-distilled-squad"
model = AutoModelForQuestionAnswering.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 准备输入
question = "What is Hugging Face?"
context = "Hugging Face is an AI company that develops tools for building applications using machine learning. Their main product is the Transformers library, which provides pre-trained models for natural language processing tasks."
# 分词
inputs = tokenizer(
question,
context,
return_tensors="pt",
max_length=512,
truncation=True
)
# 模型推理
with torch.no_grad():
outputs = model(**inputs)
# 处理输出
start_logits = outputs.start_logits
end_logits = outputs.end_logits
start_idx = torch.argmax(start_logits).item()
end_idx = torch.argmax(end_logits).item()
# 获取答案
answer_tokens = inputs["input_ids"][0][start_idx:end_idx+1]
answer = tokenizer.decode(answer_tokens)
print(f"Question: {question}")
print(f"Answer: {answer}")
使用流水线:
python
from transformers import pipeline
qa_pipeline = pipeline("question-answering")
result = qa_pipeline(
question="What is Hugging Face?",
context="Hugging Face is an AI company that develops tools for building applications using machine learning. Their main product is the Transformers library, which provides pre-trained models for natural language processing tasks."
)
print(f"Answer: {result['answer']}")
print(f"Score: {result['score']}")
print(f"Start: {result['start']}, End: {result['end']}")
5.4 命名实体识别
命名实体识别(NER)是识别文本中的命名实体(如人名、地名、组织名等)的任务。
python
from transformers import AutoModelForTokenClassification, AutoTokenizer
import torch
# 加载模型和分词器
model_name = "dbmdz/bert-large-cased-finetuned-conll03-english"
model = AutoModelForTokenClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 准备输入
text = "My name is John and I work at Google in Mountain View."
inputs = tokenizer(text, return_tensors="pt")
# 模型推理
with torch.no_grad():
outputs = model(**inputs)
# 处理输出
predictions = torch.argmax(outputs.logits, dim=2)
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])
# 获取标签
results = []
for token, prediction in zip(tokens, predictions[0].numpy()):
label = model.config.id2label[prediction]
if label != "O": # O表示"Outside",即不是命名实体
results.append((token, label))
print(results)
使用流水线:
python
from transformers import pipeline
ner = pipeline("ner")
result = ner("My name is John and I work at Google in Mountain View.")
print(result)
5.5 文本摘要
文本摘要是生成文本的简短版本,保留关键信息的任务。
python
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
# 加载模型和分词器
model_name = "facebook/bart-large-cnn"
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 准备输入
article = """
Hugging Face is an AI company that provides tools for building applications using machine learning.
Their main product is the Transformers library, which offers pre-trained models for natural language processing tasks.
The company also maintains a model hub where developers can share and discover machine learning models.
Founded in 2016, Hugging Face has grown to become a central platform in the AI community,
especially for those working with large language models and other transformer-based architectures.
"""
inputs = tokenizer(article, max_length=1024, return_tensors="pt", truncation=True)
# 生成摘要
summary_ids = model.generate(
inputs["input_ids"],
max_length=150,
min_length=40,
length_penalty=2.0,
num_beams=4,
early_stopping=True
)
# 解码输出
summary = tokenizer.decode(summary_ids[0], skip_special_tokens=True)
print(summary)
使用流水线:
python
from transformers import pipeline
summarizer = pipeline("summarization")
result = summarizer(article, max_length=100, min_length=30)
print(result[0]["summary_text"])
6. 从JAVA开发者视角理解Transformers
6.1 架构对比
JAVA应用架构:
- 分层架构(控制器、服务、数据访问)
- 依赖注入和控制反转
- 接口和实现分离
- 设计模式(工厂、单例、观察者等)
Transformers库架构:
- 模型、分词器、配置的分离
- 自动类作为工厂模式的实现
- 继承体系(基类和特定实现)
- 流水线作为外观模式(Facade Pattern)
6.2 编程范式对比
JAVA编程范式:
- 面向对象编程
- 静态类型
- 编译时类型检查
- 显式异常处理
Python/Transformers编程范式:
- 混合范式(面向对象+函数式)
- 动态类型
- 运行时类型检查
- 更简洁的语法和API
代码风格对比:
JAVA示例:
java
// JAVA中的文本处理
import java.util.List;
import org.apache.commons.text.StringEscapeUtils;
public class TextProcessor {
private final Tokenizer tokenizer;
public TextProcessor(Tokenizer tokenizer) {
this.tokenizer = tokenizer;
}
public List<String> processText(String text) throws ProcessingException {
try {
String cleanedText = StringEscapeUtils.escapeHtml4(text);
return tokenizer.tokenize(cleanedText);
} catch (Exception e) {
throw new ProcessingException("Error processing text", e);
}
}
}
Python/Transformers示例:
python
# Python/Transformers中的文本处理
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
def process_text(text):
try:
return tokenizer(text)
except Exception as e:
print(f"Error processing text: {e}")
return None
6.3 工作流对比
JAVA开发工作流:
- 定义接口和类
- 实现业务逻辑
- 编写单元测试
- 构建和部署
Transformers开发工作流:
- 选择预训练模型
- 准备数据和分词
- 微调或直接使用模型
- 评估和部署
6.4 实践建议
利用已有技能:
- 软件工程原则仍然适用
- 模块化和可测试性很重要
- 版本控制和文档同样关键
适应新范式:
- 拥抱Python的简洁性和灵活性
- 学习函数式编程概念
- 理解深度学习的特殊性质(如梯度下降、随机性)
开发习惯转变:
- 从"从头构建"到"利用预训练模型"
- 从"确定性逻辑"到"概率性预测"
- 从"编写所有代码"到"组合现有组件"
7. 实践练习
练习1:基本模型使用
- 安装Transformers库
- 加载BERT模型和分词器
- 对一段文本进行编码和解码
- 获取模型的隐藏状态输出
- 探索模型配置参数
练习2:文本分类
- 使用情感分析流水线分析5个不同的评论文本
- 加载分类模型并直接使用(不通过流水线)
- 比较不同预训练分类模型的结果
- 分析模型的置信度分数
练习3:文本生成
- 使用GPT-2模型生成文本
- 尝试不同的生成参数(温度、top-k、top-p等)
- 为生成提供不同的提示(prompt)
- 比较生成结果的质量和多样性
练习4:问答系统
- 创建一个简单的问答系统
- 准备一个包含多个段落的文档
- 对文档提出5个不同的问题
- 评估模型回答的准确性
8. 总结与反思
- Hugging Face生态系统提供了一套完整的工具,使开发者能够轻松使用、微调和部署最先进的机器学习模型
- Transformers库的核心组件包括模型、分词器和配置,它们共同工作以实现各种NLP任务
- 预训练模型可以通过简单的API调用加载和使用,大大降低了开发难度
- 分词器在NLP处理中扮演关键角色,负责将文本转换为模型可以处理的数字表示
- 不同任务(如分类、生成、问答等)有专门的模型类和流水线,使用方法类似但输出处理不同
- 对于JAVA开发者,理解Python和Transformers的编程范式和架构差异有助于更快适应大模型开发
9. 预习与延伸阅读
预习内容
- 模型微调的基本概念和方法
- 数据集准备和处理
- 评估指标和模型性能分析
- 低资源环境下的模型优化
延伸阅读
- Hugging Face官方文档:huggingface.co/docs
- Lewis Tunstall等,《Natural Language Processing with Transformers》
- Thomas Wolf等,《Transformers: State-of-the-Art Natural Language Processing》
- Jay Alammar的博客:《The Illustrated Transformer》
- Andrej Karpathy的博客:《The Unreasonable Effectiveness of Recurrent Neural Networks》
10. 明日预告
明天我们将学习如何微调预训练模型,这是大模型应用开发的核心技能之一。我们将探讨数据准备、微调策略、评估方法以及如何在资源有限的情况下进行高效微调。我们还将介绍参数高效微调方法(PEFT),如LoRA、Adapter等技术,这些技术可以大大降低微调大模型的资源需求。