问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

零基础定制大模型:从基础模型到个性化应用的完整指南

创作时间:
作者:
@小白创作中心

零基础定制大模型:从基础模型到个性化应用的完整指南

引用
CSDN
1.
https://blog.csdn.net/aiqq136/article/details/144376994

本文将带你从零开始,了解如何基于基础模型和自定义数据集来定制大模型。以《甄嬛传》为例,详细讲解大模型的基础知识、微调技术、数据准备、训练过程以及评估方法。

1.基础知识

什么是大模型?

大模型LLM(Large Language Model)是基于深度学习技术的大规模人工智能模型,拥有非常庞大的数据规模和训练数据量,可以在多种任务中表现出高度的通用性和卓越性能。例如,OpenAI的GPT-4模型拥有数千亿级别的参数。训练数据来源于互联网海量数据,涵盖多种语言、多种领域和不同的任务。

如何展现大模型通用性?

大模型并不是针对特定任务设计的,而是在训练后通过微调(Fine-tuning)或者提示学习(Prompt Learning)适应不同的任务,例如文本生成、翻译、代码编写、图像生成等。

如何定制大模型?用到的技术主要是什么?

定制大模型是指针对特定应用场景或需求,对已有的大规模预训练模型进行优化、微调或改造,以实现更高效、更贴合需求的性能。主要用到的技术包括:

  • 微调 (Fine-Tuning)
  • 知识蒸馏 (Knowledge Distillation)
  • 多模态扩展
  • 增强学习(Reinforcement Learning)

有什么参调方法呢?

  • 全参数调整(Full Tuning)
  • 参数高效微调Parameter Efficient Fine-tuning (PEFT)
  • 适配器方法(Adapter Tuning)

什么是LoRA(Low-Rank Adaptation)?

LoRA是一种通过低秩矩阵更新来降低微调复杂度的技术。例如,使用Adam对GPT-3: 175B进行微调,与使用LoRA进行微调相比,可训练参数减少10,000倍,GPU内存需求减少3倍。

如何通过LoRA进行微调?

  1. 选择一个预训练的基础模型。
  2. 选择一个要进行微调的层,例如Transformer的attention层。
  3. 引入低秩矩阵对原来的权重矩阵W,进行低秩分解,让W’=AXB近似于W,X代表矩阵乘法。
  4. 冻结原始权重矩阵W,使用目标用例数据,仅更新低秩矩阵A和B。
  5. 评估调整后的模型性能,超参数调优,模型评估。
  6. 对模型进行部署和监控。

什么是量化低秩适应(QLoRA)(Quantized Low-Rank Adaptation)?

QLoRA将LoRA与量化相结合,优化内存使用和计算效率。添加少量可训练的参数,同时保持原始参数冻结。QLoRA通过将转换器模型量化到4位精度,并使用分页优化器处理内存峰值,来改进LoRA。

什么是前缀调优(Prefix Tuning)?

前缀调优是一种通过在模型输入前添加一系列可学习向量(前缀)来微调大型预训练模型的技术。修改输入表示,而不是模型的内部参数,使其成为一种轻量级和高效的微调技术。

什么是提示优化(Prompt Tuning)?

提示优化是一种使用提示来指导模型行为的技术。提示可以是静态的(固定文本),也可以是引入输入序列的动态的(可学习的嵌入)。修改模型的输入上下文以指导它的响应,而不更改模型的内部参数。前缀调优使用可学习的向量(不是实际的文本),而提示调优可以使用固定的文本提示或可学习的嵌入。

什么是过拟合?

过拟合是指模型在训练数据上表现很好,但在新数据上表现不佳的现象。通常是因为模型记忆了过多的不必要的细节(偶然的、不重要的噪声)。

JSON和JSONL介绍

JavaScript Object Notation 使用键值对来表示数据。通常包含一个对象(用{}表示),键一般是字符串(“age”),中间用冒号连接(:),值可以为数字(30)、字符串(“Zhang San”)、boolean值(false)、数组([“Chinese”,”Math”,”English”]),或者另一个对象。

JSON Lines可以处理大型数据集,一行一个json。

主流数据集格式

Alpaca

Alpaca数据集格式包括instruction、input、output、system、history组成,人类指令、人类输入、模型回答、提示词、历史消息记录表。

ShareGPT

ShareGPT数据集格式包括人类指令、模型回答、可选的系统提示词、工具列表。

模拟甄嬛对话的微调大模型程序

相关资料

如何准备数据?

通过网络获得《甄嬛传》剧本数据,每一句的人物及对应的台词。使用正则表达式或者其他方法进行快速的提取,并抽取出关注的角色的对话。最后再将其整理成 json 格式的数据。

原始数据

第十一集
第203幕(续)
甄嬛:兔子急了也会咬人的。
眉庄:可是连苏培盛都棘手的事,陵容却能解决得这么干脆利落,实在是让我太意外了。
甄嬛:虽然意外,可陵容毕竟也是为了咱们。
眉庄:话是如此,可是我总还觉得这不像我日日面对的那个陵容。
(陵容在屏风外听得对话,默然离去。)
第204幕
(翊坤宫)
华妃:死绝了?
颂芝:死得透透的了,拉去乱葬岗的时候,有人亲眼瞧见。下手可真够狠的,脖子都勒断了半根,可吓人了。
华妃:那些没根儿的东西,做事倒是挺利落的。也难怪呀,她连皇上身边的人都敢得罪,活该她有今天。她没说漏了嘴吧?
颂芝:一句都没有。
华妃:算她识相。从前小看了那个病歪歪的甄嬛,以后走着瞧吧。(雷声)且闷了这么些天,也该下场大雨了。

提取数据

def extract_dialogues(file_path):
    result = []
    current_act_dialogues = []
    with open(file_path, 'r', encoding='utf-8') as file:
        lines = file.readlines()
        for line in lines:
            line = line.strip()
            if line.startswith("("): # 过滤旁白行
                continue
            if line.startswith("第") and line.endswith("幕"): # 解析新的一幕
                if current_act_dialogues:
                    result.append(current_act_dialogues)
                    current_act_dialogues = []
            elif ":" in line: # 按:切分角色和对话内容
                role, content = line.split(":", 1)
                role = role.strip()
                content = content.strip()
                current_act_dialogues.append({"role": role, "content": content})
        if current_act_dialogues: # 保存最后一幕
            result.append(current_act_dialogues)
    return result
file_path = '甄嬛传剧本11-20.txt'
dialogues = extract_dialogues(file_path)
print(dialogues)

处理结果

[
    {"role": "甄嬛", "content": "兔子急了也会咬人的。"},
    {"role": "眉庄", "content": "可是连苏培盛都棘手的事,陵容却能解决得这么干脆利落,实在是让我太意外了。"},
    {"role": "甄嬛", "content": "虽然意外,可陵容毕竟也是为了咱们。"},
    {"role": "眉庄", "content": "话是如此,可是我总还觉得这不像我日日面对的那个陵容。"}
],
[
    {"role": "华妃", "content": "死绝了?"},
    {"role": "颂芝", "content": "死得透透的了,拉去乱葬岗的时候,有人亲眼瞧见。下手可真够狠的,脖子都勒断了半根,可吓人了。"},
    {"role": "华妃", "content": "那些没根儿的东西,做事倒是挺利落的。也难怪呀,她连皇上身边的人都敢得罪,活该她有今天。她没说漏了嘴吧?"},
    {"role": "颂芝", "content": "一句都没有。"},
    {"role": "华妃", "content": "算她识相。从前小看了那个病歪歪的甄嬛,以后走着瞧吧。(雷声)且闷了这么些天,也该下场大雨了。"}
]

正则提取

def extract_zhenhuan_dialogues(dialogues):
    result = []
    zhenhuan_dialogues = []
    for act in dialogues:
        for i, dialogue in enumerate(act):
            if "甄嬛" in dialogue["role"] and i > 0:
                zhenhuan_dialogues.append(act[i-1])
                zhenhuan_dialogues.append(dialogue)
                result.append(zhenhuan_dialogues)
                zhenhuan_dialogues = []
    return result
zhenhuan_dialogues = extract_zhenhuan_dialogues(dialogues)
print(zhenhuan_dialogues)

数据增强

利用两到三条数据作为 example 丢给LLM,让其生成风格类似的数据。也可以找一部分日常对话的数据集,使用 RAG 生成一些固定角色风格的对话数据。

如何微调?

定制一个自己的专属大模型最方便的步骤 ≈ 指定数据集 + 开源大模型 + 微调平台(如讯飞星辰Maas)

  1. 选择基础模型
  2. 选择微调方法
  3. 上传数据集

参数调整

  1. 深度学习
  • 学习率:控制每次迭代更新模型参数的步幅。较小学习率更新慢但精确,较大学习率训练速度快但可能不稳定。
  • 训练次数:建议根据数据规模设置合理的 epochs。
  • 输入序列长度:模型输入序列的最大长度,短序列效率高,长序列适合上下文较多的任务。
  1. LORA(低秩自适应)
  • LORA秩:决定模型更新参数的数量,影响计算量与性能表现。
  • LORA随机丢弃:类似于正则化操作,避免过拟合,提升泛化能力。
  • LORA作用模块:主要在预训练模型的自注意力机制和前馈网络中进行权重适配。
  • LORA缩放因数:控制训练过程参数更新幅度,适配不同任务要求。
  1. 训练加速
  • Galore特性:通过低秩特性减少参数存储和计算量,提高模型加速效果。
  • BAdam特性:一种内存高效的优化算法,通过减少参数计算次数和内存占用,进一步提高训练效率。

如何评价生成结果?

  1. 人工评价:准确率、流畅度。
  2. 机器评价:BLEU分数、F1-score。

如何优化?

通过以下方式优化微调方式及性能

  1. 损失图:绘制训练损失和验证损失的曲线图。如果验证损失在训练损失持续下降时上升,可能表明模型过拟合。
  2. 平衡语料比例:根据原始语料和新添加语料的比例进行微调,防止模型过拟合。可以采用如80%原始语料和20%新语料的比例开始。

深入学习?

参考目录链接:https://www.datawhale.cn/activity/110/21/83?rankingPage=1

如何在自己的电脑进行训练?

参考链接:https://github.com/datawhalechina/self-llm/blob/master/examples/Chat-%E5%AC%9B%E5%AC%9B/readme.md

选择 LLaMA3_1-8B-Instruct 模型进行微调,首先还是要下载模型。其次,准备训练代码,在当前目录下放置train.py。微调教程链接:https://github.com/datawhalechina/self-llm/blob/master/models/LLaMA3/04-LLaMA3-8B-Instruct%20Lora%20%E5%BE%AE%E8%B0%83.md

  1. 指令集构建:微调数据集构建
  2. 数据格式化:需要将输入文本编码为 input_ids,将输出文本编码为 labels,编码之后的结果都是多维的向量。我们首先定义一个预处理函数,这个函数用于对每一个样本,编码其输入、输出文本并返回一个编码后的字典。
  3. 加载 tokenizer 和半精度模型
  4. 定义 LoraConfig
  5. 自定义 TrainingArguments 参数
  6. 使用 Trainer 训练
  7. 保存 lora 权重
  8. 加载 lora 权重推理

模型训练结果

训练结果体验截图显示,初始训练效果并不理想,但使用Spark Max进行十次迭代后,效果有了显著提升。

使用Spark Max模型进行训练后,效果如下:

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号