当前位置: 首页 > java >正文

PEFT实战(三)——IA3参数高效微调

一、概念

        为了使微调更加高效,IA3(Infused Adapter by Inhibiting and Amplifying Inner Activations)使用可学习向量重新缩放内部激活值。这些可学习向量被注入到典型的基于 Transformer 的架构中的注意力和前馈模块中,是微调期间唯一的可训练参数,原始权重保持冻结。这么一来,可训练参数的数量大大减少了。IA3将模型的激活值(自注意力和编码器-解码器注意力块中的键和值,以及位置相关前馈网络的中间激活值)乘以三个可学习向量。这种参数高效微调(PEFT)方法引入的可训练参数数量比低秩自适应(LoRA)还要少,LoRA引入的是权重矩阵而不是向量。原始模型的参数保持冻结状态,只有这些向量会被更新。因此,对于新的下游任务进行微调时,它更快、更便宜且更高效。

        本文我们跟着HuggingFace教程来学习如何使用 IA3 训练一个序列到序列模型,以根据一些财经新闻生成情感分析结果。原则上,IA3 可以应用于神经网络中的任何权重矩阵子集,以减少可训练参数的数量。

二、原理

1、数据准备

        我们将使用financial_phrasebank数据集的sentences_allagree子集。这个子集的情感标签均有100%标注者的一致认同。首先,我们加载数据集,这个数据集的子集只包含一个训练集,因此我们使用train_test_split函数创建一个训练集和验证集的分割,并创建一个新的text_label列,以便更容易理解label值0、1和2的含义。

from datasets import load_datasetds = load_dataset("financial_phrasebank", "sentences_allagree")
ds = ds["train"].train_test_split(test_size=0.1)
ds["validation"] = ds["test"]
del ds["test"]classes = ds["train"].features["label"].names
ds = ds.map(lambda x: {"text_label": [classes[label] for label in x["label"]]},batched=True,num_proc=1,
)ds["train"][0]
{'sentence': 'It will be operated by Nokia , and supported by its Nokia NetAct network and service management system .','label': 1,'text_label': 'neutral'}

        然后,加载分词器并创建一个预处理函数。该函数对输入进行分词,将序列填充和截断至max_length,并对标签应用相同的分词器,但使用对应于标签的更短的max_length,最后mask掉padding tokens。

from transformers import AutoTokenizertext_column = "sentence"
label_column = "text_label"
max_length = 128tokenizer = AutoTokenizer.from_pretrained("bigscience/mt0-large")def preprocess_function(examples):inputs = examples[text_column]targets = examples[label_column]model_inputs = tokenizer(inputs, max_length=max_length, padding="max_length", truncation=True, return_tensors="pt")labels = tokenizer(targets, max_length=3, padding="max_length", truncation=True, return_tensors="pt")labels = labels["input_ids"]labels[labels == tokenizer.pad_token_id] = -100model_inputs["labels"] = labelsreturn model_inputs

        使用映射函数将预处理函数应用于整个数据集。

processed_ds = ds.map(preprocess_function,batched=True,num_proc=1,remove_columns=ds["train"].column_names,load_from_cache_file=False,desc="Running tokenizer on dataset",
)

        创建一个训练和评估DataLoader,如果数据集样本在 CPU 上,则设置pin_memory=True以在训练期间加快数据传输到 GPU 的速度(如果有GPU)。

from torch.utils.data import DataLoader
from transformers import default_data_collatortrain_ds = processed_ds["train"]
eval_ds = processed_ds["validation"]batch_size = 8train_dataloader = DataLoader(train_ds, shuffle=True, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True
)
eval_dataloader = DataLoader(eval_ds, collate_fn=default_data_collator, batch_size=batch_size, pin_memory=True)

2、模型构建

        这里,我们加载一个预训练模型作为 IA3 的基础模型——bigscience/mt0-large模型。

from transformers import AutoModelForSeq2SeqLMmodel = AutoModelForSeq2SeqLM.from_pretrained("bigscience/mt0-large")

        所有 PEFT 方法都需要一个配置,该配置包含并指定有关如何应用 PEFT 方法的所有参数。创建一个带有任务类型的IA3 配置,并将推理模式设置为False(可以在API 参考中找到配置的其他参数)。

from peft import IA3Config, get_peft_modelpeft_config = IA3Config(task_type="SEQ_2_SEQ_LM")
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()

3、模型训练

        下面,我们设置一个优化器和学习率调度器。

import torch
from transformers import get_linear_schedule_with_warmuplr = 8e-3
num_epochs = 3optimizer = torch.optim.AdamW(model.parameters(), lr=lr)
lr_scheduler = get_linear_schedule_with_warmup(optimizer=optimizer,num_warmup_steps=0,num_training_steps=(len(train_dataloader) * num_epochs),
)

        将模型移动到 GPU 上(如果有,建议使用GPU,CPU分分钟跑崩。。。),并创建一个训练循环,打印每个 epoch 的损失和困惑度。

from tqdm import tqdmdevice = "cuda"
model = model.to(device)for epoch in range(num_epochs):model.train()total_loss = 0for step, batch in enumerate(tqdm(train_dataloader)):batch = {k: v.to(device) for k, v in batch.items()}outputs = model(**batch)loss = outputs.losstotal_loss += loss.detach().float()loss.backward()optimizer.step()lr_scheduler.step()optimizer.zero_grad()model.eval()eval_loss = 0eval_preds = []for step, batch in enumerate(tqdm(eval_dataloader)):batch = {k: v.to(device) for k, v in batch.items()}with torch.no_grad():outputs = model(**batch)loss = outputs.losseval_loss += loss.detach().float()eval_preds.extend(tokenizer.batch_decode(torch.argmax(outputs.logits, -1).detach().cpu().numpy(), skip_special_tokens=True))eval_epoch_loss = eval_loss / len(eval_dataloader)eval_ppl = torch.exp(eval_epoch_loss)train_epoch_loss = total_loss / len(train_dataloader)train_ppl = torch.exp(train_epoch_loss)print(f"{epoch=}: {train_ppl=} {train_epoch_loss=} {eval_ppl=} {eval_epoch_loss=}")

4、应用

        加载模型,从数据集中加载一条财经新闻句子以生成其情感倾向。

from peft import AutoPeftModelForSeq2SeqLMmodel = AutoPeftModelForSeq2SeqLM.from_pretrained("saved_model/mt0-large-ia3").to("cuda")
tokenizer = AutoTokenizer.from_pretrained("bigscience/mt0-large")i = 15
inputs = tokenizer(ds["validation"][text_column][i], return_tensors="pt")
print(ds["validation"][text_column][i])

        调用生成方法以生成预测的情感标签。

with torch.no_grad():inputs = {k: v.to(device) for k, v in inputs.items()}outputs = model.generate(input_ids=inputs["input_ids"], max_new_tokens=10)print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True))
['positive']

 

 

http://www.xdnf.cn/news/3311.html

相关文章:

  • QT6 源(62)篇五:阅读与注释 QString 这个类,先给出官方综述,带一些翻译。总篇目太大,代码就有 2000 行
  • c++ 归并排序(分治)
  • 中国1km分辨率1901-2023年均气温降水数据
  • 2025年- H15-Lc123-41.缺失的第一个正数(普通数组)---java版
  • 格雷希尔用于工业气体充装站的CZ系列气罐充装转换连接器,其日常维护有哪些
  • linux jounery 日志相关问题
  • 高性能架构设计-分库分表
  • 声明:个人从未主动把文章设置为仅vip可读
  • 国内 AI 发展路线分析
  • /var/log/sssd/` 目录解析
  • 【Linux】gcc/g++配置
  • ROS2与Carla安装设备(其三)测试 ROS 2
  • 【MySQL数据库】事务
  • [第十五章][15.3.2 shellcode注入攻击]ret2shellcode+[NewStarCTF 公开赛赛道]ret2shellcode
  • LiP-MS与TPP联用:千金藤素在高尿酸血症中的抗神经炎症作用
  • 玩转Nginx
  • 极狐GitLab 分支管理功能介绍
  • ALLEGRO怎么外扩或内缩铜皮shape?
  • 美国国家生物技术信息中心NCBI介绍
  • 信号完整性简介第二篇
  • 2025A卷-传递悄悄话
  • 01_K近邻
  • Java 集合框架优化:从基础到高级应用
  • YPay标准版系统-五彩绚丽首页主题V1.0.0
  • 2025大模型应用爆发,算力保障成关键
  • 实用Chrome插件备忘
  • 科研 | 光子技术为人工智能注入新动力
  • PCB设计工艺规范(三)走线要求
  • 第15篇:Linux设备驱动程序入门<二>
  • QuecPython+aLiYun:快速连接阿里云IoT平台