掘金 人工智能 10小时前
微调篇-基于LoRA训练图像分类模型
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了一种使用低秩分解方法(LoRA)快速训练图像分类模型的技术,尤其适用于大型模型。通过冻结预训练模型的原始权重,仅更新较小的可训练矩阵,LoRA 降低了训练时间和内存需求。文章详细阐述了 LoRA 的原理、配置方法,以及在 Food-101 数据集上训练图像分类模型的具体步骤,包括数据准备、模型选择、PEFT 配置、训练和推理。最终展示了如何将训练好的模型上传到 Hugging Face Hub,并进行图像分类预测。

🖼️ **LoRA 原理:** LoRA 通过在预训练模型的权重矩阵中插入较小的可训练矩阵,进行低秩分解,从而减少可训练参数数量,降低训练成本。

⚙️ **PEFT 配置:** PEFT(Parameter-Efficient Fine-Tuning)库支持多种 LoRA 变体,用户需要配置 LoraConfig,设置秩、缩放因子、目标模块等参数,并使用 get_peft_model() 函数创建可训练的 PeftModel。

🍎 **数据集准备:** 本文使用 Food-101 数据集,包含 101 个食物类别图像。需要加载数据集、图像处理器,并定义图像预处理的转换函数,包括随机裁剪、翻转、标准化等。

🚀 **模型训练:** 使用 Transformers 库中的 Trainer 类进行训练。配置训练超参数,如学习率、批量大小等。训练完成后,可以将模型上传到 Hugging Face Hub。

💡 **推理与应用:** 从 Hub 加载模型,使用图像处理器对图像进行预处理,然后运行模型进行预测。展示了如何使用训练好的模型对食物图像进行分类。

前言

一种有效训练大型模型的常用方法是插入(通常在注意力模块中)较小的可训练矩阵,这些矩阵是在微调期间要学习的增量权重矩阵的低秩分解。预训练模型的原始权重矩阵被冻结,只有较小的矩阵在训练期间更新。这减少了可训练参数的数量,从而减少了内存使用和训练时间,对于大型模型来说,这可能非常昂贵。

有几种不同的方法可以将权重矩阵表示为低秩分解,但低秩自适应 (LoRA)是最常用的方法。PEFT 库支持其他几种 LoRA 变体,例如低秩哈达玛积 (LoHa)低秩克罗内克积 (LoKr)自适应低秩自适应 (AdaLoRA)。您可以在适配器指南中了解有关这些方法在概念上如何工作的更多信息。如果您有兴趣将这些方法应用于其他任务和用例,例如语义分割、token 分类,请查看我们的notebook 合集

此外,PEFT 支持 X-LoRA LoRA 专家混合方法。

本指南将向您展示如何使用低秩分解方法快速训练图像分类模型,以识别图像中显示的食物类别。

熟悉图像分类模型训练的一般过程将非常有帮助,并使您能够专注于低秩分解方法。如果您是新手,我们建议您首先查看 Transformers 文档中的图像分类指南。当您准备好后,请回来看看将 PEFT 融入您的训练有多么容易!

在开始之前,请确保您已安装所有必要的库。

pip install -q peft transformers datasets

数据集

在本指南中,您将使用包含 101 个食物类别的图像的 Food-101 数据集(查看数据集查看器,以更好地了解数据集的外观)。

使用 load_dataset 函数加载数据集。

from datasets import load_datasetds = load_dataset("food101")

每个食物类别都用一个整数标记,为了更容易理解这些整数代表什么,您将创建一个 label2idid2label 字典,将整数映射到其类别标签。

labels = ds["train"].features["label"].nameslabel2id, id2label = dict(), dict()for i, label in enumerate(labels):    label2id[label] = i    id2label[i] = labelid2label[2]"baklava"

加载图像处理器以正确调整大小并标准化训练和评估图像的像素值。

from transformers import AutoImageProcessorimage_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224-in21k")

您还可以使用图像处理器来准备一些用于数据增强和像素缩放的转换函数。

from torchvision.transforms import (    CenterCrop,    Compose,    Normalize,    RandomHorizontalFlip,    RandomResizedCrop,    Resize,    ToTensor,)normalize = Normalize(mean=image_processor.image_mean, std=image_processor.image_std)train_transforms = Compose(    [        RandomResizedCrop(image_processor.size["height"]),        RandomHorizontalFlip(),        ToTensor(),        normalize,    ])val_transforms = Compose(    [        Resize(image_processor.size["height"]),        CenterCrop(image_processor.size["height"]),        ToTensor(),        normalize,    ])def preprocess_train(example_batch):    example_batch["pixel_values"] = [train_transforms(image.convert("RGB")) for image in example_batch["image"]]    return example_batchdef preprocess_val(example_batch):    example_batch["pixel_values"] = [val_transforms(image.convert("RGB")) for image in example_batch["image"]]    return example_batch

定义训练和验证数据集,并使用 set_transform 函数即时应用转换。

train_ds = ds["train"]val_ds = ds["validation"]train_ds.set_transform(preprocess_train)val_ds.set_transform(preprocess_val)

最后,您需要一个数据整理器来创建一批训练和评估数据,并将标签转换为 torch.tensor 对象。

import torchdef collate_fn(examples):    pixel_values = torch.stack([example["pixel_values"] for example in examples])    labels = torch.tensor([example["label"] for example in examples])    return {"pixel_values": pixel_values, "labels": labels}

模型

现在让我们加载一个预训练模型用作基础模型。本指南使用 google/vit-base-patch16-224-in21k 模型,但您可以使用任何您想要的图像分类模型。将 label2idid2label 字典传递给模型,以便模型知道如何将整数标签映射到其类别标签,如果您要微调已经微调过的检查点,您可以选择传递 ignore_mismatched_sizes=True 参数。

from transformers import AutoModelForImageClassification, TrainingArguments, Trainermodel = AutoModelForImageClassification.from_pretrained(    "google/vit-base-patch16-224-in21k",    label2id=label2id,    id2label=id2label,    ignore_mismatched_sizes=True,)

PEFT 配置和模型

每个 PEFT 方法都需要一个配置,其中包含指定应如何应用 PEFT 方法的所有参数。配置设置完成后,将其与基础模型一起传递给 get_peft_model() 函数,以创建一个可训练的 PeftModel

调用 print_trainable_parameters() 方法,比较 PeftModel 的参数数量与基础模型中的参数数量!

LoRA 将权重更新矩阵分解为两个较小的矩阵。这些低秩矩阵的大小由其r 决定。秩越高意味着模型有更多的参数要训练,但也意味着模型具有更强的学习能力。您还需要指定 target_modules,它确定较小矩阵的插入位置。在本指南中,您将以注意力模块的queryvalue矩阵为目标。其他要设置的重要参数包括 lora_alpha(缩放因子)、biasnoneall 还是仅训练 LoRA 偏差参数),以及 modules_to_save(除了要训练和保存的 LoRA 层之外的模块)。所有这些参数以及更多参数都可以在 LoraConfig 中找到。

from peft import LoraConfig, get_peft_modelconfig = LoraConfig(    r=16,    lora_alpha=16,    target_modules=["query", "value"],    lora_dropout=0.1,    bias="none",    modules_to_save=["classifier"],)model = get_peft_model(model, config)model.print_trainable_parameters()"trainable params: 667,493 || all params: 86,543,818 || trainable%: 0.7712775047664294"

训练

对于训练,让我们使用 Transformers 中的 Trainer 类。Trainer 包含一个 PyTorch 训练循环,当您准备好后,调用 train 开始训练。要自定义训练运行,请在 TrainingArguments 类中配置训练超参数。使用类似 LoRA 的方法,您可以负担得起使用更高的批量大小和学习率。

AdaLoRA 有一个 update_and_allocate() 方法,应在每个训练步骤中调用该方法以更新参数预算和掩码,否则不会执行自适应步骤。这需要编写自定义训练循环或子类化 Trainer 以合并此方法。例如,请查看这个 自定义训练循环

from transformers import TrainingArguments, Traineraccount = "stevhliu"peft_model_id = f"{account}/google/vit-base-patch16-224-in21k-lora"batch_size = 128args = TrainingArguments(    peft_model_id,    remove_unused_columns=False,    eval_strategy="epoch",    save_strategy="epoch",    learning_rate=5e-3,    per_device_train_batch_size=batch_size,    gradient_accumulation_steps=4,    per_device_eval_batch_size=batch_size,    fp16=True,    num_train_epochs=5,    logging_steps=10,    load_best_model_at_end=True,    label_names=["labels"],)

使用 train 开始训练。

trainer = Trainer(    model,    args,    train_dataset=train_ds,    eval_dataset=val_ds,    tokenizer=image_processor,    data_collator=collate_fn,)trainer.train()

分享你的模型

训练完成后,您可以使用 push_to_hub 方法将您的模型上传到 Hub。您需要先登录您的 Hugging Face 帐户,并在提示时输入您的令牌。

from huggingface_hub import notebook_loginnotebook_login()

调用 push_to_hub 将您的模型保存到您的存储库。

model.push_to_hub(peft_model_id)

推理

让我们从 Hub 加载模型,并在食物图像上进行测试。

from peft import PeftConfig, PeftModelfrom transformers import AutoImageProcessorfrom PIL import Imageimport requestsconfig = PeftConfig.from_pretrained("stevhliu/vit-base-patch16-224-in21k-lora")model = AutoModelForImageClassification.from_pretrained(    config.base_model_name_or_path,    label2id=label2id,    id2label=id2label,    ignore_mismatched_sizes=True,)model = PeftModel.from_pretrained(model, "stevhliu/vit-base-patch16-224-in21k-lora")url = "https://hugging-face.cn/datasets/sayakpaul/sample-datasets/resolve/main/beignets.jpeg"image = Image.open(requests.get(url, stream=True).raw)image

将图像转换为 RGB 并返回底层 PyTorch 张量。

encoding = image_processor(image.convert("RGB"), return_tensors="pt")

现在运行模型并返回预测的类别!

with torch.no_grad():    outputs = model(**encoding)    logits = outputs.logitspredicted_class_idx = logits.argmax(-1).item()print("Predicted class:", model.config.id2label[predicted_class_idx])"Predicted class: beignets"

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

LoRA 图像分类 PEFT 模型训练 Hugging Face
相关文章