【Instruction Tuning】ChatGLM 微调实战(附源码)

在之前的文章中,我们已经讲过了 ChatGPT 的三个主要流程:

  1. SFT:通过 Instruction Tuning 来微调一个监督学习模型
  2. Reward Model:通过排序序列来训练一个打分模型
  3. Reinforcement Learning:通过强化学习来进一步优化模型。

何枝:【RLHF】想训练ChatGPT?得先弄明白Reward Model怎么训(附源码)409 赞同 · 37 评论文章正在上传…重新上传取消

前两篇文章主要对 RM 和 RL 两部分进行了讲解和实验,

但无数的经验向我们证明 —— 拥有一个好的 SFT 的模型对后两步的训练至关重要。

由于在 RL 训练过程中会加入与 SFT 模型的相似度(KL-Divergence)惩罚,

这意味着 RL 模型的上限很大程度上取决于 SFT 模型

为此,我们今天来重点讲一讲如何通过 ChatGLM 来微调一个读懂我们指令的模型。

1. GLM Backbone

Paper Link:  https://arxiv.org/pdf/2103.10360.pdf

在讲微调代码之前,我们先来看看 GLM 的基本架构。

我们都知道,目前主流的两种 Backbone:一类是以 BERT 为首的 Encoder 架构(双向注意力),另一种是以 GPT 为首的 Decoder 架构(单向注意力)。

这两种架构各有各的好处,一个更适合做理解,一个更适合做生成

那么如何将这两种模型做合并,集二者优势于一身,是近年来人们一直在尝试的努力(如:T5、BART等)。

不同于 Encoder-Decoder 的堆叠,GLM 通过一种巧妙的 2D Position Embedding,并通过 Attention MASK 来使得模型在训练时 「既能在部分内容上存在双向注意力」「又能在生成任务中保持单向注意力」。

以下是 GLM 示意图:

GLM Position Embedding 示意图

  1. 首先,从原始句子中 Random Sample 出来一些 Span 用于并 [MASK] 掉(该思想源自 BERT),注意:这里是以 Span 维度进行 MASK 的。
  2. 将原句子分为两组,PART A 是原句子,只不过句子中被挑选出来的 Span 用 [MASK] 符号代替;PART B 是挑选出来的 Span 集合
  3. 将挑选出来的 MASK Span 集合(PART B)拼接在原句子(PART A)后面,注意:这里是先对 PART B 做乱序后,再拼接到句子后面(目的是为了训练 Position Embedding)。
  4. 设计 2D Position:这是我认为比较有趣的设定,位置编码分成了两组。一组用于表征「全局位置」,被挑选出的「MASK SPAN」中的所有 token 的位置索引都等于整个 Span 在原句子中的位置(例如:x5, x6 的索引都是 5);而另一组用来专门表征 MASK Span 内部 token 的相对位置编码(例如:x5, x6 的索引这两个 token 在 Mask Span 中的相对位置)。
  5. 通过设置 Attention MASK,使得 PART A 中的内容是双向可见的,且 PART B 中所有 token 也可以看到 Part A 中的内容;而对于 PART B 中的内容保持单向可见。
  6. 通过对 Part B 中的内容做「生成任务」来进行模型迭代。

以上便是我认为 GLM 中最关键的几个点。

2. Finetune GLM

2.1 数据集准备

我们以信息抽取任务为例,将一个信息抽取数据集(DuIE)添加上 Instruction,以此来教会 ChatGLM 根据我们的指令来完成抽取任务。

我们仿照 Alpaca 数据集,将数据结构设为以下形式:

{"instruction": "你现在是一个很厉害的阅读理解器,找到句子中的三元组信息并输出成json给我。","input": "九玄珠是在纵横中文网连载的一部小说,作者是龙马。","target": "```json\n[{\"predicate\": \"连载网站\", \"object_type\": \"网站\", \"subject_type\": \"网络小说\", \"object\": \"纵横中文网\", \"subject\": \"九玄珠\"}, {\"predicate\": \"作者\", \"object_type\": \"人物\", \"subject_type\": \"图书作品\", \"object\": \"龙马\", \"subject\": \"九玄珠\"}]\n```"
}

进一步的,我们将 instruction 和 input 字段合并,得到如下数据:

{"context": "Instruction: 你现在是一个很厉害的阅读理解器,找到句子中的三元组信息并输出成json给我:。\nInput: 九玄珠是在纵横中文网连载的一部小说,作者是龙马。\nAnswer: ", "target": "```json\n[{\"predicate\": \"连载网站\", \"object_type\": \"网站\", \"subject_type\": \"网络小说\", \"object\": \"纵横中文网\", \"subject\": \"九玄珠\"}, {\"predicate\": \"作者\", \"object_type\": \"人物\", \"subject_type\": \"图书作品\", \"object\": \"龙马\", \"subject\": \"九玄珠\"}]\n```"
}

其中,

  • Instruction:存放我们希望模型做的任务的指令
  • Input:存放我们喂给模型的任务数据
  • Target:存放模型的输出标签

2.2 Label 构建

将数据集解析为训练 label 的代码如下:

def convert_example(examples: dict, tokenizer,max_source_seq_len: int,max_target_seq_len: int,):"""将样本数据转换为Ptuning模型接收的输入数据。Args:examples (dict): 训练数据样本, e.g. -> {"text": ['{"context": "年基准利率4.35%。从实际看...", "target": "2017年银行贷款基准利率"}',...]}max_source_seq_len (int): prompt最大长度max_target_seq_len (int): 答案最大长度Returns:dict (str: np.array) -> tokenized_output = {'input_ids': [[1525, 10, ...], [758, 2345, ...]], 'labels': [[822, 10, ...], [125, 58...]]}"""tokenized_output = {'input_ids': [],'labels': []}max_seq_length = max_source_seq_len + max_target_seq_lenfor example in examples['text']:try:example = json.loads(example)context = example["context"]target = example["target"]prompts_ids = tokenizer.encode(text=context,add_special_tokens=False)target_ids = tokenizer.encode(text=target,add_special_tokens=False)                    if len(prompts_ids) >= max_source_seq_len:                                          # source 需要留一个 [gMASK] token 在结尾prompts_ids = prompts_ids[:max_source_seq_len - 1]if len(target_ids) >= max_target_seq_len - 1:                                       # target 需要留一个 <sop> 在开头和一个 <eop> token 在结尾target_ids = target_ids[:max_target_seq_len - 2]input_ids = tokenizer.build_inputs_with_special_tokens(prompts_ids, target_ids)     # source_ids + [gMASK] + <sop> + target_ids + <eop>context_length = input_ids.index(tokenizer.bos_token_id)                            # bos 在 target 的第一位mask_position = context_length - 1                                                  # [gMASK] 在 source 的最后一位labels = [-100] * context_length + input_ids[mask_position + 1:]                    # 从 bos 开始到后面所有的 target 到 eos 都为 labelpad_len = max_seq_length - len(input_ids)input_ids = input_ids + [tokenizer.pad_token_id] * pad_lenlabels = labels + [-100] * pad_lentokenized_output['input_ids'].append(input_ids)tokenized_output['labels'].append(labels)except:print(f'"{example}" -> {traceback.format_exc()}')continuefor k, v in tokenized_output.items():tokenized_output[k] = np.array(v)return tokenized_output

其中,

  • max_source_seq_len 用于设定模型接收的最大输入长度
  • max_target_seq_len 用于设定模型输出的最大长度

2.3 模型训练

ChatGLM 的微调存在 LoRA Finetune 和 P-Tuning 两种微调方式。

P-Tuning V.S. LoRA

这两种方式都可以使得 ChatGLM-6B 的模型能在 32G 的 V100 上进行微调训练。

通过以下两种参数配置即可选择使用 P-Tuning 还是 LoRA:

# LoRA Finetune
python train.py \--train_path data/mixed_train_dataset.jsonl \--dev_path data/mixed_dev_dataset.jsonl \--use_lora True \--lora_rank 8 \--batch_size 1 \--num_train_epochs 2 \--save_freq 1000 \--learning_rate 3e-5 \--logging_steps 100 \--max_source_seq_len 400 \--max_target_seq_len 300 \--save_dir checkpoints/finetune \--img_log_dir "log/fintune_log" \--img_log_name "ChatGLM Fine-Tune" \--device cuda:0# P-Tuning
python train.py \--train_path data/mixed_train_dataset.jsonl \--dev_path data/mixed_dev_dataset.jsonl \--use_ptuning True \--pre_seq_len 128 \--batch_size 1 \--num_train_epochs 2 \--save_freq 200 \--learning_rate 2e-4 \--logging_steps 100 \--max_source_seq_len 400 \--max_target_seq_len 300 \--save_dir checkpoints/ptuning \--img_log_dir "log/fintune_log" \--img_log_name "ChatGLM P-Tuning" \--device cuda:0

其中,pre_seq_len 是指在每个层前面添加多少个可学习的前缀 token,该值设置的越大显存占用也会越大。

在我们的实验下,两种方式的效果差异不大:

P-Tuning v.s. LoRA Finetune

模型最终的训练结果如下:

模型训练结果

好啦,以上就是 ChatGLM 的全部内容,感谢观看~

完整源码在这里:

ChatGLM Finetune Code​github.com/HarderThenHarder/transformers_tasks/blo

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王者荣耀 业务分析

王者荣耀 业务分析 王者荣耀是一款组队竞技游戏。王者荣耀有三个基本玩家财富字段:金币、钻石、点券。 英雄的获取方式有:限免的英雄可用金币或钻石购买&#xff0c;有一些非限免的可用点券购买&#xff0c;一些英雄可通过特定的游戏活动获得。并结合了游戏奖励机制。 它的主要…

王者荣耀游戏时间计算机制,王者荣耀:荣耀战力计算机制解析,如何提高到金牌乃至国服...

原标题&#xff1a;王者荣耀&#xff1a;荣耀战力计算机制解析&#xff0c;如何提高到金牌乃至国服 每个英雄都对应有一个荣耀战力&#xff0c;战力分越高一定程度上代表着你对该英雄的理解越好&#xff0c;当分数高到一定程度上时&#xff0c;会获得荣耀称号&#xff0c;由低到…

c语言王者荣耀制作,易语言制作王者荣耀刷金币脚本的代码

打开黑夜模拟器&#xff0c;按下F10&#xff0c;王者荣耀进入挑战-魔女回忆&#xff0c;开始即可。 王者荣耀刷金币脚本 此功能需要加载精易模块5.6 .版本 2 .支持库 shellEx .支持库 EThread .支持库 eAPI .程序集 窗口程序集_启动窗口 .程序集变量 热键F10, 整数型 .程序集变…

王者荣耀各服务器位置,盘点王者荣耀各位置国服战力排名,辅助榜表示只有富婆才玩的懂...

原标题&#xff1a;盘点王者荣耀各位置国服战力排名&#xff0c;辅助榜表示只有富婆才玩的懂 七月份也是终于过去了&#xff0c;而国服最新的战力榜也是新鲜出炉&#xff0c;当然小伙伴们可能觉得这些跟自己没什么关系&#xff0c;正所谓内行看门道&#xff0c;外行看热闹。今天…

王者营地登录服务器维护,王者营地怎么查看登录记录

王者营地怎么升级到5级 王者营地怎么升级到5级?具体的升级方法是什么呢?很多小伙伴还不是很了解,那么接下来,就跟随玩游戏网的小编一起继续往下看,感兴趣的小伙伴一定不要错过哦!信誉快速升到5级方法介绍:1、多参与游戏,这个是基础,不然的话信誉积分肯定是无法增加的;…

王者荣耀服务器什么时候维护好19赛季,王者荣耀:S19新赛季开启时间确定,国服战力排名会提前锁定...

S19新赛季的开启时间已经确定&#xff0c;正是之前无意间透露出来的3月31日&#xff0c;正好是周二&#xff0c;符合惯例更新的时间点&#xff0c;但并不是以往大版本更新的周四&#xff0c;为什么会出现这样的情况呢&#xff1f;或许是因为从这一次的苹果的审核比较快吧。 在S…

王者荣耀前端模仿

作品初衷 因为想着要写答辩&#xff0c;网页这东西展现的会更直观一点&#xff0c;刚好也复习一下自己基础我牢固的前端知识&#xff0c;也想着提升一下自己前端网页排版能力和逻辑能力 作品简介 编辑器&#xff1a;sublime 语言&#xff1a;htmlcssjs 代码量&#xff1a;…

鸿蒙os版王者荣耀,王者荣耀鸿蒙版

王者荣耀鸿蒙版下载&#xff0c;快猴网为大家带来的王者荣耀鸿蒙版是为了适配华为的鸿蒙系统而特别设立的版本&#xff0c;玩家可以体验远超一般系统的流畅度&#xff0c;让你的手速能轻松跟上你的意识&#xff0c;享受成为王者荣耀鸿蒙版最强王者的快乐吧! 王者荣耀鸿蒙版游戏…

王者荣耀技术指南

者荣耀技术指南&#xff1a; 本人是在2018年9月和10月都获得国服达摩称号&#xff0c;其实就打了一个月国服达摩&#xff0c;由于9月底正好赛季更新&#xff0c;我月底就打了一把10月份国服达摩了。 先讲一下达摩基本连招&#xff1a; 1闪现a3上墙2破甲3第二段贴近敌人&#xf…

国服最强王者之最良心王者

国服最强王者之最良心王者 何为lol最强王者?想成为最强王者&#xff0c;你必须是所在服务器的前50名&#xff0c;这是绝对实力的体现。并且还会面临着紧随其后的玩家的挑战&#xff0c;若有第51个人挑战”最强王者“成功&#xff0c;则原属于”最强王者“最后一名次的玩家或战…

王者荣耀服务器维护S19,王者荣耀:S19官宣31日更新,国服玩家集体声讨天美:1个月白打了...

前言&#xff1a;就在2020年3月28日深夜&#xff0c;王者荣耀官方官宣了一则重大消息&#xff0c;那就是S19赛季即将在2020年3月31日更新。也就是说今年新赛季的到来真是让人猝不及防。但是新赛季的到来&#xff0c;也意味着众多小伙伴们又有一波福利可以领了。不过几家欢喜几家…

王者荣耀各服务器位置,王者荣耀全国排行功能新上线,位置战力系统介绍[多图]...

王者荣耀全国排行功能新上线。在最近的体验服当中王者荣耀官方又尝试进行了多项改动&#xff0c;在原本的省级和国服最强之间增添了全国排名这一级别的荣耀称号&#xff0c;新添加了根据分路了来判断的位置战力和位置段位系统&#xff0c;同时还改版了国服最强的展示页面。 1.荣…

王者荣耀微信哪个服务器怎么选,王者荣耀:国服战力对比!手Q和微信哪个大区的战力更胜一筹?...

原标题&#xff1a;王者荣耀&#xff1a;国服战力对比&#xff01;手Q和微信哪个大区的战力更胜一筹&#xff1f; 每个玩家都希望自己能够获得国服称号&#xff0c;想要获得的难度却是非常大的&#xff0c;但这也不妨玩家们对国服最高战力的讨论。 在王者荣耀里将国服战力分成了…

如何获取宝宝取名软件注册码

如何获取宝宝取名软件注册码 宝宝的名字不仅要伴随宝宝的一生&#xff0c;还具有改变命运的重大意义。所以现在家长都十分重视给孩子起名&#xff0c;现在很多父母给孩子取名上网搜索、翻阅字典、参考各种资料&#xff0c;取得名字很好听&#xff0c;孩子不一定能用。主要是怕名…

宝宝智能起名,免费起名实现方案,带源码

宝宝智能起名&#xff0c;免费起名实现方案&#xff01;&#xff08;带源码&#xff09; 作为一个coder&#xff0c;没有什么问题是代码解决不了的&#xff0c;哈哈哈&#xff01;调皮一下&#xff01; 一个好的名字可以潜移默化的改变人的一生&#xff0c;很多人从来没有考虑到…

宝宝起名工具类

宝宝起名太麻烦&#xff0c;使用如下工具类选择大于96分的名字 public static void main(String[] args) {Integer pages 50;for (int i 1; i < pages; i) {//楚辞起名String chuCiUrl "https://www.mamahaoyun.com/qiming/xingdeng/nvhai/shulong/chuci/?page&qu…

好听的名字 - 收藏给宝宝起名字用

1、伟诚&#xff1a;伟大;真诚。 2、熙茂&#xff1a;形容盛美。 3、怡悦&#xff1a;喜悦;高兴。 4、鹤轩&#xff1a;鹤&#xff1a;闲云野鹤。 5、博超&#xff1a;博&#xff1a;博大;超&#xff1a;超越。 6、德懋&#xff1a;在德行上勉力。 7、淳雅&#xff1a;淳…

【直播预告】ChatGPT下技术开发的模式创新及应用实践

ChatGPT横空出世&#xff0c;标志着人工智能在自然语言处理和深度学习领域取得了跨越性的发展&#xff0c;开创了人机对话模型新篇章。不仅满足了常规的搜索引擎、问答机器人答复基础问题的功能&#xff0c;而且还具备了编故事、写情诗、敲代码、写作业等创作功能。从大量的语料…

程序员“起名”头痛根治指南

软件开发中一个著名的反直觉就是“起名儿”&#xff0c;这个看上去很平凡的任务实际上很有难度。身边统计学显示&#xff0c;越是有经验的程序员&#xff0c;越为起名头痛&#xff0c;给小孩起名儿都没这么费劲。 命名的困难可能来自于以下几个方面&#xff1a; 信息压缩&#…

微软必应(Bing)打不开解决方案(2021.12.16)

2021.12.19 0:10更新&#xff1a;现在Bing已修复&#xff0c;可直接通过https://cn.bing.com/访问~ 问题描述 2021.12.16开始必应就打不开了。。 解决方案 1. 打开主页 将原先网址https://cn.bing.com/更换为https://www4.bing.com/ 2. 更改浏览器默认主页 以Chrome为例&a…