1 引言
1.1 大模型微调技术简介
模型微调也被称为指令微调(Instruction Tuning)或者有监督微调(Supervised Fine-tuning, SFT),该方法利用成对的任务输入与预期输出数据,训练模型学会以问答的形式解答问题,从而解锁其任务解决潜能。经过指令微调后,大语言模型能够展现出较强的指令遵循能力,可以通过零样本学习的方式解决多种下游任务。
然而,值得注意的是,指令微调并非无中生有地传授新知,而是更多地扮演着催化剂的角色,激活模型内在的潜在能力,而非单纯地灌输信息。
相较于预训练所需的海量数据,指令微调所需数据量显著减少,从几十万到上百万条不等的数据,均可有效激发模型的通用任务解决能力,甚至有研究表明,少量高质量的指令数据(数千至数万条)亦能实现令人满意的微调效果。这不仅降低了对计算资源的依赖,也提升了微调的灵活性与效率。
1.2 轻量化微调技术简介
然而,由于大模型的参数量巨大, 进行全量参数微调需要消耗非常多的算力。为了解决这一问题,研究者提出了参数高效微调(Parameter-efficient Fine-tuning),也称为轻量化微调 (Lightweight Fine-tuning),这些方法通过训练极少的模型参数,同时保证微调后的模型表现可以与全量微调相媲美。
常用的轻量化微调技术有LoRA、Adapter 和 Prompt Tuning。
1.3 LoRA技术简介
LoRA 是通过低秩矩阵分解,在原始矩阵的基础上增加一个旁路矩阵,然后只更新旁路矩阵的参数。
参考资料
2 源2.0-2B 微调实战
本节将进行 源2.0-2B 微调实战,使用一个简历命名实体识别的数据集进行微调,进而开发一个AI简历助手,进而可以批量地自动识别并提取简历中的关键信息(如姓名、教育背景、工作经历等),提升简历处理的效率。
具体来说,输入一个摘录自某简历的句子,模型需要识别出所有的命名实体。实体的类别包括:姓名(NAME)、国籍(CONT)、种族(RACE)、职位(TITLE)、教育背景(EDU)、专业(PRO)、组织名(ORG)、地名(LOC)。原始的数据来自于BAAI/COIG-PC-Lite。
2.0 PAI实例创建
在实战之前,需要开通阿里云PAI-DSW试用,并在魔搭社区创建PAI实例,创建流程与速通手册一致~
如果忘记如何创建的,可以参考下面的内容复习一下~
Step0:开通阿里云PAI-DSW试用
Step1:在魔搭社区创建PAI实例!
2.1 环境准备
进入实例,点击终端。
运行下面代码,下载文件,并将Task 4:源大模型微调实战
中内容拷贝到当前目录。
git lfs install
git clone https://www.modelscope.cn/datasets/Datawhale/AICamp_yuan_baseline.git
cp AICamp_yuan_baseline/Task\ 4:源大模型微调实战/* .
双击打开Task 4:源大模型微调实战.ipynb
,运行所有单元格。
通过下面的命令,可以看到ModelScope已经提供了所需要的大部分依赖,如 torch
,transformers
等。
# 查看已安装依赖
pip list
但是为了进行Demo搭建,还需要运行下面的单元格,在环境中安装streamlit
。
# 安装 streamlit
pip install streamlit==1.24.0
安装成功后,环境就准备好了。
2.2 模型下载
Yuan2-2B-Mars支持通过多个平台进行下载,这里直接选择通过魔搭进行下载。
模型在魔搭平台的地址为 IEITYuan/Yuan2-2B-Mars-hf。
单元格 2.1 模型下载
会执行模型下载。
这里使用的是 modelscope 中的 snapshot_download 函数,第一个参数为模型名称 IEITYuan/Yuan2-2B-Mars-hf
,第二个参数 cache_dir
为模型保存路径,这里.
表示当前路径。
模型大小约为4.1G,由于是从魔搭直接进行下载,速度会非常快。
下载完成后,会在当前目录增加一个名为 IEITYuan
的文件夹,其中 Yuan2-2B-Mars-hf
里面保存着下载好的源大模型。
2.3 数据处理
运行 2.3 数据处理
下面的单元格。
使用 pandas
进行数据读取,然后转成 Dataset
格式:
然后需要加载 tokenizer:
为了完成模型训练,需要完成数据处理,这里定义了一个数据处理函数 process_func
:
def process_func(example):
MAX_LENGTH = 384 # Llama分词器会将一个中文字切分为多个token,因此需要放开一些最大长度,保证数据的完整性
instruction = tokenizer(f"{example['input']}<sep>")
response = tokenizer(f"{example['output']}<eod>")
input_ids = instruction["input_ids"] + response["input_ids"]
attention_mask = [1] * len(input_ids)
labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] # instruction 不计算loss
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
}
具体来说,需要使用tokenizer将文本转成id,同时将 input
和 output
拼接,组成 input_ids
和 attention_mask
。
这里我们可以看到,源大模型需要在 input
后面添加一个特殊的token <sep>
, 在 output
后面添加一个特殊的token <eod>
。
同时,为了防止数据超长,还有做一个截断处理。
然后使用 map
函数对整个数据集进行预处理:
处理完成后,使用tokenizer的decode函数,将id转回文本,进行最后的检查:
2.4 模型训练
首先需要加载源大模型参数,然后打印模型结构:
可以看到,源大模型中包含24层 YuanDecoderLayer
,每层中包含 self_attn
、mlp
和 layernorm
。
另外为了进行模型使用训练,需要先执行 model.enable_input_require_grads()
。
最后,打印下模型的数据类型,可以看到是 torch.bfloat16
。
在本节中,使用Lora进行轻量化微调,首先需要配置 LoraConfig
:
然后构建一个 PeftModel
:
通过 model.print_trainable_parameters()
,可看到需要训练的参数在所有参数中的占比:
然后,设置训练参数 TrainingArguments
:
同时初始化一个 Trainer
:
最后运行 trainer.train()
执行模型训练。
在训练过程中,会打印模型训练的loss,可以通过loss的降低情况,检查模型是否收敛:
模型训练完成后,会打印训练相关的信息:
同时,会看到左侧 output
文件夹下出现了3个文件夹,每个文件夹下保存着每个epoch训完的模型。
2.5 效果验证
完成模型训练后,通过定义一个生成函数 generate()
,来进行效果验证:
同时定义好输入的prompt template,这个要和训练保持一致。
最后,输入样例进行测试:
可以看到,通过模型微调,模型已经具备了相应的能力
此时,查看机器状态,如下图所示:
可以看到约占用 17G
显存。
显存的占用多少和需要训练的模型参数、batch size等相关,大家可以尝试不同的训练配置。
训练完成后,尝试使用训练好的模型,搭建Demo。
首先,点击重启内核,清空显存。
(因为Demo也需要占用显存,不先清空会因为显存不足报错。)
然后,在终端输入下面的命令,启动streamlit
服务:
streamlit run Task\ 4\ 案例:AI简历助手.py --server.address 127.0.0.1 --server.port 6006
然后点击链接,跳转到浏览器,进入Demo:
输入文本:张三,汉族,金融学硕士。
可以看到,Demo完成了信息抽取,并进行了结构化展示。
这样完成了一个AI简历助手
的构建。
2.6 关闭PAI实例!!!!
本学习笔记的参考原文链接如下:
Datawhalehttps://linklearner.com/activity/14/11/38
声明:
本学习笔记为此笔记发布者使用,以便完成Datawhale AI 夏令营第四期大模型应用开发Task04打卡任务,同时记录自己的学习过程。该笔记在原文的基础上进行删改,对个别部分用黑体或者其他字体着重强调以便及时记忆理解。本笔记并不做任何以盈利为目的的用途,仅供个人学习使用,若有侵权,请第一时间告知本人,侵删。