11 对话模型微调

news2024/9/27 15:24:26

提问:其实我一直觉的数据是最费事的一个,现在都是使用别人的数据,如果对于实际场景中那么我们该如何获取处理数据呢!

1 数据处理;

2 模型选择,调参数;

数据

llm-wizard/alpaca-gpt4-data-zh · Datasets at HF Mirror

模型

魔搭社区

1 数据

Instruction: 问题

input: 输入部分,辅助解读问题  

output: 问题的答案

数据怎么处理呢:

  1. 我们加个前缀"Human"+《instruction》+《input》:这个我为输入部分;
  2. -100 通常用于表示忽略某个位置的损失计算。我们只对回答部分做损失计算;
  3. 这样就把输入回答拼接在一起了,然后只对回答部分计算损失;

2 模型 

        "BLOOM" 是一个由 BigScience 联盟开发的大规模多语言预训练语言模型。"BLOOM" 模型的设计目的是为了能够理解和生成多种语言的文本,包括但不限于英语、汉语等。"1.4B" 这个后缀通常指的是模型的参数量,即这个版本的 BLOOM 模型拥有大约 14 亿个参数。

关于您提到的 "Bloom预训练生成模型-中文-1.4B",这可能是指一个专为中文优化的 BLOOM 模型变体,其参数量为 14 亿。这样的模型在处理中文文本时应该会有较好的表现,因为它经过了大量的中文语料训练,能够捕捉到中文语言的特性和结构。

模型的参数:1.3B,

占用内存:1.3B * 4 = 5.2G B 

训练: 5.2GB * 4 = 21GB;

GPU 低于21G那就别玩了!

我的 NVIDIA英伟达Tesla L40S 48GB;

 batchsize = 32, 不能玩了;只能为8;

2.1 全参数训练

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

# 日志
from transformers import DataCollatorWithPadding
from transformers.trainer_callback import TrainerCallback
import matplotlib.pyplot as plt


ds = Dataset.load_from_disk("../data/")
ds
# 分词
tokenizer = AutoTokenizer.from_pretrained("../bloom-model/")
tokenizer

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)
tokenized_ds


print(tokenizer.decode(tokenized_ds[1]["input_ids"]))
print()
print(tokenizer.decode(list(filter(lambda x: x != -100, tokenized_ds[1]["labels"])))
)


sum([param.numel() for param in model.parameters()]) / 1000000000

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

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",
    per_device_train_batch_size=8,
    gradient_accumulation_steps=8,
    logging_steps=10,
    num_train_epochs=2
)
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()

 过程很慢!

 2.2 Prompt-Tuning

安装依赖: installed peft-0.12.0

在Prompt Tuning方法中,主要改变的是输入结构而不是直接调整模型本身的参数。

         Prompt-Tuning 高效微调只会训练新增的Prompt的表示层,模型的其余参数全部固定;

        新增的 Prompt 内容可以分为 Hard Prompt 和 Soft Prompt 两类;

        Soft prompt 通常指的是一种较为宽泛或模糊的提示,允许模型在生成结果时有更大的自由度,通常用于启发模型进行创造性的生成;

        Hard prompt 是一种更为具体和明确的提示,要求模型按照给定的信息生成精确的结果,通常用于需要模型提供准确答案的任务;

        Soft Prompt 在 peft 中一般是随机初始化prompt的文本内容,而 Hard prompt 则一般需要设置具体的提示文本内容;

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

ds = Dataset.load_from_disk("../data/")
ds

tokenizer = AutoTokenizer.from_pretrained("../bloom-model/")
tokenizer
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)
tokenized_ds

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

from peft import PromptTuningConfig, get_peft_model, TaskType, PromptTuningInit

# Soft Prompt
# config = PromptTuningConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=10)
# config
# Hard Prompt
config = PromptTuningConfig(task_type=TaskType.CAUSAL_LM,
                            prompt_tuning_init=PromptTuningInit.TEXT,
                            prompt_tuning_init_text="下面是一段人与机器人的对话。",
                            num_virtual_tokens=len(tokenizer("下面是一段人与机器人的对话。")["input_ids"]),
                            tokenizer_name_or_path="../bloom-model/")
config


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_prompt",
    per_device_train_batch_size=8,
    gradient_accumulation_steps=8,
    logging_steps=10,
    num_train_epochs=1,
    #save_steps=20,
)
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()

效果没有全调参数好,收敛也很慢! 

2.3 推理

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


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))

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

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

相关文章

简单的二叉树问题——二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:3示例 2: 输入:root [1,null,2] 输出…

【二叉树进阶】--- 前中后序遍历非递归

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: 算法Journey 本篇博客我们将来了解有关二叉树前中后序遍历的非递归版本。 🏠 前序遍历 要迭代非递归实现二叉树的前序遍历,首先还…

【pgAdmin4】创建/删除:数据库Database和数据库表Table

目录 0.环境 1.简介 2.详细步骤 1)创建数据库 法一:UI界面创建 法二:sql语句创建数据库 2)创建数据库表 查看数据库表 查看数据库表内容 法一:UI界面创建数据库表 法二:sql语句创建数据库表 3&…

C_09_字符操作

字符串相关函数 头文件都是 string.h 概述: 由系统提供的由字符串处理的函数 属于库函数 所属头文件 string.h 1 strlen 测量字符串长度 语法: size_t strlen(const char *s);参数:要测量的字符串返回值:长度注意:测量的长度…

Screenshot Software,截屏软件

一.截屏软件 1.1 自带的一些截屏软件 (1)微信 (2)QQ 有一次无意中测试了下,截屏软件的截屏质量,发现对于同一个页面截全屏,微信截的屏质量相对于 win 自带的截图软件还要好的,所以…

Elasticsearch 开放推理 API 增加了对 Anthropic 的 Claude 的支持

作者:来自 Elastic Jonathan Buttner 我们很高兴地宣布 Elasticsearch Open Inference API 的最新功能:集成 Anthropic 的 Claude。这项功能使 Elastic 用户能够直接连接到 Anthropic 平台,并使用 Claude 3.5 Sonnet 等大型语言模型来构建 Ge…

Java 应用服务器有哪些?

应用服务器 Java 应用服务器是专门用来运行基于Java技术的Web应用程序的服务器。 这些服务器支持Java EE(Java Platform, Enterprise Edition)规范,提供了多种服务,如事务管理、Java Naming and Directory Interface (JNDI)、数…

机器之心 | 五倍吞吐量,性能全面包围Transformer:新架构Mamba引爆AI圈

本文来源公众号“机器之心”,仅用于学术分享,侵权删,干货满满。 原文链接:五倍吞吐量,性能全面包围Transformer:新架构Mamba引爆AI圈 屹立不倒的 Transformer 迎来了一个强劲竞争者。 在别的领域&#xff…

探索 HarmonyOS NEXT Developer Beta6,开启创新应用

华为的鸿蒙 NEXT 的发展越来越快 HarmonyOS NEXT Developer Beta6 版本的推出,为开发者们带来了全新的机遇和挑战。这个版本不仅拥有诸多令人振奋的新特性,还提供了丰富的新增资源和精彩的开发者活动。 新特性方面,DevEco Studio NEXT Dev…

算法练习题06:leetcode793每日温度

单调栈解法 class Solution {public int[] dailyTemperatures(int[] temperatures) {int length temperatures.length;int[] ans new int[length];Stack<Integer> stack new Stack<>();for(int i 0;i<length;i){int temperature temperatures[i];while(!…

系统功能性能优化:从问题定位到解决方案的系统性分析

引言 在现代软件系统中&#xff0c;性能优化是确保系统稳定、响应迅速和资源高效利用的关键。面对复杂的系统架构和业务逻辑&#xff0c;进行性能优化往往需要遵循一系列系统性的步骤&#xff0c;以确保问题被准确识别&#xff0c;解决方案被有效实施。以下是一套专业的系统功…

Linux下的使用字符设备驱动框架编写ADC驱动 ——MQ-4传感器

ADC的原理 ADC 的作用&#xff1a;模拟信号转换为数字信号 模拟信号一般是指连续变化的电压信号&#xff0c;其数值在一定范围内变化。 而数字信号是由一系列离散的数字表示&#xff0c; 只能取有限的值&#xff0c;通常以二进制形式表示。 ADC通常由一个采样保持电路、一个…

C++(Qt)-GIS开发-QGraphicsView显示瓦片地图简单示例2

C(Qt)-GIS开发-QGraphicsView显示瓦片地图简单示例2 文章目录 C(Qt)-GIS开发-QGraphicsView显示瓦片地图简单示例21、概述2、实现效果3、主要代码4、源码地址 更多精彩内容&#x1f449;个人内容分类汇总 &#x1f448;&#x1f449;GIS开发 &#x1f448; 1、概述 支持多线程…

Android 事件分发:为什么有时候会出现事件冲突?事件的顺序是如何的?出现事件冲突如何解决呢?比如为什么左右可以滑动,而上下却不行?

目录&#xff1a; 一、为什么要学习事件呢&#xff1f; 1.在开发复杂的应用时&#xff0c;经常需要处理复杂的用户交互逻辑。学习事件分发机制可以帮助你更好地控制事件的传递和处理流程&#xff0c;从而解决一些复杂的交互问题&#xff0c;如滑动冲突、点击穿透等。 2.面试需…

NLP笔记:BLEU

1 介绍 bleu是一种文本评估算法&#xff0c;它是用来评估机器翻译跟专业人工翻译之间的对应关系核心思想就是机器翻译越接近专业人工翻译&#xff0c;质量就越好&#xff0c;经过bleu算法得出的分数可以作为机器翻译质量的一个指标 2 BLEU原理 2.1 N-gram BLEU采用了N-gram…

NLP(三):词向量

自然语言处理&#xff0c;处理的是自然的需要&#xff0c;通过分词后得到我们想要的词&#xff0c;但是不可能直接把这种自然语言传递给计算机来理解。这时候就有一个概念叫词向量&#xff0c;用来表示词的特征向量或表征。 一&#xff0c;词向量的表示 词向量的表示主要有两…

C——四种排序方法

这一篇文章我将要详细讲解四种排序方法 1.冒泡排序 冒泡排序是我们首先接触的排序方法&#xff0c;他通过两次循环完成。 /*冒泡排序*/&#xff08;升序&#xff09; void maopao(int *a,int n) {int i;for(i 0; i < n-1; i){for (int j 0; j < n - 1 - i; j){if (a[…

mars3D使用 POI 查询、限定范围

mars3D使用 一、mars3D中使用 geocoder 进行 POI 查询二、限定范围1.初始化时渲染2.重新渲染 总结 一、mars3D中使用 geocoder 进行 POI 查询 在json文件或者自己的mapOptions中配置token "token":{"tianditu":"e5c3984ced09bc1f55e8e1107fdc5a6b&q…

论文速览【LLM-agent】—— 【ReAct】Synergizing Reasoning and Acting in Language Models

文章链接&#xff1a;ReAct: Synergizing Reasoning and Acting in Language Models发表&#xff1a;ICLR 2023领域&#xff1a;LLM agent 摘要&#xff1a;尽管大型语言模型&#xff08;LLMs&#xff09;在语言理解和交互式决策任务中展示了令人印象深刻的能力&#xff0c;但它…

正弦波振荡器工作原理及频率稳定性条件

晶发电子专注17年晶振生产,晶振产品包括石英晶体谐振器、振荡器、贴片晶振、32.768Khz时钟晶振、有源晶振、无源晶振等&#xff0c;产品性能稳定,品质过硬,价格好,交期快.国产晶振品牌您值得信赖的晶振供应商。 正弦波振荡器是一种能够自动将直流电转换为特定频率和振幅的正弦交…