12 对话模型微调2

news2024/9/28 15:24:29

1 P-Tuning

        P-Tuning 是在 Prompt-Tuning的基础上,通过新增 LSTM 或 MLP 编码模块来加速模型的收敛;

之前的实验也看到了使用prompt训练速度很慢,那么P-Tuning呢

参数占比:

trainable params: 5,267,456 || all params: 1,308,379,136 || trainable%: 0.4026

1.1 代码部分

PromptEncoderConfig: 

PromptEncoderConfig 类通常包含了以下配置项:

  1. Prompt Length:提示向量的长度,即提示向量中包含的token数量。
  2. Embedding Dimension:提示向量的嵌入维度,通常与预训练模型的隐藏层维度相同。
  3. Initialization Method:提示向量的初始化方法,可以是随机初始化或其他预定义的方式。
  4. Trainable Parameters:哪些参数是可训练的,例如提示向量本身是否可训练。
  5. Additional Layers:是否添加额外的层来进一步处理提示向量,例如线性层、LSTM层等。

示例代码

from datasets import Dataset
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer

ds = Dataset.load_from_disk("../data/")
tokenizer = AutoTokenizer.from_pretrained("../bloom-model/")
def process_func(example):
    MAX_LENGTH = 256
    input_ids, attention_mask, labels = [], [], []
    instruction = tokenizer("\n".join(["Human: " + example["instruction"], example["input"]]).strip() + "\n\nAssistant: ")
    response = tokenizer(example["output"] + tokenizer.eos_token)
    input_ids = instruction["input_ids"] + response["input_ids"]
    attention_mask = instruction["attention_mask"] + response["attention_mask"]
    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"]
    if len(input_ids) > MAX_LENGTH:
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]
    return {
        "input_ids": input_ids,
        "attention_mask": attention_mask,
        "labels": labels
    }

tokenized_ds = ds.map(process_func, remove_columns=ds.column_names)

from transformers import DataCollatorWithPadding
from transformers.trainer_callback import TrainerCallback
import matplotlib.pyplot as plt

from peft import PromptEncoderConfig, TaskType, get_peft_model, PromptEncoderReparameterizationType

config = PromptEncoderConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=10,
                             encoder_reparameterization_type=PromptEncoderReparameterizationType.MLP,
                             encoder_dropout=0.1, encoder_num_layers=5, encoder_hidden_size=1024)
config

# 自定义回调类,用于在训练过程中打印损失
model = AutoModelForCausalLM.from_pretrained("../bloom-model/")
model = get_peft_model(model, config)
print(model.print_trainable_parameters())


class PrintLossCallback(TrainerCallback):
    
    def __init__(self):
        self.losses = []
        self.steps = []

    def on_log(self, args, state, control, logs=None, **kwargs):
        # 打印训练过程中的日志信息
        try:
            if logs is not None:
                print(f"Step {state.global_step}: Loss={logs['loss']:.4f}, Learning Rate={logs['learning_rate']:.6f}")
                self.losses.append(logs['loss'])
                self.steps.append(state.global_step)

        except Exception as e :
            print(f'on_log error {e}')
    
    def plot_losses(self):
        plt.figure(figsize=(10, 5))
        plt.plot(self.steps, self.losses, label='Training Loss')
        plt.xlabel('Steps')
        plt.ylabel('Loss')
        plt.title('Training Loss Over Time')
        plt.legend()
        plt.show()
        

args = TrainingArguments(
    output_dir="./chatbot_ptune",
    per_device_train_batch_size=8,
    gradient_accumulation_steps=8,
    logging_steps=10,
    num_train_epochs=1,
    save_steps=100,
)
plot_losses_callback = PrintLossCallback()
trainer = Trainer(
    model=model,
    args=args,
    tokenizer=tokenizer,
    train_dataset=tokenized_ds,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
    callbacks=[plot_losses_callback]  # 注册自定义回调
)



if torch.cuda.is_available():
    trainer.model = trainer.model.to("cuda")
# 训练模型
trainer.train()

推理: 

from peft import PeftModel
# 在一个jupyter文件中,如果前面已经加载了模型,并对模型做了一定修改,则需要重新加载原始模型
model = AutoModelForCausalLM.from_pretrained("../bloom-model/")
peft_model = PeftModel.from_pretrained(model=model, model_id="./chatbot_ptune/")

peft_model = peft_model.cuda()
ipt = tokenizer("Human: {}\n{}".format("考试有哪些技巧?", "").strip() + "\n\nAssistant: ", return_tensors="pt").to(peft_model.device)
print(tokenizer.decode(peft_model.generate(**ipt, max_length=128,
                                           do_sample=True)[0], 
                       skip_special_tokens=True))

可能没有有关作弊的语料。 

整体上效果也不咋滴!

2 Lora

LoRA 的思想很简单:

  • 在原始 PLM (Pre-trained Language Model) 旁边增加一个旁路,做一个降维再升维的操作,来模拟所谓的intrinsic rank
  • 训练的时候固定 PLM 的参数,只训练降维矩阵 A 与升维矩阵 B 。而模型的输入输出维度不变,输出时将 BA 与 PLM 的参数叠加。
  • 用随机高斯分布初始化 A ,用 0 矩阵初始化 B ,保证训练的开始此旁路矩阵依然是 0 矩阵。

在LoRA中,降维矩阵A和升维矩阵B的初始化方式是有特定原因的。降维矩阵A使用随机高斯分布初始化,是为了保持模型的表达能力。高斯分布的随机初始化可以帮助模型在训练初期快速学习到有效的特征表示,从而提高模型的性能。而升维矩阵B使用0矩阵初始化,是为了减少对原始模型参数的影响。将B初始化为0矩阵,使得在训练初期,模型仍然保持原始预训练参数的输出,从而保证了模型在微调初期的稳定性。如果将A和B都用0矩阵初始化,那么在训练初期,模型将无法学习到有效的特征表示,导致微调效果不佳。如果A用0矩阵初始化,B用随机高斯分布初始化,那么在训练初期,模型可能会受到B矩阵的干扰,导致训练过程不稳定,甚至可能损害模型的性能。总之,LoRA中降维矩阵A和升维矩阵B的初始化方式是为了保持模型的表达能力,同时减少对原始模型参数的影响,从而提高微调的效率和稳定性。在实际应用中,可以根据具体任务和模型需求,对初始化方式进行适当调整。

from datasets import Dataset
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer

ds = Dataset.load_from_disk("../data/")
tokenizer = AutoTokenizer.from_pretrained("../bloom-model/")
def process_func(example):
    MAX_LENGTH = 256
    input_ids, attention_mask, labels = [], [], []
    instruction = tokenizer("\n".join(["Human: " + example["instruction"], example["input"]]).strip() + "\n\nAssistant: ")
    response = tokenizer(example["output"] + tokenizer.eos_token)
    input_ids = instruction["input_ids"] + response["input_ids"]
    attention_mask = instruction["attention_mask"] + response["attention_mask"]
    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"]
    if len(input_ids) > MAX_LENGTH:
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]
    return {
        "input_ids": input_ids,
        "attention_mask": attention_mask,
        "labels": labels
    }

tokenized_ds = ds.map(process_func, remove_columns=ds.column_names)


from transformers import DataCollatorWithPadding
from transformers.trainer_callback import TrainerCallback
import matplotlib.pyplot as plt

from peft import LoraConfig, TaskType, get_peft_model

config = LoraConfig(task_type=TaskType.CAUSAL_LM, 
                    target_modules=".*\.1.*query_key_value", 
                    modules_to_save=["word_embeddings"])
config

# 自定义回调类,用于在训练过程中打印损失
model = AutoModelForCausalLM.from_pretrained("../bloom-model/")
model = get_peft_model(model, config)
print(model.print_trainable_parameters())


class PrintLossCallback(TrainerCallback):
    
    def __init__(self):
        self.losses = []
        self.steps = []

    def on_log(self, args, state, control, logs=None, **kwargs):
        # 打印训练过程中的日志信息
        try:
            if logs is not None:
                print(f"Step {state.global_step}: Loss={logs['loss']:.4f}, Learning Rate={logs['learning_rate']:.6f}")
                self.losses.append(logs['loss'])
                self.steps.append(state.global_step)

        except Exception as e :
            print(f'on_log error {e}')
    
    def plot_losses(self):
        plt.figure(figsize=(10, 5))
        plt.plot(self.steps, self.losses, label='Training Loss')
        plt.xlabel('Steps')
        plt.ylabel('Loss')
        plt.title('Training Loss Over Time')
        plt.legend()
        plt.show()
        

args = TrainingArguments(
    output_dir="./chatbot_ptune",
    per_device_train_batch_size=8,
    gradient_accumulation_steps=8,
    logging_steps=10,
    num_train_epochs=1,
    save_steps=1000,
)
plot_losses_callback = PrintLossCallback()
trainer = Trainer(
    model=model,
    args=args,
    tokenizer=tokenizer,
    train_dataset=tokenized_ds,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
    callbacks=[plot_losses_callback]  # 注册自定义回调
)



if torch.cuda.is_available():
    trainer.model = trainer.model.to("cuda")
# 训练模型
trainer.train()

效果还一般般!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2089007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Golang学习总结

一、基本语法 Golang 设计理念:一种事情有且只有一种方法完成 软件包安装 直接官网下载好,配置安装下环境变量即可 /etc/profile # 在这个文件写入会对所有用户生效 ~/.profile # 在这个文件写入只会对当前用户生效# 以上两个文件中…

综合布线智能运维管理方案

布线运维管理的现状 基础档案资料分散、过时,无集中管理与自动更新机制; 缺乏变更规划工具与流程,易造成线缆混乱、变更效率低; 缺乏告警机制,关键线路中断无法及时发现。 nVisual综合布线智能运维管理系统组…

人工智能相关概念

特征选择方法 解决过拟合问题 正则化 k匿名算法 L-多样性算法 t相进性算法

MySQL中的锁详解

1.概念 锁是计算机协调多个进程或者线程并发访问某一资源的机制。那么如何保证数据并发访问的一致性、有效性是数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素,所以数据库中锁的应用极为重要,其复杂度也更高。 …

SLAM的详细介绍,包括其基本原理、主要组件、算法类型、应用场景以及面临的挑战

创作不易,您的关注、点赞、收藏和转发是我坚持下去的动力! 大家有技术交流指导、论文及技术文档写作指导、项目开发合作的需求可以私信联系我。 SLAM(Simultaneous Localization and Mapping)是一种用于机器人和计算机视觉领域的…

设计模式之生成器方法

一、生成器模式概念 Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种。Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象,通过子类继承和重载的方式…

Mudbox 2013/2018简体中文版百度云(附教程)

如大家所了解的,Autodesk Mudbox是一款专业的‌3D数字雕刻和纹理绘画软件‌,它结合了直观的用户界面和一套高性能的创作工具,使三维建模专业人员能够快速轻松地制作高度逼真的有机和无机的三维资产。‌ 目前常用的版本有Mudbox 2013和Mudbox…

微气象在线监测系统:宏观层面的电网灾害预防和应急管理

微气象受局部地形(如山谷、河谷)、地物(如建筑物、森林)和地面条件(如水面、农田)的影响较大,而大范围气象环境则更多地受气候系统和天气模式的控制。输电线路微气象监测的主要目的是为了评估和…

Java基础(6)- Java代码笔记3

目录 一、二维数组 1.二维数组定义 a.动态初始化 b.静态初始化 c.简单静态初始化 2.获取数组长度 二、方法 1.无参无返回值方法 2.有参无返回值方法 3.无参有返回值方法 4.有参有返回值方法 5.形式参数和实际参数 6.三层架构思想 7.方法注意事项 8.数组作为方法参…

如何实现DWG转DXF在线?原来很简单

DWG转DXF在线怎么转?在CAD设计领域,文件格式转换是一项常见且重要的任务。DWG和DXF作为两种广泛使用的CAD文件格式,经常需要在不同软件或平台间进行转换。那么要怎么做才能顺利转换呢?下面,本文将详细介绍三种在线转换…

通过Origin提取图片数据

第一步: Tool --> Digitizer 第二步:点击文件,导入图片 第三步:设置坐标轴位置和数值(Edit Aix) 滑动鼠标放大图片,将X1移动到0,X2移动到80,Y1移动到97.0&#xff0c…

极客天成分布式全闪存储在大模型训练中的应用

01 国内大语言模型训练使用的存储系统应用现状 近年来,中国在人工智能领域,特别是大语言模型(LLM)的研发和应用方面取得了显著进展。随着百度文心一言、阿里通义千问、讯飞星火等国产大模型的推出,中国AI产业进入了快速发展期。这一趋势带动…

SpringBoot 集成mybatis-plus

目录 前言 简介 前提 运用mybatis-plus(使用20241.1版本的idea) 1 自动创建springboot项目 1.1 点击新建,SpringBoot 1.2 添加依赖项,点击创建 2添加 MyBatis-Plus Starter 依赖 2.1 打开mybatis-plus官网,点…

适配算能BM1684开发板,bmodel推理模型转换

通过mlir转bmodel 一、文件转移 从算能官网technical center (sophgo.com)下载最新的版本,下载下来之后解压出来,再Ubuntu系统中创建一个sophon文件夹存放后续用到的文件,将tpu-mlir_v1.2.8-g32d7b3ec-20230802.tar.gz文件放入Ubuntu系统中…

《Java面试题集中营》- Redis

建议阅读《Redis开发与运维》《Redis设计与实现》《Redis深度历险:核心原理和应用实践》 Redis 为什么是单线程? 为什么单线程还能这么快? 单线程能够避免线程切换和竞态产生的消耗,而且单线程可以简化数据结构和算法的实现 至于单线程还快…

idea付费插件,SequenceDiagram有哪些优点

以下idea付费插件你们都用过哪些呢? SequenceDiagram插件是一种用于绘制时序图的工具。时序图是一种图形化的表示对象之间消息传递顺序的方法。 该插件可以在使用各种编程语言编写代码时,方便地绘制时序图,以帮助开发者更好地理解和描述系统…

Qt text-align和padding属性

1. text-align属性是用来设置文本的水平对齐方式。 text-align: center 文本将居中显示text-align: left 文本将左对齐显示text-align: right 文本将右对齐显示 2. 内边距padding: 内边距是元素内容与其边框之间的空间 padding-left: 10px; 距离内左边距10个像素点padding-r…

Crypto City盛夏狂欢:Hotcoin推出15,000 USDT迎新礼

在炎炎夏日之际,为了感谢广大用户对Hotcoin平台的支持与热爱,全球领先的数字资产交易平台Hotcoin特别推出了“Crypto City盛夏狂欢”活动。此次活动旨在通过丰厚的奖励迎接新用户,进一步提升用户体验和平台活跃度。 本次活动时间为2024年8月2…

制造企业如何启用BI工具,并构建自助式BI业务模式?

在制造业的数字化转型浪潮中,商业智能BI工具正逐渐成为推动企业增长的“加速引擎”。随着数据量的爆炸性增长,如何高效地分析和利用数据,已成为制造业提升竞争力的关键。本文将基于BI工具在制造业中的优势,深入探讨一种创新的BI分…

SSRF漏洞(三)

本文仅作为学习参考使用,本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言: 本文基于pikachu(皮卡丘)靶场进行SSRF渗透攻击教学。 靶场环境搭建:SSRF漏洞(三) 一,SSR…