【大模型专栏—进阶篇】语言模型创新大总结——“后起之秀”
大模型专栏介绍
😊你好,我是小航,一个正在变秃、变强的文艺倾年。
🔔本文为大模型专栏子篇,大模型专栏将持续更新,主要讲解大模型从入门到实战打怪升级。如有兴趣,欢迎您的阅读。
💡适合人群:本科生、研究生、大模型爱好者,期待与你一同探索、学习、进步,一起卷起来叭!
🔗篇章一:本篇主要讲解Python基础、数据分析三件套、机器学习、深度学习、CUDA等基础知识、学习使用AutoDL炼丹
🔗篇章二:本篇主要讲解基本的科研知识、认识数据和显卡、语言模型如RNN、LSTM、Attention、Transformer、Bert、T5、GPT、BLOOM、LLama、Baichuan、ChatGLM等系列、强化学习教程、大模型基础知识及微调等
🔗篇章三:本篇主要讲解智能对话、大模型基础实战如Ollama、Agent、QLoar、Deepspeed、RAG、Mobile Agent等、大模型领域前沿论文总结及创新点汇总
目录
- BLOOM
- LLaMA
- LLaMA-1
- Alpace
- Vicuna
- LLaMA-2
- LLaMA-3
- Baichuan
- Baichuan-1
- Baichuan-2
- ChatGLM
- ChatGLM-1
- ChatGLM-2
- ChatGLM-3
BLOOM
🔗BLOOM:A 176B-Parameter Open-Access Multilingual Language Model
- 研发项目发起人:Thomas Wolf (Hugging Face联合创始人兼CSO)
- 模型介绍:在
46种自然语言
和13种编程语言
上训练的1760亿参数
语言模型,其是由数百名研究人员合作开发和发布的。训练BLOOM的计算力是由来自于法国公共拨款的GENCI和IDRIS,利用了IDRIS的Jean Zay超级计算机。 - 数据集:
ROOTS语料库
,一个由498个Hugging Face数据集组成的语料。该语聊共计1.61TB的文本,包含46种自然语言和13种编程语言。- 语言的选择:首先列出
8个世界上使用人数最多的语言
,在项目早期邀请这些语言的流利使用者加入项目。然后,根据语言社区的建议进行语言的拓展,例如,将初始语言中的斯瓦希里语拓展到尼日尔-刚果语系,将印地语和乌尔都语拓展到印度语。最终,研发团队提出若某个语言只要有多于3个流利语言使用者参与,就可以添加至支持列表
。 - 源的选择:研发团队和研讨会参与者共同编写了
"BigScience Catalogue"
,涵盖多种语言的已处理和未处理来源的大列表,采用hackathons形式进行组织
。作为补充,其他参与者编写了特定语言的资源,例如以阿拉伯语为中心的Masader存储库。由此共确定了252个源,每种语言至少有21个源
。对于西班牙语、中文、法语和英语,参与者确定了适合添加到语料中的本地网站信息,并通过pseudocrawl(从Common Crawl snapshot中获取这些网站)将其添加到语料中。 - GitHub代码:通过Google’s BigQuer上的GitHub数据集合来进一步补充该目录中的编程语言数据集,然后使用精准匹配进行去重。
- OSCAR:为了不偏离使用网页作为预训练数据源的研究惯例,并且满足BLOOM预训练的数据需求,进一步使用
版本为21.09的OSCAR
作为数据源,对应于2021年2月的Common Crawl snapshot,约占最终语料的38%。【OSCAR 项目(Open Super-large Crawled Aggregated coRpus)是一个开源项目,旨在为机器学习 (ML) 和人工智能 (AI) 应用程序提供基于 Web 的多语言资源和数据集。】
- 语言的选择:首先列出
数据预处理:
- 获取源数据
从已经确定的数据源中获得文本数据
,包括从各类NLP数据集中提取数据,从文本资源中抓取和处理大量PDF文件,从列表中指定的192个网站及各地区456个网站中提取和处理文本。网站数据的获取是用研发的工具从Common Crawl WARC文件中的HTML中抽取文本,该方法能够从539个网站的URL中提取可用信息。 - 质量过滤— Text Produced by Humans for Humans
在获得文本后,研究团队发现大多数源中包含了大量的非自然语言,例如预处理错误、SEO页面或者垃圾数据。对于每种语言,采用两种方法来进行过滤:- ①
通过流利使用该语言的人逐个为每种语言选定其参数
,如阈值和支持术语列表; - ②
手动审核每个数据源
,以确定最有可能识别非自然语言的指标。
- ①
- 去重和隐私编辑
对文档进行去重,并对OSCAR语料进行个人信息脱敏。
Prompt数据集:
多任务提示微调(Instruction tuning)涉及到对预训练语言模型的微调,微调的数据集由通过自然语言提示构成的大量不同任务组成。
- T0证明了
在多任务混合的prompted数据集上微调的模型具有强大的zero-shot泛化能力
。此外,T0优于那些数量级大但是没有经过这种微调的语言模型。受此启发,研发团队探索了使用现有自然语言数据集来进行多任务prompted微调的优化策略。 - T0是在
Public Pool of Prompt(P3)
子集上进行训练的,其是一个各种现有的、开源的应用自然语言数据集的prompt集合。该prompt集合是通过BigScience合作者参与的一系列hackathons创建的,其中hackathons参与者为170+数据集编写了2000+ prompt
。P3中的数据集覆盖了各种自然语言任务
,包括情感分析、问答、自然语言推理,并且排除了有害的内容或者非自然语言内容。
对BLOOM预训练之后,应用相同的大规模多任务对其进行微调,使BLOOM具有多语言 zero-shot
任务泛化能力,我们称得到的模型为BLOOMZ
。
- 为了训练BLOOMZ,扩展了 P3 以包含英语以外语言的新数据集和新任务,例如翻译,这产生了
xP3
,它是83个数据集的提升集合,覆盖46种语言和16种任务
,语言分布与BLOOM的ROOTS数据集高度一致。 - xP3中包含跨语言和单语言任务,研发团队使用
PromptSource
(PromptSource,一个开源工具包(作为 BigScience 的一部分进行开发)促进了自然语言prompt的创建、共享和使用)来收集这些prompts,并为prompt添加额外的元数据,例如input和target Languages。 - 为了研究多语言prompt的重要性,还将xP3中的英语提示用机器翻译为相应的数据集语言,来生成一个称为
xP3mt
的集合。
模型结构:
- 背景:大多数现代语言模型
都是基于Transformer架构
,但是架构实现之间存在着显著的不同。原始的Transformer是基于encoder-decoder架构的,许多流行的模型仅选择encoder-only或者decoder-only方法。当时,所有超过100B参数的state-of-the-art模型都是decoder-only模型
。 - 问题:在BLOOM的工作之前,现有文献
缺乏不同架构和预训练目标的系统性评估zero-shot泛化能力
。 - 方法:BLOOM研发团队在Wang et al.(2022a)等人的工作中探索了这个问题,其探索了encoder-decoder和decoder-only架构以及与causal、prefix和masked language modeling预训练目标之间的交互作用。BLOOM的结果显示,
经过预训练之后,causal decoder-only模型的表现最好,验证了state-of-the-art LLM的选择。
模型细节-ALIBI:
- 长度的外推性的引入:
- 长度的外推性:在
短序列上训练的模型
,能否不用微调
直接用到长序列上
并依然保持不错的效果 - 原因:允许我们以较低成本(在较短序列上)训练出一个长序列可用的模型
- 长度的外推性:在
ALIBI是第一篇明确研究Transformer长度外推性的工作,它在Softmax之前,将Attention的计算做了修改
:
ALIBI使用与查询键距离成比例的惩罚
,假设两个token距离越远那么相互贡献也就越低,让模型主要关注查询键附近的注意力值
。
λ是超参数,每个head设置不同的值,当head=n时,使用几何序列,以
2
−
8
n
2^{-\frac{8}{n}}
2−n8为起始值,并使用此值为比率,n=8时,λ=
1
2
1
,
1
2
2
,
,
,
1
2
8
{\frac{1}{2^1}},{\frac{1}{2^2}},,,{\frac{1}{2^8}}
211,221,,,281,n=16时,λ=
1
2
0.5
,
1
2
1
,
,
,
1
2
8
{\frac{1}{2^{0.5}}},{\frac{1}{2^1}},,,{\frac{1}{2^8}}
20.51,211,,,281
ALIBI的论文在长度为1024的输入序列上训练了一个13亿个参数的模型,并将其外推到长度为2048的输入序列,实现了与在长度为2048的输入上训练的正弦位置嵌入模型相同的困惑度
,但训练速度提高了11%,并且减少了11%的内存。
模型细节-Embedding Layer Normalization:
- 背景:BLOOM研发团队在
训练104B
参数模型的初步试验中,尝试在嵌入层后立即进行layer normalization
,并发现这可以显著的改善训练稳定性。 - 方法:尽管在一些研究中发现其对zero-shot泛化有惩罚,研发团队还是在BLOOM的
第一个embedding层后添加了额外的layer normalization层来避免训练不稳定性
。 - 参数:初步的104B实验中使用float16,而
最终的训练上使用bfloat16
。因为float16一直被认为是训练LLM时观察的许多不稳定的原因。bfloat16有可能缓解对embedding LayerNorm的需要
。
模型细节-Tokenization:
- 背景:BLOOM研发团队针对
训练数据的多样性
,重新设计并训练了tokenizer以确保以无损的方式编码句子。 - Tokenizer数据集:Tokenizer的训练集来自于ROOTS数据集,对每种语言
使用与训练数据相同的比率进行采样
,并对数据集进行去重
,得到ROOTS数据集的非重复子集。 - 词表尺寸:Tokenizer的词表尺寸决定了embedding矩阵的尺寸,为了GPU运算效率,embedding尺寸必须被128整除,为了使用张量并行必须被4整除。
BLOOM最终使用了250680词表尺寸,具有200个为未来应用保留的token。
- BPE算法(Byte Pair Encoding):tokenizer使用BPE算法进行训练。为了在tokenization的过程中不丢失信息,
tokenizer从bytes开始创建合并
,而不是以字符作为最小单位。这种方式,tokenization永远不会产生未知的tokens
,因为所有256个字节都可以被包含在tokenizer的词表中。- 算法介绍:
每一步都将最常见的一对相邻数据单位替换为该数据中没有出现过的一个新单位,反复迭代直到满足停止条件。
- 算法实现:假设我们有需要编码(压缩)的数据
aaabdaaabac
。- 1)相邻字节对(相邻数据单位在BPE中看作相邻字节对)
aa最常出现
,因此我们将用一个新字节Z替换
它,得到ZabdZabac
,其中Z = aa。 - 2)下一个
常见的字节对是ab
,让我们用Y替换
它,得到ZYdZYac
,其中Z = aa,Y =ab。 - 3)剩下的
唯一字节对是ac
,它只有一个
,所以我们不对它进行编码
。 - 4)我们可以递归地使用字节对编码将
ZY编码为X
,得到XdXac
,其中X = ZY,Y = ab,Z = aa。因为没有出现多次的字节对
,所以它不能被进一步压缩
,
- 1)相邻字节对(相邻数据单位在BPE中看作相邻字节对)
- 算法介绍:
- 规范化:在BPE算法上游,为了尽可能地获得最通用的模型,
没有对文本进行规范化
。如果添加NFKC这样的unicode规范化,在使fertility轻微降低(不超过0.8%)的情况下导致模型通用性降低,例如,导致22和22以相同方法被编码。 - Pre-tokenizer:预分词是对文本进行第一次切分,从而给出tokenizer训练结束时token长度的上限。一个好的思路是,
预分词器将把文本拆分成“单词”,然后,最终tokens将是这些单词的一部分
。 BLOOM的pre-tokenization使用的是的正则表达式:?[^(\S|[.,!?...。,、|_])]+
。- 通过正则表达式将单词分开,同时保留所有的字符,特别是对编程语言至关重要的空格和换行符。
- BLOOM不使用在其他tokenizers中常见的以英文为中心的划分,也没有在数字上使用划分,否则将导致Arabic和code的编码问题。
- 评估:使用 fertility对本文使用的tokenizer(Acs,2019)与现有的单语言tokenizer进行比较。使用目标语言的 Universal Dependencies 2.9 和 OSCAR 子集来衡量。
- 比较结果:
- fertility :每个单词或者每个数据集被 tokenizer 创造的 subword数量
- 原因:
在一个语言上有非常高的 fertility 时,意味着相比于单语言 tokenizer 在下游多语言上的性能下降。
- 目标:多语言 tokenizer 与对应单语言 tokenizer 进行比较时,确保每种语言的 fertility 能力较低不超过10个百分点。
工程架构:
BLOOM模型在Jean Zay上训练,其是由法国政府资助的超级计算机,归属于GENCI所有,由法国国家科学研究中心(CNRS)的国家计算中心IDRIS运行。训练BLOOM花费了3.5个月才完成,并消耗了1082990计算小时。
- GPU概况:384张NVIDIA A100 80GB GPU (48个节点) + 32张备用GPU
- 节点配置:每个节点8张GPU,4条NVLink卡间互联,4条OmniPath链路
- CPU:AMD EPYC 7543 32核处理器
- CPU内存:每个节点512GB
- GPU显存:每个节点640GB
- 节点间连接:使用Omni-Path Architecture (OPA)网卡,网络拓扑为无阻塞网络
- NCCL -通信网络:一个完全专用的子网
- 磁盘IO网络:GPFS与其他节点和用户共享
BLOOM使用Megatron-DeepSpeed(一个用于大规模分布式训练的框架)
训练
- 组成:
- Megatron-LM提供Transformer实现、张量并行和数据加载基本操作
- DeepSpeed提供ZeRO优化器、模型流水线、通过分布式训练组件。
- 训练并行策略:
- 同时使用
DP、PP、TP
这三种并行方式(3D parallelism) - 使用
DeepSpeed ZeRO stage 1
,即仅对优化器参数进行分片。 - 意义:将训练过程扩展至数百个GPU,并具有极高的GPU利用率,能够在A100 GPU的最快配置下实现156 TFLOPs,实现了理论峰值312 TFLOPs的一半。
- 同时使用
模型评估:
SuperGLUE:
- 分类任务评估套件的子集:Ax-b、Ax-g、BoolQ、CB、WiC、WSC和RTE任务
T0:模型是instruction-tuned,因此不能直接和BLOOM以及OPT进行比较
- zero-shot效果:跨提示的平均表现总是徘徊在机会附近。
- one-shot效果:没有显着改善
OPT 和 BLOOM模型系列都随着规模的扩大而略有改善
,并且在所有任务中系列之间没有一致的差异。BLOOM-176B 在 Ax-b、CB 和 WiC 上领先于 OPT-175B
。
LLaMA
LLaMA-1
- 介绍:LLaMA是一组基础语言模型,范围从
7B到65B
参数。它在数万亿tokens上训练,并表明完全可以使用开源的数据集
训练最先进的模型,无需求助于专用或者非开源的数据集。 - 比较:
- LLaMA-13B在
大多数基准测试中的表现都优于GPT-3
(175B),并且LLaMA-65B的性能与性能优异的Chinchilla-70B和PaLM-540B相近。 - LLaMA项目的重点是
使用较小的模型
,通过使用更多的tokens进行训练
,在各种推理预算下实现最佳性能。 Alpaca,Vicuna、Baichuan-7B采用与LLaMA一致的模型结构
。
- LLaMA-13B在
预训练数据:
- 英语CommonCrawl [67%]
- CommonCrawl是一个
公开的网络文本数据集
,它包含了从2008年开始收集的数千亿个网页的原始数据、元数据和文本提取内容。 - LLaMA团队使用 CCNet pipeline 预处理了5个 CommonCrawl dumps,数据集时间跨度从2017年到2020年。此过程
在行级别(line level)消除数据重复
,使用fastText 线性分类器进行语言识别以删除非英语页面
,并使用ngram 语言模型过滤低质量内容
。 - 训练了一个
线性模型对页面分类
,判断是被Wikipedia引用,还是随机采样的页面,对于没有分类为被引用的页面,进行丢弃。
- CommonCrawl是一个
- C4 [15%]
- C4数据集是一个
巨大的、清洗过的Common Crawl网络
爬取语料库。 - 原因:在探索性实验中,观察到使用不同的预处理 CommonCrawl 数据集可以提高性能。因此,将公开可用的 C4 数据集纳入了数据集。
- C4 的预处理还包含
重复数据消除
和语言识别步骤
(language identification steps)。与 CCNet 的主要区别是它的质量过滤主要依赖于启发式
,例如标点符号的存在或网页中的单词和句子的数量。
- C4数据集是一个
- Github [4.5%]
- 使用 Google BigQuery 上提供的公共GitHub数据集。
只保留在 Apache、BSD 和 MIT许可证下的项目
。此外,根据行长度或字母数字字符的比例,使用启发式方法过滤低质量文件
,并使用正则表达式删除样板文件(boilerplate)
,如标题。最后,我们使用精确匹配(exact matches)在文件级别(file level)对生成的数据集进行重复数据消除
。
- 使用 Google BigQuery 上提供的公共GitHub数据集。
- 维基百科 [4.5%]
- 数据集添加了2022年6月至8月期间的维基百科 dumps,涵盖20种语言,它们使用拉丁语或西里尔语脚本:bg、ca、cs、da、de、en、es、fr、hr、hu、it、nl、pl、pt、ro、ru、sl、sr、sv、uk。
删除超链接、注释和其他格式样板
。
- 数据集添加了2022年6月至8月期间的维基百科 dumps,涵盖20种语言,它们使用拉丁语或西里尔语脚本:bg、ca、cs、da、de、en、es、fr、hr、hu、it、nl、pl、pt、ro、ru、sl、sr、sv、uk。
- Gutenberg和Books3 [4.5%]
- 在训练数据集中包括两个图书语料库:Gutenberg Project,其中包含公共领域的图书,以及ThePile的Books3部分,这是一个用于训练大型语言模型的公开数据集。
我们在书本级别执行重复数据消除,当两本书的内容重叠超过90%,就进行删除。
- 在训练数据集中包括两个图书语料库:Gutenberg Project,其中包含公共领域的图书,以及ThePile的Books3部分,这是一个用于训练大型语言模型的公开数据集。
- ArXiv [2.5%]
- 对 arXiv Latex 文件进行处理,从而将科学数据添加到了数据集。
删除了第一节之前的所有内容,以及参考文献,还删除了.tex文件中的注释,以及用户编写的 inline-expanded definitions 和宏,以提高论文之间的一致性。
- 对 arXiv Latex 文件进行处理,从而将科学数据添加到了数据集。
- Stack Exchange [2%]
- 数据集涵盖了一个 Stack Exchange 网站的 dumps,这是一个包含高质量问题和答案的网站,涵盖从计算机科学到化学等多个领域。
保留了28个最大网站的数据,删除了文本中的HTML标记,并按分数(从最高到最低)对答案进行排序。
- 数据集涵盖了一个 Stack Exchange 网站的 dumps,这是一个包含高质量问题和答案的网站,涵盖从计算机科学到化学等多个领域。
Tokenizer:LLaMA使用BPE算法
对数据进行tokenize,使用来自SentencePiece的实现。LLaMA将所有数字拆分为单个数字
,对于未知的UTF-8字符,回退到byte对其进行拆解表示
。
模型架构
模型参数:
LLaMA的模型结构基于Transformer架构
模型架构细节——Pre-Normalization:
- 为了提高训练稳定性,LLaMA
对每个Transformer子层的输入进行归一化
,而不是对输出进行归一化。LLaMA使用了RMSNorm归一化函数
。 - 常用Normalization方式(
LN在F前还是后
):- Post-norm:
- Pre-norm:
- 从梯度传播的角度看,Pre-norm的梯度求解公式为:可以看到,由于
对于当前层的梯度计算,有一个1的导数值
,这样上一层反向传播下来的梯度会被保留
,也就是本层梯度有一部分完全是上一层传递下来的,没有被本层的梯度削减,所以不容易造成梯度消失
。
- 从梯度传播的角度看,Pre-norm的梯度求解公式为:可以看到,由于
- Pre-norm与Post-norm的纷争:
- Post Norm效果优于Pre Norm:
- 《Understanding the Difficulty of Training Transformers》
- 《RealFormer: Transformer Likes Residual Attention》
- Pre-Norm效果优于PostNorm:
- 《On Layer Normalization in the Transformer Architecture》:提出Post Norm对参数非常敏感
- Post Norm效果优于Pre Norm:
关于Pre-norm的一个质疑:一个L层的Pre Norm模型,其实际等效层数不如L层的Post Norm,即等效层数少导致效果变差
。
上式中的每一项都是同一量级的,即t + 1层与t层的差别就在于t + 1项相加与t项相加的区别,当t较大时,新增的一项对总数值影响较小
。
当t比较大时,
x
t
x_t
xt与
x
t
+
1
x_{t+1}
xt+1相差较小,所以
F
t
+
1
(
N
o
r
m
(
x
t
+
1
)
)
F_{t+1}(Norm(x_{t+1}))
Ft+1(Norm(xt+1))与
F
t
+
1
(
N
o
r
m
(
x
t
)
)
F_{t+1}(Norm(x_{t}))
Ft+1(Norm(xt))近似
因此原本一个t层的模型与t + 1层之和,近似等效于一个更宽
的t层,所以在Pre Norm中多层叠加的结果更多是增加了宽度,而非深度,层数越多,层数就越“虚”
。
- RMS norm:RMS Norm是L2 Normalization的简单变体,在RMS Norm的论文中指出:
RMS Norm比Layer Normalization更快(可以在各个模型上减少约7%∼64%的计算时间),效果也基本一致。
- 相比与常规norm,RMS norm的主要区别在于
去掉了减去均值的部分
- 常规norm:
- RMS norm:
- 相比与常规norm,RMS norm的主要区别在于
模型架构细节——SwiGLU:
- Swish 函数: 是一种
自门控(Self-Gated)激活函数
。[Ramachandran et al., 2017]- 自门控(self-gating):使用同样的值进行门控来简化门控机制。
- 特性:
- 参数不变情况下,将模型中ReLU替换为Swish,模型性能提升;
- Swish
无上界
,不会出现梯度饱和; - Swish
有下界
,可以产生更强的正则化效果; - Swish
处处连续可导
。 - 性能不稳定,并非稳定强于ReLU;
- 对比:Swish激活函数和各种主流激活函数在基线性能上的差别,这些对比结果是
通过不同模型(Inception、MobileNet等)在不同数据集(MNIST、CIFAR或ImageNet等)上使用不同激活函数而实现的
- GLU表达式:x的
两个线性映射(linear projection)逐点相乘
,其中一个通过sigmoid函数先进行非线性激活
。- 对比:
- SwiGLU:
模型架构细节——RoPE:
LLaMA删除了绝对位置嵌入,引入了旋转位置嵌入(RoPE)
。
- 复数:
- 表示形式
- 代数形式:
- 向量形式:
- 矩阵形式:
- 推导:
- 假设:
- 转化成一个矩阵和一个向量相乘:
- z 1 z_1 z1可以表示为:
- 总结:复数可以表示为
主对⻆线为实数值
,次对⻆线为虚数值及其负数的形式
- 推导:
- 极坐标形式:
- 推导:z=a+bi,z的向量形式可以进⾏如下转换:
- 指数形式:
- 欧拉公式:
- 共轭复数:
- 复数的模:
- 2D旋转:
- 如果我们跟⼀个复数相乘,那么所做的矩阵变换是:
- 则这个矩阵代表了2D平⾯上的旋转:
- 即:
- 展开代入得:
- 转化成矩阵形式:
- 总结:将任何复数c与z相乘都是
将c逆时针旋转θ度
,并将其缩放
。其中, - 假设 ||z|| = 1,那么复数可以⽤⼀个单位向量表⽰,同时这个乘法只做旋转变换。则平⾯上的旋转可以有矩阵形式:
- 利⽤复数的代数形式:
- 继续利⽤其指数形式:
- 表示形式
- RoPE(Rotary Position Embedding):旋转位置编码,是
苏剑林老师
提出的一种旋转位置编码方法,其思想是采用绝对位置编码的形式,实现相对位置编码
。
推导如下:
我们需要设计一个f,⾸先包含绝对位置信息,并且要求两个不同向量的f的内积包含两者的相对位置信息。
我们假设通过下述运算来给q, k添加绝对位置信息
:
即q,k经过f(·,m),f(·,n)后,
q
m
,
q
k
q_m,q_k
qm,qk就带有了位置m, n的绝对位置信息
由于Attention 的核心运算是内积
,所以我们希望内积的结果带有相对位置信息
。因此存在恒等关系:
我们要求出该恒等式的⼀个(尽可能简单的)解。求解过程还需要一些初始条件,显然我们可以合理地设f(q, 0)=q,f(k, 0)=k
,即没有任何位置信息 时,f(·, 0)等于原值
。
求解:
在复数中有:
其中,Re[]代表复数的实部,上式代表向量q与向量k的乘积
,等于复数q与复数k的共轭复数k*相乘的实部
。
举个例子:
- [3,5]对应的复数为3+5i
- [1,6]对应的复数为1+6i,其共轭复数为1-6i
- 则向量内积:[3,5]*[1,6]T=33
- 复数与共轭复数相乘:(3+5i)(1-6i)=33-13i,且Re[33-13i]=33
我们将此式
带入复数表达式:
为了简单起见,我们直接假设存在复数g(q,k,m-n),使得:
我们⽤复数的指数形式
对其进⾏表⽰,其中,R代表向量模⻓。:
那么代⼊⽅程后就得到⽅程组(共轭复数,所以虚部系数为负值):
如果我们根据⽅程组求出了 R f R_f Rf(q,m)和 θ f θ_f θf(q,m)的表达式,也就求解出了f(·,m)的表达式。
方程一推导:
对于第⼀个⽅程,代⼊m=n得到:
最后⼀个等号源于初始条件f(q,0)=q,f(k,0)=k。(因为m=0时,f(q,0)=q,⽽
R
f
R_f
Rf为模⻓,因此就是q的模⻓)
现在我们可以很简单地设:
即它不依赖于m
。
结论⼀:R(q,m)=||q||
方程二推导:
对于第⼆个⽅程,同样带⼊m=n得到:
这⾥的Θ(q), Θ(k)是q, k本⾝的幅⻆,最后⼀个等号同样源于初始条件。根据上式得到:
所以q和k并没有影响
Θ
f
(
q
,
m
)
−
Θ
(
q
)
Θ_f(q, m) - Θ(q)
Θf(q,m)−Θ(q)的值,所以上式应该是⼀个只与m相关,跟q⽆关的函数,记为
φ
(
m
)
\varphi(m)
φ(m),即:
原始的⽅程⼆为:
带⼊n=m-1,得:
即{
φ
(
m
)
\varphi(m)
φ(m)}是等差数列,设右端为θ,那么就解得
φ
(
m
)
\varphi(m)
φ(m)=mθ。
结论二:Θ(q,m)=Θ(q)+ φ ( m ) \varphi(m) φ(m)=Θ(q)+mθ
编码形式:
综上,我们得到⼆维情况下⽤复数表⽰的RoPE:
最后一步推导:
根据复数乘法的⼏何意义
,该变换实际上对应着向量的旋转
,所以我们称之为“旋转式位置编码
”,它还可以写成矩阵形式:
相当于q通过乘以⼀个||z||=1的虚数,实现了向量旋转
由于内积满⾜线性叠加性,因此任意偶数维的RoPE,我们都可以表⽰为⼆维情形的拼接,即:
也就是说,给位置为m的向量q乘上矩阵
W
m
W_m
Wm、位置为n的向量k乘上矩阵
W
n
W_n
Wn,⽤变换后的Q,K序列做Attention,那么Attention就⾃动包含相对位置信息了,因为成⽴恒等式:
其中:
W
m
W_m
Wm是⼀个正交矩阵,它不会改变向量的模⻓,因此通常来说它不会改变原模型的稳
定性
由于
W
m
W_m
Wm的稀疏性,所以直接⽤矩阵乘法来实现会很浪费算⼒,推荐通过下述⽅式来实现RoPE(结果完全⼀致,避免稀疏矩阵乘法
):
其中⊗是逐位对应相乘,即计算框架中*的运算。从这个实现也可以看到,RoPE可以视为是乘性位置编码的变体。
远程衰减特性:
RoPE能够带来⼀定的远程衰减特性
(不同位置的position encoding点乘结果会随着相对位置的增加⽽递减
):
RoPE效果:
苏剑林团队使⽤RoPE改造了WoBERT模型
,得到RoFormer模型
,它跟其他模型的结构对⽐如下:
在训练上,以WoBERT Plus为基础
,采⽤了多个⻓度和batch size交替训练的⽅式,让模型能提前适应不同的训练场景:
从表格还可以看到,增⼤序列⻓度,预训练的准确率反⽽有所提升
,这侧⾯体现了RoFormer⻓⽂本语义的处理效果,也体现了RoPE具有良好的外推能⼒
。在短⽂本任务上,RoFormer与WoBERT的表现类似,RoFormer的主要特点是可以直接处理任意⻓的问题。下⾯是在CAIL2019-SCM任务上的实验结果:
结论:
- 从理论上来看,RoPE与
Sinusoidal位置编码有些相通之处
,但RoPE不依赖于泰勒展开
,更具严谨性与可解释性; - 从预训练模型RoFormer的结果来看,RoPE具有
良好的外推性
,应⽤到Transformer中体现出较好的处理⻓⽂本的能⼒。 - 此外,RoPE还是
⽬前唯⼀⼀种
可⽤于线性Attention的相对位置编码
。
模型架构细节——AdamW:
- Adam:Adam方法将
惯性保持(动量)和自适应
这两个优点集于一身。- Adam记录梯度的
一阶矩(firstmoment)
,即过往梯度与当前梯度的平均
,这体现了惯性保持
: - Adam还记录梯度的
二阶矩(secondmoment)
,即过往梯度平方与当前梯度平方的平均
,这类似AdaGrad方法,体现了自适应能力
,为不同参数产生自适应的学习速率: - 一阶矩和二阶矩采用类似于滑动窗口内求平均的思想进行融合,即
当前梯度和近一段时间内梯度的平均值,时间久远的梯度对当前平均值的贡献呈指数衰减
。 - 其中,β1,β2为衰减系数,β1通常取值0.9,β2通常取值0.999,mt是一阶矩,vt是二阶矩。
- 其中,mt^ 和 vt^ 是mt、vt偏差矫正之后的结果。
- Adam记录梯度的
- 正则化项
- 机器学习中经常会
在损失函数中添加一个正则化项
,常用的额外项一般有两种,记作L1-norm 和 L2-norm
,即L1 正则化项和 L2 正则化项
,或L1 范数,L2 范数
。- 大白话理解:L1正则化和L2正则化可以看做是
损失函数的惩罚项
:对损失函数中的某些参数做一些限制
。 - 原因:数据集中的
噪声点
往往需要比较大的w值来拟合
,也就是说w越大,模型的曲线越“陡峭”
,因而网络模型能够更好得拟合噪声点
,但也引起了过拟合
。 - 方法:l1和l2正则化都是
通过减小权值w,使某些神经元的作用变小
甚至可以勿略,从而降低网络模型的复杂度来防止过拟合。这与dropout通过以一定的概率丢弃神经元
的做法在效果上是相似的。
- 大白话理解:L1正则化和L2正则化可以看做是
- 机器学习中经常会
真正重要的模型参数可能并不多
- 方法:
- 保留
尽可能少的重要的参数可以减弱非重要特征的波动带来的模型预测影响,防止过拟合
,使模型的泛化效果更好。 参数变少可以使整个模型获得更好的可解释性
,而且还可以用做特征选择。
- 保留
复杂的模型,其参数值会比较大
-
原因:
越复杂的模型,越是会尝试对所有的样本进行拟合,这就容易造成在较小的区间里预测值产生较大的波动
,对于一些异常样本点波动就更大,这种较大的波动也反映了在这个区间里的导数很大,而只有较大的参数值才能产生较大的导数。相反地,参数小,则导数小,则对于样本特征的波动具有鲁棒性,那么模型能更好地防止过拟合,泛化效果会更好
。 -
AdamW:
- AdamW 与 Adam 对比,主要是
修改了权重衰减计算的方式
。 - Adam:在
损失函数中加入了 L2 正则化项
,也就是把权重衰减放到了梯度里,由梯度间接缩小θ
,但是这种方法并没有起到有效的正则化作用
。 - Adam-W:AdamW
直接将权重衰减项放到权重计算中
,可以在自适应地调整学习率的同时,对大的权重进行惩罚
,起到了有效的正则化作用。
- AdamW 与 Adam 对比,主要是
模型架构细节——LR-Scheduler:
- LLaMA使用
cosine
模式的LR-Scheduler,使得最终学习速率等于最大学习速率的10%。 - 使用了
0.1的权重衰减和1.0的梯度裁剪
。 - 使用
2000个warmup步骤
,并根据模型的大小改变学习速度和批量大小。
模型评估:
- 常识推理:
- LLaMA-65B在除BoolQ之外的所有报告基准上均优于Chinchilla-70B。类似地,除了BoolQ和WinoGrande之外,这款模型在任何地方都超过了PaLM540B。尽管
LLaMA-13B模型比GPT-3小10倍
,但在大多数基准测试中,LLaMA-13模型的性能也优于GPT-3
。 LLaMA-65B在zero-shot和few-shot设置中实现了最先进的性能
。更重要的是,LLaMA-13B在这些基准测试中与GPT-3和Chinchilla相比也具有竞争力,尽管更小5-10倍
。在推理过程中,该模型在单个V100 GPU上运行
。
- LLaMA-65B在除BoolQ之外的所有报告基准上均优于Chinchilla-70B。类似地,除了BoolQ和WinoGrande之外,这款模型在任何地方都超过了PaLM540B。尽管
- 阅读理解:LLaMA-65B与PaLM-540B相比具有竞争力,并且LLaMA-13B比GPT-3好几个百分点。
- 数学推理:在GSM8k上,我们观察到LLaMA65B优于Minerva-62B,尽管它还
没有根据数学数据进行微调
。 - 代码生成:对于相同数量的参数,LLaMA优于其他通用模型,如LaMDA和PaLM,这些模型没有专门针对代码进行训练或微调。具有13B参数的LLaMA在HumanEval和MBPP上均优于LaMDA 137B。即使训练时间更长,LLaMA 65B也优于PaLM 62B。
- 大规模多任务语言理解:LLaMA-65B在大多数领域平均落后于Chinchilla70B和PaLM-540B几个百分点。一种可能的解释是,
LLaMA在预训练的数据中使用了有限数量的书籍和学术论文。
对instruction数据的短暂微调可以快速改进在MMLU上的表现。基于instruction数据训练的模型称为LLaMA-I:
Alpace
🔗官方链接:https://crfm.stanford.edu/2023/03/13/alpaca.html
🔗官方Git:tatsu-lab/stanford_alpaca
🔗官方模型:https://huggingface.co/tatsu-lab/alpaca-7b-wdiff
Alpaca是一个instruction-following language model
,从Meta的LLaMA 7B模型中微调
而来的。
训练过程:
Alpaca采用OpenAI的Text-davinci-003
API配合self-instruc
t技术,使用175个self-instruct seed自动生成了52K条instruction-following的指示数据集,在LLaMa-7B上微调得到的模型,在8张80G的A100上训练了3小时
。
在self-instruct评估集上,Alpaca表现出许多接近于OpenAI的text-davinci-003的表现
,但他非常小且易于(成本低)
重现。
SELF-INSTRUCT
:无需人工标注,自生成指令框架
- 论文名称:Self-Instruct: Aligning Language Models with Self-Generated Instructions
- 论文地址:https://arxiv.org/pdf/2212.10560.pdf
- 论文代码:https://github.com/yizhongw/self-instruct
- 摘要总结:
提出了一种Bootstrap方案来让LLM基于种子指令生成新的指令的指令扩充方案
- 问题:如何
降低指令数据集的人工标注成本
- 方法:
- 指令生成:首先作者人工构建了175个种子指令,这些种子指令由1条指令和1个样本构成。每个Step作者会从中采样8个指令,其中6个来自以上种子,2个来自LLM生成的指令,当然step1全部都是种子指令。然后基于如下的prompt模板构建模型输入
"""
Come up with a series of tasks:
Task 1: {instruction for existing task 1}
Task 2: {instruction for existing task 2}
Task 3: {instruction for existing task 3}
Task 4: {instruction for existing task 4}
Task 5: {instruction for existing task 5}
Task 6: {instruction for existing task 6}
Task 7: {instruction for existing task 7}
Task 8: {instruction for existing task 8}
Task 9:
"""
- 分类任务识别:判断生成的指令
是否是一个分类任务
,将分类任务定义为output的标签是一个有限的小的标签集合的任务
。
是否是分类任务也是由模型来判断的,使用few-shot方式
来实现:
- 实例生成
- 对于非分类任务,采用
Input-first Approach
,也就是先让LLM对于指令先生成一个输入(input)
,再生成对应的输出(output)
(如果任务不需要input,就直接生成结果)。对应的prompt模板如下(论文中的table 7):
Come up with examples for the following tasks. Try to generate multiple examples when possible. If the task doesn't require additional input, you can generate the output directly.
Task: Which exercises are best for reducing belly fat at home?
Output:
- Lying Leg Raises
- Leg In And Out
- Plank
- Side Plank
- Sit-ups
Task: Extract all the country names in the paragraph, list them separated by commas.
Example 1
Paragraph: Dr. No is the sixth novel by the English author Ian Fleming to feature his British Secret Service agent James Bond. Written at Fleming's Goldeneye estate in Jamaica, it was first published in the United Kingdom by Jonathan Cape in 1958. In the novel Bond looks into the disappearance in Jamaica of two fellow MI6 operatives who had been investigating Doctor No. Bond travels to No's Caribbean island and meets Honeychile Rider, who is there to collect shells. They are captured and taken to a luxurious facility carved into a mountain. The character of Doctor No, the son of a German missionary and a Chinese woman, was influenced by Sax Rohmer's Fu Manchu stories. Dr. No was the first of Fleming's novels to face widespread negative reviews in Britain, but it was received more favourably in the United States.
Output: English, British, Jamaica, the United Kingdom, German, Chinese, Britain, the United States.
Task: Converting 85 F to Celsius.
Output: 85°F = 29.44°C
Task: Sort the given list ascendingly.
Example 1
List: [10, 92, 2, 5, -4, 92, 5, 101]
Output: [-4, 2, 5, 5, 10, 92, 92, 101]
Example 2
Input 2 - List: [9.99, 10, -5, -1000, 5e6, 999]
Output: [-1000, -5, 9.99, 10, 999, 5e6]
Task: Suggest a better and more professional rephrasing of the following sentence.
Example 1
Sentence: This house is surprisingly not constructed very well, and you probably need more money to fix it after you buy it. If you ask me, I would suggest you to consider other candidates.
Output: This house does not seem to be constructed well, so you may need to spend more money to fix it after you purchase it. I would suggest that you look at other properties.
Example 2
Sentence: Just so you know, we did an experiment last week and found really surprising results - language model can improve itself!
Output: Our experiments last week demonstrated surprising results, proving that the language model can improve itself.
Task: Read the following paragraph and answer a math question about the paragraph. You need to write out the calculation for getting the final answer.
Example 1
Paragraph: Gun violence in the United States results in tens of thousands of deaths and injuries annually, and was the leading cause of death for children 19 and younger in 2020. In 2018, the most recent year for which data are available as of 2021, the Centers for Disease Control and Prevention's (CDC) National Center for Health Statistics reports 38,390 deaths by firearm, of which 24,432 were by suicide. The rate of firearm deaths per 100,000 people rose from 10.3 per 100,000 in 1999 to 12 per 100,000 in 2017, with 109 people dying per day or about 14,542 homicides in total, being 11.9 per 100,000 in 2018. In 2010, there were 19,392 firearm-related suicides, and 11,078 firearm-related homicides in the U.S. In 2010, 358 murders were reported involving a rifle while 6,009 were reported involving a handgun; another 1,939 were reported with an unspecified type of firearm. In 2011, a total of 478,400 fatal and nonfatal violent crimes were committed with a firearm.
Question: How many more firearm-related deaths were there in 2018 compared to 2010?
Output:
38390 - (19392 + 11078) = 38390 - 30470 = 7920.
So, in 2018, there were 7920 more deaths by firearm than in 2010.
Task: Write Python code to solve this leetcode problem.
Example 1
Problem: You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Output:
class Solution(object):
def addTwoNumbers(self, l1, l2):
carry = 0
root = n = ListNode(0)
while l1 or l2 or carry:
v1 = v2 = 0
if l1:
v1 = l1.val
l1 = l1.next
if l2:
v2 = l2.val
l2 = l2.next
carry, val = divmod(v1+v2+carry, 10)
n.next = ListNode(val)
n = n.next
return root.next
Task: Solve the equation and find the value of X. Show your steps.
Example 1
Equation: 10X + 5 = 10
Output: 10X = 5, X = 0.5
Example 2
Equation: X + Y + 120 = 100
Output: X + Y = -20, X = -20 - Y
Task: Write a program to compute the sum of integers from k to n.
Output:
def sum(k, n):
sum = 0
for i in range(k, n+1):
sum += i
return sum
Task: Select the oldest person from the given list.
Example 1
List: George Washington, Confucius, Michael Jordan, Michelangelo
Output: Confucious
Example 2
List: Alan Turing, Geoffrey Hinton, Yann LeCun, Yoshua Bengio
Output: Alan Turing
Task: Turn down a job offer by sending an email to a recruiter explaining the reason.
Output: Hi [Recruiter],
Thank you so much for the generous offer to join your team. As we discussed, I’ve admired the company for a number of years, and am a proud endorser of its products. However, after further consideration of where I currently am in my career, I’ve decided to accept an offer at another company.
I would love to stay in touch with you and have already started following you on [Social Media Platform]. Again, thank you so much for your time and consideration.
Thanks again,
[Your Name]
Task: {Instruction for the target task}
- 对于分类任务,采用
Output-first Approach
,先生成一个可能的类别标签
,再在类别标签的条件下生成input
,prompt模板如下(Table 8):
Given the classification task definition and the class labels, generate an input that corresponds to each of the class labels. If the task doesn't require input, just generate possible class labels.
Task: Classify the sentiment of the sentence into positive, negative, or mixed.
Class label: mixed
Sentence: I enjoy the flavor of the restaurant but their service is too slow.
Class label: Positive
Sentence: I had a great day today. The weather was beautiful and I spent time with friends and family.
Class label: Negative
Sentence: I was really disappointed by the latest superhero movie. I would not recommend it to anyone.
Task: Given a dialogue, classify whether the user is satisfied with the service. You should respond with "Satisfied" or "Unsatisfied".
Class label: Satisfied
Dialogue:
- Agent: Thank you for your feedback. We will work to improve our service in the future.
- Customer: I am happy with the service you provided. Thank you for your help.
Class label: Unsatisfied
Dialogue:
- Agent: I am sorry we will cancel that order for you, and you will get a refund within 7 business days.
- Customer: oh that takes too long. I want you to take quicker action on this.
Task: Given some political opinions, classify whether the person belongs to Democrats or Republicans.
Class label: Democrats
Opinion: I believe that everyone should have access to quality healthcare regardless of their income level.
Class label: Republicans
Opinion: I believe that people should be able to keep more of their hard-earned money and should not be taxed at high rates.
Task: Tell me if the following email is a promotion email or not.
Class label: Promotion
Email: Check out our amazing new sale! We've got discounts on all of your favorite products.
Class label: Not Promotion
Email: We hope you are doing well. Let us know if you need any help.
Task: Detect if the Reddit thread contains hate speech.
Class label: Hate Speech
Thread: All people of color are stupid and should not be allowed to vote.
Class label: Not Hate Speech
Thread: The best way to cook a steak on the grill.
Task: Does the information in the document supports the claim? You can answer "Support" or "Unsupport".
Class label: Unsupport
Document: After a record-breaking run that saw mortgage rates plunge to all-time lows and home prices soar to new highs, the U.S. housing market finally is slowing. While demand and price gains are cooling, any correction is likely to be a modest one, housing economists and analysts say. No one expects price drops on the scale of the declines experienced during the Great Recession.
Claim: The US housing market is going to crash soon.
Class label: Support
Document: The U.S. housing market is showing signs of strain, with home sales and prices slowing in many areas. Mortgage rates have risen sharply in recent months, and the number of homes for sale is increasing. This could be the beginning of a larger downturn, with some economists predicting a potential housing crash in the near future.
Claim: The US housing market is going to crash soon.
Task: Answer the following multiple-choice question. Select A, B, C, or D for the final answer.
Class label: C
Question: What is the capital of Germany?
A. London
B. Paris
C. Berlin
D. Rome
Class label: D
Question: What is the largest planet in our solar system?
A) Earth
B) Saturn
C) Mars
D) Jupiter
Class label: A
Question: What is the process by which plants make their own food through photosynthesis?
A) Respiration
B) Fermentation
C) Digestion
D) Metabolism
Class label: B
Question: Who wrote the novel "The Great Gatsby"?
A) Ernest Hemingway
B) F. Scott Fitzgerald
C) J.D. Salinger
D) Mark Twain
Task: You need to read a code and detect if there is a syntax error or not. Output true if there is an error, output false if there is not.
Class label: true
Code:
def quick_sort(arr):
if len(arr) < 2
return arr
Class label: False
Code:
def calculate_average(numbers):
total = 0
for number in numbers:
total += number
return total / len(numbers)
Task: You are provided with a news article, and you need to identify all the categories that this article belongs to. Possible categories include Sports and Politics. Output its categories one by one, separated by a comma.
Class label: Sports
Article: The Golden State Warriors have won the NBA championship for the second year in a row.
Class label: Politics
Article: The United States has withdrawn from the Paris Climate Agreement.
Class label: Politics, Sports
Article: The government has proposed cutting funding for youth sports programs.
Task: Given a credit card statement, the cardholder's spending habits, and the account balance, classify whether the cardholder is at risk of defaulting on their payments or not.
Class label: At risk
Credit card statement: Purchases at high-end clothing stores and luxury hotels.
Cardholder's spending habits: Frequent purchases at luxury brands and high-end establishments.
Account balance: Over the credit limit and multiple missed payments.
Class label: Not at risk
Credit card statement: Purchases at grocery stores and gas stations.
Cardholder's spending habits: Regular purchases for necessary expenses and occasional dining out.
Account balance: Slightly below the credit limit and no missed payments.
Task: Given a social media post, the hashtags used, and a topic. classify whether the post is relevant to the topic or not.
Class label: Relevant
Post: I can't believe the government is still not taking action on climate change. It's time for us to take matters into our own hands.
Hashtags: #climatechange #actnow
Topic: Climate change
Class label: Not relevant
Post: I just bought the new iPhone and it is amazing!
Hashtags: #apple #technology
Topic: Travel
Task: The answer will be 'yes' if the provided sentence contains an explicit mention that answers the given question. Otherwise, answer 'no'.
Class label: Yes
Sentence: Jack played basketball for an hour after school.
Question: How long did Jack play basketball?
Class label: No
Sentence: The leaders of the Department of Homeland Security now appear before 88 committees and subcommittees of Congress.
Question: How often are they required to appear?
Task: Tell me what's the second largest city by population in Canada.
Class label: Montreal
Task: Classifying different types of mathematical equations, such as linear, and quadratic equations, based on the coefficients and terms in the equation.
Class label: Linear equation
Equation: y = 2x + 5
Class label: Quadratic equation
Equation: y = x^2 - 4x + 3
Task: Tell me the first number of the given list.
Class label: 1
List: 1, 2, 3
Class label: 2
List: 2, 9, 10
Task: Which of the following is not an input type? (a) number (b) date (c) phone number (d) email address (e) all of these are valid inputs.
Class label: (e)
Task: {Instruction for the target task}
- 过滤和后处理
为了保证指令的多样性,一个指令只有与任务池中已有的指令的ROUGE-L小于0.7
才会被考虑加入到任务池
,同时过滤掉包含一些特殊词
(如image/picture/graph等)的生成指令,因为这些指令LLM还不会处理。(注:虽然过滤是在论文中的第四个步骤,但是代码实现时,对于指令的过滤是在第一步生成指令的时候就过滤了不满足要求的指令
,当任务池中的指令达到生成数量比如52k后就停止第一步的指令生成
)
## 开源代码 https://github.com/yizhongw/self-instruct/blob/main/self_instruct/bootstrap_instructions.py#L41C1-L71C1
def post_process_gpt3_response(response):
if response is None or response["choices"][0]["finish_reason"] == "length":
return []
raw_instructions = re.split(r"\n\d+\s?\. ", response["choices"][0]["text"])
instructions = []
for inst in raw_instructions:
inst = re.sub(r"\s+", " ", inst).strip()
inst = inst.strip().capitalize()
if inst == "":
continue
# filter out too short or too long instructions
if len(inst.split()) <= 3 or len(inst.split()) > 150:
continue
# filter based on keywords that are not suitable for language models.
if any(find_word_in_string(word, inst) for word in ["image", "images", "graph", "graphs", "picture", "pictures", "file", "files", "map", "maps", "draw", "plot", "go to"]):
continue
# We found that the model tends to add "write a program" to some existing instructions, which lead to a lot of such instructions.
# And it's a bit comfusing whether the model need to write a program or directly output the result.
# Here we filter them out.
# Note this is not a comprehensive filtering for all programming instructions.
if inst.startswith("Write a program"):
continue
# filter those starting with punctuation
if inst[0] in string.punctuation:
continue
# filter those starting with non-english character
if not inst[0].isascii():
continue
instructions.append(inst)
return instructions
对于生成的实例,过滤掉重复的、过滤掉与相同input不同output的实例。并用启发式方法识别和过滤掉一些实例,比如是否太长、是否太短、输出是输入的重复等。
## 论文开源代码 https://github.com/yizhongw/self-instruct/blob/main/self_instruct/prepare_for_finetuning.py#L110C1-L192C1
def filter_duplicate_instances(instances):
# if the instances have same non-empty input, but different output, we will not use such instances
same_input_diff_output = False
for i in range(1, len(instances)):
for j in range(0, i):
if instances[i][1] == "":
continue
if instances[i][1] == instances[j][1] and instances[i][2] != instances[j][2]:
same_input_diff_output = True
break
if same_input_diff_output:
return []
# remove duplicate instances
instances = list(set(instances))
return instances
def filter_invalid_instances(instances):
filtered_instances = []
for instance in instances:
# if input and output are the same, we will not use such instances
if instance[1] == instance[2]:
continue
# if output is empty, we will not use such instances
if instance[2] == "":
continue
# if input or output ends with a colon, these are usually imcomplete generation. We will not use such instances
if instance[1].strip().endswith(":") or instance[2].strip().endswith(":"):
continue
filtered_instances.append(instance)
return filtered_instances
def parse_instances_for_generation_task(raw_text, instruction, response_metadata):
instances = []
raw_text = raw_text.strip()
if re.findall("Example\s?\d*\.?", raw_text):
instance_texts = re.split(r"Example\s?\d*\.?", raw_text)
instance_texts = [it.strip() for it in instance_texts if it.strip() != ""]
for instance_text in instance_texts:
inst_input, inst_output = parse_input_output(instance_text)
instances.append((instruction.strip(), inst_input.strip(), inst_output.strip()))
elif re.findall(r"Output\s*\d*\s*:", raw_text):
# we assume only one input/output pair in this case
inst_input, inst_output = parse_input_output(raw_text)
instances.append((instruction.strip(), inst_input.strip(), inst_output.strip()))
else:
return []
# if the generation stops because of length, we remove the last instance
if response_metadata["response"]["choices"][0]["finish_reason"] == "length":
instances = instances[:-1]
instances = filter_invalid_instances(instances)
instances = filter_duplicate_instances(instances)
return instances
def parse_instances_for_classification_task(raw_text, instruction, response_metadata):
instances = []
if not "Class label:" in raw_text:
return []
instance_texts = raw_text.split("Class label:")[1:]
for instance_text in instance_texts:
instance_text = instance_text.strip()
fields = instance_text.split("\n", 1)
if len(fields) == 2:
# the first field split by \n is the class label
class_label = fields[0].strip()
# the rest is the input
input_text = fields[1].strip()
elif len(fields) == 1:
# the first field split by \n is the input
class_label = fields[0].strip()
input_text = ""
else:
raise ValueError("Invalid instance text: {}".format(instance_text))
instances.append((instruction.strip(), input_text.strip(), class_label.strip()))
# if the generation stops because of length, we remove the last instance
if response_metadata["response"]["choices"][0]["finish_reason"] == "length":
instances = instances[:-1]
instances = filter_invalid_instances(instances)
instances = filter_duplicate_instances(instances)
return instances
Vicuna
介绍:
- Vicuna为LLaMA使用
对话数据有监督微调
后的一个ChatBot(7B & 13B)
。 - Vicuna是由UC Berkeley大学主导开发的,精调过程中使用了
大量用户分享的ShareGPT对话数据
。 - Vicuna宣称自己拥有“
ChatGPT 90%的能力
”。
训练:
- 研究人员从ShareGPT(一个供用户分享ChatGPT对话内容的网站)
收集了约7万个对话
,并增强了Alpaca提供的训练脚本
,以更好地处理多轮对话和长序列; - 训练是在一天内
通过8卡A100 GPU配合PyTorch FSDP进行的full fine-tune
。 - 为了提供演示服务,Vicuna研究人员建立了一个
轻量级的分布式服务系统
; - 创建了
八个问题类别
(如:角色扮演、编码/数学任务等)的80个不同问题,利用GPT-4来判断模型输出,借此对模型质量做初步评估。为了比较两个不同的模型,Vicuna研究人员将每个模型的输出组合成每个问题的单个提示。然后将提示发送到GPT-4,GPT-4评估
哪个模型提供更好的响应。
总结:
模型 | LLaMA | Alpaca | Vicuna |
---|---|---|---|
数据集 | 公开可用的数据集 (1T token) | Self-instruct from davinci- 003 API (52K samples) | 用户共享对话 (70K samples) |
训练代码 | 未开源 | 开源 | 开源 |
评估指标 | Academic benchmark | self-instruct evaluation | GPT-4 |
训练费用(7B) | 82K GPU-hours | $500 (data) + $100 (training) | $140 (training) |
训练费用(13B) | 135K GPU-hours | N/A | $300 (training) |
LLaMA-2
介绍:
- Llama 2模型提供
7B、13B和70B
三个版本,使用2万亿个token训练
,上下文长度是Llama 1的两倍。Llama-2-chat
模型还接受了超过10万条SFT数据训练和100万个人类偏好数据训练
。 - Llama 2训练
语料相比LLaMA多出40%
,上下文长度是由之前的2048升级到4096
,可以理解和生成更长的文本。
训练:Llama 2使用公开数据集进行预训练
,然后通过SFT进行有监督训练
,最后使用RLHF进行迭代细化
。
训练语料:Llama 2的训练语料中中文
占比0.13%
,因此中文支持依然较差
。
损失函数:
不同数据集上的效果:
LLaMA-3
Baichuan
Baichuan-1
介绍:
- baichuan-7B是由百川智能开发的一个开源的大规模预训练模型。
基于Transformer结构
,在大约1.2万亿tokens
上训练的70亿参数模型
,支持中英双语
,上下文窗口长度为4096
。在标准的中文和英文权威benchmark(C-EVAL/MMLU)上均取得同尺寸最好的效果。 - 不同于LLaMA完全禁止商业使用,baichuan-7B使用更宽松的开源协议,允许用于商业目的。
数据集:
原始数据包括开源的中英文数据和自行抓取的中文互联网数据,以及部分高质量知识性数据。
参考相关数据工作,频率
和质量
是数据处理环节重点考虑的两个维度。我们基于启发式规则和质量模型打分,对原始数据集进行篇章和句子粒度的过滤
。在全量数据上,利用局部敏感哈希方法,对篇章和句子粒度做滤重
。
- 经过不断的调整和多轮测试,最终确认了一个在下游任务上表现最好的中英文配比。
- 使用了一个基于自动学习的数据权重策略,对不同类别的数据进行配比。
分词:
分词使用SentencePiece中的Byte-Pair Encoding (BPE)作为分词算法
,并且进行了以下的优化:
- 使用2000万条以
中英
为主的多语言语料训练分词模型,显著提升对于中文的压缩率。 - 对于数学领域,参考了LLaMA和Galactica中的方案,
对数字的每一位单独分开
,避免出现数字不一致的问题,对于提升数学能力有重要帮助。 - 对于罕见字词(如特殊符号等),
支持UTF-8 characters的byte编码
,因此做到未知字词的全覆盖。
模型结构:
rotary-embedding
- 激活层采用
SwiGLU
,Feedforward变化为8/3倍的隐含层大小
,即11,008 - 基于
RMSNorm的Pre-Normalization
Baichuan在千卡A800显卡上达到了7B模型182 TFLOPS的吞吐,GPU峰值算力利用率高达58.3%。
Baichuan-2
介绍:
baichuan2基于2.6万亿tokens
训练,上下文窗口长度为4096
。提供7B和13B参数的Base和Chat版本,在多个权威的中文、英文和多语言的通用、领域benchmark上取得同尺寸最佳的效果。
数据源:
Baichuan2的数据来自多种来源,包括普通的互联网网页、书籍、研究论文、代码库等,以构建一个广泛的世界知识系统。
模型结构:
- 位置编码
- Baichuan2在其
7B版本
中采用了旋转位置嵌入(Rotary Positional Embedding, RoPE)
- Baichuan2在其
13B版本
中,采用了ALiBi
(由Press等人于2021年提出)。ALiBi是一个较新的位置编码技术,已经显示出了改进的外推性能
。
- Baichuan2在其
- Baichuan2使用
SwiGLU
作为激活函数。 - Baichuan2采用了由
xFormers2
实现的内存高效注意力。 - Baichuan2使用了
Layer Normalization
,采用RMSNorm
实现。
模型训练:
Baihuan2的超参数设置:
- 训练时使用了
AdamW优化器
,其中β1设置为0.9,β2设置为0.95; - 使用了
0.1的权重衰减
,并将梯度范数裁剪到0.5
; - 模型的学习率首先经过
2,000步的线性缩放预热
到最大学习率,然后应用余弦衰减
到最小学习率; - 整个模型使用
BFloat16混合精度
进行训练;
ChatGLM
ChatGLM-1
介绍:
ChatGLM模型是由清华大学开源
的、支持中英双语问答的对话语言模型,并针对中文进行了优化
。该模型基于General Language Model(GLM)
架构,具有62亿参数
。结合模型量化技术,用户可以在消费级的显卡上进行本地部署
。
模型:
- GLM-130B在一个由
96个NVIDIA DGX-A100(8 * 40G)GPU节点
组成的集群上进行训练,每个节点有8张A100 GPU,每张GPU负责1.35亿个参数; - GLM-130B使用了
ZeRO作为优化器
,它可以有效地减少显存占用和通信开销,提高训练效率; - GLM-130B使用了
混合精度训练
(Mixed Precision Training)和梯度累积
(GradientAccumulation)提高训练速度和稳定性; - GLM-130B的总参数量是
1300亿
,其中编码器占了60%,解码器占了40%; - GLM-130B使用了
字节对编码(BPE)
作为词表,共有50万个词,其中25万个是英语词,25万个是汉语词。
模型评估:
- 英文:
- 中文:
- 准确性、鲁棒性、公平性:
GLM原理:
GLM要一统天下,只需要同时存在单向注意力和双向注意力
即可。而在Transformer中,这两种注意力机制是通过修改attention mask
实现的。
- 当
attention_mask是全1矩阵
的时候,这时注意力是双向
的(Encoder) - 当
attention_mask是三角矩阵
的时候(Deccoder中Masked Multi-head Attention
),注意力就是单向
。
GLM uses a single Transformer with several modifications to the architecture: (1) werearrange the order of layer normalization and the residual connection, which has beenshown critical for large-scale language models to avoid numerical errors (Shoeybi et al.,2019); (2) we use a single linear layer for the output token prediction; (3) we replace ReLUactivation functions with GeLUs (Hendrycks and Gimpel, 2016).
GLM使用单个Transformer
,并对架构进行了多项修改:
- 修改了Layer-normalization和残差连接的顺序;
- 使用单个线性层进行输出标记预测;
- 用GeLU替换ReLU激活函数。
GLM提出一个Autoregressive Blank Infifilling任务
,来兼容三种预训练目标。
自回归空格填充类似MLM任务,将输入的部分内容替换为[MASK]标记,然后预测[MASK]所对应的文本片段
。与MLM不同的是,预测的过程是采用自回归
的方式。
GLM预训练阶段:
预训练阶段,选择掩码较长的文本片段,以确保GLM的文本生成能力
,并在微调阶段将自然语言理解任务也转化为生成任务
。
作者使用了两个预训练目标来优化GLM,两个目标交替进行:
文档级别
:从文档中随机采样一个文本片段进行掩码,片段的长度为文档长度的50%-100%。句子级别
:从文档中随机掩码若干文本片段,每个文本片段必须为完整的句子,被掩码的词数量为整个文档长度的15%。
GLM微调:
为了适应预训练的目标,微调阶段的NLU任务转化为Prompt-Tuning形式
,如下图所示:
GLM评估:
GLM消融实验:
ChatGLM-2
- 介绍:ChatGLM2-6B是开源中英双语对话模型ChatGLM-6B的第二代版本
- 特性:
- 保留了初代模型对话流畅、部署门槛较低等众多优秀特性
- ChatGLM2-6B使用了
GLM的混合目标函数
,经过了1.4T中英标识符的预训练与人类偏好对齐训练
- 评测结果:相比于初代模型,ChatGLM2-6B在MMLU(+23%)、CEval(+33%)、GSM8K(+571%)、BBH(+60%)等数据集上的性能取得了大幅度的提升,在同尺寸开源模型中具有较强的竞争力。
- 改进:
- 更长的上下文:基于
FlashAttention技术
,将基座模型的上下文长度(Context Length)由ChatGLM-6B的2K扩展到了32K
,并在对话阶段使用8K的上下文长度训练,允许更多轮次的对话。但当前版本的ChatGLM2-6B对单轮超长文档的理解能力有限,会在后续迭代升级中着重进行优化。 - 更高效的推理:基于
Multi-Query Attention技术
,ChatGLM2-6B有更高效的推理速度和更低的显存占用
- 在官方的模型实现下,推理速度相比初代提升了42%,INT4量化下,6G显存支持的对话长度由1K提升到了8K。
- 更长的上下文:基于
ChatGLM-3
介绍:ChatGLM3-6B是ChatGLM系列最新一代的开源模型,在保留了前两代模型对话流畅、部署门槛低等众多优秀特性的基础上,ChatGLM3-6B引入了如下特性:
- 更强大的基础模型:ChatGLM3-6B的基础模型ChatGLM3-6B-Base采用了
更多样的训练数据、更充分的训练步数和更合理的训练策略
。在语义、数学、推理、代码、知识等不同角度的数据集上测评显示,ChatGLM3-6B-Base具有在10B以下的预训练模型中最强的性能。 - 更完整的功能支持:ChatGLM3-6B采用了
全新设计的Prompt格式
,除正常的多轮对话外。同时原生支持工具调用(Function Call)、代码执行(Code Interpreter)和Agent任务等复杂场景。 - 更全面的开源序列:除了对话模型ChatGLM3-6B外,还
开源了基础模型ChatGLM-6B-Base、长文本对话模型ChatGLM3-6B-32K
。以上所有权重对学术研究完全开放,在填写问卷进行登记后亦允许免费商业使用。
📌 [ 笔者 ] 文艺倾年
📃 [ 更新 ] 2024.9.14
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,
本人也很想知道这些错误,恳望读者批评指正!