前言

近期,除了研究ChatGPT背后的各种技术细节 不断看论文(至少100篇,100篇目录见此:ChatGPT相关技术必读论文100篇),还开始研究一系列开源模型(包括各自对应的模型架构、训练方法、训练数据、本地私有化部署、硬件配置要求、微调等细节) 

本文一开始是作为此文《ChatGPT技术原理解析:从RL之PPO算法、RLHF到GPT4、instructGPT》的第4部分,但随着研究深入 为避免该文篇幅又过长,将把『第4部分 开源项目』抽取出来 独立成本文,然后不断续写本文到最终2万字左右(3.22日7000余字)

毕竟我上半年的目标之一,便是把ChatGPT涉及的所有一切关键技术细节,以及相关的开源项目都研究的透透的,故过程中会不断产出一篇篇新文章出来,比如:

  1. 微积分和概率统计极简入门
  2. 一文通透优化算法
  3. 强化学习极简入门:通俗理解MDP、DP MC TC和Q学习、策略梯度、PPO
  4. ChatGPT技术原理解析(本系列核心主体,也是同类解读里最清晰、全面、细致的一篇)
  5. ChatGPT相关技术论文100篇
  6. 类ChatGPT开源项目
  7. CV多模态模型发展史(23年4月发布),详述GPT4背后多模态的能力起源与发展历史,包括但不限于DTER、DDPM、Vision Transformer、CLIP、Swin Transformer、DALL·E 2、Stable Diffusion、BEiT-3、Visual ChatGPT、GPT4等.

第一部分 Colossal-AI、PaLM-rlhf-pytorch、Open-Assistant等

 虽说GPT3在2020年就出来了,但OpenAI并未开源,所以直到一年半后以后才有国内外各个团队比如DeepMind等陆续复现出来,这些大厂的复现代码我们自然无法窥知一二,毕竟人家也未开源出来

再到后来基于GPT3的InstructGPT、基于GPT3.5ChatGPT初版(GPT3.5的参数规模也尚无准确定论)、GPT4均未开源,OpenAI不再open,好在Meta等公司或研究者开源出了一系列类ChatGPT项目,本部分针对其中部分做下简要推荐(根据发布顺序排序)

1.1 基于Colossal-AI低成本实现类ChatGPT迷你版的训练过程

2.15,很多朋友在GitHub上发现了一个基于Colossal-AI低成本实现类ChatGPT迷你版训练过程的开源项目(基于OPT + RLHF + PPO),虽是类似GPT3的开源项目与RLHF的结合,但可以增进我们对ChatGPT的理解,该项目有几个不错的特点

  1. 很多同学一看到DL,便会想到大数据,而数据量一大,还用CPU处理的话很可能训练一个小任务都得半天,而如果用GPU跑,可能一两分钟就出来了。于此,在深度学习大火的那几年,特别是AlphaGo出来的16年起,我司七月在线便分别为VIP、AI系统大课、在职提升大课、求职/论文/申博/留学1V1辅导提供GPU云平台进行实战训练

    但如果想训练那种千亿参数规模的开源模型,就不只是有GPU就完事了,比如1750亿参数规模这种得用64张AI 100(即便经过一系列内存开销上的优化,也得至少32张AI 100,单张AI 100售价10万以上,且现在还经常没货),这样的硬件要求是大部分个人是无法具备的,所以该开源项目提供了单GPU、独立4/8-GPUs 的版本
  2. 如下代码所示,启动简单
    from chatgpt.nn import GPTActor, GPTCritic, RewardModel
    from chatgpt.trainer import PPOTrainer
    from chatgpt.trainer.strategies import ColossalAIStrategy
    
    strategy = ColossalAIStrategy(stage=3, placement_policy='cuda')
    
    with strategy.model_init_context():
        actor = GPTActor().cuda()
        critic = GPTCritic().cuda()
        initial_model = deepcopy(actor).cuda()
        reward_model = RewardModel(deepcopy(critic.model)).cuda()
    
    trainer = PPOTrainer(strategy, actor, critic, reward_model, initial_model, ...)
    trainer.fit(prompts)
  3. 训练过程明确清晰,如下图(由于此文已经详细介绍过ChatGPT的训练步骤,故不再赘述)

    ​此外,据钟博士在我所维护的『Machine Learning读书会群』里所说,Colossal-AI的并行效率确实不错,是新加坡的一个初创团队推出的,但目前尚没有团队采用Colossal-AI框架来做主训练框架训练175b级别的超大模型,可以再了解下Meta家训练OPT用的Metaseq

1.2 PaLM-rlhf-pytorch、Open-Assistant等项目

此外,GitHub上还有这些项目

  • PaLM-rlhf-pytorch
    该项目是在PaLM架构之上实现RLHF,可以理解为基于PaLM的ChatGPT
  • Open-Assistant
    它旨在让每一个人都可以访问基于聊天的大语言模型,项目作者希望借此在语言创新方面掀起一场革命,就像 stable diffusion 帮助世界以新的方式创造艺术和图像一样
    项目作者计划收集高质量人工生成指令执行样本(指示 + 响应),目标大于 50k,对于收集到的每个指示,他们将采样多个补全结果,之后进入基于指示和奖励模型的RLHF训练阶段

第二部分 从LLaMA、ChatLLaMA到Stanford Alpaca、BELLE

2.1 Meta发布大语言模型LLaMA:参数少但多数任务的效果好于GPT3

一直致力于LLM模型研究的国外TOP 3大厂除了OpenAI、Google,便是Meta(原来的Facebook)

Meta曾第一个发布了基于LLM的聊天机器人——BlenderBot 3,但输出不够安全,很快下线;再后来,Meta发布一个专门为科学研究设计的模型Galactica,但用户期望过高,发布三天后又下线

2.1.1 LLaMA:多个参数规模的版本(7B 13B 33B 65B)

2.24日,Meta通过论文《LLaMA: Open and Efficient Foundation Language Models》发布了自家的大型语言模型LLaMA(这是解读之一),有多个参数规模的版本(7B 13B 33B 65B)

LLaMA只使用公开的数据(总计1.4T即1,400GB的token,其中CommonCrawl的数据占比67%,C4数据占比15%,Github Wikipedia Books这三项数据均各自占比4.5%,ArXiv占比2.5%,StackExchange占比2%),论文中提到

When training a 65B-parameter model, our code processes around 380 tokens/sec/GPU on 2048 A100 GPU with 80GB of RAM.

This means that training over our dataset containing 1.4T tokens takes approximately 21 days

且试图证明小模型在足够多的的数据上训练后,也能达到甚至超过大模型的效果

  • 比如13B参数的版本在多项基准上测试的效果好于2020年的参数规模达175B的GPT-3
  • 而对于65B参数的LLaMA,则可与DeepMind的Chinchilla(70B参数)和谷歌的PaLM(540B参数)旗鼓相当
  • 且Meta还尝试使用了论文「Scaling Instruction-Finetuned Language Models」中介绍的指令微调方法,由此产生的模型LLaMA-I,在MMLU(Massive Multitask Language Understanding,大型多任务语言理解)上要优于Google的指令微调模型Flan-PaLM-cont(62B)

2.1.2 LLaMA的模型架构、Optimizer设计、模型加速优化

模型结构上,除了继续基于Transformer这个架构外

  • 为了提高训练的稳定性,对每个transformer子层的输入进行归一化,而不是对输出进行归一化
    且使用由Zhang和Sennrich(2019)提出的RMSNorm归一化函数
  • 用Shazeer(2020)提出的SwiGLU替代ReLU,在维度上使用的维度是2/3*4d,而不是PaLM中的4d
  • 在位置编码上,删除了绝对位置嵌入,而在网络的每一层增加了Su等人(2021)介绍的旋转位置嵌入(RoPE)

在Optimizer设计上

  • 该模型使用AdamW优化器(Loshchilov和Hutter,2017)进行训练,超参数设置为β1=0.9,β2=0.95
    此外,使用余弦学习率方式,使最终学习率等于最大学习率的10%,以及使用0.1的权重衰减和1.0的梯度剪裁,和2,000个warm up策略,使得可以根据模型的大小改变学习率和批次大小

在模型的加速优化方面

  1. 首先,使用一个高效的因果多头注意力方式的实现,灵感来自Rabe和Staats(2021)以及Dao等人(2022),这个实现可在xformers库中找到,可以有效减少内存的使用和计算
    具体原理为通过不存储注意力权重和不计算由于语言建模任务的因果性质而被掩盖的键/查询分数来实现的
  2. 其次,为了进一步提高训练效率,减少了在check point的后向传递中重新计算的激活量,在实现上,通过手动实现trasnformer层的后向函数来进行操作
    为了充分受益于这种优化,还通过如Korthikanti等人(2022)中采用的方法,进行使用模型和序列并行来减少模型的内存使用
  3. 最后,该工作还尽可能地重叠激活的计算和GPU之间在网络上的通信
    最终的优化性能效果为:当训练一个65B参数的模型时,代码在2048A100的GPU上处理大约380个token/秒/GPU,并耗费80GB的内存,这意味着对包含1.4Ttoken的数据集进行训练大约花费了21天

LLaMA发布不久后,一些研究者基于它做了不少工作

  • 一开始最小参数7B的模型也需要近30GB的GPU才能运行,但通过比特和字节库进行浮点优化,能够让模型在单个NVIDIA RTX 3060上运行
  • 之后,GitHub 上的一名研究人员甚至能够在Ryzen 7900X CPU上运行LLM的7B 版本,每秒能推断出几个单词
  • 再之后,有研究者推出了llama.cpp,无需 GPU,就能运行 LLaMA
    llama.cpp 项目实现了在MacBook上运行 LLaMA,还有开发者成功的在 4GB RAM 的树莓派上运行了 LLaMA 7B

2.2 ChatLLaMA:给LLaMA加上RLHF

由于LLaMA没有使用RLHF方法,初创公司 Nebuly AI开源了RLHF版的LLaMA,即ChatLLaMA

其训练过程类似 ChatGPT,该项目允许基于预训练的 LLaMA 模型构建 ChatGPT 形式的服务
与 ChatGPT 相比,LLaMA 架构更小,但训练过程和单GPU推理速度更快,成本更低,且该库还支持所有的 LLaMA 模型架构(7B/13B/33B/65B),因此用户可以根据训练时间和推理性能偏好对模型进行微调

以下是其主函数的代码,代码结构还是很清晰的

import argparse

from chatllama.rlhf.actor import ActorTrainer
from chatllama.rlhf.config import Config
from chatllama.rlhf.dataset import BaseDataset
from chatllama.rlhf.reward import RewardTrainer
from chatllama.rlhf.trainer import RLTrainer


# Setup argument parser
parser = argparse.ArgumentParser(
    prog="main.py", description="RLHF Training of ChatBots"
)

parser.add_argument("configfile", help="Path to config.yaml file")
parser.add_argument(
    "-t",
    "--type",
    help=(
        "Specify the training type. RL: Training of the model using RL."
        "ACTOR: Training of the actor model. "
        "REWARD: Training of the reward model."
        "RL: The whole pipeline with the three training steps"
    ),
    default="ALL",
    choices=["ALL", "RL", "ACTOR", "REWARD"],
)
parser.add_argument(
    "-a", "--actor", help="Specify actor model by name", default=None
)
parser.add_argument(
    "-r", "--reward", help="Specify reward model by name", default=None
)

# parse arguments
args = parser.parse_args()

# load config.yaml with all the project informations
config = Config(args.configfile)

# overwrite config if specified differently
if args.actor is not None:
    config.actor.model = args.actor
if args.reward is not None:
    config.reward.model = args.reward

# perform the desired training
if args.type == "RL":
    max_seq = min(
        config.actor.max_sequence_length,
        config.reward.max_sequence_length,
        config.critic.max_sequence_length,
    )
    config.actor.max_sequence_length = max_seq
    BaseDataset.clean_dataset(config)
    rlhf_trainer = RLTrainer(config)
    rlhf_trainer.train()
elif args.type == "ACTOR":
    BaseDataset.clean_dataset(config.actor)
    actor_trainer = ActorTrainer(config.actor)
    actor_trainer.train()
elif args.type == "REWARD":
    BaseDataset.clean_dataset(config.reward)
    reward_trainer = RewardTrainer(config.reward)
    reward_trainer.train()
elif args.type == "ALL":
    reward_trainer = RewardTrainer(config.reward)
    reward_trainer.train()
    actor_trainer = ActorTrainer(config.actor)
    actor_trainer.train()
    rlhf_trainer = RLTrainer(config)
    rlhf_trainer.train()

2.3 Stanford Alpaca:结合英文语料通过Self Instruct方式微调LLaMA 7B

3月中旬,斯坦福发布Alpaca:号称只花100美元,人人都可微调Meta家70亿参数的LLaMA大模型(即LLaMA 7B),具体做法是通过52k指令数据,然后在8个80GB A100上训练3个小时,最终性能比肩GPT-3.5(text-davinci-003)

  • 论文《Alpaca: A Strong Open-Source Instruction-Following Model》
  • 代码地址:https://github/tatsu-lab/stanford_alpaca

而斯坦福团队微调LLaMA 7B所用的52K指令数据,便是通过Self-Instruct『Self-Instruct是来自华盛顿大学Yizhong Wang等22年12月通过这篇论文《SELF-INSTRUCT: Aligning Language Model with Self Generated Instructions》提出的』提示GPT3的API拿到的

​具体而言,论文中提出

  1. 人工设计175个任务,每个任务都有对应的{指令 输入 输出/实例}或{指令 输出/实例},将这175个任务数据作为种子集
  2. 然后提示模型比如GPT3对应的text-davinci-001 (原论文中没用text-davinci-003,because their newer engines are trained with the latest user data and are likely to already see the SUPERNI evaluation set,但实际应用时比如斯坦福Alpaca可以指定text-davinci-003生成指令),使用种子集作为上下文示例来生成更多新的指令
  3. 对该模型生成的指令判断是否分类任务
  4. 使用模型生成实例
  5. 对上述模型生成的数据{指令 输入 输出/实例}过滤掉低质量或相似度高的
  6. 将经过过滤和后处理的数据添加到种子池中
    一直重复上述2-6步直到种子池有足够多的数据

而斯坦福的Alpaca,就是花了不到500美元使用OpenAI API生成了5.2万个这样的示例微调LLaMA搞出来的,个人觉得可以取名为 instructLLaMA-7B,^_^

2.4 BELLE(中文版Stanford Alpaca):通过Self Instruct方式微调BLOOMZ-7B

Stanford Alpaca的种子任务都是英语,收集的数据也都是英文,因此训练出来的模型未对中文优化。为了提升对话模型在中文上的效果,开源中文对话大模型70 亿参数的 BELLE(Bloom-Enhanced Large Language model Engine)来了(项目地址)。

它基于Stanford Alpaca完成,但进行了中文优化,并对生成代码进行了一些修改,不仅如此,模型调优也仅使用由 GPT3.5 (默认使用模型text-davinci-003,如果想使用ChatGPT的API比如gpt-3.5-turbo模型,可通过参数控制) 生产的数据(不包含任何其他数据)。

在数据方面,该项目开源了基于Stanford Alpaca的数据收集代码,基于这段代码生成了约 100 万条中文数据,结合 Alpaca 的 5.2 万条英文数据,在 BLOOMZ-7B 模型训练得到的 checkpoint 上传在 Hugging Face

BLOOM是由HuggingFace于2022年3月中旬推出的大模型,规模最大版本的参数量达到176B(GPT-3是175B),基于从 Megatron-LM GPT-2修改而来的仅解码器 transformer 模型架构,对应的论文为《BLOOM: A 176B-Parameter Open-Access Multilingual Language Model》(翻译之一,解读之一)
至于HuggingFace是著名开源工具Transformers的开发公司,很多推理工具都会支持Transformers中的模型


截至23年3月中旬,超过100B参数量且能够支持中文的开源大模型只有BLOOM和GLM-130B

该项目主要包含以下三部分内容:

  • 175 个中文种子任务,斯坦福Alpaca一样,每个任务都包含对应的指令/任务、prompt、输出
      zh_seed_tasks.jsonl:样例如下
     {  "id": "seed_task_20", "name": "horror_movie_opening",
    "instruction": "你需要为一部恐怖电影写一个创意的开场场景。",
    "instances": [{"input": "","output":" 太阳已经落山,留下了一个黑暗的小镇。微风吹拂空荡的街道,让每一个冒险走出门外的人感到一阵寒意。唯一的声音是被风吹动的树叶发出的轻微沙沙声。突然,一声令人毛骨悚然的尖叫声划破了寂静,随后是玻璃破碎的声音。一所房子亮起了灯光,可以看到一个人影朝镇中心奔跑。当> 那个人影越来越靠近时,清楚地看到那是一个年轻女子,她浑身血迹斑斑。"}],
    "is_classification": false  }
  •   prompt_cn.txt: 生成所使用的提示语
      0.5M 生成的数据
  • 生成数据及其代码
    沿用 Alpaca 的方式:
    pip install -r requirements.txt
    export OPENAI_API_KEY=YOUR_API_KEY
    python generate_instruction.py generate_instruction_following_data

    默认使用 Completion API,模型 text-davinci-003。如果想使用 Chat API 并使用 gpt-3.5-turbo 模型,可通过参数控制:
    python generate_instruction.py generate_instruction_following_data \
      --api=chat --model_name=gpt-3.5-turbo

    输出文件在 Belle.train.json,可以人工筛选后再使用
  • 基于 BLOOMZ-7B1-mt 模型和 Belle.train.json 训练模型

第三部分 国内的GLM与类ChatGPT项目ChatGLM-6B

3.1 GLM: General Language Model Pretraining with Autoregressive Blank Infilling

在2022年上半年,当时主流的预训练框架可以分为三种:

  • autoregressive,自回归模型的代表是单向的GPT,本质上是一个从左到右的语言模型,常用于无条件生成任务(unconditional generation),缺点是无法利用到下文的信息
  • autoencoding,自编码模型是通过某个降噪目标(如掩码语言模型,简单理解就是通过挖洞,训练模型做完形填空的能力)训练的语言编码器,如双向的BERT、ALBERT、RoBERTa、DeBERTa
    自编码模型擅长自然语言理解任务(natural language understanding tasks),常被用来生成句子的上下文表示,缺点是不适合生成任务
  • encoder-decoder,则是一个完整的Transformer结构,包含一个编码器和一个解码器,以T5、BART为代表,常用于有条件的生成任务 (conditional generation)
    细致来说,T5的编码器中的注意力是双向,解码器中的注意力是单向的,因此可同时应用于自然语言理解任务和生成任务。但T5为了达到和RoBERTa和DeBERTa相似的性能,往往需要更多的参数量

这三种预训练模型各自称霸一方,那么问题来了,可否结合三种预训练模型,以成天下之一统?这便是2022年5月发表的这篇论文《GLM: General Language Model Pretraining with Autoregressive Blank Infilling》的出发点,它提出了GLM架构(这是张义策关于GLM论文的解读之一,下面三小节的内容主要参考自该篇解读)

3.1.1 如何将生成模型GPT和掩码语言模型BERT结合在一起

首先,考虑到三类预训练模型的训练目标

  • GPT的训练目标是从左到右的文本生成
  • BERT的训练目标是对文本进行随机掩码,然后预测被掩码的词
  • T5则是接受一段文本,从左到右的生成另一段文本

为了大一统,我们必须在结构和训练目标上兼容这三种预训练模型。如何实现呢?文章给出的解决方法

  • 结构上,只需要GLM中同时存在单向注意力和双向注意力即可
    在原本的Transformer模型中,这两种注意力机制是通过修改attention mask实现的
    当attention_mask是全1矩阵的时候,这时注意力是双向的
    当attention_mask是三角矩阵的时候(如下图),注意力就是单向

    类似地,我们可以在只使用Transformer编码器的情况下,自定义attention mask来兼容三种模型结构

  • 训练目标上,这篇文章提出一个自回归空格填充的任务(Autoregressive Blank Infifilling),来兼容三种预训练目标
    自回归填充有些类似掩码语言模型,首先采样输入文本中部分片段,将其替换为[MASK]标记,然后预测[MASK]所对应的文本片段,与掩码语言模型不同的是,预测的过程是采用自回归的方式

    具体来说,
      当被掩码的片段长度为1的时候,空格填充任务等价于掩码语言建模,类似BERT
      当将文本1和文本2拼接在一起,然后将文本2整体掩码掉,空格填充任务就等价于条件语言生成任务,类似T5/BART
      当全部的文本都被掩码时,空格填充任务就等价于无条件语言生成任务,类似GPT

3.1.2 如何理解GLM的自回归空格填充任务

假设原始的文本序列为,采样的两个文本片段为  和  ,那么掩码后的文本序列为 (以下简称Part A),如上图所示,拆解图中的三块分别可得

  • 我们要根据第一个  解码出  ,根据第二个依次解码出  ,那怎么从  处解码出变长的序列吗?这就需要用到开始标记  和结束标记  了
  • 我们从开始标记 开始依次解码出被掩码的文本片段,直至结束标记  。通过本博客内的Transformer笔记可知,Transformer中的位置信息是通过位置向量来记录的
    在GLM中,位置向量有两个,一个 用来记录Part A中的相对顺序,一个 用来记录被掩码的文本片段(简称为Part B)中的相对顺序
  • 此外,还需要通过自定义自注意掩码(attention mask)来达到以下目的:
      双向编码器Part A中的词彼此可见,即图(d)中蓝色框中的区域
      单向解码器Part B中的词单向可见,即图(d)黄色框的区域
      Part B可见Part A
      其余不可见,即图(d)中灰色的区域

需要说明的是,Part B包含所有被掩码的文本片段,但是文本片段的相对顺序是随机打乱的

3.1.3 GLM的预训练和微调

作者使用了两个预训练目标来优化GLM,两个目标交替进行:

  • 文档级别的预测/生成:从文档中随机采样一个文本片段进行掩码,片段的长度为文档长度的50%-100%
  • 句子级别的预测/生成:从文档中随机掩码若干文本片段,每个文本片段必须为完整的句子,被掩码的词数量为整个文档长度的15%

尽管GLM是BERT、GPT、T5三者的结合,但是在预训练时,为了适应预训练的目标,作者还是选择掩码较长的文本片段,以确保GLM的文本生成能力,并在微调的时候将自然语言理解任务也转化为生成任务,如情感分类任务转化为填充空白的任务

  • 输入:{Sentence},prompt:It is really  ,对应的标签为good和bad

此外,模型架构层面,除了整体基于Transformer之外

  1. 重新排列了层归一化和残差连接的顺序
  2. 针对token的输出预测使用单一线性层
  3. 用GeLU替换ReLU激活函数

3.2 GLM-130B:国内为数不多的可比肩GPT3的大模型之一 

2022年8月,清华背景的智谱AI基于GLM框架,正式推出拥有1300亿参数的中英双语稠密模型 GLM-130B(论文地址、代码地址,论文解读之一,GLM-130B is trained on a cluster of 96 DGX-A100 GPU (8×40G) servers with a 60-day,可以较好的支持2048个token的上下文窗口)

其在一些任务上的表现优于GPT3-175B,是国内与2020年5月的GPT3在综合能力上差不多的模型之一(即便放到23年年初也并不多),这是它的一些重要特点

3.3 类ChatGPT开源项目ChatGLM-6B的训练框架与部署步骤

ChatGLM-6B(介绍页面、代码地址),是智谱 AI 开源、支持中英双语的对话语言模型,其

  • 基于General Language Model(GLM)架构,具有62亿参数,无量化下占用显存13G,INT8量化级别下支持在单张11G显存的 2080Ti 上进行推理使用(因为INT8下占用显存10G,而INT4下最低只需 6GB显存)

    这里需要解释下的是,INT8量化是一种将深度学习模型中的权重和激活值从32位浮点数(FP32)减少到8位整数(INT8)的技术。这种技术可以降低模型的内存占用和计算复杂度,从而减少计算资源需求,提高推理速度,同时降低能耗
    量化的过程通常包括以下几个步骤:
    1 量化范围选择:确定权重和激活值的最小值和最大值
    2 量化映射:根据范围将32位浮点数映射到8位整数
    3 反量化:将8位整数转换回浮点数,用于计算
  • ChatGLM-6B参考了 ChatGPT 的训练思路,在千亿基座模型GLM-130B中注入了代码预训练,通过监督微调(Supervised Fine-Tuning)、反馈自助(Feedback Bootstrap)、人类反馈强化学习(Reinforcement Learning from Human Feedback)等方式等技术实现人类意图对齐,并针对中文问答和对话进行优化
  • 最终经过约 1T 标识符的中英双语训练,生成符合人类偏好的回答

虽尚有很多不足(比如因为6B的大小限制,导致模型的记忆能力、编码、推理能力皆有限),但在6B这个参数量级下不错了,部署也非常简单,我七月在线的同事朝阳花了一两个小时即部署好了(主要时间花在模型下载上,实际的部署操作很快)

以下是具体的部署过程(机器用的七月的GPU服务器,显存大小为16G的P100,最终占用13G)

  1. 配置环境:pip install -r requirements.txt(特别注意torch版本大于1.10,transformers大于4.23)
    torch的安装命令参考pytorch官网:https://pytorch/
  2. 下载项目仓库:
    git clone https://github/THUDM/ChatGLM-6B
    cd ChatGLM-6B
  3. 下载ChatGLM-6B模型文件
    下载地址:https://huggingface.co/THUDM/chatglm-6b
  4. 有两种运行方式,一种是基于Gradio,一种是基于streamlit
    基于Gradio:
    运行web_demo.py即可(注意可以设置share=True,便于公网访问):python web_demo.py(注意运行前确认下模型文件路径)

    基于streamlit:
    pip install streamlit
    pip install streamlit-chat
    streamlit run web_demo2.py --server.port 6006(可以将6006端口放出,便于公网访问)

此外,据介绍,GLM团队正在内测130B参数的ChatGLM,相信从6B到130B,效果应该能提升很多

3.4 如何微调ChatGLM-6B:基于Stanford Alpaca的52K数据集 + LoRA

从上文可知,Stanford Alpaca的52K数据集是通过Self Instruct方式提示GPT3对应的API产生的指令数据,然后通过这批指令数据微调Meta的LLaMA 7B

而GitHub上的这个微调ChatGLM-6B项目(作者:mymusise),则通过Stanford Alpaca的52K数据集通过LoRA(low-rank adaptation)的方式微调ChatGLM-6B

所谓LoRA的思想其实也很简单,通过论文《LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS》可知(这是解读之一)

  1. 首先在原始PLM旁边增加一个旁路,做一个降维再升维的操作,来模拟所谓的 intrinsic rank 
  2. 然后训练的时候固定PLM的参数,只训练降维矩阵A与升维矩阵B,而模型的输入输出维度不变,输出时将BA与PLM的参数叠加
    过程中,用随机高斯分布初始化A,用0矩阵初始化B,保证训练的开始此旁路矩阵依然是0矩阵

比如针对上文介绍过的Stanford Alpaca,便有个Alpaca-LoRA: Low-Rank LLaMA Instruct-Tuning

言归正传,微调ChatGLM-6B的具体步骤如下

3.4.1 环境准备

  • 显卡: 显存 >= 16G (最好24G或者以上)
  • 环境:
    • python>=3.8
    • cuda>=11.6, cupti, cuDNN, TensorRT等深度学习环境
    • pip3 install -r requirements.txt

3.4.2 数据预处理

转化alpaca数据集为jsonl

python cover_alpaca2jsonl.py \
    --data_path data/alpaca_data.json \
    --save_path data/alpaca_data.jsonl \

tokenization

python tokenize_dataset_rows.py \
    --jsonl_path data/alpaca_data.jsonl \
    --save_path data/alpaca \
    --max_seq_length 320
  • --jsonl_path 微调的数据路径, 格式jsonl, 对每行的['context']和['target']字段进行encode
  • --save_path 输出路径
  • --max_seq_length 样本的最大长度

3.4.3 训练

python finetune.py \
    --dataset_path data/alpaca \
    --lora_rank 8 \
    --per_device_train_batch_size 2 \
    --gradient_accumulation_steps 1 \
    --max_steps 52000 \
    --save_steps 1000 \
    --save_total_limit 2 \
    --learning_rate 2e-5 \
    --fp16 \
    --remove_unused_columns false \
    --logging_steps 50 \
    --output_dir output

3.4.4 推理

参考 infer.ipynb

利用Alpaca数据集合对ChatGLM-6B Finetune后,在Alpaca数据集上表现得更好:

  • Answer: 是模型的输出
  • #### Answer: 是原答案

更多推荐

类ChatGPT开源项目的部署与微调:从LLaMA到ChatGLM-6B