Article

模型加载 Transformers 官方文档

更新于:2026-07-20

快速教程

1. pipeline 支持的任务

任务描述模态Pipeline
文本分类为给定的文本序列分配一个标签NLPpipeline(task="sentiment-analysis")
文本生成根据给定的提示生成文本NLPpipeline(task="text-generation")
命名实体识别为序列里的每个 token 分配一个标签(人, 组织, 地址等等)NLPpipeline(task="ner")
问答系统通过给定的上下文和问题, 在文本中提取答案NLPpipeline(task="question-answering")
掩盖填充预测出正确的在序列中被掩盖的 tokenNLPpipeline(task="fill-mask")
文本摘要为文本序列或文档生成总结NLPpipeline(task="summarization")
文本翻译将文本从一种语言翻译为另一种语言NLPpipeline(task="translation")
图像分类为图像分配一个标签Computer visionpipeline(task="image-classification")
图像分割为图像中每个独立的像素分配标签(支持语义、全景和实例分割)Computer visionpipeline(task="image-segmentation")
目标检测预测图像中目标对象的边界框和类别Computer visionpipeline(task="object-detection")
音频分类给音频文件分配一个标签Audiopipeline(task="audio-classification")
自动语音识别将音频文件中的语音提取为文本Audiopipeline(task="automatic-speech-recognition")
视觉问答给定一个图像和一个问题,正确地回答有关图像的问题Multimodalpipeline(task="vqa")

pipeline 使用示例:

# 加载
from transformers import pipeline

classifier = pipeline("sentiment-analysis")

# 测试单个文本
classifier("We are very happy to show you the 🤗 Transformers library.")
# 测试多个文本
results = classifier(["We are very happy to show you the 🤗 Transformers library.", "We hope you don't hate it."])
for result in results:
    print(f"label: {result['label']}, with score: {round(result['score'], 4)}")

# 加载模型与分词器
model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
from transformers import AutoTokenizer, AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 测试
classifier = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer)
classifier("Nous sommes très heureux de vous présenter la bibliothèque 🤗 Transformers.")

2. AutoClass

a. AutoTokenizer

from transformers import AutoTokenizer

model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 测试-处理单个文本
encoding = tokenizer("We are very happy to show you the 🤗 Transformers library.")
print(encoding)

分词器返回了含有如下内容的字典:

  • input_ids:用数字表示的 token。
  • attention_mask:应该关注哪些 token 的指示。
# 测试-处理多个文本
pt_batch = tokenizer(
    ["We are very happy to show you the 🤗 Transformers library.", "We hope you don't hate it."],
    padding=True,
    truncation=True,
    max_length=512,
    return_tensors="pt",
)

b. AutoModel

from transformers import AutoModelForSequenceClassification

model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
pt_model = AutoModelForSequenceClassification.from_pretrained(model_name)

pt_outputs = pt_model(**pt_batch)
# 应用softmax将logits转换为概率
from torch import nn

pt_predictions = nn.functional.softmax(pt_outputs.logits, dim=-1)
print(pt_predictions)

c. 保存模型

# 保存
pt_save_directory = "./pt_save_pretrained"
tokenizer.save_pretrained(pt_save_directory)
pt_model.save_pretrained(pt_save_directory)

# 加载
pt_model = AutoModelForSequenceClassification.from_pretrained("./pt_save_pretrained")

# 模型类型转换
from transformers import AutoModel

tokenizer = AutoTokenizer.from_pretrained(pt_save_directory)
pt_model = AutoModelForSequenceClassification.from_pretrained(pt_save_directory, from_pt=True)

3. 自定义模型构建

# 导入参数
from transformers import AutoConfig

my_config = AutoConfig.from_pretrained("distilbert/distilbert-base-uncased", n_heads=12)
# 根据config创建模型
from transformers import AutoModel

my_model = AutoModel.from_config(my_config)

4. Trainer - PyTorch 优化训练循环

a. 加载模型

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained("distilbert/distilbert-base-uncased")

b. 修改模型参数

from transformers import TrainingArguments

training_args = TrainingArguments(
    output_dir="path/to/save/folder/",
    learning_rate=2e-5,
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    num_train_epochs=2,
)

c. 分词器

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")

d. 加载数据集

from datasets import load_dataset

dataset = load_dataset("rotten_tomatoes")  # doctest: +IGNORE_RESULT

e. 创建数据集处理函数,使用 map 对数据集进行处理

def tokenize_dataset(dataset):
    return tokenizer(dataset["text"])

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

f. 创建数据整理器

from transformers import DataCollatorWithPadding

data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

g. 完善 Trainer,启动训练

from transformers import Trainer

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=dataset["train"],
    eval_dataset=dataset["test"],
    processing_class=tokenizer,
    data_collator=data_collator,
)  # doctest: +SKIP

trainer.train()

安装:https://huggingface.co/docs/transformers/v4.52.3/zh/installation


使用 pipeline 进行推理

1. pipeline 的使用

a. 创建 pipeline

from transformers import pipeline

transcriber = pipeline(task="automatic-speech-recognition")

b. 使用 pipeline

# 处理单个输入
transcriber("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")
# 处理多个输入
transcriber(
    [
        "https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac",
        "https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/1.flac",
    ]
)

2. 参数

a. 指定设备上创建 pipeline

transcriber = pipeline(model="openai/whisper-large-v2", device=0)

b. 指定批量大小

transcriber = pipeline(model="openai/whisper-large-v2", device=0, batch_size=2)
audio_filenames = [f"https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/{i}.flac" for i in range(1, 5)]
texts = transcriber(audio_filenames)

c. 指定任务参数

transcriber = pipeline(model="openai/whisper-large-v2", chunk_length_s=30, return_timestamps=True)
transcriber("https://huggingface.co/datasets/sanchit-gandhi/librispeech_long/resolve/main/audio.wav")

3. 在数据集上使用 pipeline

# 从迭代器中获取数据
def data():
    for i in range(1000):
        yield f"My example {i}"


pipe = pipeline(model="openai-community/gpt2", device=0)
generated_characters = 0
for out in pipe(data()):
    generated_characters += len(out[0]["generated_text"])
# 从数据集中获取数据
# KeyDataset is a util that will just output the item we're interested in.
from transformers.pipelines.pt_utils import KeyDataset
from datasets import load_dataset

pipe = pipeline(model="hf-internal-testing/tiny-random-wav2vec2", device=0)
dataset = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation[:10]")

for out in pipe(KeyDataset(dataset, "audio")):
    print(out)

4. 在 Web 服务器上使用 pipeline

a. 视觉 pipeline

from transformers import pipeline

vision_classifier = pipeline(model="google/vit-base-patch16-224")
preds = vision_classifier(
    images="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg"
)
preds = [{"score": round(pred["score"], 4), "label": pred["label"]} for pred in preds]
preds

b. 文本 pipeline

from transformers import pipeline

# This model is a `zero-shot-classification` model.
# It will classify text, except you are free to choose any label you might imagine
classifier = pipeline(model="facebook/bart-large-mnli")
classifier(
    "I have a problem with my iphone that needs to be resolved asap!!",
    candidate_labels=["urgent", "not urgent", "phone", "tablet", "computer"],
)

c. 多模态 pipeline

from transformers import pipeline

vqa = pipeline(model="impira/layoutlm-document-qa")
output = vqa(
    image="https://huggingface.co/spaces/impira/docquery/resolve/2359223c1837a7587402bda0f2643382a6eefeab/invoice.png",
    question="What is the invoice number?",
)
output[0]["score"] = round(output[0]["score"], 3)
output

5. 使用 Accelerate 在大模型上运行 pipeline

# 加载moxing
# pip install accelerate
import torch
from transformers import pipeline

pipe = pipeline(model="facebook/opt-1.3b", torch_dtype=torch.bfloat16, device_map="auto")
output = pipe("This is a cool example!", do_sample=True, top_p=0.95)

# 安装bitsandbytes并添加参数Accelerate=True
# pip install accelerate bitsandbytes
import torch
from transformers import pipeline

pipe = pipeline(model="facebook/opt-1.3b", device_map="auto", model_kwargs={"load_in_8bit": True})
output = pipe("This is a cool example!", do_sample=True, top_p=0.95)

使用 AutoClass 编写可移植的代码

1. 加载预训练的分词器

# 加载
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
# 测试
sequence = "In a hole in the ground there lived a hobbit."
print(tokenizer(sequence))

2. 加载预训练的图像处理器

# 加载
from transformers import AutoImageProcessor

image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")

3. 加载预训练的特征提取器

# 加载
from transformers import AutoFeatureExtractor

feature_extractor = AutoFeatureExtractor.from_pretrained(
    "ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition"
)

4. 加载预训练的处理器

# 加载
from transformers import AutoProcessor

processor = AutoProcessor.from_pretrained("microsoft/layoutlmv2-base-uncased")

5. 加载预训练的模型

# 加载
from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained("distilbert/distilbert-base-uncased")

预处理数据

任务预处理类型作用
自然语言处理分词器Tokenizer将文本转换为一系列标记(tokens),并创建 tokens 的数字表示,将它们组合成张量
音频处理特征提取器Feature extractor从音频波形中提取顺序特征并将其转换为张量
图像处理图像处理器ImageProcessor将图像转换为张量
多模态输入处理器Processor结合了 Tokenizer 和 ImageProcessor 或 Processor

1. 自然语言处理

# 加载分词器
from transformers import AutoTokenizer

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

# 处理单个文本
encoded_input = tokenizer("Do not meddle in the affairs of wizards, for they are subtle and quick to anger.")
print(encoded_input)

# 处理多个文本
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_inputs = tokenizer(batch_sentences)
print(encoded_inputs)

# 解码器
tokenizer.decode(encoded_input["input_ids"])

分词器返回内容:

  • input_ids 是与句子中每个 token 对应的索引。
  • attention_mask 指示是否应该关注一个 token。
  • token_type_ids 在存在多个序列时标识一个 token 属于哪个序列。

a. 填充

# 将 padding 参数设置为 True,以使批次中较短的序列填充到与最长序列相匹配的长度
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True)
print(encoded_input)

b. 截断

# 将 truncation 参数设置为 True,以将序列截断为模型接受的最大长度
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True)
print(encoded_input)

c. 构建张量

# 将 return_tensors 参数设置为 pt(对于PyTorch)或 tf(对于TensorFlow)
batch_sentences = [
    "But what about second breakfast?",
    "Don't think he knows about second breakfast, Pip.",
    "What about elevensies?",
]
encoded_input = tokenizer(batch_sentences, padding=True, truncation=True, return_tensors="pt")
print(encoded_input)

2. 音频

# 加载数据集
from datasets import load_dataset, Audio

dataset = load_dataset("PolyAI/minds14", name="en-US", split="train")

# 查看输入
dataset[0]["audio"]

返回内容:

  • array 是加载的语音信号 - 并在必要时重新采为 1D array。
  • path 指向音频文件的位置。
  • sampling_rate 是每秒测量的语音信号数据点数量。
# 使用🤗 Datasets的cast_column方法将采样率提升到16kHz:
dataset = dataset.cast_column("audio", Audio(sampling_rate=16_000))
# 再次调用 audio 列以重新采样音频文件:
dataset[0]["audio"]

# 加载特征提取器
from transformers import AutoFeatureExtractor

feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")

# 使用
audio_input = [dataset[0]["audio"]["array"]]
feature_extractor(audio_input, sampling_rate=16000)

# 填充与截断
def preprocess_function(examples):
    audio_arrays = [x["array"] for x in examples["audio"]]
    inputs = feature_extractor(
        audio_arrays,
        sampling_rate=16000,
        padding=True,
        max_length=100000,
        truncation=True,
    )
    return inputs

processed_dataset = preprocess_function(dataset[:5])

# 查看填充、截断效果
processed_dataset["input_values"][0].shape

processed_dataset["input_values"][1].shape

3. 计算机视觉

# 数据集加载
from datasets import load_dataset

dataset = load_dataset("food101", split="train[:100]")

# 查看图像
dataset[0]["image"]

# 加载图像处理器
from transformers import AutoImageProcessor

image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")

# 调整大小、随机裁剪、调整颜色
from torchvision.transforms import RandomResizedCrop, ColorJitter, Compose

size = (
    image_processor.size["shortest_edge"]
    if "shortest_edge" in image_processor.size
    else (image_processor.size["height"], image_processor.size["width"])
)

_transforms = Compose([RandomResizedCrop(size), ColorJitter(brightness=0.5, hue=0.5)])

# 图像标准化
def transforms(examples):
    images = [_transforms(img.convert("RGB")) for img in examples["image"]]
    examples["pixel_values"] = image_processor(images, do_resize=False, return_tensors="pt")["pixel_values"]
    return examples

# 应用变换
dataset.set_transform(transforms)

# 查看变换结果
import numpy as np
import matplotlib.pyplot as plt

img = dataset[0]["pixel_values"]
plt.imshow(img.permute(1, 2, 0))

# 填充
def collate_fn(batch):
    pixel_values = [item["pixel_values"] for item in batch]
    encoding = image_processor.pad(pixel_values, return_tensors="pt")
    labels = [item["labels"] for item in batch]
    batch = {}
    batch["pixel_values"] = encoding["pixel_values"]
    batch["pixel_mask"] = encoding["pixel_mask"]
    batch["labels"] = labels
    return batch

4. 多模态

# 加载数据集
from datasets import load_dataset

lj_speech = load_dataset("lj_speech", split="train")

# 删除多余列
lj_speech = lj_speech.map(remove_columns=["file", "id", "normalized_text"])

# 查看列
lj_speech[0]["audio"]

lj_speech[0]["text"]

# 重采样,改变采样率
lj_speech = lj_speech.cast_column("audio", Audio(sampling_rate=16_000))

# 加载处理器
from transformers import AutoProcessor

processor = AutoProcessor.from_pretrained("facebook/wav2vec2-base-960h")

# 构建数据集
def prepare_dataset(example):
    audio = example["audio"]

    example.update(processor(audio=audio["array"], text=example["text"], sampling_rate=16000))

    return example

# 测试
prepare_dataset(lj_speech[0])

微调预训练模型

1. 准备数据集

# 加载Yelp评论集
from datasets import load_dataset

dataset = load_dataset("yelp_review_full")
dataset["train"][100]

# 加载分词器,处理数据集
from transformers import AutoTokenizer

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


def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True)


tokenized_datasets = dataset.map(tokenize_function, batched=True)

# 数据集抽取
small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))

2. 训练

a. 使用 Trainer 进行训练

# 模型加载
from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained("google-bert/bert-base-cased", num_labels=5)
i. 训练超参数
# 默认超参数
from transformers import TrainingArguments

training_args = TrainingArguments(output_dir="test_trainer")
ii. 评估
# 加载accuracy函数
import numpy as np
import evaluate

metric = evaluate.load("accuracy")

# 评估函数
def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)

# 微调过程中监控评估指标
from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(output_dir="test_trainer", eval_strategy="epoch")
iii. 训练器
# 创建训练器
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=small_train_dataset,
    eval_dataset=small_eval_dataset,
    compute_metrics=compute_metrics,
)

# 微调模型
trainer.train()

b. 使用 Keras 训练 TensorFlow 模型

i. 加载用于 Keras 的数据
# 加载数据集
from datasets import load_dataset

dataset = load_dataset("glue", "cola")
dataset = dataset["train"]  # Just take the training split for now

# 加载分词器
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-cased")
tokenized_data = tokenizer(dataset["sentence"], return_tensors="np", padding=True)
# Tokenizer returns a BatchEncoding, but we convert that to a dict for Keras
tokenized_data = dict(tokenized_data)

labels = np.array(dataset["label"])  # Label is already an array of 0 and 1

# 加载、编译、使用模型
from transformers import TFAutoModelForSequenceClassification
from tensorflow.keras.optimizers import Adam

# Load and compile our model
model = TFAutoModelForSequenceClassification.from_pretrained("google-bert/bert-base-cased")
# Lower learning rates are often better for fine-tuning transformers
model.compile(optimizer=Adam(3e-5))  # No loss argument!

model.fit(tokenized_data, labels)
ii. 将数据加载为 tf.data.Dataset
# 处理tokenizer输出,添加到数据集
def tokenize_dataset(data):
    # Keys of the returned dictionary will be added to the dataset as columns
    return tokenizer(data["text"])


dataset = dataset.map(tokenize_dataset)

# 流式传输批次数据
tf_dataset = model.prepare_tf_dataset(dataset["train"], batch_size=16, shuffle=True, tokenizer=tokenizer)

# 编译、训练模型
model.compile(optimizer=Adam(3e-5))  # No loss argument!

model.fit(tf_dataset)

c. 在原生 PyTorch 中训练

# 释放内存
del model
del trainer
torch.cuda.empty_cache()

# 移除text列
tokenized_datasets = tokenized_datasets.remove_columns(["text"])

# label列重命名为labels
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")

# 转换数据集格式为PyTorch张量
tokenized_datasets.set_format("torch")

# 数据集抽取
small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))
i. DataLoader
# 创建数据集
from torch.utils.data import DataLoader

train_dataloader = DataLoader(small_train_dataset, shuffle=True, batch_size=8)
eval_dataloader = DataLoader(small_eval_dataset, batch_size=8)

# 加载模型,指定标签数量
from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained("google-bert/bert-base-cased", num_labels=5)
ii. Optimizer、lr_scheduler
# 创建优化器
from torch.optim import AdamW

optimizer = AdamW(model.parameters(), lr=5e-5)

# 创建学习率调度器
from transformers import get_scheduler

num_epochs = 3
num_training_steps = num_epochs * len(train_dataloader)
lr_scheduler = get_scheduler(
    name="linear", optimizer=optimizer, num_warmup_steps=0, num_training_steps=num_training_steps
)

# 指定训练设备
import torch

device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
model.to(device)
iii. 训练循环
from tqdm.auto import tqdm

progress_bar = tqdm(range(num_training_steps))

model.train()
for epoch in range(num_epochs):
    for batch in train_dataloader:
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        loss = outputs.loss
        loss.backward()

        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()
        progress_bar.update(1)
iv. 评估
# 使用 add_batch 累积所有批次,并在最后计算指标
import evaluate

metric = evaluate.load("accuracy")
model.eval()
for batch in eval_dataloader:
    batch = {k: v.to(device) for k, v in batch.items()}
    with torch.no_grad():
        outputs = model(**batch)

    logits = outputs.logits
    predictions = torch.argmax(logits, dim=-1)
    metric.add_batch(predictions=predictions, references=batch["labels"])

metric.compute()

通过脚本训练模型:https://huggingface.co/docs/transformers/v4.52.3/zh/run_scripts


使用 Accelerate 进行分布式训练

1. 设置

# 安装
pip install accelerate
# 创建Accelerate对象
from accelerate import Accelerator

accelerator = Accelerator()

2. 准备加速

# 用加速的backward替换训练循环中的loss.backward()
for epoch in range(num_epochs):
    for batch in train_dataloader:
        outputs = model(**batch)
        loss = outputs.loss
        accelerator.backward(loss)

        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()
        progress_bar.update(1)

3. 反向传播

Accelerate 加速代码与原代码的区别(+ 为 Accelerate 代码,- 为原代码):

+ from accelerate import Accelerator
  from transformers import AdamW, AutoModelForSequenceClassification, get_scheduler

+ accelerator = Accelerator()

  model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)
  optimizer = AdamW(model.parameters(), lr=3e-5)

- device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
- model.to(device)

+ train_dataloader, eval_dataloader, model, optimizer = accelerator.prepare(
+     train_dataloader, eval_dataloader, model, optimizer
+ )

  num_epochs = 3
  num_training_steps = num_epochs * len(train_dataloader)
  lr_scheduler = get_scheduler(
      "linear",
      optimizer=optimizer,
      num_warmup_steps=0,
      num_training_steps=num_training_steps
  )

  progress_bar = tqdm(range(num_training_steps))

  model.train()
  for epoch in range(num_epochs):
      for batch in train_dataloader:
-         batch = {k: v.to(device) for k, v in batch.items()}
          outputs = model(**batch)
          loss = outputs.loss
-         loss.backward()
+         accelerator.backward(loss)

          optimizer.step()
          lr_scheduler.step()
          optimizer.zero_grad()
          progress_bar.update(1)

4. 训练

a. 用脚本训练

# 命令行进行配置
accelerate config
# 命令行启动训练
accelerate launch train.py

b. 用 Notebook 训练

from accelerate import notebook_launcher

notebook_launcher(training_function)

使用 PEFT 加载和训练 adapters

参数高效微调(PEFT)方法:在微调过程中冻结预训练模型的参数,并在其顶部添加少量可训练参数(adapters)。adapters 被训练以学习特定任务的信息。这种方法已被证明非常节省内存,同时具有较低的计算使用量,同时产生与完全微调模型相当的结果。

1. 设置

# 安装peft
pip install peft

# 或者安装新版本
pip install git+https://github.com/huggingface/peft.git

2. 支持的 PEFT 模型

Transformers 库支持以下 PEFT 方法:

  • Low Rank Adapters
  • IA3
  • AdaLoRA

3. 加载 PEFT adapter

从 huggingface 的 Transformers 库中加载并使用 PEFT adapter 模型,Hub 仓库或本地目录中包含一个 adapter_config.json 文件和 adapter 权重。

# 加载PEFT adapter模型
from transformers import AutoModelForCausalLM, AutoTokenizer

peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(peft_model_id)

# 通过load_adapter方法加载PEFT adapter
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "facebook/opt-350m"
peft_model_id = "ybelkada/opt-350m-lora"

model = AutoModelForCausalLM.from_pretrained(model_id)
model.load_adapter(peft_model_id)

4. 基于 8bit 或 4bit 进行加载

bitsandbytes 集成支持 8bit 和 4bit 精度数据类型,这对于加载大模型非常有用,因为它可以节省内存。

from_pretrained() 中添加 load_in_8bitload_in_4bit 参数,并将 device_map 设置为 "auto"

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

peft_model_id = "ybelkada/opt-350m-lora"
model = AutoModelForCausalLM.from_pretrained(peft_model_id, quantization_config=BitsAndBytesConfig(load_in_8bit=True))

5. 添加新的 adapter

添加新的 adapter,新的 adapter 类型需要和当前 adapter 相同。

from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer
from peft import PeftConfig

model_id = "facebook/opt-350m"
model = AutoModelForCausalLM.from_pretrained(model_id)

lora_config = LoraConfig(
    target_modules=["q_proj", "k_proj"],
    init_lora_weights=False
)

model.add_adapter(lora_config, adapter_name="adapter_1")

# 添加新的adapter
# attach new adapter with same config
model.add_adapter(lora_config, adapter_name="adapter_2")

# 使用~peft.PeftModel.set_adapter来设置要使用的adapter
# use adapter_1
model.set_adapter("adapter_1")
output = model.generate(**inputs)
print(tokenizer.decode(output_disabled[0], skip_special_tokens=True))

# use adapter_2
model.set_adapter("adapter_2")
output_enabled = model.generate(**inputs)
print(tokenizer.decode(output_enabled[0], skip_special_tokens=True))

6. 启用和禁用 adapter

# 启用adapter模块
from transformers import AutoModelForCausalLM, OPTForCausalLM, AutoTokenizer
from peft import PeftConfig

model_id = "facebook/opt-350m"
adapter_model_id = "ybelkada/opt-350m-lora"
tokenizer = AutoTokenizer.from_pretrained(model_id)
text = "Hello"
inputs = tokenizer(text, return_tensors="pt")

model = AutoModelForCausalLM.from_pretrained(model_id)
peft_config = PeftConfig.from_pretrained(adapter_model_id)

# to initiate with random weights
peft_config.init_lora_weights = False

model.add_adapter(peft_config)
model.enable_adapters()
output = model.generate(**inputs)

# 禁用adapter模块
model.disable_adapters()
output = model.generate(**inputs)

7. 训练一个 PEFT adapter

训练一个 LoRA adapter:

# 定义adapter配置
from peft import LoraConfig

peft_config = LoraConfig(
    lora_alpha=16,
    lora_dropout=0.1,
    r=64,
    bias="none",
    task_type="CAUSAL_LM",
)

# 将adapter添加到模型中
model.add_adapter(peft_config)

# 将模型传递给Trainer
trainer = Trainer(model=model, ...)
trainer.train()

# 保存训练好的adapter并重新加载
model.save_pretrained(save_dir)
model = AutoModelForCausalLM.from_pretrained(save_dir)

分享模型

1. 仓库功能

仓库通过 revision 参数,提供版本控制功能:

model = AutoModel.from_pretrained(
    "julien-c/EsperBERTo-small", revision="4c77982"  # tag name, or branch name, or commit hash
)

2. 设置

在命令行执行以下命令,在 Hugging Face 缓存文件夹(默认为 ~/.cache/)中存储 access token:

huggingface-cli login

如果在 Notebook 中,可以安装 huggingface_hub 库进行交互:

pip install huggingface_hub

在 Notebook 中,生成 token 并登录:

from huggingface_hub import notebook_login

notebook_login()

3. 转换模型适用于所有框架

建议将 PyTorch 和 TensorFlow checkpoint 都互相转换,一起上传,省去其他用户在下载时进行实时转化的时间。

# 指定from_tf=True将checkpoint从TensorFlow转换为PyTorch。
pt_model = DistilBertForSequenceClassification.from_pretrained("path/to/awesome-name-you-picked", from_tf=True)
pt_model.save_pretrained("path/to/awesome-name-you-picked")

# 指定from_pt=True将checkpoint从PyTorch转换为TensorFlow。
tf_model = TFDistilBertForSequenceClassification.from_pretrained("path/to/awesome-name-you-picked", from_pt=True)
tf_model.save_pretrained("path/to/awesome-name-you-picked")

4. 在训练过程中推送模型

TrainingArguments 中设置 push_to_hub=True,可以将模型推送至 Hub:

training_args = TrainingArguments(output_dir="my-awesome-model", push_to_hub=True)

# 将TrainingArguments传递给Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=small_train_dataset,
    eval_dataset=small_eval_dataset,
    compute_metrics=compute_metrics,
)

# 微调结束后,将训练好的模型推送至Hub,超参数、训练结果、框架版本添加到模型卡片中
trainer.push_to_hub()

5. 使用 push_to_hub 功能

# 通过模型名称上传至Hub
pt_model.push_to_hub("my-awesome-model")

# 加载Hub仓库中的模型
from transformers import AutoModel

model = AutoModel.from_pretrained("your_username/my-awesome-model")

# 可以指定组织名称前缀
pt_model.push_to_hub("my-awesome-org/my-awesome-model")

# 将tokenizer上传至模型仓库
tokenizer.push_to_hub("my-awesome-model")

6. 使用 Web 界面上传

【不推荐】Web 界面上传有模型大小限制。

7. 添加模型卡片

通过以下方式添加模型卡片:

  • 手动创建并上传一个 README.md 文件。
  • 在你的模型仓库中点击编辑模型卡片按钮。

使用 LLMs 进行生成

1. 使用 LLM 生成文本

# 安装必要的库
pip install transformers bitsandbytes>=0.39.0 -q

一个用于因果语言建模训练的语言模型,将文本 tokens 序列作为输入,并返回下一个 token 的概率分布。

使用 LLM 进行自回归生成的一个关键方面是如何从这个概率分布中选择下一个 token。这个步骤可以随意进行,只要最终得到下一个迭代的 token。这意味着可以简单的从概率分布中选择最可能的 token,也可以复杂的在对结果分布进行采样之前应用多种变换,这取决于你的需求。

上述过程是迭代重复的,直到达到某个停止条件。理想情况下,停止条件由模型决定,该模型应学会在何时输出一个结束序列(EOS)标记。如果不是这种情况,生成将在达到某个预定义的最大长度时停止。

正确设置 token 选择步骤和停止条件对于让你的模型按照预期的方式执行任务至关重要。这就是为什么我们为每个模型都有一个 [~generation.GenerationConfig] 文件,它包含一个效果不错的默认生成参数配置,并与模型一起加载。

# 加载模型
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
    "mistralai/Mistral-7B-v0.1", device_map="auto", load_in_4bit=True
)

参数说明:from_pretrained 调用中的两个参数:

  • device_map 确保模型被移动到您的 GPU(s) 上
  • load_in_4bit 应用 4 位动态量化来极大地减少资源需求
# 加载tokenizer
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1", padding_side="left")
model_inputs = tokenizer(["A list of colors: red, blue"], return_tensors="pt").to("cuda")

model_inputs 变量保存着分词后的文本输入以及注意力掩码。

尽管 generate() 在未传递注意力掩码时会尽其所能推断出注意力掩码,但建议尽可能传递它以获得最佳结果。

在对输入进行分词后,可以调用 generate() 方法来返回生成的 tokens。生成的 tokens 应该在打印之前转换为文本。

generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

不需要一次处理一个序列!可以批量输入,这将在小延迟和低内存成本下显著提高吞吐量。只需要确保正确地填充输入:

tokenizer.pad_token = tokenizer.eos_token  # Most LLMs don't have a pad token by default
model_inputs = tokenizer(
    ["A list of colors: red, blue", "Portugal is"], return_tensors="pt", padding=True
).to("cuda")
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)

2. 避免常见陷阱

# 加载模型作为样例
from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1")
tokenizer.pad_token = tokenizer.eos_token  # Most LLMs don't have a pad token by default
model = AutoModelForCausalLM.from_pretrained(
    "mistralai/Mistral-7B-v0.1", device_map="auto", load_in_4bit=True
)

陷阱:生成的输出太短/太长

建议:generate 调用中手动设置 max_new_tokens 以控制它可以返回的最大新 tokens 数量。

model_inputs = tokenizer(["A sequence of numbers: 1, 2"], return_tensors="pt").to("cuda")

# By default, the output will contain up to 20 tokens
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

# Setting `max_new_tokens` allows you to control the maximum length
generated_ids = model.generate(**model_inputs, max_new_tokens=50)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

陷阱:错误的生成模式

建议:通过将 do_sample=True 启用采样。

# Set seed or reproducibility -- you don't need this unless you want full reproducibility
from transformers import set_seed
set_seed(42)

model_inputs = tokenizer(["I am a cat."], return_tensors="pt").to("cuda")

# LLM + greedy decoding = repetitive, boring output
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

# With sampling, the output becomes more creative!
generated_ids = model.generate(**model_inputs, do_sample=True)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

陷阱:错误的填充位置

建议:输入长度不相同,则需要对它们进行填充,LLMs 没有接受过从 pad tokens 继续训练,因此您的输入需要左填充。确保在生成时不要忘记传递注意力掩码。

# The tokenizer initialized above has right-padding active by default: the 1st sequence,
# which is shorter, has padding on the right side. Generation fails to capture the logic.
model_inputs = tokenizer(
    ["1, 2, 3", "A, B, C, D, E"], padding=True, return_tensors="pt"
).to("cuda")
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

# With left-padding, it works as expected!
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1", padding_side="left")
tokenizer.pad_token = tokenizer.eos_token  # Most LLMs don't have a pad token by default
model_inputs = tokenizer(
    ["1, 2, 3", "A, B, C, D, E"], padding=True, return_tensors="pt"
).to("cuda")
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

陷阱:错误的提示

建议:一些模型和任务期望某种输入提示格式才能正常工作。当未应用此格式时,模型性能会下降:模型能工作,但不如预期提示那样好。

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-alpha")
model = AutoModelForCausalLM.from_pretrained(
    "HuggingFaceH4/zephyr-7b-alpha", device_map="auto", load_in_4bit=True
)
set_seed(0)
prompt = """How many helicopters can a human eat in one sitting? Reply as a thug."""
model_inputs = tokenizer([prompt], return_tensors="pt").to("cuda")
input_length = model_inputs.input_ids.shape[1]
generated_ids = model.generate(**model_inputs, max_new_tokens=20)
print(tokenizer.batch_decode(generated_ids[:, input_length:], skip_special_tokens=True)[0])
# Oh no, it did not follow our instruction to reply as a thug! Let's see what happens when we write
# a better prompt and use the right template for this model (through `tokenizer.apply_chat_template`)

set_seed(0)
messages = [
    {
        "role": "system",
        "content": "You are a friendly chatbot who always responds in the style of a thug",
    },
    {"role": "user", "content": "How many helicopters can a human eat in one sitting?"},
]
model_inputs = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to("cuda")
input_length = model_inputs.shape[1]
generated_ids = model.generate(model_inputs, do_sample=True, max_new_tokens=20)
print(tokenizer.batch_decode(generated_ids[:, input_length:], skip_special_tokens=True)[0])
# As we can see, it followed a proper thug style 😎

使用 Tokenizers 中的分词器

1. 自定义分词器

# 创建虚拟的分词器
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import Whitespace

tokenizer = Tokenizer(BPE(unk_token="[UNK]"))
trainer = BpeTrainer(special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"])

tokenizer.pre_tokenizer = Whitespace()
files = [...]
tokenizer.train(files, trainer)

2. 从分词器对象加载

from transformers import PreTrainedTokenizerFast

fast_tokenizer = PreTrainedTokenizerFast(tokenizer_object=tokenizer)

3. 从 JSON 文件加载

# 将分词器对象保存为JSON文件
tokenizer.save("tokenizer.json")
# 使用PreTrainedTokenizerFast加载
from transformers import PreTrainedTokenizerFast

fast_tokenizer = PreTrainedTokenizerFast(tokenizer_file="tokenizer.json")

使用多语言模型进行推理

1. XLM

XLM 有十个不同的 checkpoint,其中只有一个是单语言的,剩下的九个 checkpoint 可以归为两类:使用语言嵌入的 checkpoint、不使用语言嵌入的 checkpoint。

a. 带有语言嵌入的 XLM

XLM 版本建模类型支持语言
FacebookAI/xlm-mlm-ende-1024掩码语言建模英语-德语
FacebookAI/xlm-mlm-enfr-1024掩码语言建模英语-法语
FacebookAI/xlm-mlm-enro-1024掩码语言建模英语-罗马尼亚语
FacebookAI/xlm-mlm-xnli15-1024掩码语言建模XNLI 数据集语言
FacebookAI/xlm-mlm-tlm-xnli15-1024掩码语言建模+翻译XNLI 数据集语言
FacebookAI/xlm-clm-enfr-1024因果语言建模英语-法语
FacebookAI/xlm-clm-ende-1024因果语言建模英语-德语

语言嵌入被表示为一个张量,形状与传递给模型的 input_ids 相同,这些张量中的值取决于所使用的语言,并由分词器的 lang2idid2lang 属性识别。

# 模型加载,示例:加载 FacebookAI/xlm-clm-enfr-1024 检查点(因果语言建模,英语-法语)
import torch
from transformers import XLMTokenizer, XLMWithLMHeadModel

tokenizer = XLMTokenizer.from_pretrained("FacebookAI/xlm-clm-enfr-1024")
model = XLMWithLMHeadModel.from_pretrained("FacebookAI/xlm-clm-enfr-1024")

# 分词器的lang2id属性显示了该模型的语言及其对应的id
print(tokenizer.lang2id)

# 示例输入
input_ids = torch.tensor([tokenizer.encode("Wikipedia was used to")])  # batch size 为 1

# 将语言id设置为"en"并用其定义语言嵌入。语言嵌入式用0填充的张量,张量大小与input_ids相同
language_id = tokenizer.lang2id["en"]  # 0
langs = torch.tensor([language_id] * input_ids.shape[1])  # torch.tensor([0, 0, 0, ..., 0])

# 我们将其 reshape 为 (batch_size, sequence_length) 大小
langs = langs.view(1, -1)  # 现在的形状是 [1, sequence_length] (我们的 batch size 为 1)

# 将input_ids和语言嵌入传递给模型
outputs = model(input_ids, langs=langs)

run_generation.py 脚本可以使用 xlm-clm 检查点生成带有语言嵌入的文本。

b. 不带语言嵌入的 XLM

以下 XLM 模型在推理时不需要语言嵌入:

XLM 版本模型类型支持语言
FacebookAI/xlm-mlm-17-1280掩码语言建模支持 17 种语言
FacebookAI/xlm-mlm-100-1280掩码语言建模支持 100 种语言

与之前的 XLM 版本不同,这些模型用于通用句子表示。

2. BERT

以下 BERT 模型可用于多语言任务:

BERT 版本模型类型支持语言
google-bert/bert-base-multilingual-uncased掩码语言建模 + 下一句预测支持 102 种语言
google-bert/bert-base-multilingual-cased掩码语言建模 + 下一句预测支持 104 种语言

这些模型在推理时不需要语言嵌入,能够从上下文中识别语言并进行相应的推理。

3. XLM-RoBERTa

以下 XLM-RoBERTa 模型可用于多语言任务:

XLM-RoBERTa 版本模型类型支持语言
FacebookAI/xlm-roberta-base掩码语言建模支持 100 种语言
FacebookAI/xlm-roberta-large掩码语言建模支持 100 种语言

XLM-RoBERTa 使用 100 种语言的 2.5TB 新创建和清理的 CommonCrawl 数据进行了训练。

与之前发布的 mBERT 或 XLM 等多语言模型相比,它在分类、序列标记和问答等下游任务上提供了更强大的优势。

4. M2M100

以下 M2M100 模型可用于多语言翻译:

M2M100 模型模型类型
facebook/m2m100_418M翻译
facebook/m2m100_1.2B翻译
# 加载 facebook/m2m100_418M 检查点以将中文翻译为英文
# 在分词器中设置源语言为中文
from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer

en_text = "Do not meddle in the affairs of wizards, for they are subtle and quick to anger."
chinese_text = "不要插手巫師的事務, 因為他們是微妙的, 很快就會發怒."

tokenizer = M2M100Tokenizer.from_pretrained("facebook/m2m100_418M", src_lang="zh")
model = M2M100ForConditionalGeneration.from_pretrained("facebook/m2m100_418M")

# 分词
encoded_zh = tokenizer(chinese_text, return_tensors="pt")

# M2M100强制将目标语言ID作为第一个生成的标记,以进行到目标语言的翻译
# 在generate方法中将forced_bos_token_id设置为en以翻译成英语
generated_tokens = model.generate(**encoded_zh, forced_bos_token_id=tokenizer.get_lang_id("en"))
tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)

5. MBart

MBart 版本模型类型支持语言
facebook/mbart-large-50-one-to-many-mmt一对多多语言机器翻译支持 50 种语言
facebook/mbart-large-50-many-to-many-mmt多对多多语言机器翻译支持 50 种语言
facebook/mbart-large-50-many-to-one-mmt多对一多语言机器翻译支持 50 种语言
facebook/mbart-large-50多语言翻译支持 50 种语言
facebook/mbart-large-cc25多语言翻译-
# 加载 facebook/mbart-large-50-many-to-many-mmt 检查点以将芬兰语翻译为英语
# 在分词器中设置源语言:
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

en_text = "Do not meddle in the affairs of wizards, for they are subtle and quick to anger."
fi_text = "Älä sekaannu velhojen asioihin, sillä ne ovat hienovaraisia ja nopeasti vihaisia."

tokenizer = AutoTokenizer.from_pretrained("facebook/mbart-large-50-many-to-many-mmt", src_lang="fi_FI")
model = AutoModelForSeq2SeqLM.from_pretrained("facebook/mbart-large-50-many-to-many-mmt")

# 对文本进行分词
encoded_en = tokenizer(en_text, return_tensors="pt")

# MBart 强制将目标语言 id 作为第一个生成的标记,以进行到目标语言的翻译
# 在 generate 方法中将 forced_bos_token_id 设置为 en 以翻译成英语
generated_tokens = model.generate(**encoded_en, forced_bos_token_id=tokenizer.lang_code_to_id["en_XX"])
tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)
# 如果使用的是 facebook/mbart-large-50-many-to-one-mmt 检查点,则无需强制目标语言 id 作为第一个生成的令牌,否则用法是相同的

使用特定模型的 API

1. 加载并自定义模型配置

# 创建默认的DistilBertConfig配置
from transformers import DistilBertConfig

config = DistilBertConfig()
print(config)
# DistilBertConfig 显示了构建基础 DistilBertModel 所使用的所有默认属性。所有属性都可以进行自定义

模型参数自定义:

# activation参数尝试不同的激活函数
# attention_dropout参数为attention probabilities指定更高的dropout ratio
my_config = DistilBertConfig(activation="relu", attention_dropout=0.4)
print(my_config)

# 预训练模型属性可以在from_pretrained()函数中进行修改
my_config = DistilBertConfig.from_pretrained("distilbert/distilbert-base-uncased", activation="relu", attention_dropout=0.4)

# 模型配置完成后,可以使用save_pretrained()保存配置
# 配置文件以JSON文件的形式保存在指定的保存目录中
my_config.save_pretrained(save_directory="./your_model_save_path")

# 重新加载模型配置文件
my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json")

2. 创建模型

模型定义了架构,定义了每一层网络的行为以及进行的操作。例如,配置中的 num_hidden_layers 等属性用于定义架构。

每个模型都共享基类 PreTrainedModel 和一些常用方法,例如输入嵌入的大小、修剪自注意力头等。

所有模型都是 torch.nn.Moduletf.keras.Modelflax.linen.Module 的子类,意味着模型与各自框架的用法兼容。

# 加载自定义配置属性到模型中
from transformers import DistilBertModel

my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json")
model = DistilBertModel(my_config)

这里加载了一个具有随机参数的、未经过预训练权重的模型。

训练是一项昂贵且耗时的过程,通常来说,使用预训练模型可以更快获得更好的结果,同时仅需要很小的训练资源。

使用 from_pretrained() 创建预训练模型:

model = DistilBertModel.from_pretrained("distilbert/distilbert-base-uncased")

# 当加载预训练权重时,如果模型是由Transformers提供的,自动加载默认模型配置,也可以使用config加载自定义配置
model = DistilBertModel.from_pretrained("distilbert/distilbert-base-uncased", config=my_config)

a. 模型头

Transformers 为每个任务提供不同的模型头,只要模型支持该任务(例如,不能使用 DistilBERT 执行类似翻译这种序列到序列任务)。

# 添加模型头,DistilBertForSequenceClassification是一个带有序列分类头的DistilBERT模型。序列分类头是池化输出之上的线性层
from transformers import DistilBertForSequenceClassification

model = DistilBertForSequenceClassification.from_pretrained("distilbert/distilbert-base-uncased")

# 通过切换不同的模型头,可以将checkpoint复用于其他任务,对于问答任务,可以使用DistilBertForQuestionAnswering模型头
# 问答头与序列分类头相似,不同点在于它是隐藏状态输出之上的线性层
from transformers import DistilBertForQuestionAnswering

model = DistilBertForQuestionAnswering.from_pretrained("distilbert/distilbert-base-uncased")

3. 为文本创建慢速和快速分词器

分词器(tokenizer):用于将原始文本转换为张量。

Transformers 支持两种分词器,两种分词器都支持常用的方法,如编码和解码、添加新标记、管理特殊标记:

  • PreTrainedTokenizer:分词器的 Python 实现
  • PreTrainedTokenizerFast:来自基于 Rust 的 Tokenizer 库的分词器。因为其使用了 Rust 实现,这种分词器类型的速度要快得多,尤其是在批量分词(batch tokenization)的时候。快速分词器还提供其他的方法,例如偏移映射(offset mapping),它将标记(token)映射到其原始单词或字符。
# 假设已经训练了分词器,可以从词表文件创建分词器
from transformers import DistilBertTokenizer

my_tokenizer = DistilBertTokenizer(vocab_file="my_vocab_file.txt", do_lower_case=False, padding_side="left")

注意:如果使用预训练模型,必须使用预训练模型的词表,否则输入将没有意义,因为自定义分词器生成的词表与预训练模型分词器生成的词表是不同的。

# 加载预训练模型的分词器
from transformers import DistilBertTokenizer

slow_tokenizer = DistilBertTokenizer.from_pretrained("distilbert/distilbert-base-uncased")

# 使用DistilBertTokenizerFast类创建快速分词器
from transformers import DistilBertTokenizerFast

fast_tokenizer = DistilBertTokenizerFast.from_pretrained("distilbert/distilbert-base-uncased")
# 注意:默认情况下,AutoTokenizer 将尝试加载快速标记生成器。你可以通过在 from_pretrained 中设置 use_fast=False 以禁用此行为

4. 为视觉任务创建图像处理器

# 创建图像处理器:需要创建一个与使用的模型关联的图像处理器,例如,如果使用ViT进行图像分类,则需要创建一个ViTImageProcessor
from transformers import ViTImageProcessor

vit_extractor = ViTImageProcessor()
print(vit_extractor)
# 修改图像处理器的参数
from transformers import ViTImageProcessor

my_vit_extractor = ViTImageProcessor(resample="PIL.Image.BOX", do_normalize=False, image_mean=[0.3, 0.3, 0.3])
print(my_vit_extractor)

5. 为音频任务创建特征提取器

# 创建特征提取器:需要创建一个是使用的模型关联的特征提取器,例如,如果使用Wav2Vec2进行音频分类,则需要创建一个Wav2Vec2FeatureExtractor
from transformers import Wav2Vec2FeatureExtractor

w2v2_extractor = Wav2Vec2FeatureExtractor()
print(w2v2_extractor)
# 修改特征提取器的参数
from transformers import Wav2Vec2FeatureExtractor

w2v2_extractor = Wav2Vec2FeatureExtractor(sampling_rate=8000, do_normalize=False)
print(w2v2_extractor)

6. 为多模态任务创建处理器

为支持多模式任务的模型,Transformers 提供了处理类,可以将特征提取器和分词器等处理类包装到单个对象中。

例如,使用 Wav2Vec2Processor 执行自动语音识别任务(ASR)。ASR 将语音转录为文本,因此需要创建一个特征提取器和一个分词器。

# 创建一个特征提取器用于处理音频输入
from transformers import Wav2Vec2FeatureExtractor

feature_extractor = Wav2Vec2FeatureExtractor(padding_value=1.0, do_normalize=True)

# 创建一个分词器用于处理文本输入
from transformers import Wav2Vec2CTCTokenizer

tokenizer = Wav2Vec2CTCTokenizer(vocab_file="my_vocab_file.txt")

# 将特征提取器和分词器合并到Wav2Vec2Processor中
from transformers import Wav2Vec2Processor

processor = Wav2Vec2Processor(feature_extractor=feature_extractor, tokenizer=tokenizer)

通过两个基类 - 配置类和模型类 - 以及一个附加的预处理类(分词器、图像处理器、特征提取器或处理器),你可以创建 Transformers 支持的任何模型。每个基类都是可配置的,允许你使用所需的特定属性。你可以轻松设置模型进行训练或修改现有的预训练模型进行微调。


共享自定义模型

Transformers 库设计得易于扩展。每个模型的代码都在仓库给定的子文件夹中,没有进行抽象,因此你可以轻松复制模型代码文件并根据需要进行调整。

1. 编写自定义配置

编写自定义配置的注意事项:

  1. 必须继承自 PretrainedConfig
  2. PretrainedConfig__init__ 方法必须接受任何 kwargs
  3. 这些 kwargs 需要传递给超类的 __init__ 方法
# 自定义ResNet配置
from transformers import PretrainedConfig
from typing import List


class ResnetConfig(PretrainedConfig): # 注意事项1:必须继承PretrainedConfig
    model_type = "resnet"

    def __init__(
        self,
        block_type="bottleneck",
        layers: List[int] = [3, 4, 6, 3],
        num_classes: int = 1000,
        input_channels: int = 3,
        cardinality: int = 1,
        base_width: int = 64,
        stem_width: int = 64,
        stem_type: str = "",
        avg_down: bool = False,
        **kwargs, # 注意事项2:必须能够接受任何kwargs
    ):
        if block_type not in ["basic", "bottleneck"]:
            raise ValueError(f"`block_type` must be 'basic' or bottleneck', got {block_type}.")
        if stem_type not in ["", "deep", "deep-tiered"]:
            raise ValueError(f"`stem_type` must be '', 'deep' or 'deep-tiered', got {stem_type}.")

        self.block_type = block_type
        self.layers = layers
        self.num_classes = num_classes
        self.input_channels = input_channels
        self.cardinality = cardinality
        self.base_width = base_width
        self.stem_width = stem_width
        self.stem_type = stem_type
        self.avg_down = avg_down
        super().__init__(**kwargs) # 注意事项3:kwargs 需要传递给超类的 __init__ 方法

# 使用自定义配置,创建和保存配置
resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d_config.save_pretrained("custom-resnet")

# 这行代码将在custom-resnet文件夹内保存config.json文件
# 重新加载配置
resnet50d_config = ResnetConfig.from_pretrained("custom-resnet")

# 上传至Hub
ResnetConfig.push_to_hub()

2. 编写自定义模型

# 自定义模型用于提取隐藏特征,类似BertModel
from transformers import PreTrainedModel
from timm.models.resnet import BasicBlock, Bottleneck, ResNet
from .configuration_resnet import ResnetConfig

# 建立块类型(block types)与实际块类(block classes)之间的映射
BLOCK_MAPPING = {"basic": BasicBlock, "bottleneck": Bottleneck}

# 继承PreTrainedModel
class ResnetModel(PreTrainedModel):
    # 这一行非必需
    config_class = ResnetConfig
    # 使用config调用超类的初始化方法
    def __init__(self, config):
        super().__init__(config)
        block_layer = BLOCK_MAPPING[config.block_type]
        self.model = ResNet(
            block_layer,
            config.layers,
            num_classes=config.num_classes,
            in_chans=config.input_channels,
            cardinality=config.cardinality,
            base_width=config.base_width,
            stem_width=config.stem_width,
            stem_type=config.stem_type,
            avg_down=config.avg_down,
        )

    def forward(self, tensor):
        return self.model.forward_features(tensor)

# 自定义模型用于图像分类,类似BertForSequenceClassification
import torch


class ResnetModelForImageClassification(PreTrainedModel):
    # 这一行非必需
    config_class = ResnetConfig

    def __init__(self, config):
        super().__init__(config)
        block_layer = BLOCK_MAPPING[config.block_type]
        self.model = ResNet(
            block_layer,
            config.layers,
            num_classes=config.num_classes,
            in_chans=config.input_channels,
            cardinality=config.cardinality,
            base_width=config.base_width,
            stem_width=config.stem_width,
            stem_type=config.stem_type,
            avg_down=config.avg_down,
        )
    # 需要更改前向方法
    def forward(self, tensor, labels=None):
        logits = self.model(tensor)
        if labels is not None:
            loss = torch.nn.functional.cross_entropy(logits, labels)
            return {"loss": loss, "logits": logits}
        return {"logits": logits}
# 创建自定义模型
resnet50d = ResnetModelForImageClassification(resnet50d_config)
# 自定义模型支持使用 PreTrainedModel 的任何方法,比如 save_pretrained() 或者 push_to_hub()

# 使用timm,加载预训练模型
import timm

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

3. 将代码发送到 Hub

自定义模型代码的项目结构:

  • 确保模型都在一个 .py 文件中定义
  • 所有文件都位于同一目录,方便依赖文件的相对导入
  • __init__.py:可以为空,这个文件是为了让 Python 将 resnet_model 目录作为模块
  • configuration_resnet.py:配置文件,包含 ResnetConfig 代码
  • modeling_resnet.py:模型文件,包含 ResnetModelResnetModelForImageClassfication 代码
.
└── resnet_model
    ├── __init__.py
    ├── configuration_resnet.py
    └── modeling_resnet.py
# 重用现有模型,导入自定义配置和模型
from resnet_model.configuration_resnet import ResnetConfig
from resnet_model.modeling_resnet import ResnetModel, ResnetModelForImageClassification

# 将自定义模型注册为Auto类
ResnetConfig.register_for_auto_class()
ResnetModel.register_for_auto_class("AutoModel")
ResnetModelForImageClassification.register_for_auto_class("AutoModelForImageClassification")

注意:

  • 对于配置,只有一个自动类 AutoConfig,不需要指定自动类的类型
  • 对于模型,需要特定类型的自动类,例如 AutoModelForImageClassification
# 使用注册的自动类,创建配置和模型
resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d = ResnetModelForImageClassification(resnet50d_config)

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

# 命令行登录到hub
huggingface-cli login

# 或在笔记本中运行以下代码
from huggingface_hub import notebook_login

notebook_login()

# 推送到远程仓库:包含模型权重、JSON格式配置文件、.py代码文件
resnet50d.push_to_hub("custom-resnet50d")

4. 使用带有自定义代码的模型

# 使用自动类(AutoClass)和from_pretrained方法,使用模型仓库里的自定义代码的配置、模型、分词器文件
# 所有上传、下载都会进行恶意软件扫描,设置trust_remote_code=True使用自定义代码的模型
from transformers import AutoModelForImageClassification

model = AutoModelForImageClassification.from_pretrained("sgugger/custom-resnet50d", trust_remote_code=True)

# 【建议】:使用revision参数提交哈希(commit hash),限定模型版本,确保模型作者没有更新恶意代码
commit_hash = "ed94a7c6247d8aedce4647f00f20de6875b5b292"
model = AutoModelForImageClassification.from_pretrained(
    "sgugger/custom-resnet50d", trust_remote_code=True, revision=commit_hash
)
# 提示:在 Hub 上浏览模型仓库的提交历史时,有一个按钮可以轻松复制任何提交的提交哈希

5. 将自定义代码的模型注册到自动类

# 将自定义模型添加到自动类中
# 注意:自定义模型配置的model_type属性与现有模型类型不同,且模型类具有正确的config_class属性
from transformers import AutoConfig, AutoModel, AutoModelForImageClassification

AutoConfig.register("resnet", ResnetConfig)
AutoModel.register(ResnetConfig, ResnetModel)
AutoModelForImageClassification.register(ResnetConfig, ResnetModelForImageClassification)
# 注意:
# 将自定义配置注册到AutoConfig时,使用的第一个参数需要与自定义配置的model_type匹配
# 将自定义模型注册到任何自动模型类时,使用的第一个参数需要与config_class相匹配

聊天模型的模板

1. 介绍

LLM 的常见应用场景是聊天。聊天上下文中,不再是连续的文本字符串构成的语句,而是由一条或多条消息组成的对话,每条消息都有一个”用户”或”助手”等角色,还包括消息文本。

不同的模型对聊天的输入格式要求不同,这是添加聊天模板作为功能的原因。

聊天模板是 Tokenizer 的一部分,用来把问答的对话内容转换为模型的输入 prompt。

示例:BlenderBot 模型

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("facebook/blenderbot-400M-distill")

chat = [
   {"role": "user", "content": "Hello, how are you?"},
   {"role": "assistant", "content": "I'm doing great. How can I help you today?"},
   {"role": "user", "content": "I'd like to show off how chat templating works!"},
]

tokenizer.apply_chat_template(chat, tokenize=False)

注意:整个聊天对话内容被压缩成了一个字符串。如果使用默认设置的 tokenizer=True,那么字符串也将被 tokenized 处理。

# 加载mistralai/Mistral-7B-Instruct-v0.1模型,演示模板的实际运行
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")

chat = [
  {"role": "user", "content": "Hello, how are you?"},
  {"role": "assistant", "content": "I'm doing great. How can I help you today?"},
  {"role": "user", "content": "I'd like to show off how chat templating works!"},
]

tokenizer.apply_chat_template(chat, tokenize=False)

说明:tokenizer 添加了 [INST][/INST] 来表示用户消息的开始和结束。Mistral-instruct 使用这些 token 进行训练,但 BlenderBot 没有。

2. 使用聊天模板

使用聊天模板:构建一系列带有 rolecontent 的字典,传递给 apply_chat_template() 方法。将聊天模板用作模型预测的输入时,建议使用 add_generation_prompt=True 来添加 generation prompt。

# 示例:使用Zephyr模型,调用model.generate()方法
from transformers import AutoModelForCausalLM, AutoTokenizer

checkpoint = "HuggingFaceH4/zephyr-7b-beta"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint)  # You may want to use bfloat16 and/or move to GPU here

messages = [
    {
        "role": "system",
        "content": "You are a friendly chatbot who always responds in the style of a pirate",
    },
    {"role": "user", "content": "How many helicopters can a human eat in one sitting?"},
 ]
tokenized_chat = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt")
print(tokenizer.decode(tokenized_chat[0]))
# 输出:生成Zephyr期望的输入格式的字符串
<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s>
<|user|>
How many helicopters can a human eat in one sitting?</s>
<|assistant|>

按照 Zephyr 的要求传入 prompt,使用模型生成对用户问题的回复:

outputs = model.generate(tokenized_chat, max_new_tokens=128)
print(tokenizer.decode(outputs[0]))

# 输出结果:
<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s>
<|user|>
How many helicopters can a human eat in one sitting?</s>
<|assistant|>
Matey, I'm afraid I must inform ye that humans cannot eat helicopters. Helicopters are not food, they are flying machines. Food is meant to be eaten, like a hearty plate o' grog, a savory bowl o' stew, or a delicious loaf o' bread. But helicopters, they be for transportin' and movin' around, not for eatin'. So, I'd say none, me hearties. None at all.

3. 自动化的聊天 pipeline

TextGenerationPipeline:这个 pipeline 设计用于方便使用聊天模型。

# 使用示例:
from transformers import pipeline

pipe = pipeline("text-generation", "HuggingFaceH4/zephyr-7b-beta")
messages = [
    {
        "role": "system",
        "content": "You are a friendly chatbot who always responds in the style of a pirate",
    },
    {"role": "user", "content": "How many helicopters can a human eat in one sitting?"},
]
print(pipe(messages, max_new_tokens=256)['generated_text'][-1])
# 输出:
{'role': 'assistant', 'content': "Matey, I'm afraid I must inform ye that humans cannot eat helicopters. Helicopters are not food, they are flying machines. Food is meant to be eaten, like a hearty plate o' grog, a savory bowl o' stew, or a delicious loaf o' bread. But helicopters, they be for transportin' and movin' around, not for eatin'. So, I'd say none, me hearties. None at all."}

TextGenerationPipeline 将负责处理所有的 tokenized 并调用 apply_chat_template,一旦模型有了聊天模板,您只需要初始化 pipeline 并传递消息列表!

4. generation prompts

# 示例对话:
messages = [
    {"role": "user", "content": "Hi there!"},
    {"role": "assistant", "content": "Nice to meet you!"},
    {"role": "user", "content": "Can I ask a question?"}
]
# apply_chat_template方法,指定add_generation_prompt=False时,输出结果:
tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=False)
"""<|im_start|>user
Hi there!<|im_end|>
<|im_start|>assistant
Nice to meet you!<|im_end|>
<|im_start|>user
Can I ask a question?<|im_end|>
"""
# apply_chat_template方法,指定add_generation_prompt=True时,输出结果:
tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
"""<|im_start|>user
Hi there!<|im_end|>
<|im_start|>assistant
Nice to meet you!<|im_end|>
<|im_start|>user
Can I ask a question?<|im_end|>
<|im_start|>assistant
"""

两者区别:指定 add_generation_promptTrue 时,会添加模型开始答复的标记,确保模型生成文本时只会给出答复,而不会做出意外的行为。

聊天模型只是语言模型,他们被训练来继续文本,聊天对于他们来说是一种特殊的文本,需要用适当的控制标记来引导,让模型知道自己应该做什么。

并非所有模型都需要生成提示,例如 BlenderBot 和 LLaMA,在模型回复之前没有任何特殊标记,这种情况下,add_generation_prompt 参数将不起作用,add_generation_prompt 参数是否生效取决于你所使用的模板。

5. 训练中使用聊天模板

聊天模板应用为数据集的预处理步骤,之后,可以像进行任何其他语言模型训练任务一样继续。

训练时,通常应该设置 add_generation_prompt=False,因为添加的助手标记在训练过程中并不会有帮助。

from transformers import AutoTokenizer
from datasets import Dataset

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-beta")

chat1 = [
    {"role": "user", "content": "Which is bigger, the moon or the sun?"},
    {"role": "assistant", "content": "The sun."}
]
chat2 = [
    {"role": "user", "content": "Which is bigger, a virus or a bacterium?"},
    {"role": "assistant", "content": "A bacterium."}
]

dataset = Dataset.from_dict({"chat": [chat1, chat2]})
dataset = dataset.map(lambda x: {"formatted_chat": tokenizer.apply_chat_template(x["chat"], tokenize=False, add_generation_prompt=False)})
print(dataset['formatted_chat'][0])
# 输出:
<|user|>
Which is bigger, the moon or the sun?</s>
<|assistant|>
The sun.</s>
# 后续可以使用formatted_chat列,跟标准语言建模任务中一样训练即可

6. 聊天模板的工作方式

模型的聊天模板存储在 tokenizer.chat_template 属性上,属于 tokenizer 的一部分。如果没有设置,则使用该模型的默认模板。

# 示例:BlenderBot的聊天模板
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("facebook/blenderbot-400M-distill")

tokenizer.chat_template

# 输出:模板使用Jinja模板生成,使用换行和缩进美化后的输出如下
{% for message in messages %}
    {% if message['role'] == 'user' %}
        {{ ' ' }}
    {% endif %}
    {{ message['content'] }}
    {% if not loop.last %}
        {{ '  ' }}
    {% endif %}
{% endfor %}
{{ eos_token }}

Jinja 是一种模板语言,允许编写简单的代码来生成文本,代码和语法类似于 Python,使用 Python 语法实现模板如下:

for idx, message in enumerate(messages):
    if message['role'] == 'user':
        print(' ')
    print(message['content'])
    if not idx == len(messages) - 1:  # Check for the last message in the conversation
        print('  ')
print(eos_token)

这里使用 Jinja 模板处理如下三步:

  1. 对于每条消息,如果消息是用户消息,则在前面加一个空格,否则不打印任何内容
  2. 添加消息内容
  3. 如果消息不是最后一条,在消息后面添加两个空格;如果是最后一条消息,在消息后面打印 EOS

Jinja 模板,可以实现类似于 LLaMA 的 prompt 输入。模板的作用:它根据每条消息的”角色”添加对应的消息。user、assistant、system 的消息需要分别处理,因为它们代表不同的角色输入。

{% for message in messages %}
    {% if message['role'] == 'user' %}
        {{ bos_token + '[INST] ' + message['content'] + ' [/INST]' }}
    {% elif message['role'] == 'system' %}
        {{ '<<SYS>>\\n' + message['content'] + '\\n<</SYS>>\\n\\n' }}
    {% elif message['role'] == 'assistant' %}
        {{ ' '  + message['content'] + ' ' + eos_token }}
    {% endif %}
{% endfor %}

7. 聊天模板的自定义

a. 创建聊天模板

创建聊天模板:编写一个 Jinja 模板并设置 tokenizer.chat_template

复用上面的 LLaMA 模板,在助手消息中添加 [ASST][/ASST]

{% for message in messages %}
    {% if message['role'] == 'user' %}
        {{ bos_token + '[INST] ' + message['content'].strip() + ' [/INST]' }}
    {% elif message['role'] == 'system' %}
        {{ '<<SYS>>\\n' + message['content'].strip() + '\\n<</SYS>>\\n\\n' }}
    {% elif message['role'] == 'assistant' %}
        {{ '[ASST] '  + message['content'] + ' [/ASST]' + eos_token }}
    {% endif %}
{% endfor %}

设置 tokenizer.chat_template 属性:

# 设置tokenizer.chat_template属性,这里简单替换原有的模板属性
template = tokenizer.chat_template
template = template.replace("SYS", "SYSTEM")  # Change the system token
tokenizer.chat_template = template  # Set the new template
tokenizer.push_to_hub("model_name")  # Upload your new template to the Hub!

b. 默认模板

默认模板:聊天 prompt 是在模型中通过硬编码处理的。如果一个模型没有设置聊天模板,但模型有默认模板,TextGenerationPipeline 类和 apply_chat_template 方法将使用该模型的聊天模板。聊天模板可以通过 tokenizer.default_chat_template 属性查看。

默认聊天模板是向前兼容的功能,建议通过显示设置 chat_template 属性覆盖默认模板,以防未来默认模板被修改或弃用的情况。

c. 选用模板

在为已经训练过的聊天模型设置模板时,应确保模板与模型在训练期间看到的信息格式完全匹配,否则可能导致性能下降。

即使继续对模型进行训练,也应保持聊天模板不变,以便获得最佳性能。与 tokenization 类似,推断时,应选用训练时一样的 tokenization,通常会获得最佳性能。

默认模板的形式:

{% for message in messages %}
    {{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}
{% endfor %}

使用默认模板显式覆盖 tokenizer.chat_template 属性:

tokenizer.chat_template = "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}"

# 模板输出:
<|im_start|>system
You are a helpful chatbot that will do its best not to say anything so stupid that people tweet about it.<|im_end|>
<|im_start|>user
How are you?<|im_end|>
<|im_start|>assistant
I'm doing great!<|im_end|>

d. 添加模板

设置 tokenizer.chat_template 属性,通过 apply_chat_template 方法调用。

8. 聊天模板的开发技巧

使用 Jinja 代码语法创建模板。

a. for 循环

# jinja的for循环
{% for message in messages %}
{{ message['content'] }}
{% endfor %}
# 在表达式块中可以使用+连接字符串

b. if 语句

# jinja的if语句
{% if message['role'] == 'user' %}
{{ message['content'] }}
{% endif %}
# jinja使用{% endfor %}{% endif %}表示for和if的结束

c. 特殊变量

# 示例:设置add_generation_prompt=True,在对话结束时添加generate_prompt
{% if loop.last and add_generation_prompt %}
{{ bos_token + 'Assistant:\n' }}
{% endif %}

d. 空格的注意事项

建议:忽略除 {{ expressions }} 之外的空格,Jinja 是一个通用的模板引擎,可能会将同一行文本块之间的空格视为重要,并将其打印到输出中。


## 导出为 ONNX

### 1. ONNX 简介

ONNX (Open Neural Network eXchange) 是一个开放的标准,它定义了一组通用的运算符和一种通用的文件格式,用于表示包括 PyTorch 和 TensorFlow 在内的各种框架中的深度学习模型。

ONNX 使得模型能够轻松在不同深度学习框架间切换。例如,在 PyTorch 中训练的模型可以被导出为 ONNX,然后再导入到 TensorFlow(反之亦然)。

导出 ONNX 后,模型可以:

- 通过**图优化(graph optimization)**和**量化(quantization)**等技术进行推理优化
- 通过 `ORTModelForXXX` 类使用 ONNX Runtime 运行,它同样遵循 Transformers 中的 `AutoModel` API
- 使用**优化推理流水线(pipeline)**运行,其 API 与 Transformers 中的 `pipeline()` 函数相同

有两种方式可以将 Transformers 模型导出为 ONNX:

- 使用 Optimum 的 CLI(命令行)导出
- 使用 Optimum 的 `optimum.onnxruntime` 模块导出

### 2. 使用 CLI 将 Transformers 模型导出为 ONNX

安装依赖:

```bash
pip install optimum[exporters]

查看帮助:

optimum-cli export onnx --help

从 Hub 导出模型的检查点,以 distilbert/distilbert-base-uncased-distilled-squad 为例:

optimum-cli export onnx --model distilbert/distilbert-base-uncased-distilled-squad distilbert_base_uncased_squad_onnx/

从日志中查看导出进度以及生成对 model.onnx 文件的保存位置:

Validating ONNX model distilbert_base_uncased_squad_onnx/model.onnx...
    -[✓] ONNX model output names match reference model (start_logits, end_logits)
    - Validating ONNX Model output "start_logits":
        -[✓] (2, 16) matches (2, 16)
        -[✓] all values close (atol: 0.0001)
    - Validating ONNX Model output "end_logits":
        -[✓] (2, 16) matches (2, 16)
        -[✓] all values close (atol: 0.0001)
The ONNX export succeeded and the exported model was saved at: distilbert_base_uncased_squad_onnx

从本地导出模型的检查点,需要提供 --task 参数,如果未提供 task 参数,将默认导出不带特定任务头的模型架构:

optimum-cli export onnx --model local_path --task question-answering distilbert_base_uncased_squad_onnx/

使用 ONNX Runtime 加载和运行模型:

from transformers import AutoTokenizer
from optimum.onnxruntime import ORTModelForQuestionAnswering

tokenizer = AutoTokenizer.from_pretrained("distilbert_base_uncased_squad_onnx")
model = ORTModelForQuestionAnswering.from_pretrained("distilbert_base_uncased_squad_onnx")
inputs = tokenizer("What am I using?", "Using DistilBERT with ONNX Runtime!", return_tensors="pt")
outputs = model(**inputs)

从 Hub 导出 TensorFlow 检查点:

optimum-cli export onnx --model keras-io/transformers-qa distilbert_base_cased_squad_onnx/

3. 使用 optimum.onnxruntime 将 Transformers 模型导出为 ONNX

使用代码将 Transformers 模型导出为 ONNX:

from optimum.onnxruntime import ORTModelForSequenceClassification
from transformers import AutoTokenizer

model_checkpoint = "distilbert_base_uncased_squad"
save_directory = "onnx/"

# 从 transformers 加载模型并将其导出为 ONNX
ort_model = ORTModelForSequenceClassification.from_pretrained(model_checkpoint, export=True)
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)

# 保存 onnx 模型以及分词器
ort_model.save_pretrained(save_directory)
tokenizer.save_pretrained(save_directory)

4. 使用 transformers.onnx 导出模型

使用 transformers.onnx 将 Transformers 模型导出为 ONNX,需要安装额外依赖:

pip install transformers[onnx]

transformers.onnx 包作为 Python 模块使用:

python -m transformers.onnx --model=distilbert/distilbert-base-uncased onnx/

使用 ONNX Runtime 加载并运行模型:

from transformers import AutoTokenizer
from onnxruntime import InferenceSession

tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")
session = InferenceSession("onnx/model.onnx")
# ONNX Runtime expects NumPy arrays as input
inputs = tokenizer("Using DistilBERT with ONNX Runtime!", return_tensors="np")
outputs = session.run(output_names=["last_hidden_state"], input_feed=dict(inputs))

通过查看每个模型对 ONNX 配置来获取所需的输出名(例如 ["last_hidden_state"])。例如,对于 DistilBERT,可以使用以下代码获取输出名称:

from transformers.models.distilbert import DistilBertConfig, DistilBertOnnxConfig

config = DistilBertConfig()
onnx_config = DistilBertOnnxConfig(config)
print(list(onnx_config.outputs.keys()))

从 Hub 导出 TensorFlow 检查点:

python -m transformers.onnx --model=keras-io/transformers-qa onnx/

导出本地存储的模型,需要将模型权重和分词器文件保存在同一目录中(例如 local-pt-checkpoint),然后将 transformers.onnx--model 参数指向该目录,将其导出为 ONNX:

python -m transformers.onnx --model=local-pt-checkpoint onnx/

导出为 TFLite

TensorFlow Lite 是一个轻量级框架,用于资源受限的设备上,如手机、嵌入式系统和物联网(IoT)设备,部署机器学习模型。TFLite 旨在在计算能力、内存和功耗有限的设备上优化和高效运行模型。模型以一种特殊的高效可移植格式表示,其文件扩展名为 .tflite

Optimum 通过 exporters.tflite 模块提供将 Transformers 模型导出至 TFLite 格式的功能。

导出 TFLite 格式前,需要安装依赖:

pip install optimum[exporters-tf]

命令行中查看帮助:

optimum-cli export tflite --help

从 Hub 导出模型检查点,以 google-bert/bert-base-uncased 为例:

optimum-cli export tflite --model google-bert/bert-base-uncased --sequence_length 128 bert_tflite/

在日志中查看导出进度以及生成对 model.tflite 文件的保存位置:

Validating TFLite model...
    -[✓] TFLite model output names match reference model (logits)
    - Validating TFLite Model output "logits":
        -[✓] (1, 128, 30522) matches (1, 128, 30522)
        -[x] values not close enough, max diff: 5.817413330078125e-05 (atol: 1e-05)
The TensorFlow Lite export succeeded with the warning: The maximum absolute difference between the output of the reference model and the TFLite exported model is not within the set tolerance 1e-05:
- logits: max diff = 5.817413330078125e-05.
 The exported model was saved at: bert_tflite

导出本地模型时,需要确保将模型的权重和分词器文件保存在同一目录 local_path 中,在使用 CLI(命令行)时,将 local_path 传递给 model 参数。

导出为 TorchScript

TorchScript 是从 PyTorch 代码创建可序列化和可优化的模型的一种方式。

有两个 PyTorch 模块:JITTRACE。这两个模块允许开发人员将其模型导出到其他程序中重用,比如面向效率的 C++ 程序。

导出模型需要两个步骤:

  • 使用 torchscript 参数实例化模型
  • 使用虚拟输入进行前向传递

1. TorchScript 参数和绑定权重

torchscript 参数是必需的,因为大多数 🤗 Transformers 语言模型的 Embedding 层和 Decoding 层之间有绑定权重。TorchScript 不允许导出具有绑定权重的模型,因此必须事先解绑和克隆权重。

使用 torchscript 参数实例化的模型将其 Embedding 层和 Decoding 层分开,这意味着它们不应该在后续进行训练。训练将导致这两层不同步,产生意外结果。

对于没有语言模型头部的模型,情况不同,因为这些模型没有绑定权重。这些模型可以安全地导出而无需 torchscript 参数。

2. 虚拟输入和标准长度

虚拟输入用于模型的前向传递。当输入的值传播到各层时,PyTorch 会跟踪在每个张量上执行的不同操作。然后使用记录的操作来创建模型的 trace。

跟踪是相对于输入的维度创建的。因此,它受到虚拟输入的维度限制,对于任何其他序列长度或批量大小都不起作用。当尝试使用不同大小时,会引发以下错误:

The expanded size of the tensor (3) must match the existing size (7) at non-singleton dimension 2

我们建议使用至少与推断期间将馈送到模型的最大输入一样大的虚拟输入大小进行跟踪。填充可以帮助填补缺失的值。然而,由于模型是使用更大的输入大小进行跟踪的,矩阵的维度也会很大,导致更多的计算。

在每个输入上执行的操作总数要仔细考虑,并在导出不同序列长度模型时密切关注性能。

3. 在 Python 中使用 TorchScript

a. 保存模型

要使用 TorchScript 导出 BertModel,请从 BertConfig 类实例化 BertModel,然后将其保存到名为 traced_bert.pt 的磁盘文件中:

from transformers import BertModel, BertTokenizer, BertConfig
import torch

enc = BertTokenizer.from_pretrained("google-bert/bert-base-uncased")

# 对输入文本分词
text = "[CLS] Who was Jim Henson ? [SEP] Jim Henson was a puppeteer [SEP]"
tokenized_text = enc.tokenize(text)

# 屏蔽一个输入 token
masked_index = 8
tokenized_text[masked_index] = "[MASK]"
indexed_tokens = enc.convert_tokens_to_ids(tokenized_text)
segments_ids = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]

# 创建虚拟输入
tokens_tensor = torch.tensor([indexed_tokens])
segments_tensors = torch.tensor([segments_ids])
dummy_input = [tokens_tensor, segments_tensors]

# 使用 torchscript 参数初始化模型
# 即使此模型没有 LM Head,也将参数设置为 True。
config = BertConfig(
    vocab_size_or_config_json_file=32000,
    hidden_size=768,
    num_hidden_layers=12,
    num_attention_heads=12,
    intermediate_size=3072,
    torchscript=True,
)

# 实例化模型
model = BertModel(config)

# 模型需要处于评估模式
model.eval()

# 如果您使用 *from_pretrained* 实例化模型,还可以轻松设置 TorchScript 参数
model = BertModel.from_pretrained("google-bert/bert-base-uncased", torchscript=True)

# 创建 trace
traced_model = torch.jit.trace(model, [tokens_tensor, segments_tensors])
torch.jit.save(traced_model, "traced_bert.pt")

b. 加载模型

从磁盘加载先前保存的 BertModeltraced_bert.pt,并在先前初始化的 dummy_input 上使用:

loaded_model = torch.jit.load("traced_bert.pt")
loaded_model.eval()

all_encoder_layers, pooled_output = loaded_model(*dummy_input)

c. 使用 trace 模型进行推断

通过使用其 __call__ dunder 方法使用 trace 模型进行推断:

traced_model(tokens_tensor, segments_tensors)

4. 使用 Neuron SDK 将 Hugging Face TorchScript 模型部署到 AWS

AWS 引入了用于云端低成本、高性能机器学习推理的 Amazon EC2 Inf1 实例系列。Inf1 实例由 AWS Inferentia 芯片提供支持,这是一款专为深度学习推理工作负载而构建的定制硬件加速器。

AWS Neuron 是 Inferentia 的 SDK,支持对 transformers 模型进行跟踪和优化,以便在 Inf1 上部署。Neuron SDK 提供:

  • 简单易用的 API,只需更改一行代码即可为云端推理跟踪和优化 TorchScript 模型
  • 针对改进的性能成本的即插即用性能优化
  • 支持使用 PyTorch 或 TensorFlow 构建的 Hugging Face transformers 模型

a. 影响

基于 BERT(来自 Transformers 的双向编码器表示)架构的 transformers 模型,或其变体,如 distilBERT 和 roBERTa 在 Inf1 上运行最佳,可用于生成抽取式问答、序列分类和标记分类等任务。

b. 依赖关系

使用 AWS Neuron 将模型转换为模型需要一个 Neuron SDK 环境,它已经预先配置在 AWS 深度学习 AMI 上。

c. 将模型转换为 AWS Neuron

导入 torch.neuron 框架扩展,通过 Python API 访问 Neuron SDK 组件,只需要修改一行代码即可:

from transformers import BertModel, BertTokenizer, BertConfig
import torch
import torch.neuron

# 只需要修改一行代码,使用Neuron SDK跟踪模型并进行优化,以在Inf1实例上运行
# 原始代码:
# torch.jit.trace(model, [tokens_tensor, segments_tensors])
# 替换为:
torch.neuron.trace(model, [token_tensor, segments_tensors])

性能与扩展

1. 训练

训练方式文档链接
单 GPU 训练perf_train_gpu_one
多 GPU 训练perf_train_gpu_many
单 CPU 训练perf_train_cpu
多 CPU 训练perf_train_cpu_many
TPU 训练perf_train_tpu_tf
自定义硬件训练perf_hardware
Trainer 超参数搜索hpo_train

2. 推理

推理方式文档链接
单 CPU 推理perf_infer_cpu
单 GPU 推理perf_infer_gpu_one
多 GPU 推理perf_infer_gpu_one
TensorFlow 模型 XLA 集成tf_xla

3. 训练和推理的技巧

技巧文档链接
实例化大型模型big_models
性能优化debugging

安全分片数据并行

1. 简介

**完全分片数据并行(FSDP)**将模型的参数、梯度和优化器状态,在每个 GPU 上进行分片,单卡仅保留部分分片。

**分布式数据并行(DDP)**将模型的参数、梯度和优化器状态,在每个 GPU 上复制完整模型副本。

FSDP 已经集成到 Accelerate 中,这是一个用于在分布式环境中轻松管理训练的库,这意味着可以从 Trainer 类中调用这个库。

2. FSDP 配置

运行 accelerate config 命令,创建一个配置文件。运行 accelerate config 时,将被提示一系列选项来配置训练环境。

3. 分片策略

FSDP 提供了多种可选择的分片策略:

策略描述选项
FULL_SHARD将模型参数、梯度和优化器状态跨 Worker 进行分片选择 1
SHARD_GRAD_OP将梯度和优化器状态跨 Worker 进行分片选择 2
NO_SHARD不分片任何内容(这等同于 DDP)选择 3
HYBRID_SHARD在每个 Worker 中分片模型参数、梯度和优化器状态,其中每个 Worker 也有完整副本选择 4
HYBRID_SHARD_ZERO2在每个 Worker 中分片梯度和优化器状态,其中每个 Worker 也有完整副本选择 5

fsdp_sharding_strategy 标志启用。

4. CPU 卸载

当参数和梯度在不使用时可以卸载到 CPU 上,以节省更多 GPU 内存。运行 accelerate config 时,通过设置 fsdp_offload_params: true 来启用此功能。

5. 包装策略

通常,包装是以嵌套方式应用的,其中完整的权重在每次前向传递后被丢弃,以便为下一层节省内存。

自动包装策略:

  • fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP 来包装一个 Transformer 层
  • fsdp_transformer_layer_cls_to_wrap 来指定要包装的层(例如 BertLayer

6. 检查点

应该使用 fsdp_state_dict_type: SHARDED_STATE_DICT 来保存中间检查点,因为保存完整状态字典需要很长时间,通常会导致 NCCL Timeout 错误,因为在广播过程中会无限期挂起。

可以使用 load_state 方法加载分片状态字典以恢复训练:

# ckpt是包含检查点的目录
accelerator.load_state("ckpt")

当训练结束,希望保存完整状态字典,因为分片状态字典仅与 FSDP 兼容:

if trainer.is_fsdp_enabled:
    trainer.accelerator.state.fsdp_plugin.set_state_dict_type("FULL_STATE_DICT")

trainer.save_model(script_args.output_dir)

7. TPU

PyTorch XLA 支持用于 TPUs 的 FSDP 训练,可以通过修改由 accelerate config 生成的 FSDP 配置文件来启用。

除了上面指定的分片策略和包装选项外,还可以将以下参数添加到文件中:

xla: True  # 必须设置为 True 以启用 PyTorch/XLA
xla_fsdp_settings:  # XLA 特定的 FSDP 参数
xla_fsdp_grad_ckpt: True  # 使用梯度检查点

8. 启动训练

FSDP 配置文件示例:

compute_environment: LOCAL_MACHINE
debug: false
distributed_type: FSDP
downcast_bf16: "no"
fsdp_config:
  fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP
  fsdp_backward_prefetch_policy: BACKWARD_PRE
  fsdp_cpu_ram_efficient_loading: true
  fsdp_forward_prefetch: false
  fsdp_offload_params: true
  fsdp_sharding_strategy: 1
  fsdp_state_dict_type: SHARDED_STATE_DICT
  fsdp_sync_module_states: true
  fsdp_transformer_layer_cls_to_wrap: BertLayer
  fsdp_use_orig_params: true
machine_rank: 0
main_training_function: main
mixed_precision: bf16
num_machines: 1
num_processes: 2
rdzv_backend: static
same_network: true
tpu_env: []
tpu_use_cluster: false
tpu_use_sudo: false
use_cpu: false

启动训练,使用默认配置:

accelerate launch my-trainer-script.py

启动训练,使用自定义 FSDP 配置文件:

accelerate launch --fsdp="full shard" --fsdp_config="path/to/fsdp_config/ my-trainer-script.py

多 GPU 推理

启用张量并行,只需在调用 from_pretrained() 时传递参数 tp_plan="auto"

import os
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "meta-llama/Meta-Llama-3-8B-Instruct"

# 初始化分布式环境
rank = int(os.environ["RANK"])
device = torch.device(f"cuda:{rank}")
torch.cuda.set_device(device)
torch.distributed.init_process_group("nccl", device_id=device)

# 获取支持张量并行的模型
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    tp_plan="auto",
)

# 准备输入tokens
tokenizer = AutoTokenizer.from_pretrained(model_id)
prompt = "Can I help"
inputs = tokenizer(prompt, return_tensors="pt").input_ids.to(device)

# 分布式运行
outputs = model(inputs)

使用 torchrun 命令启动上述脚本,多进程模式会自动将每个进程映射到一张 GPU:

torchrun --nproc-per-node 4 demo.py

多 CPU 训练

1. 使用 IPEX 进行混合精度训练

混合精度训练在模型中可以同时使用单精度(fp32)和半精度(bf16/fp16)的数据类型来加速训练或推理过程,并且仍然能保留大部分单精度的准确性。

例如:

  • 第三代、第四代和第五代 Intel® Xeon® Scalable 处理器,原生支持 bf16
  • 第六代 Intel® Xeon® Scalable 处理器原生支持 bf16 和 fp16
  • 在训练时启用 bf16 或 fp16 的混合精度训练可以直接提高处理性能

为了进一步最大化训练性能,可以使用 Intel® PyTorch 扩展(IPEX)

IPEX 是一个基于 PyTorch 构建的库,增加了额外的 CPU 指令集架构(ISA)级别的支持。

例如:

  • Intel® 高级向量扩展 512(Intel® AVX512-VNNI)和 Intel® 高级矩阵扩展(Intel® AMX),为 Intel CPU 提供额外的性能提升
  • 仅支持 AVX2 的 CPU(例如 AMD 或较旧的 Intel CPU)在使用 IPEX 时并不保证能提高性能

2. IPEX 安装

IPEX 的发布与 PyTorch 一致,可以通过 pip 安装:

PyTorch VersionIPEX version
2.5.02.5.0+cpu
2.4.02.4.0+cpu
2.3.02.3.0+cpu
2.2.02.2.0+cpu

运行 pip list | grep torch 以获取您的 pytorch_version,然后根据该版本安装相应的 IPEX version_name

pip install intel_extension_for_pytorch==<version_name> -f https://developer.intel.com/ipex-whl-stable-cpu

3. 在 Trainer 中使用 IPEX

命令行的方式,CPU 上使用 BF16 自动混合精度训练,以 Transformers 问答任务为例:

python examples/pytorch/question-answering/run_qa.py \
--model_name_or_path google-bert/bert-base-uncased \
--dataset_name squad \
--do_train \
--do_eval \
--per_device_train_batch_size 12 \
--learning_rate 3e-5 \
--num_train_epochs 2 \
--max_seq_length 384 \
--doc_stride 128 \
--output_dir /tmp/debug_squad/ \
--use_ipex \
--bf16 \
--use_cpu

代码的方式,CPU 上使用 BF16 自动混合精度训练,将 use_ipexbf16 参数添加到 TrainingArguments 中:

training_args = TrainingArguments(
    output_dir=args.output_path,
    bf16=True,
    use_ipex=True,
    use_cpu=True,
    **kwargs
)

用于训练的定制硬件

1. GPU

当你训练更大的模型时,基本上有三种选择:

  • 更大的 GPU
  • 更多的 GPU
  • 更多的 CPU 和 NVMe(通过 DeepSpeed-Infinity 实现)

2. 供电

高端消费者级 GPU 卡具有 2 个,有时甚至 3 个 PCI-E-8 针电源插口。请确保将与插口数量相同的独立 12V PCI-E-8 针线缆插入卡中。不要使用同一根线缆两端的 2 个分叉(也称为 pigtail cable)。

也就是说,如果您的 GPU 上有 2 个插口,您需要使用 2 条单独的 PCI-E-8 针线缆连接电源和显卡,而不是使用一条末端有 2 个 PCI-E-8 针连接器的线缆!否则,您无法充分发挥卡的性能。

每个 PCI-E-8 针电源线缆需要插入电源侧的 12V 轨上,并且可以提供最多 150W 的功率。如果可以使用 PCI-E-12 针连接器,可以提供最多 500-600W 的功率。低端卡可能使用 6 针连接器,可以提供最多 75W 的功率。

3. 散热

当 GPU 过热时,将开始降频,不会提供完整的性能。如果温度过高,可能会缩短 GPU 的使用寿命。

当 GPU 负载很重时,温度越低越好:

  • 在 70-75 度之间最佳
  • 尽量保持在 80 度以下
  • 大约 84-90 度之间,GPU 开始降频

4. 多 GPU 连接

使用多个 GPU,则卡之间的互连方式可能会对总训练时间产生巨大影响。

如果 GPU 位于同一物理节点,可以运行如下代码查看连接方式:

nvidia-smi topo -m

在具有双 GPU 并通过 NVLink 连接的机器,可能看到如下内容(NV2 表示 GPU 通过 2 个 NVLink 互连):

        GPU0    GPU1    CPU Affinity    NUMA Affinity
GPU0     X      NV2     0-23            N/A
GPU1    NV2      X      0-23            N/A

如果没有 NVLink,可能看到如下内容(PHB 表示 PCIe+Bridge 连接):

        GPU0    GPU1    CPU Affinity    NUMA Affinity
GPU0     X      PHB     0-11            N/A
GPU1    PHB      X      0-11            N/A

总之,NVLink 通信速度较快,PHB 通信速度较慢。如果 GPU 很少需要同步,就像在 DDP 中一样,那么较慢的连接的影响将不那么显著。如果 GPU 经常需要相互发送消息,就像在 FSDP 中一样,那么更快的连接对于实现更快的训练变得非常重要。

NVLink 是由 Nvidia 开发的一种基于线缆的串行多通道近程通信链接。

nvidia-smi topo -m 输出的 NVX 报告中获取到的更高的 X 值意味着更好的性能。生成的结果将取决于 GPU 架构。

基准测试代码和输出样例:

硬件: 2x TITAN RTX 24GB each + NVlink with 2 NVLinks (NV2 in nvidia-smi topo -m) 软件: pytorch-1.8-to-be + cuda-11.0 / transformers==4.3.0.dev0

DDP w/ NVLink:

rm -r /tmp/test-clm; CUDA_VISIBLE_DEVICES=0,1 torchrun \
--nproc_per_node 2 examples/pytorch/language-modeling/run_clm.py --model_name_or_path openai-community/gpt2 \
--dataset_name wikitext --dataset_config_name wikitext-2-raw-v1 --do_train \
--output_dir /tmp/test-clm --per_device_train_batch_size 4 --max_steps 200

# {'train_runtime': 101.9003, 'train_samples_per_second': 1.963, 'epoch': 0.69}

DDP w/o NVLink:

rm -r /tmp/test-clm; CUDA_VISIBLE_DEVICES=0,1 NCCL_P2P_DISABLE=1 torchrun \
--nproc_per_node 2 examples/pytorch/language-modeling/run_clm.py --model_name_or_path openai-community/gpt2 \
--dataset_name wikitext --dataset_config_name wikitext-2-raw-v1 --do_train
--output_dir /tmp/test-clm --per_device_train_batch_size 4 --max_steps 200

# {'train_runtime': 131.4367, 'train_samples_per_second': 1.522, 'epoch': 0.69}

使用 Trainer API 进行超参数搜索

1. 超参数搜索后端

Trainer 目前支持四种超参数搜索后端:optunasigoptraytunewandb

安装依赖:

pip install optuna/sigopt/wandb/ray[tune]

2. 启用超参数搜索

不同后端需要不同的格式:

a. sigopt

参阅 sigopt object_parameter

def sigopt_hp_space(trial):
    return [
        {"bounds": {"min": 1e-6, "max": 1e-4}, "name": "learning_rate", "type": "double"},
        {
            "categorical_values": ["16", "32", "64", "128"],
            "name": "per_device_train_batch_size",
            "type": "categorical",
        },
    ]

b. optuna

参阅 optuna object_parameter

def optuna_hp_space(trial):
    return {
        "learning_rate": trial.suggest_float("learning_rate", 1e-6, 1e-4, log=True),
        "per_device_train_batch_size": trial.suggest_categorical("per_device_train_batch_size", [16, 32, 64, 128]),
    }

optuna 提供了多目标 HPO,向 hyperparameter_search 中传递 direction 参数,定义自己的 compute_objective 返回多个目标值:

best_trials = trainer.hyperparameter_search(
    direction=["minimize", "maximize"],
    backend="optuna",
    hp_space=optuna_hp_space,
    n_trials=20,
    compute_objective=compute_objective,
)

c. raytune

参考 raytune object_parameter

def ray_hp_space(trial):
    return {
        "learning_rate": tune.loguniform(1e-6, 1e-4),
        "per_device_train_batch_size": tune.choice([16, 32, 64, 128]),
    }

d. wandb

参考 wandb object_parameter

def wandb_hp_space(trial):
    return {
        "method": "random",
        "metric": {"name": "objective", "goal": "minimize"},
        "parameters": {
            "learning_rate": {"distribution": "uniform", "min": 1e-6, "max": 1e-4},
            "per_device_train_batch_size": {"values": [16, 32, 64, 128]},
        },
    }

e. 定义 model_init 用于初始化

def model_init(trial):
    return AutoModelForSequenceClassification.from_pretrained(
        model_args.model_name_or_path,
        from_tf=bool(".ckpt" in model_args.model_name_or_path),
        config=config,
        cache_dir=model_args.cache_dir,
        revision=model_args.model_revision,
        use_auth_token=True if model_args.use_auth_token else None,
    )

f. 创建 Trainer

trainer = Trainer(
    model=None,
    args=training_args,
    train_dataset=small_train_dataset,
    eval_dataset=small_eval_dataset,
    compute_metrics=compute_metrics,
    processing_class=tokenizer,
    model_init=model_init,
    data_collator=data_collator,
)

调用超参数搜索,获取最佳试验参数,后端可以是 "optuna" / "sigopt" / "wandb" / "ray"。方向可以是 "minimize""maximize",表示是否优化更大或更低的目标。

g. 将评估指标之和作为目标值返回

best_trial = trainer.hyperparameter_search(
    direction="maximize",
    backend="optuna",
    hp_space=optuna_hp_space,
    n_trials=20,
    compute_objective=compute_objective,
)

3. 针对 DDP 微调的超参数搜索

Optuna 和 Sigopt 已启用针对 DDP 的超参数搜索。只有 rank-zero 进程会进行超参数搜索并将参数传递给其他进程。

实例化大模型

1. 启动分布式训练时的问题

使用一个非常大的预训练模型时,一个挑战是尽量减少对内存的使用。从 PyTorch 开始的实例化过程如下:

  1. 用随机权重创建你的模型
  2. 加载你的预训练权重
  3. 将这些预训练权重放入你的随机模型中

遇到的问题:

  • 当模型达到几个 GB 大小,模型权重和预训练权重的副本会超出内存限制
  • 如果使用 torch.distributed 启动分布式训练,每个进程都会加载预训练模型,并将这两个副本存储在内存中

2. 分片 checkpoint

自 4.18.0 版本起,占用空间超过 10GB 的模型检查点将自动分成较小的片段。

在使用 model.save_pretrained(save_dir) 时,最终会得到几个部分 checkpoints(每个的大小都小于 10GB)以及一个索引,该索引将参数名称映射到存储它们的文件。

加载示例模型:

from transformers import AutoModel

model = AutoModel.from_pretrained("google-bert/bert-base-cased")

模型保存,得到新的文件夹,以及模型配置和模型权重文件:

import os
import tempfile

with tempfile.TemporaryDirectory() as tmp_dir:
    model.save_pretrained(tmp_dir)
    print(sorted(os.listdir(tmp_dir)))
# 输出:单个模型权重文件
# ['config.json', 'pytorch_model.bin']

使用 max_shard_size 参数来控制分片大小:

with tempfile.TemporaryDirectory() as tmp_dir:
    model.save_pretrained(tmp_dir, max_shard_size="200MB")
    print(sorted(os.listdir(tmp_dir)))
# 输出:多个分片文件
# ['config.json', 'pytorch_model-00001-of-00003.bin', 'pytorch_model-00002-of-00003.bin', 'pytorch_model-00003-of-00003.bin', 'pytorch_model.bin.index.json']

使用 from_pretrained() 方法加载分片文件:

with tempfile.TemporaryDirectory() as tmp_dir:
    model.save_pretrained(tmp_dir, max_shard_size="200MB")
    new_model = AutoModel.from_pretrained(tmp_dir)

查看索引文件,包含了模型的元数据和权重:

import json

with tempfile.TemporaryDirectory() as tmp_dir:
    model.save_pretrained(tmp_dir, max_shard_size="200MB")
    with open(os.path.join(tmp_dir, "pytorch_model.bin.index.json"), "r") as f:
        index = json.load(f)

print(index.keys())
print(index["metadata"])
print(index["weight_map"])
# 输出:json文件的键、元数据、权重映射
# dict_keys(['metadata', 'weight_map'])
# {'total_size': 433245184}
# {'embeddings.LayerNorm.bias': 'pytorch_model-00001-of-00003.bin',
#  'embeddings.LayerNorm.weight': 'pytorch_model-00001-of-00003.bin',
#  ...

或者使用 load_sharded_checkpoint() 方法加载分片后的 checkpoint:

from transformers.modeling_utils import load_sharded_checkpoint

with tempfile.TemporaryDirectory() as tmp_dir:
    model.save_pretrained(tmp_dir, max_shard_size="200MB")
    load_sharded_checkpoint(model, tmp_dir)

3. 低内存加载

使用 Accelerate 进行大模型加载,参考:Large model loading

使用 torch.compile() 优化推理

根据模型和 GPU 的不同,torch.compile() 在推理过程中可以提高多达 30% 的速度。要使用 torch.compile(),只需安装 2.0 及以上版本的 torch 即可。

调用 torch.compile(model) 编译模型:

from transformers import AutoModelForImageClassification

model = AutoModelForImageClassification.from_pretrained(MODEL_ID).to("cuda")
model = torch.compile(model, mode="default")

compile() 提供多种编译模式:

模式触发指令优化目标适用场景编译时间显存占用
defaultmode="default"平衡编译开销与加速比通用场景⭐⭐⭐⭐
reduce-overheadmode="reduce-overhead"最小化框架开销小模型/小批量⭐⭐⭐
max-autotunemode="max-autotune"极致性能优化计算密集型大模型⭐⭐⭐

主要类型

1. Callbacks

Callbacks 本质:用于自定义 PyTorch Trainer 训练循环行为的可插拔组件,通过只读方式访问训练状态并控制训练流程(如提前停止),但不能直接修改训练逻辑。

核心特性:

  • 只读访问:可查看训练状态(TrainerState),但不能修改训练逻辑
  • 流程控制:通过返回 TrainerControl 对象影响训练流程
  • 事件驱动:在训练循环关键节点触发回调
  • 模块化:支持多回调组合,互不干扰

TrainerCallback 事件接口

事件方法触发时机适用场景关键参数作用
on_init_endTrainer 初始化完成后环境检查/资源分配args: 训练配置, state: 训练状态, control: 流程控制
on_train_begin训练循环开始时初始化自定义指标args, state, control
on_epoch_begin每个 epoch 开始时动态调整学习率/数据采样args, state, control
on_step_begin每个优化步骤开始前梯度裁剪/输入预处理args, state, control
on_step_end每个优化步骤完成后梯度监控/自定义日志args, state, control
on_substep_end梯度累积子步骤完成自定义梯度累积逻辑args, state, control
on_optimizer_step优化器更新后梯度分析/权重监控optimizer: 当前优化器实例
on_epoch_end每个 epoch 结束时模型验证/检查点保存args, state, control
on_evaluate评估阶段自定义评估指标metrics: 评估指标字典
on_log日志记录后日志增强/第三方集成logs: 待记录日志字典
on_save保存检查点后模型压缩/云存储同步args, state, control
on_train_end训练完全结束时资源释放/模型导出args, state, control

接口调用样例:

  1. 环境初始化检查
class EnvCheckCallback(TrainerCallback):
    def on_init_end(self, args, state, control, **kwargs):
        if not torch.cuda.is_available():
            print("警告: 未检测到GPU,训练性能将受限")
  1. 训练开始通知
class TrainingStartCallback(TrainerCallback):
    def on_train_begin(self, args, state, control, **kwargs):
        slack_notify(f"训练启动: 模型 {args.model_name}")
  1. 动态学习率调整
class DynamicLRCallback(TrainerCallback):
    def on_epoch_begin(self, args, state, control, **kwargs):
        if state.epoch > 5:
            for pg in state.optimizer.param_groups:
                pg['lr'] *= 0.95  # 5轮后每轮衰减5%
  1. 梯度裁剪
class GradientClipCallback(TrainerCallback):
    def on_step_begin(self, args, state, control, **kwargs):
        torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
  1. 梯度监控
class GradMonitorCallback(TrainerCallback):
    def on_step_end(self, args, state, control, **kwargs):
        if state.global_step % 100 == 0:
            grads = [p.grad.norm() for p in model.parameters()]
            print(f"Step {state.global_step} | 梯度均值: {np.mean(grads):.4f}")
  1. 梯度累积控制
class AccumulationCallback(TrainerCallback):
    def on_substep_end(self, args, state, control, **kwargs):
        if state.gradient_step == args.grad_accum_steps // 2:
            print("50%梯度累积完成")
  1. 权重监控
class WeightMonitorCallback(TrainerCallback):
    def on_optimizer_step(self, args, state, control, **kwargs):
        weights = [p.data.mean() for p in model.parameters()]
        wandb.log({"weights/mean": np.mean(weights)})
  1. 自动保存最佳模型
class BestModelSaver(TrainerCallback):
    def on_epoch_end(self, args, state, control, **kwargs):
        if state.metrics['eval_acc'] > state.best_metric:
            torch.save(model.state_dict(), "best_model.pt")
            control.should_save = True  # 触发官方保存
  1. 自定义评估指标
class F1ScoreCallback(TrainerCallback):
    def on_evaluate(self, args, state, control, metrics, **kwargs):
        predictions, labels = gather_predictions()
        metrics["eval_f1"] = calculate_f1(predictions, labels)
  1. 日志增强
class MemoryLogger(TrainerCallback):
    def on_log(self, args, state, control, logs, **kwargs):
        logs["memory_usage"] = torch.cuda.memory_allocated() / 1e9
  1. 检查点云同步
class CloudSyncCallback(TrainerCallback):
    def on_save(self, args, state, control, **kwargs):
        upload_to_s3(f"{args.output_dir}/checkpoint-{state.global_step}")
  1. 训练完成处理
class CleanupCallback(TrainerCallback):
    def on_train_end(self, args, state, control, **kwargs):
        compress_folder(args.output_dir)
        send_email("训练完成通知")

内置 Callbacks 功能对照

Callback 类核心用途关键配置参数适用场景
EarlyStoppingCallback验证损失无改善时停止训练early_stopping_patience: 容忍轮次, early_stopping_threshold: 最小改善阈值防止过拟合/资源优化
TensorBoardCallback记录指标到 TensorBoardtb_writer: SummaryWriter 实例训练可视化/性能分析
WandbCallback集成 Weights & Biaseswandb_project: 项目名, wandb_run_name: 实验名实验追踪/团队协作
MLflowCallback集成 MLflow 实验管理MLFLOW_EXPERIMENT_NAME: 实验名, MLFLOW_TAGS: 标签字典企业级模型管理
CodeCarbonCallback跟踪训练碳排放量measure_power_secs: 功耗测量间隔绿色 AI/能效优化
ProgressCallback显示训练进度条max_str_len: 日志截断长度交互式训练监控
DefaultFlowCallback处理默认日志/保存/评估基础训练流程管理

使用技巧

i. 多回调组合:

trainer = Trainer(
    callbacks=[EarlyStoppingCallback(patience=3),
              WandbCallback(project="exp1"),
              CustomMetricsCallback()]
)

ii. 动态流程控制:

def on_step_end(self, args, state, control, **kwargs):
    if state.global_step > 1000 and loss > 10:
        control.should_training_stop = True  # 异常终止

iii. 状态访问:

def on_epoch_end(self, args, state, control, **kwargs):
    print(f"Epoch {state.epoch} | LR: {state.optimizer.param_groups[0]['lr']}")

2. Configuration

PretrainedConfig 本质:Transformers 库中所有模型配置的基类,用于管理模型的结构参数和训练设置,支持从本地/Hugging Face Hub 加载、保存和共享配置。

核心特性:

  • 统一配置管理:标准化处理模型超参数
  • 跨框架兼容:支持 PyTorch/TensorFlow 的专用参数
  • 序列化能力:支持 JSON 格式的保存/加载
  • Hub 集成:直接推送/拉取云端配置

PretrainedConfig 关键属性

属性类别属性名称数据类型作用适用场景
通用架构hidden_sizeint隐藏层维度所有 Transformer 模型
num_attention_headsint注意力头数多头注意力机制
num_hidden_layersint隐藏层数量模型深度控制
文本模型vocab_sizeint词表大小NLP 模型
max_position_embeddingsint最大序列长度位置编码
输出控制output_hidden_statesbool是否输出所有隐藏状态特征提取任务
output_attentionsbool是否输出注意力权重可解释性分析
任务适配num_labelsint分类标签数分类任务微调
id2labelDict[int, str]ID 到标签映射分类头配置
problem_typestr问题类型(回归/分类)自动适配损失函数
分词器关联bos_token_idint起始符 ID文本生成
eos_token_idint结束符 ID文本生成控制
pad_token_idint填充符 ID批量处理

PretrainedConfig 核心 API

方法名称用途关键参数参数作用
from_pretrained加载预训练配置pretrained_model_name_or_path: 模型 ID/本地路径初始化模型
cache_dir: 自定义缓存目录cache_dir="./model_cache"
revision: Git 分支/标签revision="v2.0"
save_pretrained保存配置save_directory: 保存路径本地存储配置
push_to_hub: 是否推送至 Hubpush_to_hub=True
push_to_hub推送至 Hubrepo_id: 仓库 ID共享配置
private: 是否私有仓库private=True
to_dict转为字典内存操作配置
from_dict从字典创建config_dict: 配置字典动态配置
to_json_string转为 JSONuse_diff: 是否仅输出差异配置传输
from_json_file从 JSON 加载json_file: JSON 文件路径本地加载
update更新配置config_dict: 更新参数字典动态修改
register_for_auto_class注册自动类auto_class: 自动类名自定义模型

配置使用示例

  1. 基础加载与保存
from transformers import BertConfig
# 从Hub加载配置
config = BertConfig.from_pretrained("bert-base-uncased")
# 修改配置
config.num_hidden_layers = 8
config.hidden_size = 512
# 本地保存
config.save_pretrained("./custom_bert")
# 推送到Hub
config.push_to_hub("my-org/custom-bert", private=True)
  1. 动态创建配置
from transformers import PretrainedConfig
# 从字典创建
custom_config = PretrainedConfig.from_dict({
    "vocab_size": 32000,
    "hidden_size": 1024,
    "num_attention_heads": 16
})
# 更新配置
custom_config.update({"num_hidden_layers": 24})
  1. 任务适配配置
from transformers import AutoConfig
# 分类任务配置
config = AutoConfig.from_pretrained("roberta-base")
config.update({
    "num_labels": 5,
    "id2label": {0: "体育", 1: "科技", 2: "政治", 3: "娱乐", 4: "经济"},
    "problem_type": "single_label_classification"
})

最佳实践建议

  1. 配置继承:自定义配置应继承 PretrainedConfig
class MyModelConfig(PretrainedConfig):
    model_type = "mymodel"
    def __init__(self, custom_param=128, **kwargs):
        self.custom_param = custom_param
        super().__init__(**kwargs)
  1. 云配置管理:团队协作时使用 Hub 存储配置
# 推送配置
config.push_to_hub("team-project/model-v1")

# 其他成员加载
remote_config = AutoConfig.from_pretrained("team-project/model-v1")
  1. 配置版本控制:结合 revision 参数管理迭代
# 加载特定版本
config_v2 = AutoConfig.from_pretrained(
    "my-model",
    revision="v2.0",
    num_labels=10  # 覆盖原配置
)

Data Collator

Data Collators 用于将数据集元素(如文本、标签)组合成批次,支持预处理(如填充)和数据增强(如随机掩码)。

1. DefaultDataCollator

属性说明
名称DefaultDataCollator / transformers.default_data_collator
用途基础数据整理器,仅合并字典类对象,不进行额外预处理
场景通用任务(如 GLUE、NER),输入数据已预处理,只需简单批次合并
参数return_tensors:返回张量类型("pt" / "np" / "tf"),默认为 PyTorch

使用样例:

collator = DefaultDataCollator(return_tensors="pt")

2. DataCollatorWithPadding

属性说明
名称DataCollatorWithPadding
用途动态填充输入序列至批次内最大长度
场景需处理变长序列的任务(如文本分类)
参数tokenizer: 分词器, padding: 填充策略(True / 'longest' / 'max_length'), max_length: 最大填充长度, pad_to_multiple_of: 填充至该值的倍数, return_tensors: 返回张量类型

使用样例:

collator = DataCollatorWithPadding(tokenizer, padding='max_length', max_length=128)

3. DataCollatorForTokenClassification

属性说明
名称DataCollatorForTokenClassification
用途动态填充输入序列和标签,支持标签掩码
场景序列标注任务(如命名实体识别)
参数DataCollatorWithPadding,新增 label_pad_token_id: 标签填充 ID(默认为 -100,被 PyTorch 忽略)

使用样例:

collator = DataCollatorForTokenClassification(tokenizer, label_pad_token_id=-100)

4. DataCollatorForSeq2Seq

属性说明
名称DataCollatorForSeq2Seq
用途动态填充输入序列和标签,支持序列到序列任务
场景机器翻译、文本生成等 Seq2Seq 任务
参数DataCollatorForTokenClassification,新增 model: 用于生成 decoder_input_ids 的模型

使用样例:

collator = DataCollatorForSeq2Seq(tokenizer, model=model)

5. DataCollatorForLanguageModeling

属性说明
名称DataCollatorForLanguageModeling
用途动态填充输入,并应用掩码语言建模(MLM)增强
场景BERT 等掩码语言模型预训练
参数tokenizer: 分词器, mlm: 是否启用 MLM, mlm_probability: 掩码概率, mask_replace_prob: 掩码替换概率(默认 0.8), random_replace_prob: 随机替换概率(默认 0.1), return_tensors: 返回张量类型

使用样例:

collator = DataCollatorForLanguageModeling(tokenizer, mlm_probability=0.15)

掩码行为:

  • 80% 替换为 [MASK]
  • 10% 替换为随机词
  • 10% 保持原词

6. DataCollatorForWholeWordMask

属性说明
名称DataCollatorForWholeWordMask
用途对整个单词进行掩码(而非子词),增强语言模型训练
场景需整词掩码的任务(如 BERT 整词掩码策略)
参数DataCollatorForLanguageModeling

使用样例:

collator = DataCollatorForWholeWordMask(tokenizer)

7. DataCollatorForPermutationLanguageModeling

属性说明
名称DataCollatorForPermutationLanguageModeling
用途生成排列语言建模(PLM)所需的掩码序列(XLNet 专用)
场景XLNet 等排列语言模型预训练
参数tokenizer: 分词器, plm_probability: 排列掩码概率(默认 1/6), max_span_length: 最大掩码跨度长度(默认 5)

使用样例:

collator = DataCollatorForPermutationLanguageModeling(tokenizer)

掩码生成逻辑:

  1. 从序列开头开始,设置当前长度 cur_len=0
  2. 采样掩码跨度长度 span_length ∈ [1, max_span_length]
  3. 计算上下文长度 context_length = span_length / plm_probability
  4. [cur_len, cur_len + context_length - span_length] 内采样起始位置并掩码
  5. 更新 cur_len += context_length,重复直到覆盖整个序列

关键点总结

  • 基础整理器DefaultDataCollator(无预处理)和 DataCollatorWithPadding(动态填充)
  • 任务专用:序列标注(TokenClassification)、Seq2Seq、语言建模(LanguageModeling
  • 掩码策略
    • 随机子词掩码(LanguageModeling
    • 整词掩码(WholeWordMask
    • 排列掩码(PermutationLanguageModeling,XLNet 专用)

Keras Callbacks

在 Keras 中训练 Transformers 模型时,可以使用以下库特定的回调函数自动执行常见任务。

1. KerasMetricCallback

属性说明
名称KerasMetricCallback
用途在每轮(epoch)结束时计算自定义指标(如 BLEU、ROUGE 等复杂指标)
场景NLP 生成任务(文本摘要、翻译等)需要字符串操作或生成循环的指标计算
参数metric_fn: 自定义指标函数,接收 predictions 和 labels 返回指标字典;eval_dataset: 验证数据集;predict_with_generate: 是否用 model.generate() 生成输出(生成任务设为 True);use_xla_generation: 是否用 XLA 加速生成(提升 100x 速度,需固定输入形状);generate_kwargs: 传递给 model.generate() 的参数

使用样例:

callback = KerasMetricCallback(
    metric_fn=rouge_fn,
    eval_dataset=val_data,
    predict_with_generate=True
)
model.fit(..., callbacks=[callback])

指标函数示例(ROUGE):

def rouge_fn(predictions, labels):
    decoded_preds = tokenizer.batch_decode(predictions, skip_special_tokens=True)
    decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)
    result = rouge_metric.compute(predictions=decoded_preds, references=decoded_labels)
    return {k: v.mid.fmeasure * 100 for k, v in result.items()}  # 返回格式: {'rouge1': 37.41}

2. PushToHubCallback

属性说明
名称PushToHubCallback
用途定期将模型和分词器自动保存并推送到 Hugging Face Hub
场景训练过程中持续保存/共享模型到 Hub
参数output_dir: 本地保存路径;save_strategy: 保存策略("epoch" / "steps" / "no");save_steps: 按步保存时的步数间隔;tokenizer: 需上传的分词器;hub_model_id: Hub 模型 ID(如 "user_name/model");checkpoint: 是否保存完整检查点(含优化器状态)

使用样例:

callback = PushToHubCallback(
    output_dir="./gpt5-model",
    tokenizer=tokenizer,
    hub_model_id="gpt5-7xlarge",
    save_strategy="epoch"
)
model.fit(..., callbacks=[callback])

关键参数说明:

  • save_strategy
    • "epoch":每轮结束保存(默认)
    • "steps":每 N 步保存(需配合 save_steps
    • "no":仅训练结束保存
  • checkpoint=True:保存完整检查点(可恢复训练)

核心功能对比

回调函数核心能力典型使用场景
KerasMetricCallback计算非 TensorFlow 原生支持的复杂指标文本生成任务的质量评估(ROUGE/BLEU)
PushToHubCallback自动化模型版本管理与共享持续训练并发布模型到 Hub

Logging

Transformers 提供集中式日志系统,支持自定义日志详细程度、进度条控制等。

1. 日志级别设置函数

名称用途场景参数
set_verbosity_error()设置日志级别为 ERROR (40)仅需查看错误信息
set_verbosity_warning()设置日志级别为 WARNING (30)默认级别,显示错误和警告
set_verbosity_info()设置日志级别为 INFO (20)查看基础训练信息
set_verbosity_debug()设置日志级别为 DEBUG (10)调试时查看全部信息
set_verbosity(verbosity)自定义日志级别精确控制日志输出verbosity: 整数日志级别(10/20/30/40/50)

使用样例:

函数样例
set_verbosity_errortransformers.logging.set_verbosity_error()
set_verbosity_warningtransformers.logging.set_verbosity_warning()
set_verbosity_infotransformers.logging.set_verbosity_info()
set_verbosity_debugtransformers.logging.set_verbosity_debug()
set_verbositytransformers.logging.set_verbosity(20)

日志级别对照:

级别整数值说明
CRITICAL/FATAL50仅关键错误
ERROR40仅错误
WARNING/WARN30错误 + 警告(默认级别)
INFO20基础信息 + 错误/警告
DEBUG10全部信息

2. 日志控制函数

名称用途场景参数
get_verbosity()获取当前日志级别检查系统状态
get_logger(name)获取指定名称的日志记录器自定义模块集成日志系统name: 日志器名称(如 "transformers"
enable_default_handler()启用根日志器的默认处理器恢复默认日志输出
disable_default_handler()禁用根日志器的默认处理器临时关闭日志输出
enable_explicit_format()启用显式格式化([LEVEL FILE LINE] TIME >> MSG需要详细日志来源信息
reset_format()重置日志格式为默认恢复简洁日志格式
enable_progress_bar()启用 tqdm 进度条显示模型下载/训练进度
disable_progress_bar()禁用 tqdm 进度条无干扰日志输出
captureWarnings(capture)将 warnings 捕获到日志系统统一管理警告信息capture: 是否捕获(True/False

使用样例:

函数样例
get_verbositylevel = transformers.logging.get_verbosity()
get_loggerlogger = logging.get_logger("my_module")
enable_default_handlerlogging.enable_default_handler()
disable_default_handlerlogging.disable_default_handler()
enable_explicit_formatlogging.enable_explicit_format()
reset_formatlogging.reset_format()
enable_progress_barlogging.enable_progress_bar()
disable_progress_barlogging.disable_progress_bar()
captureWarningslogging.captureWarnings(True)

3. 环境变量控制

变量名用途值示例效果
TRANSFORMERS_VERBOSITY覆盖默认日志级别error, info, debugTRANSFORMERS_VERBOSITY=error ./main.py
TRANSFORMERS_NO_ADVISORY_WARNINGS禁用建议类警告(如弃用警告)1 (true)TRANSFORMERS_NO_ADVISORY_WARNINGS=1 ./main.py

使用场景

  1. 自定义日志输出:
from transformers.utils import logging
# 设置INFO级别日志 + 显式格式
logging.set_verbosity_info()
logging.enable_explicit_format()
# 获取日志器并记录
logger = logging.get_logger("transformers")
logger.info("Training started")
  1. 禁用进度条:
logging.disable_progress_bar()  # 静默下载模型
model = AutoModel.from_pretrained("bert-base-uncased")
  1. 捕获警告到日志:
logging.captureWarnings(True)  # 将DeprecationWarning等转为日志
  1. 环境变量全局控制:
# 仅显示错误 + 禁用建议警告
TRANSFORMERS_VERBOSITY=error \
TRANSFORMERS_NO_ADVISORY_WARNINGS=1 \
python train.py

模型

1. 模型基类与通用方法

PyTorch (PreTrainedModel)

接口名称用途场景关键参数
from_pretrained加载预训练模型初始化模型pretrained_model_name_or_path: 模型 ID/路径;device_map="auto": 自动设备分配;torch_dtype: 数据类型(如 torch.float16);ignore_mismatched_sizes: 忽略尺寸不匹配
save_pretrained保存模型模型持久化save_directory: 保存路径;safe_serialization=True: 使用 safetensors 格式;max_shard_size="5GB": 分片大小
push_to_hub推送模型到 Hugging Face Hub模型共享repo_id: 仓库 ID;private=True: 设为私有;token: 访问令牌
resize_token_embeddings调整词嵌入大小增加新词汇new_num_tokens: 新词表大小;pad_to_multiple_of=128: 填充至 128 的倍数
gradient_checkpointing_enable激活梯度检查点减少训练显存
to_bettertransformer转换为优化版 Transformer加速推理

使用样例:

接口样例
from_pretrainedmodel = BertModel.from_pretrained("bert-base-uncased", device_map="auto")
save_pretrainedmodel.save_pretrained("./model", safe_serialization=True)
push_to_hubmodel.push_to_hub("my-bert-model")
resize_token_embeddingsmodel.resize_token_embeddings(32000)
gradient_checkpointing_enablemodel.gradient_checkpointing_enable()
to_bettertransformermodel = model.to_bettertransformer()

TensorFlow (TFPreTrainedModel)

接口名称用途关键差异点样例
from_pretrained加载预训练模型支持 from_pt=True 加载 PyTorch 权重model = TFBertModel.from_pretrained("bert-base-uncased", from_pt=True)
compile编译模型Keras 特有方法model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')

Flax/JAX (FlaxPreTrainedModel)

接口名称用途关键特性样例
from_pretrained加载预训练模型支持 dtype=jnp.bfloat16model = FlaxBertModel.from_pretrained("bert-base-uncased", dtype=jnp.bfloat16)
to_bf16/to_fp16转换参数精度半精度训练支持model.params = model.to_bf16(model.params)

2. 模型工具类

PyTorch (ModuleUtilsMixin)

接口名称用途场景参数样例
num_parameters计算参数量模型分析only_trainable=True: 仅统计可训练参数;exclude_embeddings=True: 排除嵌入层num_params = model.num_parameters()
get_extended_attention_mask生成扩展注意力掩码处理因果掩码attention_mask: 原始掩码;input_shape: 输入形状mask = model.get_extended_attention_mask(attn_mask, input_shape)

TensorFlow (TFModelUtilsMixin)

接口名称用途样例
num_parameters计算参数量num_params = model.num_parameters(only_trainable=True)

3. 大模型加载技巧 (PyTorch)

技术参数/方法效果使用场景
设备映射device_map="auto"自动分配层到 GPU/CPU/磁盘超大模型推理
自动 dtypetorch_dtype="auto"自动匹配权重数据类型节省显存
分片加载max_shard_size="5GB"避免内存溢出>10B 参数模型
量化加载load_in_4bit=True4 位量化低显存设备推理

大模型加载示例 (15B+ 参数):

model = AutoModelForSeq2SeqLM.from_pretrained(
    "bigscience/T0pp",
    device_map="auto",          # 自动分配设备
    torch_dtype="auto",         # 自动推断数据类型
    load_in_4bit=True,          # 4位量化
    max_shard_size="10GB"       # 分片加载
)

4. 分片检查点工具

接口名称用途场景参数
load_sharded_checkpoint加载分片检查点超大模型加载folder: 分片目录;prefer_safe=True: 优先 safetensors 格式
save_pretrained分片保存模型保存超大模型max_shard_size="5GB": 分片大小
# 分片保存与加载
model.save_pretrained("./big_model", max_shard_size="5GB")
loaded_model = load_sharded_checkpoint(model, "./big_model")

关键特性对比

功能PyTorchTensorFlowFlax/JAX
设备映射 (device_map)
半精度自动转换✅ (torch_dtype="auto")✅ (dtype=jnp.bfloat16)
梯度检查点
分片加载/保存
量化支持 (4/8 bit)

典型工作流示例

# PyTorch 完整流程
from transformers import BertModel

# 1. 加载模型 (自动设备分配 + 半精度)
model = BertModel.from_pretrained(
    "bert-base-uncased",
    device_map="auto",
    torch_dtype=torch.float16
)

# 2. 训练配置
model.gradient_checkpointing_enable()  # 激活梯度检查点
model.train()                         # 训练模式

# 3. 保存与共享
model.save_pretrained("./my_bert", safe_serialization=True)
model.push_to_hub("my-bert-finetuned")

文本生成

1. GenerationConfig 配置类

控制生成行为的参数集合,可通过 JSON 保存/加载。

参数类别关键参数作用典型值
长度控制max_lengthmax_new_tokens控制生成的最大长度max_new_tokens=100
解码策略do_samplenum_beamspenalty_alpha选择贪婪/采样/束搜索/对比搜索等策略do_sample=True, num_beams=4
采样控制temperaturetop_ktop_p调整采样随机性temperature=0.7, top_p=0.9
重复惩罚repetition_penaltyno_repeat_ngram_size减少重复生成repetition_penalty=1.2
日志处理bad_words_idsforce_words_ids禁止或强制某些词生成bad_words_ids=[[暴力词ID]]
辅助生成assistant_modelnum_assistant_tokens使用草稿模型加速生成num_assistant_tokens=5
输出控制num_return_sequencesoutput_scores返回序列数量和分数num_return_sequences=3

主要方法:

方法用途样例
from_pretrained()从 Hub 加载配置config = GenerationConfig.from_pretrained("gpt2")
save_pretrained()保存配置到本地config.save_pretrained("./my_config")

2. 生成方法 (generate)

各框架统一接口,支持多种解码策略。

PyTorch (GenerationMixin.generate):

outputs = model.generate(
    inputs,
    generation_config=config,
    do_sample=True,
    num_beams=4,
    max_new_tokens=50
)

TensorFlow (TFGenerationMixin.generate):

outputs = model.generate(
    inputs,
    do_sample=True,
    temperature=0.8,
    num_return_sequences=2
)

Flax/JAX (FlaxGenerationMixin.generate):

outputs = model.generate(
    input_ids,
    prng_key=jax.random.PRNGKey(0),
    max_length=100
)

通用参数:

参数作用特殊场景
generation_config预定义的配置对象复用配置
logits_processor自定义 logit 处理逻辑高级控制采样
stopping_criteria自定义停止条件特殊停止规则
assistant_model加速生成的草稿模型大模型加速
streamer流式输出处理器实时显示生成结果

3. 分数计算工具

计算生成序列的转移分数(token 级概率)。

PyTorch (compute_transition_scores):

# 生成时返回分数
outputs = model.generate(..., output_scores=True)
# 计算转移分数
scores = model.compute_transition_scores(
    outputs.sequences,
    outputs.scores,
    normalize_logits=True
)

TensorFlow (compute_transition_scores):

scores = model.compute_transition_scores(
    sequences,
    scores_tuple,
    beam_indices=beam_indices
)

参数说明:

参数作用注意
sequences生成的序列shape: (batch_size, seq_length)
scores生成过程中的分数元组每个元素对应一个生成步的 logits
beam_indices束搜索的索引(束搜索时必需)shape: (batch_size*num_beams, seq_len)
normalize_logits是否归一化 logits建议设为 True

4. 解码策略对照表

策略启用条件适用场景
贪婪解码num_beams=1, do_sample=False确定性输出
对比搜索penalty_alpha>0, top_k>1高质量长文本
采样生成num_beams=1, do_sample=True创造性文本
束搜索num_beams>1, do_sample=False精确性任务(翻译等)
束搜索采样num_beams>1, do_sample=True多样性与精确性平衡
辅助生成assistant_model 非空加速大模型推理
DoLa 解码dola_layers 指定层分层推理优化

典型工作流

from transformers import AutoModelForCausalLM, GenerationConfig

# 1. 加载模型
model = AutoModelForCausalLM.from_pretrained("gpt2")

# 2. 配置生成参数
config = GenerationConfig.from_pretrained("gpt2")
config.update(
    max_new_tokens=100,
    do_sample=True,
    top_k=50,
    temperature=0.7
)

# 3. 生成文本
inputs = tokenizer("The future of AI is", return_tensors="pt")
outputs = model.generate(**inputs, generation_config=config)

# 4. 解码输出
print(tokenizer.decode(outputs[0]))

关键特性

  1. 统一接口:PyTorch/TensorFlow/Flax 保持相同参数名
  2. 策略丰富:支持 7+ 解码策略
  3. 精细控制:提供 token 级概率分析工具
  4. 性能优化:辅助生成加速推理 2-3 倍
  5. 配置持久化:通过 GenerationConfig 保存/加载配置

ONNX

1. ONNX 配置抽象类

定义模型导出到 ONNX 的元数据和结构。

类名继承模型类型核心方法用途参数说明
OnnxConfig编码器模型(如 BERT)generate_dummy_inputs()use_external_data_format()基础配置config: 模型配置;task: 任务类型(如 'default'
OnnxConfigWithPast解码器模型(如 GPT)with_past()fill_with_past_key_values_()处理 past_key_valuesuse_past=True: 启用 KV 缓存
OnnxSeq2SeqConfigWithPast编码器-解码器模型(如 T5)OnnxConfigWithPastSeq2Seq 结构支持额外处理编码器-解码器交互

关键方法说明:

  • generate_dummy_inputs(): 生成用于导出的虚拟输入
dummy_inputs = config.generate_dummy_inputs(
    tokenizer,
    batch_size=1,
    seq_length=128
)
  • use_external_data_format(): 检查是否需要外部数据格式(>2GB 模型)
if config.use_external_data_format(num_parameters=100e6):
    # 处理大模型

2. ONNX 特性管理器 (FeaturesManager)

管理不同模型架构的 ONNX 导出支持。

方法名用途参数返回使用场景
get_config(model_type, feature)获取模型类型的 ONNX 配置model_type: 模型类型(如 'bert');feature: 特性名(如 'default'OnnxConfig 实例初始化导出配置
get_supported_features_for_model_type()获取模型支持的特性列表model_type: 模型类型特性名字典检查导出兼容性
check_supported_model_or_raise()验证模型是否支持导出特性model: 模型实例;feature: 特性名无(异常验证)导出前预检查
get_model_from_feature()通过特性名加载模型feature: 特性名;model: 模型名;framework: 框架模型实例动态加载兼容模型

特性列表示例:

from transformers.onnx import FeaturesManager
# 获取 BERT 支持的特性
features = FeaturesManager.get_supported_features_for_model_type("bert")
print(features)  # 输出: {'default', 'masked-lm', 'sequence-classification'}

3. 导出工作流

步骤 1:获取配置

from transformers.onnx import FeaturesManager
# 获取模型类型的 ONNX 配置
model_type = "gpt2"
feature = "causal-lm"
onnx_config = FeaturesManager.get_config(model_type, feature)

步骤 2:生成虚拟输入

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")
dummy_inputs = onnx_config.generate_dummy_inputs(tokenizer, batch_size=1, seq_length=128)

步骤 3:执行导出

from pathlib import Path
from transformers.onnx import export

output_path = Path("model.onnx")
export(
    pretrained_model="gpt2",
    onnx_config=onnx_config,
    output=output_path,
    dummy_inputs=dummy_inputs
)

大模型特殊处理:

if onnx_config.use_external_data_format(model.num_parameters()):
    export(..., use_external_data_format=True)  # 分割权重文件

4. 高级场景支持

带 KV 缓存的解码器:

# 启用 past_key_values 支持
onnx_config = OnnxConfigWithPast.with_past(config, task="causal-lm")

# 生成带缓存的虚拟输入
dummy_inputs = onnx_config.generate_dummy_inputs(
    tokenizer,
    batch_size=1,
    seq_length=128,
    past_seq_length=64  # 历史长度
)

Seq2Seq 模型导出:

from transformers.onnx import OnnxSeq2SeqConfigWithPast

# 初始化 T5 配置
onnx_config = OnnxSeq2SeqConfigWithPast(config, task="seq2seq-lm")

5. 特性对照表

模型类型ONNX 特性名适用任务对应配置类
BERT/RoBERTadefault基础编码器OnnxConfig
masked-lm掩码语言建模OnnxConfig
GPT/LLaMAcausal-lm因果语言建模OnnxConfigWithPast
T5/BARTseq2seq-lm序列到序列生成OnnxSeq2SeqConfigWithPast
ViTimage-classification图像分类OnnxConfig
Whisperspeech2seq-lm语音到文本OnnxSeq2SeqConfigWithPast

Optimization

1. 优化器接口

名称用途场景参数作用
Adafactor自适应学习率优化器,内存效率高微调大模型(如 T5),资源受限场景lr: 外部学习率;eps: 梯度/参数的正则化常数;clip_threshold: 梯度更新阈值;decay_rate: 平方梯度平均系数;scale_parameter: 是否按 RMS 缩放学习率;relative_step: 是否使用时间依赖学习率
AdamWeightDecayAdam 优化器 + 解耦权重衰减(L2 正则)TensorFlow 模型训练learning_rate: 基础学习率;beta_1/beta_2: 动量衰减率;weight_decay_rate: 权重衰减系数;include/exclude_from_weight_decay: 指定参数是否参与权重衰减

使用样例:

# Adafactor
Adafactor(
    model.parameters(),
    scale_parameter=False,
    relative_step=False,
    lr=1e-3
)

# AdamWeightDecay
AdamWeightDecay(
    learning_rate=1e-3,
    weight_decay_rate=0.01,
    exclude_from_weight_decay=["bias"]
)

2. 调度器接口

名称用途场景参数作用
get_constant_schedule恒定学习率稳定训练阶段optimizer: 关联的优化器
get_linear_schedule_with_warmup线性预热后线性衰减微调 Transformer 模型num_warmup_steps: 预热步数;num_training_steps: 总训练步数
get_cosine_schedule_with_warmup余弦衰减学习率图像分类/生成任务num_cycles: 余弦周期数(默认 0.5)
AdafactorSchedule适配 Adafactor 的时间依赖学习率搭配 Adafactor 优化器optimizer: 已配置的 Adafactor 优化器
WarmUp (TensorFlow)多项式预热学习率TensorFlow 模型预热阶段initial_learning_rate: 基础学习率;warmup_steps: 预热步数;power: 多项式指数(默认 1.0 线性)

使用样例:

# 恒定学习率
get_constant_schedule(optimizer)

# 线性预热后线性衰减
get_linear_schedule_with_warmup(
    optimizer,
    num_warmup_steps=100,
    num_training_steps=1000
)

# 余弦衰减
get_cosine_schedule_with_warmup(
    optimizer,
    num_warmup_steps=100,
    num_training_steps=1000
)

# AdafactorSchedule
optimizer = Adafactor(...)
lr_scheduler = AdafactorSchedule(optimizer)

# WarmUp (TensorFlow)
lr_schedule = WarmUp(
    initial_learning_rate,
    decay_schedule_fn,
    warmup_steps=500
)

3. 梯度策略接口

名称用途场景参数作用
GradientAccumulator无同步梯度累积大批次训练(内存不足时)无参数

使用样例:

accumulator = GradientAccumulator()
accumulator.reset()

关键说明

  1. Adafactor 优化器建议

    • 禁用梯度裁剪(与内置 clip_threshold 冲突)
    • T5 微调推荐配置:scale_parameter=False, relative_step=False, lr=1e-3
  2. 调度器选择

    • SchedulerType 提供枚举值(如 "cosine", "polynomial"),通过 get_scheduler 统一创建
    • 示例:get_scheduler("cosine", optimizer, num_warmup_steps=100, num_training_steps=1000)
  3. TensorFlow 工具

    • create_optimizer 整合预热+线性衰减:
create_optimizer(init_lr=5e-5, num_train_steps=10000, num_warmup_steps=500)

模型输出

1. 基础输出类

名称用途场景参数作用样例
ModelOutput所有模型输出的基类,支持字典/元组访问所有模型的通用输出无特定参数;自动处理非 None 属性outputs["last_hidden_state"]
BaseModelOutput基础模型输出,含最后隐藏状态编码器模型(如 BERT)last_hidden_state: 末层隐藏状态;hidden_states: 各层隐藏状态(可选);attentions: 注意力权重(可选)BERT、RoBERTa 的输出
BaseModelOutputWithPooling增加池化层输出的基础输出需池化操作的模型(如分类)BaseModelOutput 基础上增加 pooler_output: 首词符的池化表示BERT 用于句子分类时的输出
BaseModelOutputWithCrossAttentions含交叉注意力的输出解码器模型(如 GPT-2)BaseModelOutput 基础上增加 cross_attentions: 解码器对编码器的注意力权重多模态模型、生成任务的解码器输出
BaseModelOutputWithPast含过去键值缓存的输出,加速序列生成自回归模型(如 GPT)BaseModelOutput 基础上增加 past_key_values: 预先计算的键/值缓存GPT 生成文本时的输出
Seq2SeqModelOutput序列到序列模型的完整输出编码器-解码器模型(如 T5)包含编码器/解码器的 last_hidden_statehidden_statesattentionspast_key_valuesT5、BART 的编码器-解码器输出

2. 语言建模输出

名称用途场景参数作用样例
CausalLMOutput因果语言模型输出GPT 类模型loss: 语言建模损失;logits: 词汇预测分数;hidden_states/attentions: 隐藏状态和注意力权重model(**inputs, labels=labels)
MaskedLMOutput掩码语言模型输出BERT 类预训练loss: MLM 损失;logits: 掩码位置预测分数BERT 的 fill-mask 任务输出
Seq2SeqLMOutput序列到序列语言模型输出文本生成(如 T5)Seq2SeqModelOutput 基础上增加 losslogitsT5 的文本生成输出

3. 分类任务输出

名称用途场景参数作用样例
SequenceClassifierOutput单句分类输出情感分析、文本分类loss: 分类损失;logits: 分类分数;hidden_states/attentions: 可选BERT 分类模型的输出
MultipleChoiceModelOutput多项选择任务输出SWAG、ReCoRDloss: 选择损失;logits: 选项分数 (batch_size, num_choices)多项选择题模型输出
TokenClassifierOutput词符级分类输出NER、词性标注loss: 分类损失;logits: 每个词符的分类分数 (batch_size, seq_len, num_labels)BERT 的 NER 任务输出
NextSentencePredictorOutput下一句预测输出BERT 预训练任务loss: NSP 损失;logits: 句子连续性分数 (batch_size, 2)BERT 的 NSP 任务输出

4. 问答任务输出

名称用途场景参数作用样例
QuestionAnsweringModelOutput问答模型输出SQuAD、抽取式问答loss: 跨度损失;start_logits/end_logits: 答案开始/结束位置分数BERT 的问答模型输出
Seq2SeqQuestionAnsweringModelOutput序列到序列问答输出生成式问答(如 T5)Seq2SeqModelOutput 基础上增加 lossstart_logitsend_logitsT5 的问答任务输出

5. 多模态/音频输出

名称用途场景参数作用样例
Wav2Vec2BaseModelOutputWav2Vec2 基础输出音频特征提取last_hidden_state: 音频特征;extract_features: 卷积层特征Wav2Vec2 预训练模型输出
XVectorOutput说话人识别输出声纹识别loss: 分类损失;logits: 说话人分数;embeddings: 说话人嵌入向量说话人验证模型输出

6. 计算机视觉输出

名称用途场景参数作用样例
ImageClassifierOutput图像分类输出ImageNet 分类loss: 分类损失;logits: 分类分数;hidden_states: 各阶段特征图ViT、ResNet 图像分类输出
SemanticSegmenterOutput语义分割输出图像分割loss: 分割损失;logits: 像素级分类分数 (batch_size, num_labels, height, width)SegFormer、DeepLabV3 输出
DepthEstimatorOutput深度估计输出单目深度估计loss: 估计损失;predicted_depth: 深度图 (batch_size, height, width)DPT 深度估计模型输出

关键特性说明

通用行为:

  • 所有输出类继承自 ModelOutput,支持字典式访问(output["key"])和元组式访问(output[0]),自动忽略 None
  • 使用 to_tuple() 方法可转换为元组

参数说明:

  • loss:仅当提供标签(labels)时返回
  • hidden_states/attentions:需设置 output_hidden_states=Trueoutput_attentions=True
  • past_key_values:用于加速自回归生成(use_cache=True

示例代码:

# 序列分类输出示例
outputs = model(**inputs, labels=labels)
print(outputs.loss)  # 分类损失
print(outputs.logits)  # 分类分数

# 启用隐藏状态和注意力
outputs = model(**inputs, output_hidden_states=True, output_attentions=True)
print(outputs.hidden_states[-1])  # 最后一层隐藏状态

Pipelines

Pipelines 总览

名称用途场景参数作用样例
pipeline()模型推理的高级抽象封装所有任务管道,提供统一接口task: 任务类型(如文本分类);model: 模型标识符;device: 运行设备(CPU/GPU)pipe = pipeline("text-classification")pipe("This restaurant is awesome")

音频任务 Pipelines

名称用途场景参数作用样例
AudioClassificationPipeline音频分类预测音频类别(如音乐类型)inputs: 音频文件路径/原始波形;top_k: 返回概率最高的标签数量classifier = pipeline("audio-classification")classifier("audio.flac")
AutomaticSpeechRecognitionPipeline语音转文本转录语音内容(ASR)inputs: 音频文件;return_timestamps: 是否返回时间戳transcriber = pipeline("automatic-speech-recognition")transcriber("speech.wav")
TextToAudioPipeline文本转语音生成语音/音频内容text_inputs: 输入文本;forward_params: 控制生成质量pipe = pipeline("text-to-audio")pipe("Hello world")
ZeroShotAudioClassificationPipeline零样本音频分类无训练数据时分类音频audios: 音频文件;candidate_labels: 候选标签列表classifier = pipeline("zero-shot-audio-classification")classifier(audio, labels=["sound", "silence"])

计算机视觉 Pipelines

名称用途场景参数作用样例
DepthEstimationPipeline深度估计预测图像深度图(3D 重建)inputs: 图像文件/PIL 对象depth_estimator = pipeline("depth-estimation")depth_estimator("image.jpg")
ImageClassificationPipeline图像分类识别图像内容类别inputs: 图像;top_k: 返回概率最高的类别数classifier = pipeline("image-classification")classifier("cat.jpg")
ImageSegmentationPipeline图像分割分割图像中的对象/区域inputs: 图像;threshold: 过滤低概率掩码segmenter = pipeline("image-segmentation")segmenter("street.jpg")
ObjectDetectionPipeline目标检测检测图像中的对象及位置inputs: 图像;threshold: 置信度阈值detector = pipeline("object-detection")detector("cars.jpg")
ZeroShotImageClassificationPipeline零样本图像分类无训练数据时分类图像image: 图像;candidate_labels: 候选标签列表classifier = pipeline("zero-shot-image-classification")classifier(img, labels=["cat", "dog"])

自然语言处理 Pipelines

名称用途场景参数作用样例
FillMaskPipeline掩码填充预测被遮盖的词汇inputs: 含 [MASK] 的文本;top_k: 返回最佳预测数量fill_masker = pipeline("fill-mask")fill_masker("The capital of France is [MASK].")
TokenClassificationPipeline标记分类命名实体识别(NER)inputs: 文本;aggregation_strategy: 实体分组策略ner = pipeline("ner")ner("John works in New York")
QuestionAnsweringPipeline问答系统从文本中提取答案question: 问题;context: 背景文本;top_k: 返回最佳答案数量qa = pipeline("question-answering")qa(question="Where?", context="Paris is in France")
TextGenerationPipeline文本生成生成连贯文本(如对话)text_inputs: 提示文本;max_new_tokens: 生成最大长度generator = pipeline("text-generation")generator("Once upon a time")
TranslationPipeline文本翻译语言翻译(如英译法)src_lang/tgt_lang: 源/目标语言translator = pipeline("translation_en_to_fr")translator("Hello world")

多模态 Pipelines

名称用途场景参数作用样例
DocumentQuestionAnsweringPipeline文档问答从图像文档中提取答案image: 文档图像;question: 问题doc_qa = pipeline("document-question-answering")doc_qa(image="invoice.png", question="Total amount?")
ImageToTextPipeline图像描述生成为图像生成文本描述inputs: 图像;generate_kwargs: 控制生成质量captioner = pipeline("image-to-text")captioner("landscape.jpg")
VisualQuestionAnsweringPipeline视觉问答回答关于图像的问题image: 图像;question: 问题vqa = pipeline("visual-question-answering")vqa(image="photo.jpg", question="What color is the car?")

关键参数说明

通用参数:

  • device:指定计算设备(如 device=0 使用第一块 GPU)
  • batch_size:批量处理输入(提升 GPU 利用率)
  • framework:强制使用 PyTorch("pt")或 TensorFlow("tf"

任务特定参数:

  • 文本生成:max_new_tokens 控制输出长度
  • 目标检测:threshold 过滤低置信度预测
  • 零样本分类:candidate_labels 提供自定义标签列表

使用示例

# 文本情感分析
from transformers import pipeline
sentiment_analyzer = pipeline("text-classification")
result = sentiment_analyzer("I love this product!")
# 输出: [{'label': 'POSITIVE', 'score': 0.9998}]

# 图像描述生成
caption_generator = pipeline("image-to-text")
caption = caption_generator("https://huggingface.co/datasets/Narsil/image_dummy/raw/main/parrots.png")
# 输出: [{'generated_text': 'Two colorful parrots standing on a branch'}]

Processors

1. 多模态 Processors

用于处理多模态模型(如文本+图像/音频)的输入预处理,组合多个处理组件(如 tokenizer、image processor)。

核心类:ProcessorMixin

名称用途场景参数作用样例
ProcessorMixin提供处理器的保存/加载功能所有处理器类的基类无直接参数通过子类如 CLIPProcessor 使用
apply_chat_template()格式化多模态对话处理含文本/图像/视频的对话conversation: 对话内容;chat_template: Jinja 模板processor.apply_chat_template([{"role":"user", "content": [...]}])
from_pretrained()加载预训练处理器初始化多模态处理器pretrained_model_name_or_path: 模型 ID 或路径;token: 访问令牌processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")
save_pretrained()保存处理器配置本地存储或共享处理器save_directory: 存储路径;push_to_hub: 是否上传到 Hubprocessor.save_pretrained("my_processor")
push_to_hub()上传处理器到 Hub分享自定义处理器repo_id: 仓库 ID;private: 是否私有processor.push_to_hub("my-username/my-processor")

2. 已弃用的 Processors

用于旧版 GLUE/SQuAD 数据预处理(不再推荐使用)。

核心类:

名称用途场景参数作用样例
DataProcessor处理序列分类数据集GLUE/SQuAD 数据转换data_dir: 数据目录路径processor.get_train_examples("data/")
InputExample存储单个样本表示训练/测试样本guid: 唯一 ID;text_a/text_b: 文本;label: 标签InputExample(guid="0", text_a="Hello", label="positive")
InputFeatures存储模型输入特征转换为模型输入格式input_ids: 分词 ID;attention_mask: 注意力掩码InputFeatures(input_ids=[1,2,3], label=1)

数据集特定 Processors:

名称用途场景参数作用样例
GLUE Processors(如 MrpcProcessor处理 GLUE 任务数据MRPC/MNLI 等文本分类data_dir: 数据路径processor = MrpcProcessor()
XnliProcessor处理跨语言 NLI 数据XNLI 多语言文本蕴含DataProcessor同 GLUE 使用方式
SquadProcessor处理问答数据SQuAD v1.1/v2.0data_dir: 数据路径;filename: 自定义文件名processor.get_dev_examples(squad_dir)

转换函数:

名称用途场景参数作用样例
glue_convert_examples_to_features转换 GLUE 样本为特征准备 GLUE 模型输入examples: 样本列表;tokenizer: 分词器;max_length: 最大长度features = glue_convert_examples_to_features(examples, tokenizer, max_length=128)
squad_convert_examples_to_features转换 SQuAD 样本为特征准备问答模型输入doc_stride: 滑动窗口步长;max_query_length: 问题最大长度features = squad_convert_examples_to_features(examples, tokenizer, max_seq_length=384)

使用示例对比

多模态处理器示例:

# 加载CLIP处理器(文本+图像)
from transformers import AutoProcessor
processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32")

# 处理多模态输入
image_input = processor(images=image, return_tensors="pt")  # 图像处理
text_input = processor(text="a photo of a cat", return_tensors="pt")  # 文本处理

已弃用处理器示例(旧版):

# GLUE数据预处理(已弃用)
from transformers import glue_convert_examples_to_features, MrpcProcessor

processor = MrpcProcessor()
examples = processor.get_train_examples("data/MRPC")
features = glue_convert_examples_to_features(
    examples,
    tokenizer,
    max_length=128,
    task="mrpc"
)

# SQuAD数据预处理(已弃用)
from transformers import squad_convert_examples_to_features, SquadV2Processor
processor = SquadV2Processor()
examples = processor.get_dev_examples("data/SQuAD")
features = squad_convert_examples_to_features(
    examples,
    tokenizer,
    max_seq_length=384,
    doc_stride=128
)

关键区别

特性多模态 Processors已弃用 Processors
适用场景多模态模型(文本+图像/音频)单模态文本任务(GLUE/SQuAD)
状态当前推荐使用已弃用,推荐改用 datasets
核心功能组合多个处理组件转换原始数据为 InputExample
依赖关系与多模态模型强绑定独立数据预处理流程
示例模型CLIP, Wav2Vec2, LayoutLMBERT 用于 GLUE/SQuAD

Quantization

1. AWQ (Activation-aware Weight Quantization)

在保留原始性能的前提下,将模型量化为 4 位精度,实现高吞吐量推理。

核心类与接口:

名称用途场景参数作用样例
AwqConfig配置 AWQ 量化参数加载/量化 AWQ 模型bits: 量化位数(默认 4);group_size: 量化组大小;version: 算法版本(GEMM/GEMV)config = AwqConfig(bits=4, group_size=128)
from_pretrained(load_in_4bit=True)加载 AWQ 量化模型推理优化device_map: 设备映射策略;attn_implementation: 注意力实现方式model = AutoModelForCausalLM.from_pretrained("TheBloke/zephyr-7B-AWQ", load_in_4bit=True)
apply_chat_template()格式化多模态输入含图像的对话场景conversation: 对话内容列表;chat_template: Jinja 模板processor.apply_chat_template([{"role":"user", "content": [...]}])

2. GPTQ (GPT Quantization)

通过权重校准实现 8/4/3/2 位量化,平衡精度与效率。

核心类与接口:

名称用途场景参数作用样例
GPTQConfig配置 GPTQ 量化参数模型量化与加载bits: 量化位数;dataset: 校准数据集;use_exllama: 启用 Exllama 内核config = GPTQConfig(bits=4, dataset="c4")
from_pretrained(quantization_config)加载 GPTQ 模型减少内存占用device_map: 设备映射策略model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=config)
push_to_hub()推送量化模型到 Hub模型共享repo_id: 仓库 IDquantized_model.push_to_hub("my-model-gptq")

3. bitsandbytes

支持 8 位和 4 位量化,广泛兼容 GPU 硬件。

核心类与接口:

名称用途场景参数作用样例
BitsAndBytesConfig配置 bitsandbytes 参数8/4 位量化load_in_4bit: 启用 4 位量化;bnb_4bit_quant_type: 量化类型(fp4/nf4)config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4")
from_pretrained(load_in_4bit=True)加载 4 位量化模型超大规模模型部署device_map: 设备映射策略model = AutoModelForCausalLM.from_pretrained("bigscience/bloom-1b7", load_in_4bit=True)
get_memory_footprint()获取模型内存占用资源监控无参数print(model.get_memory_footprint())
llm_int8_threshold设置异常值阈值提升不稳定模型性能阈值范围(建议 6.0)config = BitsAndBytesConfig(llm_int8_threshold=10.0)

关键特性对比

特性AWQGPTQbitsandbytes
量化位数4 位2/3/4/8 位4/8 位
精度损失接近无损极小损失可控损失
推理速度超快(类 float16)平衡
硬件要求NVIDIA GPUNVIDIA GPU多数 GPU
训练支持配合 PEFT 微调配合 PEFT 微调直接训练受限
典型场景生产环境部署研究/实验通用优化

使用示例

AWQ 示例:

from transformers import AutoModelForCausalLM, AwqConfig

# 加载AWQ量化模型
model = AutoModelForCausalLM.from_pretrained(
    "TheBloke/zephyr-7B-alpha-AWQ",
    device_map="auto",
    quantization_config=AwqConfig(bits=4)
)

GPTQ 示例:

from transformers import AutoModelForCausalLM, GPTQConfig

# 配置GPTQ量化
gptq_config = GPTQConfig(bits=4, dataset="c4")
model = AutoModelForCausalLM.from_pretrained(
    "facebook/opt-125m",
    quantization_config=gptq_config
)

# 推送量化模型到Hub
model.push_to_hub("opt-125m-gptq")

bitsandbytes 示例:

from transformers import BitsAndBytesConfig, AutoModelForCausalLM

# 配置4位NF4量化
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_use_double_quant=True
)

# 加载量化模型
model = AutoModelForCausalLM.from_pretrained(
    "bigscience/bloom-1b7",
    quantization_config=bnb_config,
    device_map="auto"
)

混合精度推理:

# AWQ + Flash Attention
model = AutoModelForCausalLM.from_pretrained(
    "TheBloke/zephyr-7B-AWQ",
    attn_implementation="flash_attention_2",
    device_map="auto"
)

最佳实践建议

  1. 生产部署:优先选择 AWQ(最高吞吐量)
  2. 实验研究:GPTQ 支持灵活位数选择
  3. 资源受限环境:bitsandbytes 4 位量化 + 嵌套量化
  4. 大模型微调:所有方法均需配合 PEFT 库
  5. 硬件兼容:bitsandbytes 支持最广泛 GPU 硬件

注:量化模型不支持直接训练,但可通过参数高效微调(PEFT)技术适配新任务。

Tokenizer

Tokenizer 核心类

名称用途场景参数作用样例
PreTrainedTokenizerPython 实现的慢速分词器基类需要纯 Python 分词逻辑时model_max_length(最大长度)、special_tokens(特殊标记)、padding_side(填充方向)tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
PreTrainedTokenizerFast基于 Rust 的快速分词器基类需要高性能分词/批量处理/字符映射时tokenizer_object(🤗 Tokenizers 对象)、tokenizer_file(本地文件路径)tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased")
BatchEncoding存储编码结果的数据容器处理分词器输出时encoding(原始编码数据)、tensor_type(张量转换类型)inputs = tokenizer("text"); type(inputs) # BatchEncoding

核心方法

名称用途场景参数作用样例
__call__主要分词编码方法文本转模型输入text(输入文本)、padding(填充策略)、truncation(截断策略)、return_tensors(返回张量类型)inputs = tokenizer("Hello world!", padding=True)
add_tokens添加新词汇扩展领域专有词汇new_tokens(新词列表)、special_tokens(是否特殊标记)num_added = tokenizer.add_tokens(["new_word"])
add_special_tokens添加特殊标记自定义 [CLS]/[SEP]special_tokens_dict(特殊标记字典)tokenizer.add_special_tokens({"cls_token": "<CLS>"})
batch_decode批量 ID 转文本模型输出解码sequences(ID 序列)、skip_special_tokens(跳过特殊标记)texts = tokenizer.batch_decode([[101, 2023, 2000, 102]])
decode单序列 ID 转文本单个结果解码token_ids(ID 序列)text = tokenizer.decode([101, 2023, 2000, 102])
encode文本转 ID 序列快速编码文本text(输入文本)、max_length(最大长度)ids = tokenizer.encode("Hello world!")
convert_ids_to_tokensID 转单词片段可视化分词结果ids(标记 ID)tokens = tokenizer.convert_ids_to_tokens([2023, 2000])
token_to_chars标记定位字符位置实体识别/文本对齐token_index(标记索引)char_span = inputs.token_to_chars(0, 3)
word_to_tokens单词定位标记范围词级分析word_index(单词索引)token_span = inputs.word_to_tokens(0, 2)
push_to_hub上传至 HuggingFace Hub模型分享/部署repo_id(仓库 ID)、private(是否私有)tokenizer.push_to_hub("my-model")

关键参数说明

padding 策略:

  • True/'longest':按批次最长序列填充
  • 'max_length':按指定 max_length 填充
  • False:不填充

truncation 策略:

  • True/'longest_first':从最长序列截断
  • 'only_first':仅截断首序列
  • 'only_second':仅截断次序列

特殊标记:

  • bos_token:序列开始,eos_token:序列结束
  • unk_token:未知词,pad_token:填充标记
  • mask_token:掩码标记(MLM 任务)

Trainer

核心训练类

名称用途场景参数作用样例
Trainer提供标准训练循环通用模型训练/微调见下方 TrainingArgumentstrainer = Trainer(model, args, train_dataset)
Seq2SeqTrainer序列到序列任务专用训练器翻译/摘要/文本生成继承 Trainer 并扩展生成方法trainer = Seq2SeqTrainer(..., predict_with_generate=True)

参数配置类

名称用途场景关键参数样例
TrainingArguments训练过程配置容器控制训练行为output_dir(输出路径)、per_device_train_batch_size(批次大小)、learning_rate(学习率)、fp16(混合精度)示例配置
Seq2SeqTrainingArguments序列任务专用配置控制生成任务行为predict_with_generate(使用生成指标)、generation_max_length(最大生成长度)TrainingArguments

TrainingArguments 示例:

training_args = TrainingArguments(
    output_dir="./results",
    per_device_train_batch_size=32,
    learning_rate=2e-5,
    num_train_epochs=3,
    fp16=True,
    fsdp="full_shard auto_wrap",  # FSDP配置
    neftune_noise_alpha=0.1  # NEFTune噪声
)

高级训练功能

功能名称用途激活方式关键配置参数适用场景
FSDP (PyTorch)完全分片数据并行--fsdp + 配置文件fsdp_transformer_layer_cls_to_wrap(包装层)、fsdp_min_num_params(最小参数量)超大模型训练(>10B)
PyTorch/XLA FSDPTPU 分片训练xla=True + xla_fsdp_settingsxla_fsdp_grad_ckpt(梯度检查点)、fsdp_transformer_layer_cls_to_wrapTPU 集群训练
MPS 加速 (Mac)Apple Silicon GPU 加速自动启用PYTORCH_ENABLE_MPS_FALLBACK=1(回退 CPU)Mac M1/M2 训练
NEFTune噪声嵌入提升性能neftune_noise_alpha噪声系数(建议 0.1)指令微调任务

工具与集成

名称用途使用方式关键命令/配置优势
Accelerate Launcher统一分布式启动器accelerate config + accelerate launch生成统一配置模板简化多 GPU/TPU 部署
DeepSpeed 集成深度学习优化库--deepspeed + 配置文件zero_stage(优化级别)、offload_optimizer(卸载优化器)内存优化/巨大模型
Checkpoint 恢复断点续训resume_from_checkpointcheckpoint-xxx 目录路径训练中断恢复

关键功能详解

1. FSDP 分片策略 (PyTorch):

# 启用方式(命令行)
python script.py --fsdp "full_shard auto_wrap" \
--fsdp_config fsdp_config.json

fsdp_config.json 示例:

{
  "fsdp_transformer_layer_cls_to_wrap": ["BertLayer"],
  "fsdp_min_num_params": 1e8,
  "activation_checkpointing": true
}

2. 分布式训练环境变量:

变量名功能示例值效果
CUDA_VISIBLE_DEVICES可见 GPU 选择0,2仅使用 GPU 0 和 2
CUDA_DEVICE_ORDERGPU 排序策略FASTEST_FIRST性能强的 GPU 优先
PYTORCH_ENABLE_MPS_FALLBACKMac GPU 回退1不支持操作回退 CPU

3. 日志控制参数:

TrainingArguments(
    log_level="warning",          # 主进程日志级别
    log_level_replica="error",    # 副本进程日志级别
    log_on_each_node=False        # 仅主节点记录
)

4. 自定义训练器示例(加权损失):

class CustomTrainer(Trainer):
    def compute_loss(self, model, inputs, return_outputs=False):
        labels = inputs.pop("labels")
        outputs = model(**inputs)
        loss_fct = nn.CrossEntropyLoss(weight=[1.0, 2.0, 3.0])
        loss = loss_fct(outputs.logits, labels)
        return (loss, outputs) if return_outputs else loss

DeepSpeed 集成

核心启动与配置接口

名称用途场景参数作用样例
deepspeedDeepSpeed 启动器分布式训练/推理--num_gpus:GPU 数量;--hostfile:多节点配置;--master_addr:主节点地址deepspeed --num_gpus=2 run.py --deepspeed ds_config.json
HfDeepSpeedConfigTransformers 与 DeepSpeed 桥接ZeRO-3 模型加载config_file_or_dict:配置文件路径或字典dschf = HfDeepSpeedConfig(ds_config)

ZeRO 核心配置(zero_optimization 部分)

参数用途场景推荐值注意事项
stageZeRO 优化阶段内存优化选择0(禁用)、1(优化器状态)、2(梯度)、3(参数)Stage 3 支持万亿参数模型
offload_optimizer优化器卸载目标CPU/NVMe 卸载device: "cpu""nvme"需配合 pin_memory: true
offload_param参数卸载目标超大模型支持nvme_path:NVMe 路径需要高速 NVMe 设备
stage3_gather_16bit_weights保存完整权重ZeRO-3 模型导出true/false必须开启才能生成 pytorch_model.bin
reduce_bucket_size通信缓冲区大小性能调优auto 或模型 hidden_size²值越大通信越快,内存占用越高

精度与训练配置

配置组关键参数用途场景样例值
fp16enabledFP16 混合精度旧 GPU 架构{"enabled": true, "loss_scale": 0}
bf16enabledBF16 混合精度Ampere+ 新 GPU{"enabled": true}
optimizertype, params优化器配置训练优化{"type": "AdamW", "params": {"lr": "auto"}}
schedulertype, params学习率调度训练优化{"type": "WarmupLR", "params": {"warmup_num_steps": "auto"}}
gradient_accumulationsteps梯度累积步数小批量训练"auto" 或整数
train_micro_batch_sizeper_gpu单 GPU 批大小内存不足时减小"auto" 或整数

工具与转换接口

名称用途场景参数使用样例
zero_to_fp32.pyZeRO 权重转换模型导出.:checkpoint 目录;pytorch_model.bin:输出文件python zero_to_fp32.py . pytorch_model.bin
load_state_dict_from_zero加载完整权重Python 环境转换model:空模型;checkpoint_dir:路径load_state_dict_from_zero_checkpoint(model, dir)
estimate_zero3_model_mem内存预估资源规划model:模型对象;num_gpus:GPU 数量见文档示例代码

典型配置样例

ZeRO-2 最小配置:

{
  "zero_optimization": {
    "stage": 2,
    "offload_optimizer": {"device": "cpu"},
    "allgather_bucket_size": 5e8
  },
  "fp16": {"enabled": true},
  "train_batch_size": "auto"
}

ZeRO-3 NVMe 卸载配置:

{
  "zero_optimization": {
    "stage": 3,
    "offload_optimizer": {
      "device": "nvme",
      "nvme_path": "/local_nvme"
    },
    "offload_param": {
      "device": "nvme",
      "nvme_path": "/local_nvme"
    },
    "stage3_gather_16bit_weights": true
  },
  "bf16": {"enabled": true},
  "aio": {"block_size": 262144}
}

单 GPU CPU 卸载推理:

# 初始化配置
dschf = HfDeepSpeedConfig({
  "zero_optimization": {
    "stage": 3,
    "offload_param": {"device": "cpu"}
  }
})

# 加载模型
model = AutoModel.from_pretrained("bigscience/T0_3B")

关键使用场景对照表

场景推荐配置启动命令内存优化
单 GPU 微调ZeRO-2 + CPU 卸载deepspeed --num_gpus=1减少约 60% GPU 内存
多节点训练ZeRO-3 + BF16deepspeed --hostfile hostfile千亿参数支持
超大模型推理ZeRO-Infinity同上CPU/NVMe 分级存储
Mac M1 训练Stage 0 + MPS无需 DeepSpeed苹果芯片优化
8GB GPU 训练ZeRO-3 + 双卸载deepspeed --num_gpus=1支持 30B+ 模型

Feature Extractor

核心特征提取类

名称用途场景参数作用样例
FeatureExtractionMixin特征提取器基类提供保存/加载功能见下方方法feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained("facebook/wav2vec2-base-960h")
SequenceFeatureExtractor序列特征处理器音频特征处理feature_size:特征维度;sampling_rate:采样率;padding_value:填充值processor = Wav2Vec2FeatureExtractor(feature_size=1, sampling_rate=16000)
ImageFeatureExtractionMixin图像处理工具集图像预处理见下方方法用于 ViT 等视觉模型的特征提取

核心方法

名称所属类用途关键参数样例
from_pretrainedFeatureExtractionMixin加载预训练配置pretrained_model_name_or_path:模型 ID/路径;cache_dir:缓存目录;revision:版本号extractor = Wav2Vec2FeatureExtractor.from_pretrained("facebook/wav2vec2-base-960h")
save_pretrainedFeatureExtractionMixin保存配置save_directory:保存路径;push_to_hub:是否推送 Hubextractor.save_pretrained("./my_model")
padSequenceFeatureExtractor填充序列processed_features:输入特征;padding:填充策略;max_length:最大长度见下方示例
convert_to_tensorsBatchFeature转为张量tensor_type:张量类型(pt/tf/nptensors = batch_feature.convert_to_tensors("pt")
center_cropImageFeatureExtractionMixin中心裁剪图像size:裁剪尺寸cropped_img = feature_extractor.center_crop(image, (224,224))
normalizeImageFeatureExtractionMixin图像归一化mean:均值;std:标准差norm_img = feature_extractor.normalize(img, [0.5], [0.5])

图像处理工具方法

名称用途关键参数返回类型
resize调整图像尺寸size:目标尺寸;resample:重采样方法PIL.Image
rotate旋转图像angle:旋转角度;resample:重采样方法PIL.Image
convert_rgb转为 RGB 格式image:输入图像RGB 格式图像
to_numpy_array转为 NumPy 数组rescale:是否缩放;channel_first:通道优先np.ndarray
to_pil_image转为 PIL 图像rescale:是否缩放PIL.Image
flip_channel_order翻转通道顺序image:输入图像BGR/RGB 转换图像

典型使用示例

音频特征处理:

from transformers import Wav2Vec2FeatureExtractor

# 加载预训练特征提取器
feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained("facebook/wav2vec2-base-960h")

# 处理音频
audio_input = [...]  # 原始音频数据
processed = feature_extractor(audio_input, sampling_rate=16000, return_tensors="pt")

# 填充序列
padded = feature_extractor.pad(
    processed,
    padding=True,
    max_length=1000,
    return_tensors="pt"
)

图像特征处理:

from transformers import ViTFeatureExtractor
from PIL import Image

# 加载预训练特征提取器
feature_extractor = ViTFeatureExtractor.from_pretrained("google/vit-base-patch16-224")

# 处理图像
image = Image.open("cat.jpg")
processed = feature_extractor(
    images=image,
    return_tensors="pt",
    do_resize=True,
    size=224,
    do_normalize=True
)

# 图像预处理流程
image = feature_extractor.convert_rgb(image)
image = feature_extractor.resize(image, (256, 256))
image = feature_extractor.center_crop(image, (224, 224))
image = feature_extractor.to_numpy_array(image)

批特征操作:

# 假设 batch_features 是 BatchFeature 对象
batch_features.convert_to_tensors("pt")  # 转为 PyTorch 张量
batch_features.to("cuda")  # 转移到 GPU(PyTorch)

参数详解

pad 方法关键参数:

  • paddingTrue/'longest'(按最长序列填充)、'max_length'(固定长度填充)
  • max_length:填充目标长度
  • truncation:是否截断超长序列
  • pad_to_multiple_of:填充至指定倍数(优化硬件性能)
  • return_tensors:返回张量类型('pt'/'tf'/'np'

图像归一化参数:

normalize(
    image,
    mean=[0.485, 0.456, 0.406],  # ImageNet 均值
    std=[0.229, 0.224, 0.225]     # ImageNet 标准差
)

Image Processor

核心图像处理类

名称用途场景参数作用样例
ImageProcessingMixin图像处理器基类提供保存/加载功能见下方方法processor = CLIPImageProcessor.from_pretrained("openai/clip-vit-base-patch32")
BaseImageProcessor图像处理基类基础图像处理操作见下方方法用于自定义图像处理器

核心方法

名称所属类用途关键参数样例
from_pretrainedImageProcessingMixin加载预训练配置pretrained_model_name_or_path:模型 ID/路径;cache_dir:缓存目录processor = CLIPImageProcessor.from_pretrained("google/vit-base-patch16-224")
save_pretrainedImageProcessingMixin保存配置save_directory:保存路径;push_to_hub:是否推送 Hubprocessor.save_pretrained("./my_model")
center_cropBaseImageProcessor中心裁剪图像size:目标尺寸字典;data_format:通道格式cropped = processor.center_crop(image, size={"height":224,"width":224})
normalizeBaseImageProcessor图像归一化mean:均值;std:标准差norm_img = processor.normalize(img, mean=[0.5], std=[0.5])
rescaleBaseImageProcessor像素值缩放scale:缩放因子rescaled = processor.rescale(img, scale=1/255.0)

批特征操作类

名称用途关键方法场景
BatchFeature存储处理结果convert_to_tensors():转为张量;to():设备转移模型输入处理

典型使用示例

加载和使用图像处理器:

from transformers import CLIPImageProcessor

# 加载预训练处理器
processor = CLIPImageProcessor.from_pretrained(
    "openai/clip-vit-base-patch32",
    do_normalize=False  # 自定义参数
)

# 处理图像
inputs = processor(
    images=image,
    return_tensors="pt",
    do_resize=True,
    size=(224, 224),
    do_normalize=True
)

# 保存配置
processor.save_pretrained("./my_model")

基础图像处理操作:

# 中心裁剪
cropped = processor.center_crop(
    image,
    size={"height": 256, "width": 256},
    data_format="channels_last"
)

# 图像归一化
normalized = processor.normalize(
    cropped,
    mean=[0.485, 0.456, 0.406],
    std=[0.229, 0.224, 0.225]
)

# 像素值缩放
rescaled = processor.rescale(
    normalized,
    scale=2.0
)

批特征操作:

# 创建批特征对象
batch = BatchFeature(data={"pixel_values": [img1, img2]})

# 转为 PyTorch 张量
tensors = batch.convert_to_tensors("pt")

# 转移到 GPU
gpu_batch = batch.to("cuda")

参数详解

center_crop 参数:

center_crop(
    image,
    size={"height": 224, "width": 224},  # 目标尺寸
    data_format="channels_first",         # 通道格式
    input_data_format="channels_last"     # 输入格式
)

normalize 参数:

normalize(
    image,
    mean=[0.485, 0.456, 0.406],  # 各通道均值
    std=[0.229, 0.224, 0.225],    # 各通道标准差
    data_format="channels_last"    # 输出格式
)

rescale 参数:

rescale(
    image,
    scale=0.5,  # 缩放因子
    data_format="channels_first"  # 通道格式
)

辅助工具

自定义层和工具

PyTorch 自定义模块

名称用途场景参数作用样例
Conv1D1D 转置卷积层GPT 系列模型nf:输出特征数;nx:输入特征数layer = Conv1D(768, 3072)

PyTorch 帮助函数

名称用途场景参数作用样例
apply_chunking_to_forward分块前向传播大模型内存优化chunk_size:分块大小;chunk_dim:分块维度见下方示例
find_pruneable_heads_and_indices查找可修剪注意力头模型压缩heads:待修剪头索引;n_heads:总头数见下方示例
prune_layer通用层修剪模型压缩layer:待修剪层;index:保留索引pruned_layer = prune_layer(linear_layer, keep_indices)
prune_conv1d_layerConv1D 层专用修剪GPT 模型压缩dim:修剪维度pruned_conv = prune_conv1d_layer(conv1d, keep_indices, dim=1)
prune_linear_layer线性层专用修剪通用模型压缩dim:修剪维度pruned_linear = prune_linear_layer(linear, keep_indices, dim=0)

TensorFlow 自定义层

名称用途场景参数作用样例
TFConv1DTF 版 1D 转置卷积GPT 系列模型initializer_range:权重初始化范围layer = TFConv1D(768, 3072, initializer_range=0.02)
TFSequenceSummary序列摘要生成分类任务特征提取summary_type:摘要类型;summary_use_proj:是否投影见下方示例

TensorFlow 损失函数

名称用途场景特殊处理
TFCausalLanguageModelingLoss因果语言建模损失GPT 类模型忽略 -100 标签
TFMaskedLanguageModelingLoss掩码语言建模损失BERT 类模型忽略 -100 标签
TFMultipleChoiceLoss多项选择损失选择题任务-
TFQuestionAnsweringLoss问答损失阅读理解任务-
TFSequenceClassificationLoss序列分类损失文本分类任务-
TFTokenClassificationLoss令牌分类损失NER 任务忽略 -100 标签

TensorFlow 帮助函数

名称用途场景参数作用样例
get_initializer初始化器生成权重初始化initializer_range:标准差init = get_initializer(0.02)
keras_serializable序列化装饰器自定义层保存类装饰器@keras_serializable() class CustomLayer:
shape_list动态形状处理TF 张量操作tensor:输入张量dims = shape_list(tensor)

典型使用示例

PyTorch 分块处理:

# 定义分块前向传播
def forward_chunk(self, hidden_states):
    return self.decoder(hidden_states)

# 应用分块处理
def forward(self, hidden_states):
    return apply_chunking_to_forward(
        self.forward_chunk,
        chunk_size=128,
        chunk_dim=1,
        hidden_states
    )

注意力头修剪:

# 查找可修剪头
prune_heads, keep_indices = find_pruneable_heads_and_indices(
    heads=[3,5],
    n_heads=12,
    head_size=64,
    already_pruned_heads=set()
)

# 修剪线性层
pruned_layer = prune_linear_layer(
    layer=attention.query,
    index=keep_indices,
    dim=0
)

TensorFlow 序列摘要:

summary = TFSequenceSummary(
    config=model.config,
    summary_type='first',  # 取首个 token
    summary_use_proj=True
)(sequence_output)

TensorFlow 自定义层:

@keras_serializable()
class CustomLayer(tf.keras.layers.Layer):
    def __init__(self, config):
        super().__init__()
        self.dense = tf.keras.layers.Dense(config.hidden_size)

    def call(self, inputs):
        return self.dense(inputs)

关键参数详解

TFSequenceSummary 配置:

TFSequenceSummary(
    summary_type='cls_index',  # 支持 last/first/mean/cls_index
    summary_use_proj=True,     # 是否添加投影层
    summary_proj_to_labels=False, # 投影到标签维度
    summary_activation='tanh', # 激活函数
    summary_first_dropout=0.1, # 投影前 dropout
    summary_last_dropout=0.1   # 投影后 dropout
)

分块处理参数:

apply_chunking_to_forward(
    forward_fn,    # 分块处理函数
    chunk_size=64, # 每块大小
    chunk_dim=1,   # 分块维度(通常是序列维度)
    *input_tensors # 输入张量
)

修剪函数参数:

prune_linear_layer(
    layer,     # 待修剪层
    index,     # 保留索引
    dim=0      # 权重矩阵维度
)

Pipelines 工具

参数处理类(Argument Handling)

名称用途场景参数作用样例
ArgumentHandler处理 Pipeline 参数的基础接口自定义 Pipeline 参数解析无直接参数基类,需子类化使用
ZeroShotClassificationArgumentHandler将分类标签转为 NLI 前提/假设对零样本文本分类任务无公开参数自动处理标签格式:("This is a premise", "This is a hypothesis")
QuestionAnsweringArgumentHandler将用户输入映射为 SquadExample 对象问答任务(需问题+上下文)无公开参数输入:{"question": "...", "context": "..."} → 输出 SquadExample

数据格式类(Data Format)

名称用途场景参数作用样例
PipelineDataFormat处理 Pipeline 输入/输出数据的基类统一管理数据格式(JSON/CSV/管道)output_path:输出路径;input_path:输入路径;column:读取列名;overwrite:是否覆盖输出文件通过 from_str() 动态创建子类实例
CsvPipelineDataFormat读写 CSV 格式数据CSV 文件处理同上保存数据:save([{"text": "example"}]) → 生成 CSV 文件
JsonPipelineDataFormat读写 JSON 格式数据JSON 文件处理同上保存数据:save({"key": "value"}) → 生成 JSON 文件
PipedPipelineDataFormat从标准输入/输出读写数据命令行管道操作同上输入:echo "data" | pipeline → 输出打印到终端

实用函数(Utility Functions)

名称用途场景参数作用样例
PipelineException抛出 Pipeline 处理异常Pipeline 执行错误时task:任务名称;model:模型名称;reason:错误原因抛出异常:PipelineException(task="text-classification", model="BERT", reason="Invalid input")

关键方法说明

PipelineDataFormat.from_str()

参数作用
format数据格式("json"/"csv"/"pipe"
output_path输出文件路径(可选)
input_path输入文件路径(可选)
column需读取的数据列(可选)
overwrite覆盖输出文件(默认 False

样例:

format = PipelineDataFormat.from_str("csv", output_path="out.csv", column="text")

PipelineDataFormat.save()

参数作用
data要保存的数据(字典或字典列表)

样例:

csv_format.save([{"label": 1, "text": "example"}])

PipelineDataFormat.save_binary()

参数作用
data要保存的数据(字典或字典列表)
返回保存后的文件路径(二进制格式)

使用场景总结

  • 参数处理类:解析任务特定输入(如零样本分类标签、问答对)
  • 数据格式类
    • CSV/JSON:文件读写场景(如批量处理数据集)
    • Pipe:命令行流式处理(如 cat data.txt | pipeline
  • 异常类:统一处理 Pipeline 运行时错误

Tokenizers 工具

核心类:PreTrainedTokenizerBase

名称用途场景关键参数作用样例
__call__主入口:分词并准备模型输入文本编码(单句/句对)text:输入文本;padding:填充策略(True/'longest'/'max_length');truncation:截断策略(True/'longest_first');return_tensors:返回张量类型('pt'/'tf'/'np'tokenizer("Hello world", return_tensors="pt") → 输出包含 input_idsattention_mask 的字典
apply_chat_template格式化对话历史为模型输入对话模型(ChatGPT 等)conversation:对话历史(角色+内容);tools:可调用函数列表(函数调用场景);add_generation_prompt:是否添加助理响应提示tokenizer.apply_chat_template([{"role":"user","content":"Hello"}]) → 格式化的对话字符串或 ID 列表
batch_decode批量 ID 序列解码为文本模型输出后处理skip_special_tokens:是否跳过特殊标记(如 [CLS]);clean_up_tokenization_spaces:清理多余空格tokenizer.batch_decode([[101, 7592, 102]])["[CLS] hello [SEP]"]
from_pretrained加载预训练分词器初始化模型pretrained_model_name_or_path:模型 ID 或本地路径;token:HuggingFace 认证令牌;trust_remote_code:是否信任远程自定义代码BertTokenizer.from_pretrained("google-bert/bert-base-uncased")
save_pretrained保存分词器到本地模型持久化save_directory:保存路径;legacy_format:是否保存旧格式(兼容慢速分词器)tokenizer.save_pretrained("./my_model") → 生成 vocab.txttokenizer_config.json
add_tokens添加新词到词表扩展自定义词汇new_tokens:新词(字符串或 AddedToken 对象);special_tokens:是否标记为特殊词tokenizer.add_tokens(["new_word"], special_tokens=False) → 返回添加词数(1)
encode文本 → ID 序列(单条)快速编码text_pair:第二段文本(如问答);max_length:最大序列长度tokenizer.encode("Hello")[101, 7592, 102]
decodeID 序列 → 文本(单条)快速解码skip_special_tokens:跳过特殊标记tokenizer.decode([101, 7592, 102])"[CLS] hello [SEP]"
pad填充批处理数据批处理对齐encoded_inputs:批输入数据;pad_to_multiple_of:填充至倍数(如 8 的倍数加速 GPU)__call__padding 参数

特殊标记处理:SpecialTokensMixin

名称用途场景关键参数作用样例
add_special_tokens添加/更新特殊标记自定义特殊标记special_tokens_dict:字典(如 {"cls_token":"<CLS>"}tokenizer.add_special_tokens({"cls_token": "<CLS>"}) → 更新 tokenizer.cls_token
bos_token句子开头标记文本生成类属性(可修改)tokenizer.bos_token = "<BOS>"
eos_token句子结束标记文本生成类属性tokenizer.eos_token_id 获取 ID
pad_token填充标记批处理类属性设置 tokenizer.pad_token = tokenizer.eos_token(GPT-2 场景)

枚举和命名元组

名称用途场景关键值/属性样例
TruncationStrategy截断策略枚举控制文本截断方式longest_first:优先截断较长句;only_first:仅截断第一句;do_not_truncate:不截断truncation="only_first"
CharSpan字符级位置标记原始文本定位start:起始字符索引;end:结束字符索引用于问答任务定位答案位置
TokenSpan词元级位置标记分词后定位start:起始词元索引;end:结束词元索引用于序列标注任务(如 NER)

关键方法详解

__call__ 核心参数:

参数作用
text输入文本(支持字符串、字符串列表、分词后列表)
text_pair第二段文本(用于句对任务如 NLI)
max_length最大序列长度(如 512)
return_attention_mask是否返回注意力掩码(默认 True
return_token_type_ids是否返回段落标记(如 BERT 句对任务)

apply_chat_template 核心参数:

参数作用
conversation对话历史(例如:[{"role":"user", "content":"Hello"}]
tokenize是否返回分词后 ID(默认 True
add_generation_prompt是否添加助理响应提示(如 <|im_start|>assistant

使用场景示例

1. 基础编码:

inputs = tokenizer("Hello world!", padding=True, return_tensors="pt")
# 输出: {'input_ids': tensor([[101, 7592, 2088, 999, 102]]), 'attention_mask': tensor([[1, 1, 1, 1, 1]])}

2. 对话模型格式化:

messages = [{"role": "user", "content": "Hello!"}]
inputs = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt")
# 输出: tensor([1, 367, 1234, ...])  # 包含助理响应提示的 ID 序列

3. 添加自定义词:

num_added = tokenizer.add_tokens(["<SPECIAL>"])
model.resize_token_embeddings(len(tokenizer))  # 调整模型词嵌入层大小

4. 批处理填充:

batch = [["Hello"], ["Hi there!"]]
inputs = tokenizer(batch, padding='max_length', max_length=10, return_tensors="pt")
# 所有序列填充至长度 10

训练器工具

核心工具类

名称用途场景关键参数作用样例
EvalPrediction封装评估预测结果自定义评估指标计算predictions:模型预测值;label_ids:真实标签;inputs:原始输入数据用于计算准确率:accuracy = (preds == labels).mean()
IntervalStrategy训练策略枚举控制评估/保存频率STEPS:按步数间隔;EPOCH:按轮次间隔evaluation_strategy="steps"
enable_full_determinism启用完全确定性训练可复现性实验seed:随机种子;warn_only:仅警告不强制enable_full_determinism(42)
set_seed设置随机种子实验可复现seed:随机种子;deterministic:启用确定性算法set_seed(42)
torch_distributed_zero_first分布式训练同步多 GPU/多节点训练local_rank:本地进程 IDwith torch_distributed_zero_first(local_rank): preprocess_data()
DistributedTensorGatherer分布式张量收集分布式评估world_size:进程数;num_samples:样本总数;padding_index:填充值索引gatherer.add_arrays(predictions)
HfArgumentParser参数解析器解析命令行到数据类dataclass_types:目标数据类parser = HfArgumentParser(TrainingArguments); args = parser.parse_args()
DebugUnderflowOverflow数值异常检测FP16 混合精度训练调试model:待监控模型;trace_batch_nums:追踪批次号;abort_after_batch_num:终止批次debugger = DebugUnderflowOverflow(model)

参数解析方法

名称用途关键参数返回值
parse_args_into_dataclasses解析命令行参数look_for_args_file:自动查找 .args 文件数据类实例元组
parse_dict解析字典到数据类allow_extra_keys:是否允许额外键数据类实例元组
parse_json_file解析 JSON 文件json_file:JSON 文件路径数据类实例元组
parse_yaml_file解析 YAML 文件yaml_file:YAML 文件路径数据类实例元组

调试工具详解

DebugUnderflowOverflow 工作模式:

模式触发条件输出内容使用场景
异常检测自动检测 NaN/Inf打印导致异常的调用栈(默认 21 帧)定位 FP16 训练崩溃点
指定批次追踪设置 trace_batch_nums输出指定批次各层的绝对值 min/max分析特定批次数值问题

典型检测报告片段:

Detected inf/nan during batch_number=5
Last 5 forward frames:
abs min  abs max  metadata
                  layer.4.attention.dense Linear
1.23e-07 2.50e+00 weight
3.45e-06 4.80e+00 input[0]
2.78e-06 3.60e+01 output  <-- 接近FP16上限(64K)
                  layer.4.dropout Dropout
2.78e-06 3.60e+01 input[0]
0.00e+00      inf output  <-- 检测到溢出

使用场景示例

1. 分布式评估收集:

gatherer = DistributedTensorGatherer(world_size=4, num_samples=1000)
for batch in eval_dataloader:
    preds = model(**batch).logits
    gatherer.add_arrays(preds.cpu().numpy())
all_preds = gatherer.finalize()  # 收集所有进程结果

2. 参数解析:

parser = HfArgumentParser((ModelArguments, DataArguments, TrainingArguments))
model_args, data_args, training_args = parser.parse_json_file("config.json")

3. FP16 训练调试:

# 监控第10-15批次
debugger = DebugUnderflowOverflow(
    model,
    trace_batch_nums=[10, 11, 12, 13, 14, 15],
    abort_after_batch_num=15
)
trainer = Trainer(..., debug=debugger)
trainer.train()

生成工具

生成输出接口(ModelOutput 子类)

名称用途场景参数作用样例
GenerateDecoderOnlyOutput存储 decoder-only 模型非 beam 搜索生成结果GPT 类模型生成sequences:生成的 token 序列;scores:预测分数;attentions:注意力权重model.generate(return_dict_in_generate=True)
GenerateEncoderDecoderOutput存储 encoder-decoder 模型非 beam 搜索生成结果T5/BART 类模型生成增加 encoder_attentionscross_attentions 等 encoder 特有属性同上
GenerateBeamDecoderOnlyOutput存储 decoder-only 模型 beam 搜索生成结果GPT 类模型的 beam 搜索增加 sequences_scoresbeam_indices 等 beam 特有属性model.generate(num_beams=4)
GenerateBeamEncoderDecoderOutput存储 encoder-decoder 模型 beam 搜索生成结果T5/BART 类模型的 beam 搜索包含 encoder 和 decoder 的 beam 相关信息同上

生成工具(LogitsProcessor)

名称用途场景参数作用样例
TemperatureLogitsWarper控制输出随机性提高/降低生成多样性temperature:>1 增加随机性,<1 降低随机性generate(temperature=0.7)
TopKLogitsWarper限制采样到 Top K token提高生成质量top_k:保留的最高概率 token 数量generate(top_k=50)
TopPLogitsWarper限制采样到累计概率 Top P 的 token平衡生成多样性和质量top_p:概率累计阈值(0.9-0.95)generate(top_p=0.92)
RepetitionPenaltyProcessor惩罚重复 token减少重复生成penalty:>1 惩罚重复,<1 鼓励重复generate(repetition_penalty=1.2)
NoRepeatNGramProcessor禁止 n-gram 重复避免短语重复ngram_size:禁止重复的 n-gram 长度generate(no_repeat_ngram_size=3)

流式输出工具

名称用途场景参数作用样例
TextStreamer实时打印生成文本控制台实时输出tokenizer:用于解码;skip_prompt:是否跳过提示generate(streamer=TextStreamer(tokenizer))
TextIteratorStreamer异步生成文本迭代器Gradio 等交互应用timeout:队列超时设置for text in streamer: ...

使用示例

基础生成:

from transformers import GPT2LMHeadModel, GPT2Tokenizer
model = GPT2LMHeadModel.from_pretrained("gpt2")
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
inputs = tokenizer("Hello, my dog is", return_tensors="pt")
outputs = model.generate(**inputs)

带参数的高级生成:

outputs = model.generate(
    **inputs,
    do_sample=True,
    top_k=50,
    temperature=0.7,
    max_length=100,
    repetition_penalty=1.2
)

流式输出:

from transformers import TextStreamer
streamer = TextStreamer(tokenizer)
model.generate(**inputs, streamer=streamer, max_new_tokens=100)

关键点总结

  1. 输出结构generate() 返回 ModelOutput 子类对象,可通过属性/元组/字典访问结果
  2. 参数控制
    • output_scores=True 获取预测分数
    • return_dict_in_generate=True 获取结构化输出
    • max_length 控制最大长度
  3. 处理器应用
    • LogitsProcessor 修改预测分数
    • LogitsWarper 调整采样分布
  4. 流式处理
    • TextStreamer 实时输出文本
    • TextIteratorStreamer 支持异步迭代

注意:完整接口列表包含 PyTorch/TensorFlow/FLAX 的实现变体,此处展示核心 PyTorch 接口。实际应用需根据框架选择对应实现。

图像处理工具

图像变换工具(image_transforms

名称用途场景参数作用样例
center_crop中心裁剪图像图像预处理size:目标尺寸;data_format:通道格式(channels_first/lastcenter_crop(image, (224,224))
normalize标准化图像输入归一化mean/std:均值/标准差;支持单值或通道级参数normalize(image, mean=0.5, std=0.5)
resize调整图像尺寸尺寸统一化size:目标尺寸;resample:重采样方法(如 BILINEARresize(image, (256,256), resample=PILImageResampling.BICUBIC)
pad图像填充尺寸标准化padding:填充量;mode:填充模式(constant/reflect 等)pad(image, ((10,20),(5,15)), mode='constant')
rescale缩放像素值数值范围调整scale:缩放因子rescale(image, scale=1/255)
to_pil_image转为 PIL 图像对象格式转换do_rescale:是否缩放至 0-255;image_mode:PIL 模式to_pil_image(tensor)
center_to_corners_format边界框中心格式 → 角点格式目标检测bboxes_center(center_x, center_y, width, height)corners = center_to_corners_format(bboxes)
corners_to_center_format边界框角点格式 → 中心格式目标检测bboxes_corners(x1, y1, x2, y2)centers = corners_to_center_format(corners)
id_to_rgb/rgb_to_idID 与 RGB 互转语义分割id_map/color:映射数据rgb = id_to_rgb(id_map)

图像处理器基类(ImageProcessingMixin

名称用途场景参数作用样例
from_pretrained加载预训练处理器模型部署pretrained_model_name_or_path:模型 ID/路径;revision:版本CLIPImageProcessor.from_pretrained("openai/clip-vit-base-patch32")
save_pretrained保存处理器配置模型保存save_directory:保存路径;push_to_hub:是否上传到 Hubprocessor.save_pretrained("./my_model")
push_to_hub上传处理器到 Hub模型共享repo_id:仓库 ID;private:是否私有;token:访问令牌processor.push_to_hub("my-org/my-processor")
fetch_images下载 URL 转 PIL 图像远程数据预处理image_url_or_urls:单个/多个 URLimgs = fetch_images(["http://example.com/img.jpg"])
to_dict序列化为字典配置导出无参数config_dict = processor.to_dict()
to_json_string序列化为 JSON 字符串配置传输无参数json_str = processor.to_json_string()
register_for_auto_class注册自定义处理器到 AutoClass扩展框架auto_class:目标自动类(默认 AutoImageProcessorprocessor.register_for_auto_class()

使用示例

图像预处理流程:

from transformers import CLIPImageProcessor, image_transforms

# 加载预训练处理器
processor = CLIPImageProcessor.from_pretrained("openai/clip-vit-base-patch32")

# 图像变换组合
def process_image(image):
    image = image_transforms.resize(image, (256,256))
    image = image_transforms.center_crop(image, (224,224))
    image = image_transforms.normalize(image, mean=[0.485,0.456,0.406], std=[0.229,0.224,0.225])
    return processor(image, return_tensors="pt")

# 保存自定义配置
processor.save_pretrained("custom_processor")

核心功能总结

  1. 图像变换
    • 几何变换:裁剪/缩放/填充
    • 数值变换:归一化/标准化
    • 格式转换:tensor/PIL/边界框格式互转
  2. 处理器管理
    • 支持从 Hub 加载/保存预训练配置
    • 无缝集成到 transformers pipeline
    • 支持自定义处理器注册
  3. 边界框处理
    • 中心格式 ↔ 角点格式转换
    • 适用于目标检测任务
  4. 远程数据支持
    • 直接从 URL 获取图像
    • 自动转换为 PIL 格式

注意:所有函数支持多种输入格式(numpy array/PIL/tensor)并自动处理通道维度(channels_first/last)。

音频处理工具

音频特征提取工具(audio_utils

名称用途场景参数作用样例
hertz_to_mel赫兹转梅尔频率语音特征提取freq:输入频率;mel_scale:梅尔尺度类型(htk/kaldi/slaneymel = hertz_to_mel(1000.0)
mel_to_hertz梅尔频率转赫兹频率尺度转换mels:梅尔值;mel_scale:梅尔尺度类型hz = mel_to_hertz(1000.0)
mel_filter_bank生成梅尔滤波器组梅尔频谱计算num_frequency_bins:频率 bin 数;num_mel_filters:滤波器数量;min/max_frequency:频率范围filters = mel_filter_bank(257, 80, 20, 8000, 16000)
optimal_fft_length计算最佳 FFT 长度频谱分析优化window_length:窗口长度(自动取最近的 2 的幂)fft_len = optimal_fft_length(400) # 返回512
window_function生成窗函数信号加窗window_length:窗口长度;name:窗类型(hann/hamming 等);periodic:周期窗window = window_function(400, 'hann')
spectrogram计算频谱图音频特征提取waveform:输入波形;window:窗函数;frame/hop_length:帧参数;power:幅度/功率谱spec = spectrogram(waveform, window, 400, 160)
power_to_db功率谱转分贝特征归一化/可视化spectrogram:功率谱;reference:参考值;min_value:最小阈值db_spec = power_to_db(spec, reference=np.max(spec))
amplitude_to_db幅度谱转分贝特征归一化/可视化spectrogram:幅度谱;reference:参考值;min_value:最小阈值db_spec = amplitude_to_db(spec)

关键参数详解

  1. 梅尔滤波器组

    • mel_scale:支持三种标准:
      • htk:HTK 工具包标准
      • kaldi:Kaldi 语音识别工具包标准
      • slaney:MATLAB Auditory Toolbox 标准
    • triangularize_in_mel_spaceTrue 时在梅尔空间应用三角滤波器
  2. 频谱计算

    • dither:添加高斯噪声(>0)避免数值下溢
    • preemphasis:预加重滤波器系数
    • log_mel:支持 "log""log10""dB" 三种对数转换
    • remove_dc_offset:移除直流偏移
  3. 分贝转换

    • reference:0dB 对应的参考值
    • db_range:动态范围限制(如 80dB)
    • min_value:避免 log(0) 的阈值

使用示例

完整的梅尔频谱提取流程:

import numpy as np
from transformers.audio_utils import *

# 生成汉宁窗
window = window_function(400, 'hann')

# 计算最佳 FFT 长度
fft_len = optimal_fft_length(400)  # 512

# 创建梅尔滤波器组
mel_filters = mel_filter_bank(
    num_frequency_bins=fft_len//2 + 1,
    num_mel_filters=80,
    min_frequency=20,
    max_frequency=8000,
    sampling_rate=16000,
    mel_scale='htk'
)

# 生成示例音频(1秒,16kHz)
waveform = np.random.randn(16000)

# 计算梅尔频谱
mel_spec = spectrogram(
    waveform,
    window=window,
    frame_length=400,
    hop_length=160,
    fft_length=fft_len,
    mel_filters=mel_filters,
    power=2.0,  # 功率谱
    log_mel='dB'  # 分贝梅尔谱
)

# 转换为分贝尺度(备选方案)
db_mel = power_to_db(mel_spec, reference=1.0, min_value=1e-10)

核心功能总结

  1. 频率尺度转换
    • 线性赫兹 ↔ 感知梅尔尺度
    • 支持三种行业标准转换方式
  2. 滤波器设计
    • 梅尔滤波器组生成
    • 可定制滤波器数量和频率范围
  3. 频谱分析
    • 短时傅里叶变换(STFT)
    • 支持幅度谱/功率谱
    • 可选的预加重/加噪处理
  4. 特征后处理
    • 线性 → 对数尺度转换
    • 分贝归一化
    • 动态范围控制

这些工具通常被集成在音频特征提取器(如 WhisperFeatureExtractor)中,用于语音识别、音频分类等任务的预处理。

通用工具

通用工具总结

类别名称用途场景参数作用样例
枚举类ExplicitEnum提供更明确的错误消息需要精确错误提示的枚举场景value:枚举值;其他参数用于元数据class ModelType(ExplicitEnum): TF="tf"; PT="pt"
PaddingStrategy定义 tokenizer 的 padding 策略tokenizer 调用时的 padding 参数预定义值:LONGESTMAX_LENGTHDO_NOT_PADtokenizer(text, padding=PaddingStrategy.MAX_LENGTH)
TensorType定义 tokenizer 返回张量类型tokenizer 调用时的 return_tensors 参数预定义值:PYTORCHTENSORFLOWNUMPYJAXtokenizer(text, return_tensors=TensorType.PYTORCH)
文档装饰器add_start_docstrings为类/函数添加起始文档字符串统一 API 文档格式*docstr:要添加的文档字符串@add_start_docstrings("模型说明") class BertModel:
add_end_docstrings为类/函数添加结束文档字符串统一 API 文档格式*docstr:要添加的文档字符串@add_end_docstrings("\n返回: 输出张量")
add_code_sample_docstrings添加含代码示例的文档提供使用示例checkpoint:模型名;output_type:输出类型;expected_output:预期输出用于模型前向传播方法的装饰
replace_return_docstrings替换返回类型文档统一返回说明格式output_type:输出类型描述;config_class:配置类用于模型 forward 方法的文档装饰
特殊属性cached_property缓存属性计算结果避免重复计算昂贵操作无直接参数,作为装饰器使用@cached_property def config(self): return load_config()
惰性加载_LazyModule按需导入模块内容减少大型库的初始化时间name:模块名;module_file:文件路径;import_structure:导入结构内部使用,用于组织 transformers 库的子模块

关键工具详解

  1. 枚举类

    • 提供 IDE 自动补全支持
    • 确保参数值合法性
    • 示例:PaddingStrategy.MAX_LENGTH 确保使用有效的填充策略
  2. 文档装饰器

    • 自动生成统一格式的 API 文档
    • 支持代码示例插入
    • 示例:为模型类添加标准化的说明文档
  3. 缓存属性

    • 首次访问时计算并缓存结果
    • 后续访问直接返回缓存值
    • 示例:模型配置加载只需执行一次
  4. 惰性模块

    • 延迟导入子模块直到实际使用
    • 显著减少库导入时间
    • 示例:transformers.models 按需加载具体模型实现

使用示例

枚举类使用:

from transformers import PaddingStrategy, TensorType
from transformers.utils import ExplicitEnum

class ModelType(ExplicitEnum):
    TF = "tf"
    PT = "pt"

# 在 tokenizer 中使用枚举
encoded = tokenizer(
    text,
    padding=PaddingStrategy.MAX_LENGTH,
    return_tensors=TensorType.PYTORCH
)

缓存属性示例:

class ModelLoader:
    @cached_property
    def heavy_config(self):
        print("Loading config...")
        return load_huge_config_file()

loader = ModelLoader()
config1 = loader.heavy_config  # 首次加载
config2 = loader.heavy_config  # 直接返回缓存

文档装饰器示例:

@add_start_docstrings("BERT模型实现")
@add_end_docstrings("\n返回: <torch.Tensor>")
class BertModel:
    @add_code_sample_docstrings(
        checkpoint="bert-base-uncased",
        output_type="last_hidden_state"
    )
    def forward(self, inputs):
        return outputs

这些工具主要服务于库开发者,用于构建一致、高效的 API 接口,普通用户更多是通过预定义枚举值(如 PaddingStrategy)和装饰生成的文档来受益。

时序数据工具

时间序列核心工具总结

名称用途场景参数作用样例
NormalOutput定义正态分布输出适用于连续值预测,如销售额预测、温度预测等dim:输出维度(默认 1 维)model.output_distribution = NormalOutput(dim=1)
StudentTOutput定义学生 T 分布输出适用于存在异常值的预测场景,如金融数据预测dim:输出维度(默认 1 维)model.output_distribution = StudentTOutput()
NegativeBinomialOutput定义负二项分布输出适用于计数数据预测,如客流量预测、事件发生率预测等dim:输出维度(默认 1 维)model.output_distribution = NegativeBinomialOutput(dim=2)

关键特性详解

  1. 分布类型

    • 正态分布:对称钟形曲线,适用于大多数连续变量预测
    • 学生 T 分布:重尾分布,对异常值更鲁棒
    • 负二项分布:离散分布,适用于过离散计数数据
  2. 参数作用

    • dim:控制输出分布的维度
    • dim=1:单变量预测
    • dim>1:多变量联合预测

使用示例

from transformers import TimeSeriesTransformerForPrediction
from transformers.time_series_utils import NormalOutput, StudentTOutput

# 使用正态分布输出的时间序列模型
model_normal = TimeSeriesTransformerForPrediction(
    config=config,
    output_distribution=NormalOutput(dim=1)
)

# 使用学生T分布输出的金融预测模型
model_studentt = TimeSeriesTransformerForPrediction(
    config=config,
    output_distribution=StudentTOutput(dim=3)  # 3维联合预测
)

# 使用负二项分布的客流量预测模型
model_negbin = TimeSeriesTransformerForPrediction(
    config=config,
    output_distribution=NegativeBinomialOutput(dim=1)
)

# 预测并获取分布参数
outputs = model_normal(inputs)
loc = outputs.loc  # 均值参数
scale = outputs.scale  # 标准差参数

典型应用场景

  1. 零售预测

    • 正态分布:预测商品日销售额
    • 负二项分布:预测顾客到店人数
  2. 气象预测

    • 正态分布:预测温度变化
    • 学生 T 分布:预测极端天气事件概率
  3. 经济预测

    • 学生 T 分布:预测股票收益率(处理肥尾特性)
    • 正态分布:预测 GDP 增长

这些分布输出类通常与 TimeSeriesTransformerForPrediction 等时间序列预测模型结合使用,为模型提供概率预测能力,不仅能预测未来值,还能量化预测的不确定性。