pip install transformers datasets evaluate accelerate pillow torchvision scikit-learn
我们鼓励您登录您的 Hugging Face 账户,上传并与社区分享您的模型。当提示时,输入您的令牌以登录:
from huggingface_hub import notebook_login
notebook_login()
加载 Food-101 数据集¶
首先,从 🤗 Datasets 库中加载 Food-101 数据集的一个较小的子集。这将让您有机会进行实验,并确保一切正常工作,然后再在完整数据集上花费更多时间进行训练。
from datasets import load_dataset
food = load_dataset("food101", split="train[:5000]")
使用 train_test_split 方法将数据集的 train 分割成训练集和测试集:
food = food.train_test_split(test_size=0.2)
然后查看一个示例:
food["train"][0]
数据集中的每个示例都有两个字段:
image:食物项的 PIL 图像label:食物项的标签类别
为了使模型能够从标签 ID 获取标签名称,创建一个将标签名称映射到整数和反之亦然的字典:
labels = food["train"].features["label"].names
label2id, id2label = dict(), dict()
for i, label in enumerate(labels):
label2id[label] = str(i)
id2label[str(i)] = label
现在,您可以将标签 ID 转换为标签名称:
id2label[str(79)]
预处理¶
下一步是加载 ViT 图像处理器,将图像处理成张量:
from transformers import AutoImageProcessor
checkpoint = "google/vit-base-patch16-224-in21k"
image_processor = AutoImageProcessor.from_pretrained(checkpoint)
Pytorch
对图像应用一些图像变换,使模型更能抵抗过拟合。这里您将使用 torchvision 的 transforms 模块,但您也可以使用您喜欢的任何图像库。
裁剪图像的随机部分,调整其大小,并使用图像均值和标准差进行归一化:
from torchvision.transforms import RandomResizedCrop, Compose, Normalize, ToTensor
normalize = Normalize(mean=image_processor.image_mean, std=image_processor.image_std)
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), ToTensor(), normalize])
然后创建一个预处理函数,应用变换并返回图像的 pixel_values - 模型的输入:
def transforms(examples):
examples["pixel_values"] = [_transforms(img.convert("RGB")) for img in examples["image"]]
del examples["image"]
return examples
要使用 🤗 Datasets 的 with_transform 方法在整个数据集上应用预处理函数。当您加载数据集的元素时,变换将动态应用:
food = food.with_transform(transforms)
现在,使用 DefaultDataCollator 创建一个示例批次。与 🤗 Transformers 中的其他数据整理器不同,DefaultDataCollator 不会应用额外的预处理,例如填充。
from transformers import DefaultDataCollator
data_collator = DefaultDataCollator()
TensorFlow
为了避免过拟合并使模型更强大,请在数据集的训练部分添加一些数据增强。这里我们使用 Keras 预处理层来定义训练数据的变换(包括数据增强),以及验证数据的变换(仅中心裁剪、调整大小和归一化)。您可以使用 tf.image 或您喜欢的任何其他库。
from tensorflow import keras
from tensorflow.keras import layers
size = (image_processor.size["height"], image_processor.size["width"])
train_data_augmentation = keras.Sequential(
[
layers.RandomCrop(size[0], size[1]),
layers.Rescaling(scale=1.0 / 127.5, offset=-1),
layers.RandomFlip("horizontal"),
layers.RandomRotation(factor=0.02),
layers.RandomZoom(height_factor=0.2, width_factor=0.2),
],
name="train_data_augmentation",
)
val_data_augmentation = keras.Sequential(
[
layers.CenterCrop(size[0], size[1]),
layers.Rescaling(scale=1.0 / 127.5, offset=-1),
],
name="val_data_augmentation",
)
接下来,创建函数以对一批图像而不是单个图像应用适当的变换。
import numpy as np
import tensorflow as tf
from PIL import Image
def convert_to_tf_tensor(image: Image):
np_image = np.array(image)
tf_image = tf.convert_to_tensor(np_image)
# `expand_dims()` 用于添加一个批次维度,因为
# TF 增强层对批处理输入进行操作。
return tf.expand_dims(tf_image, 0)
def preprocess_train(example_batch):
"""Apply train_transforms across a batch."""
images = [
train_data_augmentation(convert_to_tf_tensor(image.convert("RGB"))) for image in example_batch["image"]
]
example_batch["pixel_values"] = [tf.transpose(tf.squeeze(image)) for image in images]
return example_batch
def preprocess_val(example_batch):
"""Apply val_transforms across a batch."""
images = [
val_data_augmentation(convert_to_tf_tensor(image.convert("RGB"))) for image in example_batch["image"]
]
example_batch["pixel_values"] = [tf.transpose(tf.squeeze(image)) for image in images]
return example_batch
使用 🤗 Datasets 的 set_transform 方法在加载时应用变换:
food["train"].set_transform(preprocess_train)
food["test"].set_transform(preprocess_val)
作为预处理步骤的最后一步,使用 DefaultDataCollator 创建一个示例批次。与 🤗 Transformers 中的其他数据整理器不同,DefaultDataCollator 不会应用额外的预处理,例如填充。
from transformers import DefaultDataCollator
data_collator = DefaultDataCollator(return_tensors="tf")
import evaluate
accuracy = evaluate.load("accuracy")
然后创建一个函数,将您的预测和标签传递给 compute 以计算准确率:
import numpy as np
def compute_metrics(eval_pred):
predictions, labels = eval_pred
predictions = np.argmax(predictions, axis=1)
return accuracy.compute(predictions=predictions, references=labels)
您的 compute_metrics 函数现在准备好了,当您设置训练时,您将返回到它。
训练¶
Pytorch
如果您不熟悉使用 Trainer 微调模型,请查看 这里 的基本教程!
您现在可以开始训练您的模型了!使用 AutoModelForImageClassification 加载 ViT。指定标签数量以及预期的标签数量和标签映射:
from transformers import AutoModelForImageClassification, TrainingArguments, Trainer
model = AutoModelForImageClassification.from_pretrained(
checkpoint,
num_labels=len(labels),
id2label=id2label,
label2id=label2id,
)
在这一点上,只剩下三个步骤:
- 在 TrainingArguments 中定义您的训练超参数。重要的是您不要删除未使用的列,因为这会删除
image列。如果没有image列,您就无法创建pixel_values。设置remove_unused_columns=False以防止这种行为!唯一其他必需的参数是output_dir,它指定保存模型的位置。您将通过设置push_to_hub=True将模型推送到 Hub(您需要登录 Hugging Face 才能上传模型)。在每个 epoch 结束时,Trainer 将评估准确率并保存训练检查点。 - 将训练参数传递给 Trainer,以及模型、数据集、标记器、数据整理器和
compute_metrics函数。 - 调用 train() 以微调您的模型。
training_args = TrainingArguments(
output_dir="my_awesome_food_model",
remove_unused_columns=False,
eval_strategy="epoch",
save_strategy="epoch",
learning_rate=5e-5,
per_device_train_batch_size=16,
gradient_accumulation_steps=4,
per_device_eval_batch_size=16,
num_train_epochs=3,
warmup_ratio=0.1,
logging_steps=10,
load_best_model_at_end=True,
metric_for_best_model="accuracy",
push_to_hub=True,
)
trainer = Trainer(
model=model,
args=training_args,
data_collator=data_collator,
train_dataset=food["train"],
eval_dataset=food["test"],
processing_class=image_processor,
compute_metrics=compute_metrics,
)
trainer.train()
训练完成后,使用 push_to_hub() 方法将您的模型分享到 Hub,以便每个人都可以使用您的模型:
trainer.push_to_hub()
TensorFlow
如果您不熟悉使用 Keras 微调模型,请先查看 基本教程!
要在 TensorFlow 中微调模型,请按照以下步骤操作:
- 定义训练超参数,并设置优化器和学习率计划。
- 实例化预训练模型。
- 将 🤗 Dataset 转换为
tf.data.Dataset。 - 编译您的模型。
- 添加回调并使用
fit()方法运行训练。 - 将您的模型上传到 🤗 Hub 以与社区分享。
首先定义超参数、优化器和学习率计划:
from transformers import create_optimizer
batch_size = 16
num_epochs = 5
num_train_steps = len(food["train"]) * num_epochs
learning_rate = 3e-5
weight_decay_rate = 0.01
optimizer, lr_schedule = create_optimizer(
init_lr=learning_rate,
num_train_steps=num_train_steps,
weight_decay_rate=weight_decay_rate,
num_warmup_steps=0,
)
然后,使用 TFAutoModelForImageClassification 加载 ViT 以及标签映射:
from transformers import TFAutoModelForImageClassification
model = TFAutoModelForImageClassification.from_pretrained(
checkpoint,
id2label=id2label,
label2id=label2id,
)
使用 to_tf_dataset 和您的 data_collator 将您的数据集转换为 tf.data.Dataset 格式:
# 将我们的训练数据集转换为 tf.data.Dataset
tf_train_dataset = food["train"].to_tf_dataset(
columns="pixel_values", label_cols="label", shuffle=True, batch_size=batch_size, collate_fn=data_collator
)
# 将我们的测试数据集转换为 tf.data.Dataset
tf_eval_dataset = food["test"].to_tf_dataset(
columns="pixel_values", label_cols="label", shuffle=True, batch_size=batch_size, collate_fn=data_collator
)
使用 compile() 配置模型进行训练:
from tensorflow.keras.losses import SparseCategoricalCrossentropy
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
model.compile(optimizer=optimizer, loss=loss)
要计算准确率并将模型推送到 🤗 Hub,请使用 Keras 回调。将您的 compute_metrics 函数传递给 KerasMetricCallback,并使用 PushToHubCallback 上传模型:
from transformers.keras_callbacks import KerasMetricCallback, PushToHubCallback
metric_callback = KerasMetricCallback(metric_fn=compute_metrics, eval_dataset=tf_eval_dataset)
push_to_hub_callback = PushToHubCallback(
output_dir="food_classifier",
tokenizer=image_processor,
save_strategy="no",
)
callbacks = [metric_callback, push_to_hub_callback]
最后,您现在可以训练您的模型了!调用 fit() 并传入您的训练和验证数据集、epoch 数量以及回调以微调模型:
model.fit(tf_train_dataset, validation_data=tf_eval_dataset, epochs=num_epochs, callbacks=callbacks)
恭喜!您已经微调了您的模型并将其分享在 🤗 Hub 上。现在,您可以使用它进行推理了!
有关如何为图像分类微调模型的更深入示例,请查看相应的 PyTorch 笔记本。
推理¶
太好了,现在您已经微调了一个模型,您可以使用它进行推理了!
加载您想要运行推理的图像:
ds = load_dataset("food101", split="validation[:10]")
image = ds["image"][0]

尝试使用微调模型进行推理的最简单方法是将其用于 pipeline()。为图像分类实例化一个 pipeline 并传入您的图像:
from transformers import pipeline
classifier = pipeline("image-classification", model="my_awesome_food_model")
classifier(image)
如果您愿意,您也可以手动复制 pipeline 的结果:
Pytorch
加载图像处理器以预处理图像并返回 PyTorch 张量的 input:
from transformers import AutoImageProcessor
import torch
image_processor = AutoImageProcessor.from_pretrained("my_awesome_food_model")
inputs = image_processor(image, return_tensors="pt")
将您的输入传递给模型并返回 logits:
from transformers import AutoModelForImageClassification
model = AutoModelForImageClassification.from_pretrained("my_awesome_food_model")
with torch.no_grad():
logits = model(**inputs).logits
获取概率最高的预测标签,并使用模型的 id2label 映射将其转换为标签:
predicted_label = logits.argmax(-1).item()
model.config.id2label[predicted_label]
TensorFlow
加载图像处理器以预处理图像并返回 TensorFlow 张量的 input:
from transformers import AutoImageProcessor
image_processor = AutoImageProcessor.from_pretrained("MariaK/food_classifier")
inputs = image_processor(image, return_tensors="tf")
将您的输入传递给模型并返回 logits:
from transformers import TFAutoModelForImageClassification
model = TFAutoModelForImageClassification.from_pretrained("MariaK/food_classifier")
logits = model(**inputs).logits
获取概率最高的预测标签,并使用模型的 id2label 映射将其转换为标签:
predicted_class_id = int(tf.math.argmax(logits, axis=-1)[0])
model.config.id2label[predicted_class_id]