1. 数据处理流程
在AI领域有句名言:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。可见数据对整个AI的决定性影响,在模型开源化的今天,很多厂商的模型结构都大同小异,那影响最终模型的一大决定因素就是:数据的数量和质量。
1.1 数据选择和采集
微调数据的选择应该基于目标应用场景:
1)领域相关性:选择与预期应用场景密切相关的文本数据。例如,如果目标是法律助理,应选择法律文档和案例。本实验目的是提升模型的推理和识别逻辑陷阱的能力,因此选择弱智吧的数据。
2)质量高:这里指的是问题和回答都要是高质量的,通常需要语法正确,信息准确,风格一致。具体来说,好的回复应该遵循“无害(Harmless)、诚实(Honest)、有帮助(Helpful)”的三H原则。其中Harmless最重要,即回复应避免有害内容、保护隐私、同时避免文化偏见和刻板印象;其次是Honest,即回复应当是真实的,而不是虚构的事实;最后是Helpful,即回复是否能帮助到使用者,这个方面通常比较主观。
3)多样性:确保数据覆盖所有相关子话题,以促进模型的泛化能力。
1.2 数据预处理
为了提高模型的效率和效果,数据预处理是必不可少的步骤:
1)清洗:去除无关的内容,如广告、HTML标签、无意义的填充词等。
2)标准化:统一词汇的格式,比如时间、日期、货币单位等。
3)分词:根据目标模型的需求进行适当的分词处理。
去噪声:消除文本中的错误,如拼写错误、语法错误等
1.3 数据标注
由于微调数据规模不大,因此可以通过标注的方式来进行构造,这里有两种不同的标注方法:
1)人工标注:由人工专家进行标注,确保标注的准确性和一致性。采用人工的方式成本比较高,但质量相对较好,尤其在涉及一些专业领域的时候,领域专家能够更好的理解问题并给出回复。
2)自动标注:使用已有的模型进行初步标注,然后由人工校验和修正。可以采用GPT4来生成回复,再由人工来判断回答的好坏,并进行修正。
1.4 数据增强
数据增强可以提高模型的鲁棒性和泛化能力,常见方法有:
1) 文本重述:用不同的方式表达同一意思,增加文本的多样性。
2) 翻译循环:将文本翻译成一种语言,然后再翻译回原语言,通常用于生成新的文本表达。
3) 合成数据生成:使用规则或模型生成新的训练样本。
1.5 数据划分
通常分为训练集、验证集和测试集。合理划分数据,确保模型能在未见过的数据上进行有效的泛化测试。
2. 模型微调
类似于【InternLM】XTuner微调LLM的流程,在internlm2_1.8b
模型的基础上,利用弱智吧数据进行微调训练。
2.1 数据构造
2.1.1 数据的获取
为什么要采用弱智吧的数据进行构造?论文COIG-CQIA: Quality is All You Need for Chinese Instruction Fine-tuning
的试验结果让人大跌眼镜:采用弱智吧在内的数据进行微调,模型在8项测试第一,远超知乎豆瓣小红书等传统意义上的优质数据源,其原因可能是弱智吧的数据像脑筋急转弯,增加了指令多样性,所以提升了模型最终性能,具体分析可参考:https://zhuanlan.zhihu.com/p/690701799
访问 OpenDatalab ,利用cli直接进行弱智吧数据集的下载:
pip install openxlab #安装
pip install -U openxlab #版本升级
openxlab login #进行登录,输入对应的AK/SK
openxlab dataset ls --dataset-repo OpenDataLab/COIG-CQIA #数据集文件列表查看, 发现弱智吧数据的目录为/ruozhiba/ruozhiba_ruozhiba.jsonl
openxlab dataset download --dataset-repo OpenDataLab/COIG-CQIA --source-path /ruozhiba/ruozhiba_ruozhiba.jsonl --target-path /root/ft-ruozhiba/data #数据集文件下载
2.1.2 数据格式转换&划分
参考官方教程将数据转为 XTuner 的数据格式和划分训练集和测试集部分的论述,利用ChatGPT等AI工具,通过自然文本描述生成对应的python代码,最终得到的数据集目录如下:
2.2 微调
调用xtuner
命令进行微调:
xtuner train /root/ft-ruozhiba/config/internlm2_1_8b_qlora_ruozhiba_e3.py --work-dir /root/ft-ruozhiba/train --deepspeed deepspeed_zero2
注意:这里有个隐形的坑,若前面下载数据库阶段在同一个python环境下安装了openxlab
,那requests
库的版本是不符合xtuner要求的,将无法正常进行微调。此外还缺少axiver
库,具体提示如下图:
对这两个冲突的库进行重新安装:
pip install requests==2.31.1
pip install arxiv
2.3 测试数据效果
选择测试数据集中的三条样本作为效果验证:
可见,在整个微调,模型的效果会有一些波动,整体而言微调后的模型相较于原始模型有所提升,但在问题1和问题2上的回答也很牵强。
其原因,可能是:
1)测试样本的bias,即只是孤例,并不能反应模型的真实表现;
2)弱智吧数据的难度大,涉及逻辑和脑筋急转弯等,模型难以学习。
2.3 部署和验证
利用xtuner convert
命令将上面得到的 PTH 模型转换为 HuggingFace 模型,利用xtuner convert
命令将 HuggingFace adapter 合并到大语言模型,最后利用xtuner chat
命令在终端与合并后的模型进行对话。采用和与合并后的模型对话部分一样的两个问题进行测试:
问题1: 浓硫酸里有2%的水,那我喝50杯硫酸是不是相当于喝了杯纯水?
回答1:不,喝50杯浓硫酸实际上喝的是浓硫酸,而不是水。浓硫酸是一种高度腐蚀性的强酸,其密度比水大,因此会浮在水面上。如果你将浓硫酸倒入水中,浓硫酸会溶解在水中,形成硫酸溶液。然而,喝浓硫酸是非常危险的,因为它会迅速导致烧伤和失明。因此,喝浓硫酸是不安全的,应该避免。
问题2:我用水兑水,得到的是稀水还是浓水
回答2:这个问题看似简单,但实际上包含了文字游戏和思维陷阱的元素。在这里,我们需要深入思考“兑”字的含义。首先,让我们来分析这个问题。“兑”在中文中通常表示“混合、混合液体或水”。在这个问题中,“兑”字的使用暗示了一种将一种液体与另一种液体混合的情况。接下来,我们来看看“稀水”和“浓水”这两个词。“稀水”通常是指一种液体中水分的含量较少,通常用于描述液体中水分的含量低于某个特定值。而“浓水”则是指一种液体中水分的含量较高,通常用于描述液体中水分的含量高于某个特定值。现在,让我们来分析这个问题中的情境。问题中提到,通过“兑”来得到“稀水”或“浓水”。这里有一个关键的信息点是,“兑”的结果是改变了液体中水分的含量。基于这个情境,我们可以做出一些推断:1. “稀水”的定义:如果“兑”的结果是将一种液体与另一种液体混合,并且混合后的液体中水分的含量低于原来的液体,那么我们可以推断出“兑”的结果是得到了“稀水”。2. “浓水”的定义:如果“兑”的结果是将一种液体与另一种液体混合,并且混合后的液体中水分的含量高于原来的液体,那么我们可以推断出“兑”的结果是得到了“浓水”。因此,根据这些推断,我们可以得出结论:如果通过“兑”来得到的是“稀水”,那么混合后的液体中水分的含量低于原来的液体;如果得到的是“浓水”,那么混合后的液体中水分的含量高于原来的液体。综上所述,这个问题中的“兑”字使用巧妙,通过改变液体中水分的含量来引出一个关于“稀水”和“浓水”的推断。这个问题考验的是思维的灵活性和对语言文字含义的深刻理解。
与官方资料中的答案并不一致(模型训练的随机性),回答1还是比较科学的,但回答2有点不知所云,感觉像个偏哲学的回答。这再次说明大模型微调中存在一定的不确定性。
3、 参考资料
- https://github.com/InternLM/Tutorial/blob/camp2/data_fine_tuning/data_fine_tuning.md