利用大模型构造数据集,并微调大模型

一、前言

目前大模型的微调方法有很多,而且大多可以在消费级显卡上进行,每个人都可以在自己的电脑上微调自己的大模型。

但是在微调时我们时常面对一个问题,就是数据集问题。网络上有许多开源数据集,但是很多时候我们并不想用这些数据集微调模型,我们更希望使用某本书、某个作者的作品、我们自己的聊天记录、某个角色的对话来微调模型。

用于微调的数据通常是成千上万的问答对,如果手工搜集,需要花费大量时间。

文本将介绍一种方式,利用大模型来构造自己的数据集,并使用我们构造的数据集来微调大模型。
在这里插入图片描述

二、构造数据集

2.1 目的

数据集通常是问答对形式,比如alpaca数据集的形式如下:

  {
    "instruction": "保持健康的三个提示。",
    "input": "",
    "output": "以下是保持健康的三个提示:\n\n1. 保持身体活动。每天做适当的身体运动,如散步、跑步或游泳,能促进心血管健康,增强肌肉力量,并有助于减少体重。\n\n2. 均衡饮食。每天食用新鲜的蔬菜、水果、全谷物和脂肪含量低的蛋白质食物,避免高糖、高脂肪和加工食品,以保持健康的饮食习惯。\n\n3. 睡眠充足。睡眠对人体健康至关重要,成年人每天应保证 7-8 小时的睡眠。良好的睡眠有助于减轻压力,促进身体恢复,并提高注意力和记忆力。"
  }

但是实际上我们能拿到的数据通常是一大段文本的形式,比如:

    小时候,那时我还只有6岁,看到一本描写原始森林壮观景象的书,名叫真实的故事。书里有一幅很精彩的插画,画的是一条大蟒蛇正在吞食一只动物,下面就是那幅插画的复制品。
    这本书上说:“大蟒蛇把它们的猎物不加咀嚼地整个吞下去,之后,就再也不动了,然后通过长达六个月的睡眠来消化掉这些食物。”
	...

现在我们要做的就是把大段文本形式的数据转换成alpaca的形式。

在以往我们只能通过人工的方式完成,而现在我们可以借助大模型的能力。大致思路就是让大模型根据文本,总结出对话、问答内容。这点可以通过Prompt工程实现。

2.2 Prompt设计

在系统Prompt中,我们需要强调根据上下文内容,让模型提取对话、问答等内容。比如:

QA_PAIRS_SYSTEM_PROMPT = """  
<Context></Context> 标记中是一段文本,学习和分析它,并整理学习成果:  
- 提出问题并给出每个问题的答案。  
- 答案需详细完整,尽可能保留原文描述。  
- 答案可以包含普通文字、链接、代码、表格、公示、媒体链接等 Markdown 元素。  
- 最多提出 30 个问题。  
"""

这样就可以让模型自己提问,自己回答。然后我们需要规定输出的格式,我们希望得到字典数组,所以用户Prompt可以设置成:

QA_PAIRS_HUMAN_PROMPT = """  
请按以下格式整理学习成果:  
<Context>  
文本  
</Context>  
[  
{{"question": "问题1","answer":"答案1"}},  
{{"question": "问题2","answer":"答案2"}},  
]  
------  
  
我们开始吧!  
  
<Context>  
{text}  
<Context/>  
"""

根据问题不同,可以对上面的内容进行一些调整。下面可以开始编写代码。

2.3 处理文档

首先导入需要用到的模块:

import json  
from typing import List  
  
from tqdm import tqdm  
from langchain_core.prompts import ChatPromptTemplate  
from langchain_core.pydantic_v1 import BaseModel, Field  
from langchain_core.output_parsers import JsonOutputParser  
from langchain_openai import AzureChatOpenAI  
from langchain_community.document_loaders import UnstructuredFileLoader  
from langchain_text_splitters import RecursiveCharacterTextSplitter

在构建chain前,我们先完成文档处理的操作。我们希望传入的内容是文本数据,这里可以是txt等文件形式。我们这里以txt为例:

def split_document(filepath):  
	loader = UnstructuredFileLoader(filepath)  
	text_spliter = RecursiveCharacterTextSplitter(  
		chunk_size=2048,  
		chunk_overlap=128  
	)  
	documents = loader.load_and_split(text_spliter)  
	return documents

使用上面的函数,可以返回大段的文本片段。

2.4 构建chain

下面就是构建用于生成数据集的chain,包括Prompt、LLM、Outputparser三个部分内容分别如下:

2.4.1 Prompt

我们使用ChatPromptTemplate将上面的Prompt整合起来,代码如下:

QA_PAIRS_SYSTEM_PROMPT = "..."
QA_PAIRS_HUMAN_PROMPT = "..."
prompt = ChatPromptTemplate.from_messages([  
	("system", QA_PAIRS_SYSTEM_PROMPT),  
	("human", QA_PAIRS_HUMAN_PROMPT)  
])

在QA_PAIRS_HUMAN_PROMPT中我们添加了{text}占位,invoke时需要传入{“text”: “xxx”}。

2.4.2 LLM

大模型的选择非常多,一般的建议是选择长上下文、且能力比你要微调的模型强的模型。这里使用GPT-3.5-16k,代码如下:

llm = AzureChatOpenAI(  
	azure_endpoint=endpoint,  
	deployment_name=deployment_name,  
	openai_api_key=api_key,  
	openai_api_version="2024-02-01",  
)

2.4.3 OutputParser

最后是提取出结果,我们定义结果的Model:

class QaPair(BaseModel):  
	question: str = Field(description='问题内容')  
	answer: str = Field(description='问题的回答')  
	  
  
class QaPairs(BaseModel):  
	qas: List[QaPair] = Field(description='问答对列表')

parser = JsonOutputParser(pydantic_object=QaPairs)

最后将三者连接起来:

chain = prompt | llm | parser

我们把构建chain的操作写成create_chain函数:

def create_chain():  
	prompt = ChatPromptTemplate.from_messages([  
		("system", QA_PAIRS_SYSTEM_PROMPT),  
		("human", QA_PAIRS_HUMAN_PROMPT)  
	])  
	llm = AzureChatOpenAI(  
		azure_endpoint=endpoint,  
		deployment_name=deployment_name,  
		openai_api_key=api_key,  
		openai_api_version="2024-02-01",  
	)  
	parser = JsonOutputParser(pydantic_object=QaPairs)  
	chain = prompt | llm | parser  
	return chain

下面我们可以来试一试效果:

def main():  
	chain = create_chain()  
	documents = split_document('The.Little.Prince.txt')  
	with open(f'dataset.json', 'w', encoding='utf-8') as f:  
	datas = []  
	bar = tqdm(total=len(documents))  
	for idx, doc in enumerate(documents):  
		bar.update(idx + 1)  
		out = chain.invoke({'text': doc.page_content})  
		datas += out  
		f.write(json.dumps(datas, ensure_ascii=False))  
  
  
if __name__ == '__main__':  
	main()

我使用小王子的书作为测试,下面是生成的部分数据集:

[  	{  		"question": "作者小时候看了一本关于什么的书?",  		"answer": "描写原始森林壮观景象的书"  	},  	{  		"question": "这本书上说大蟒蛇通过什么方式来消化食物?",  		"answer": "通过长达六个月的睡眠来消化食物"  	}	...]

我们可以收集同一作者的大量书籍,使用上面的方式构建数据集。在构建过程中,每次执行后,结果可能不一样,因此可以通过多次构建的方式生成更多样本。

三、微调模型

在准备好数据集后,我们就可以进行微调了,我们可以使用已有的项目进行微调,比如LLaMA-Factory就是一个不错的选择。

具体的微调方式可以参考项目文档。

本文选择使用peft模块实现微调操作,其实其它项目也是使用这个项目来完成。先导入必要的模块:

from peft import LoraConfig, TaskType  
from transformers import Trainer  
from datasets import load_dataset  
from transformers import AutoModelForCausalLM, TrainingArguments, AutoTokenizer  
from peft import get_peft_model

3.1 加载模型和配置LoRA

首先需要加载模型以及配置微调模型,我们选择使用LoRA进行微调:

# 配置参数  
peft_config = LoraConfig(task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1)  
# 加载模型  
model = AutoModelForCausalLM.from_pretrained(  
	"microsoft/Phi-3-mini-4k-instruct",  
	trust_remote_code=True  
)  
tokenizer = AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-4k-instruct")  
model = get_peft_model(model, peft_config)  
model.print_trainable_parameters()

3.2 加载数据集

接下来加载我们创建的数据集:

def tokenize_function(example):  
	encoded = tokenizer(
		example['question'], 
		truncation=True, 
		padding='max_length', 
		max_length=128
	)  
	encoded["labels"] = tokenizer(
		example["answer"], 
		truncation=True, 
		padding="max_length", 
		max_length=128
	)["input_ids"]  
	return encoded

# 加载数据集  
data_files = {"train": "train.json", "validation": "train.json"}  
dataset = load_dataset('./dataset', data_files=data_files)  
tokenized_dataset = dataset.map(tokenize_function, batched=True)

3.3 配置训练参数并训练

接下来配置训练参数开始训练:

training_args = TrainingArguments(  
	output_dir="outputs",  
	learning_rate=1e-3,  
	per_device_train_batch_size=4,  
	per_device_eval_batch_size=4,  
	num_train_epochs=2,  
	weight_decay=0.01,  
	evaluation_strategy="epoch",  
	save_strategy="epoch",  
	load_best_model_at_end=True,  
)  
trainer = Trainer(  
	model=model,  
	args=training_args,  
	train_dataset=tokenized_dataset["train"],  
	eval_dataset=tokenized_dataset["validation"],  
	tokenizer=tokenizer,  
)  
  
trainer.train()  
model.save_pretrained("outputs")

我们可以根据硬件情况调整per_device_train_batch_size和per_device_eval_batch_size。现在只需要运行代码,等待片刻即可训练完成。

四、推理

接下来我们要做的就是推理了。LoRA是一个旁支网络,我们需要在原有的模型上,添加LoRA,添加方式如下:

model.load_adapter('outputs', adapter_name='lora01')  
model.set_adapter("lora01")

调用上面代码后,model的推理操作就是添加LoRA后的推理。推理的完整代码如下:

from transformers import AutoModelForCausalLM, AutoTokenizer  
  
model = AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct")  
tokenizer = AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-4k-instruct")  
  
model = model.to("cuda")  
model.load_adapter('outputs', adapter_name='lora01')  
model.set_adapter("lora01")  
model.eval()  
inputs = tokenizer("作者小时候看了一本关于什么的书?", return_tensors="pt")  
  
outputs = model.generate(input_ids=inputs["input_ids"].to("cuda"), max_new_tokens=50)  
print(tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)[0])

最后我们可以和使用正常的AutoModelForCausalLM模型一样使用微调后的模型。

👉AI大模型学习路线汇总👈
大模型学习路线图,整体分为7个大的阶段:(全套教程文末领取哈)
在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

👉大模型实战案例👈
光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

在这里插入图片描述

👉大模型视频和PDF合集👈
观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

在这里插入图片描述
在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Gerchberg-Saxton (GS) 和混合输入输出(Hybrid Input-Output, HIO)算法

文章目录 1. 简介2. 算法描述3. 混合输入输出&#xff08;Hybrid Input-Output, HIO&#xff09;算法3.1 HIO算法步骤3.2 HIO算法的优势3.3 算法描述 4. 算法实现与对比5. 总结参考文献 1. 简介 Gerchberg-Saxton (GS) 算法是一种常用于相位恢复和光学成像的迭代算法。该算法最…

【抽代复习笔记】18-置换练习题(2)及两个重要定理

最近一直忙于学校的事情&#xff0c;好久没更新了&#xff0c;实在抱歉。接下来几期大概也会更得慢一些&#xff0c;望见谅。 练习4&#xff1a;写出4次对称群S4中所有置换。 解&#xff1a;由上一篇笔记结尾的定理我们知道&#xff0c;4次对称群的阶&#xff08;也就是所含元…

JSON的序列化与反序列化以及VSCode执行Run Code 报错

JSON JSON: JavaScript Object Notation JS对象简谱 , 是一种轻量级的数据交换格式。 JSON格式 { "name":"金苹果", "info":"种苹果" } 一个对象&#xff1a;由一个大括号表示.括号中通过键值对来描述对象的属性 (可以理解为, 大…

2024年 电工杯 (A题)大学生数学建模挑战赛 | 园区微电网风光储协调优化配置 | 数学建模完整代码解析

DeepVisionary 每日深度学习前沿科技推送&顶会论文&数学建模与科技信息前沿资讯分享&#xff0c;与你一起了解前沿科技知识&#xff01; 本次DeepVisionary带来的是电工杯的详细解读&#xff1a; 完整内容可以在文章末尾全文免费领取&阅读&#xff01; 问题重述…

MVS net笔记和理解

文章目录 传统的方法有什么缺陷吗&#xff1f;MVSnet深度的预估 传统的方法有什么缺陷吗&#xff1f; 传统的mvs算法它对图像的光照要求相对较高&#xff0c;但是在实际中要保证照片的光照效果很好是很难的。所以传统算法对镜面反射&#xff0c;白墙这种的重建效果就比较差。 …

【Python自动化测试】:Unittest单元测试与HTMLTestRunner自动生成测试用例的好帮手

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 &#x1f525;前言&#x1f680;unittest编写测试用例&#x1f680;unittest测…

【408精华知识】Cache类题目解题套路大揭秘

有关Cache的题目&#xff0c;需要理解Cache的工作原理&#xff0c;也即给出一个地址&#xff0c;要知道如何在Cache中寻找或者如何将其从主存中复制入Cache&#xff0c;同时理解Cache中具体是如何存储的&#xff0c;包含三种存储方式&#xff0c;分别是直接映射、全相联映射、组…

clion/pycharm 安装中文

楼主版本 2024.1 mac 操作系统&#xff0c;理论上不同版本和不同操作系统操作应该大同小异 首先找到插件的位置 方式一 1、进入工程&#xff0c;右上角找到设置 2、找到插件&#xff08;欢迎界面也能找到这个&#xff09; 方式二 在欢迎界面找到插件 最后 插件商店搜索 l…

矩阵乘法不满足交换律-反证法

假定有2个矩阵A和B A*B 不等于 B*A 手写证明&#xff1a; A*B为 B*A为 由此可以看出&#xff0c;矩阵乘法不满足交换律&#xff01;&#xff01;

Python | Leetcode Python题解之第100题相同的树

题目&#xff1a; 题解&#xff1a; class Solution:def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:if not p and not q:return Trueif not p or not q:return Falsequeue1 collections.deque([p])queue2 collections.deque([q])while queue1 and queue2:node…

centos7和centos8安装mysql5.6 5.7 8.0

https://dev.mysql.com/downloads/repo/yum/ 注意构造下http://repo.mysql.com/mysql-community-release-el*-*.noarch.rpm 【以centos7为例】 安装mysql5.6 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm rpm -ivh mysql-community-release-el7-5…

初识Qt:从Hello world到对象树的深度解析

Qt中的对象树深度解析 Hello world1.图形化界面创建命令行式创建在栈上创建在堆上创建为什么传文本需要QString&#xff0c;std::string不行吗&#xff1f;那为什么要传入this指针&#xff1f;为什么new后不用显示调用delete函数呢&#xff0c;不会造成内存泄漏问题吗&#xff…

国产操作系统上使用SQLynx连接数据库 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上使用SQLynx连接数据库 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天我们将探讨如何在国产操作系统上使用SQLynx。这是一款功能强大的数据库管理工具&#xff0c;可以帮助用户高效地管理和操作数据库。本文将详细介绍…

2024 电工杯高校数学建模竞赛(A题)数学建模完整思路+完整代码全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024电工杯数学建模竞赛&#xff08;B题&#xff09;的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有详尽的建模过程和解…

Docker搭建mysql性能测试环境

OpenEuler使用Docker搭建mysql性能测试环境 一、安装Docker二、docker安装mysql三、测试mysql连接 一、安装Docker 建立源文件vim /etc/yum.repos.d/docker-ce.repo增加内容[docker-ce-stable] nameDocker CE Stable - $basearch baseurlhttps://repo.huaweicloud.com/docker…

NLP(18)--大模型发展(2)

前言 仅记录学习过程&#xff0c;有问题欢迎讨论 Transformer结构&#xff1a; LLM的结构变化&#xff1a; Muti-head 共享&#xff1a; Q继续切割为muti-head,但是K,V少切&#xff0c;比如切为2个&#xff0c;然后复制到n个muti-head减少参数量&#xff0c;加速训练 atte…

STM32-串口通信波特率计算以及寄存器的配置详解

您好&#xff0c;我们一些喜欢嵌入式的朋友一起建立的一个技术交流平台&#xff0c;本着大家一起互相学习的心态而建立&#xff0c;不太成熟&#xff0c;希望志同道合的朋友一起来&#xff0c;抱歉打扰您了QQ群372991598 串口通信基本原理 处理器与外部设备通信的两种方式 并行…

flume使用实例

1、监听端口a1.sources.r1.type netcat 配置文件nc-flume-console.conf # Name the components on this agent a1 表示jvm进程名 a1.sources r1 a1.sinks k1 a1.channels c1 # Describe/configure the source a1.sources.r1.type netcat a1.sources.r1.bind node…

《王者荣耀》4月狂揽2.34亿美元 单日流水1亿美元 全球销量第二

易采游戏网5月24日消息&#xff0c;在刚刚过去的四月&#xff0c;全球手游市场迎来了一场收益的盛宴&#xff0c;其中《王者荣耀》以其惊人的吸金能力&#xff0c;以2.34亿美元的月收入在全球手游排行榜上位列第二。4月5日&#xff0c;这款由腾讯游戏开发的多人在线战斗竞技游戏…

软考考前前怎么复习?

有一些经验&#xff0c;可以和大家分享一下。 软考的考试内容 软考包含许多科目&#xff0c;共分为五大类&#xff0c;27个专业。 软考的等级不同&#xff0c;考试内容也有所不同。初级和中级考试只包括两门科目&#xff0c;而高级则需要考三门科目。每门科目满分75分&#x…