人工智能的世界充满了看似神奇的过程,却从不解释其中的奥秘,重要的步骤被当作黑盒子展示。今天,我们将揭开这些黑盒子,看看学习和意义等人类概念是如何从简单的计算和笔纸工作中产生的。我将详细描述AI工具是如何构建的,以及它们是如何产生结果的,而不依赖复杂的数学或未解释的术语。让我们开始吧!
本文属于我的AI Library系列。文章按照复杂度顺序排列。它们并非作为先决条件,而是作为这些主题的替代入口点:
在人工智能的世界里,就像在许多学术研究中一样,我们发现有无数的新词汇来描述已经存在的概念,而这些概念本可以用其他方式解释。不幸的是,你需要掌握这些新词汇才能理解别人在这个话题上写的东西。
我会尽量温和地介绍这些术语。当它们第一次出现时,我会将它们加粗,这样你就知道它们是其他关于AI的文章中会看到的确切术语。我还会在每个新引入的术语
的每一节中进行标记。
虽然这篇文章没有布置任何作业,但如果你对编程感兴趣,这里提供了足够多的内容来开始探索构建你自己的AI应用程序的方法和工具。
如果你不是程序员,你可以用计算器、铅笔和纸理解并甚至重构我即将展示的一切,你也可以考虑在小范围内这样做以巩固你的理解——尤其是如果你的数学能力像我一样糟糕的话!
我不是人工智能领域的专家。我的专长在于我们更熟悉的那种软件。在撰写这篇文章的过程中,我花了几天时间在ChatGPT的帮助下整理和改进我的笔记。你在这里看到的所有文字都不是它写的,但它在纠正我提出的150个要点中的一些误解时非常有帮助。
如果你是第一次深入探讨这个话题,可以试着通过向ChatGPT陈述你的理解,然后询问你的理解是否正确来测试你的收获。好的问题应该以“是否正确……”开头,并以一个结论结尾,就像律师那样。这样,LLM本身就能帮助你提升调查的水平。
你有没有去过一家餐厅,菜单上的文字一个都看不懂?这个1950年代的中式餐厅菜单来自洛杉矶公共图书馆的收藏,洛杉矶公共图书馆收藏,里面全部是英文,但菜单上的中文标志指的是“蓬莱”,一个具有“仙境”属性的神话之地。就像你或我在面对一张家乡以外的不熟悉语言的菜单时一样,一个大型语言模型(LLM)开始时对任何语言都一无所知。
LLM
第一个重要的词是我们要构建的东西——一个LLM或大型语言模型。就像一个模型火车一样,它并不是真实的东西。一个LLM并不包含任何语言或知识,但它很好地模拟了这些内容。
名称中的“大”指的是需要建模的文本量才能发挥作用。LLM无法对它未曾见过的文本中的任何知识进行建模。它也无法创造任何新的知识。
“语言”这个词的存在是因为模型试图表示整个语言,而不是像传统数据库那样处理特定的数据。如果我们只是想返回我们存储的精确文字,已经有更简单的数据库可以做到这一点。事实上,LLM 并不会返回它们接收到的精确文本,并且不能作为可靠的数据库使用。
与常规数据(如银行余额)完全相反,即使是信息的存储方式也不可预测。没有人能告诉你某个特定的LLM是如何“相信”任何文本的任何内容的。想象一下,你的银行无法告诉你你的余额是如何形成的。
相反,LLM 模型化了人类语言,使得 语言陈述 可以用来驱动传统软件中的其他流程。我们可以将这视为一种新的编程方式,即提示驱动编程。
在最常见的例子中,LLM 用于生成新的文本(回答问题),就像 ChatGPT 一样。这些答案并没有以任何形式预先存储。它们是由传统的计算机代码生成的,该代码根据模型预测正确的下一个单词。
在一个银行应用程序中,我们可能希望使用自然语言来查询余额,但数据检索部分仍然通过传统软件完成。为了完成整个流程,我们可以让LLM使用传统代码中的数据生成新的英文文本,例如编写一句包含我们余额的礼貌用语。
transformer
训练
GPT
生成式
预训练
涌现式
注意力
在关于人工智能的大众讨论中,我们看到了支持者和反对者都做出了大胆的声明。支持者指出,像OpenAI的新o1模型这样的工具所产出的惊人成果,证明至少某种形式的人类智能正在被体现。与此同时,批评者则指出,一个仅仅通过拼凑他人作品中的文字来运作的系统不可能具备任何智能。而这两方的观点都是正确的。
这是如何做到的呢?解释在于通过一系列简单的数学运算,将关于词语的随机信息转化为代表高级人类概念(如语法、语境和整段文本的意义)的数字。
我们都有听过无线电噪音,这是一种随机的信息形式。它听起来像噪音,是因为它包含的是无序的音调(声音频率),而不是我们大脑听到的有序音乐。现在想象一下,一个机器人能够随着时间推移过滤掉无线电噪音中的随机性,并精炼信息,使我们只保留听起来像音乐的部分。
一种用于过滤和精炼文本以提取其含义的操作称为 transformer。每次精炼过程被称为 训练 步骤。通常我们希望使用这些LLM来生成新的文本,专门用于此工作的LLM被称为 GPT 或 生成预训练 transformer。名称中的“预训练”指的是生成一个有用的模型所需的大量训练步骤(以及计算时间和成本)。
需要注意的是,我们赋予文本的上下文和含义完全来源于这一过程。在AI术语中,我们说这种上下文是涌现的。它不是直接由人们指定的。换句话说,没有人告诉模型狗是一种动物,是一种宠物,像猫一样但又有所不同等等。从这个角度来看,Transformer方法与自20世纪60年代以来计算机科学家遵循的AI方法完全相反。
2017年,两位谷歌研究人员撰写了一篇关键论文,题为Attention Is All You Need,表明我们即将探讨的transformer过程,特别是被称为注意力的概念,确实只需要简单的数学运算就能使大量的人类语境和意义浮现出来。
从AI国际象棋玩家开始,我们发现这种注意力机制不仅在有限的领域内与人工编码的信息一样有效,甚至还能表现得更好。这一事实被称为2019年同名文章中的The Bitter Lesson,它表明,我们可以通过不向信息中添加任何人工智能,而是增加更多的_计算能力_来简单的关系计算和预测,从而获得更好的“人工智能”。那么,让我们看看这些计算是什么样子……
向量
数组
维度
我永远不会忘记在西班牙马拉加上高一数学课的第一天,老师一开场就说:“今天我们来学习向量,你们还记得去年学的内容。”而我刚从美国的高二转学过来,之前从未听说过这个概念!
原来,自从我们学会下跳棋以来,我们就已经知道了向量。向量不过是空间中两个物体之间的方向和距离,就像跳棋盘上的两枚棋子之间的方向和距离。
这里的线表示两个向量,这两个向量描述了棋盘上两个棋子之间的距离和方向。这个棋盘是二维的,而大型语言模型中的变换器使用的向量包含更多的维度。
如果我们用一个数字给每一行和每一列标号,然后为每个棋子写下这些数字,我们就得到了一个列表(或 数组),它表示该棋子在二维棋盘上的位置。
因为棋盘有两 维度 ,每个棋子的数组也需要两个维度来存储其位置的两个部分。在数学(以及许多编程语言中),这些维度用方括号表示,每个项目之间用逗号分隔。
检查数组
黑色
顶行黑色: [1,1]
中行黑色: [2,2]红色
底行红色: [3,1]
顶行红色: [1,3]
有了这些信息,我们就可以计算出棋盘上任意两块之间的距离,并用一个向量来描述这一点。
只是为了消除任何混淆,向量和其他数组之间没有区别。我们使用“向量”这一术语来表示我们将使用标准数学运算将数组的值视为多维空间中的位置,而不是其他可能用于存储账户ID或其他数据的数组。
为了加冕国王,我们需要知道每颗棋子必须移动的距离和方向,以便最终到达与其同色棋子相同的位置。如果我们把这些移动直接写出来,就会得到类似这样的结果:
检查向量
中黑 ➔ 顶黑
黑:[-1,-1]顶红 ➔ 底红
红:[2,2]
在国际跳棋中,“棋子离王棋格的距离”包含有价值的信息——即谁即将赢得比赛。通过计算每个棋子与其对应的棋子之间的距离,我们可以判断出谁更有可能喊出“王我!”
在这个例子中,就像真正的国际跳棋一样,国王的位置位于棋盘的相对两侧。中间的黑色棋子需要向上移动一格,然后再向后移动一格才能到达那里——而红色棋子则需要向下移动两格,再向旁边移动两格。
事实证明,在计算距离时方向并不重要,就像无论从哪个城市开始,两个城市之间的距离都是相同的。一个简单而巧妙的数学概念叫做 点积
(用“·”表示)解决了这个问题。
点积是通过将一个向量中的每个值与另一个向量中对应的值相乘,然后将所有这些乘积相加来创建的。
当我们那样做时,我们发现黑色更接近获胜。
点积(Checker Distances)
黑色
[1,1] · [2,2] ➔ 12 + 12
2 + 2 = 4红色
[1,3] · [3,1] ➔ 13 + 31
3 + 3 = 6
黑色棋子的两个向量之间的距离是4,而红色棋子的则是6。虽然这里用跳棋作为视觉示例,但请注意,我们并不是在寻找棋子之间的移动次数或实际棋盘格子的数量。
我们这里要找的是向量本身,它表示两个点之间的移动方向。每个向量都有方向和长度,我们可以通过比较这些方向和长度,在二维空间中找到相似的向量。
在乔迪·福斯特主演的电影《接触》中,建造了一艘复杂的飞船,试图与外星生命取得联系。尽管她在“旅程”中有了令人惊叹的发现,并伴随着令人震撼的特效,后来我们得知这艘飞船实际上并没有真正航行,只是将平台降到了海中。机器学习的实际效果也是如此,它们本身并非真实存在,但它们在我们脑海中留下的意义却常常是真实的。
magnitude
token
上下文
语料库
忽略国际跳棋的规则,我们可以在棋盘上的任意两枚棋子之间计算这样的向量。我们还可以比较它们的长度,也就是所谓的向量的 大小。
为了用向量存储比棋盘位置更复杂的东西,我们将需要更多的维度。从二维棋盘到像视频游戏中那样的三维世界,这并不是一个难以理解的概念飞跃。但是,超出三个维度后,我们的大脑就很难形成一个可视化的图像了。
好消息是,我们不需要一幅视觉图像,因为这些并不是代表空间中任何事物的物理向量。它们仅仅是值的容器,我们将用非常“接地气”的数学方法逐一操作这些值。
在大型语言模型(LLM)中,棋盘上的检查器代表一个词或标记。我们希望计算文本中两个标记之间的关系。额外的维度将包含该词在整个文本体中的上下文,这个文本体被称为语料库。
我们需要多少维度?300 是一个简单的模型的良好起点。理论上,更多的维度意味着我们可以捕捉到更多的上下文信息。实际上,每一个维度都会花费真正的金钱去计算和存储。很多钱。
究竟存储的是什么样的上下文信息,每个维度又代表什么?我们一无所知。建立上下文是LLM的涌现行为的一部分。
事实证明,人类的写作(以及音乐和绘画)充满了模式。当这些模式在我们后来的聆听或观看中再次出现时,它们会触发由我们所有学习经历所暗示的整个背景。
就像音乐一样,文本周围的环境信息提供了背景。在短语“早睡早起”中,“rise”这个词的意思与短语“在烘焙前让面包发酵”中的“rise”不同。通过分析足够的文本,人们可以找到单个词的不同背景,而无需了解银行或烘焙的知识。正是这种信息,我们将为每个词元提取并存储。
是什么让音乐成为音乐而不是无线电噪音,是因为音乐使用了持续的音调和模式,以及这些音调和模式之间的关系。我们的大脑通过这些模式而不是单独的声音来识别音乐。无论在什么音调上,《生日快乐》这首歌都是一样的,你不能仅仅通过改变歌词就把一首葬礼进行曲变成这首歌。音乐本身包含了上下文信息。
同样,对于词语也是如此。我们将看到LLM如何找到这些模式并在多维向量空间中记录它们,尽管它本身并没有理解这些词语的意义。当人类阅读从模型中选择的词语时,理解这些词语的意义发生在我们的大脑中。即使没有LLM,同一个词语可以有不同的含义,不同的词语也可以用来传达相同的意思。
以“狗与猫”的例子为例,LLM是如何知道狗和猫在某些方面是相同的,而在其他方面又是不同的呢?许多关于狗的文本会有一些与关于猫的文本相同的概念,比如在室内和室外活动、喂食和看兽医。其他概念则只属于某一物种,比如狗在散步时随地大小便,或者猫会抓挠你的眼睛。LLM无法真正“知道”或“找到”这些差异,但它可以在你提问时预测出正确的答案。
这里展示的是2016年在一次娱乐业展览上展出的世界上最大的吃豆人游戏机。这款游戏最初于1980年推出,当时每玩一次需要投入一枚硬币。而在我在Dave & Buster’s玩这款游戏的地方,每次游戏的费用远不止一枚硬币,而且这些硬币本身的价格也各不相同。啊,科技。
上下文向量
字对
分词
输入序列
词汇表
标记ID
现在我们知道了向量是什么,以及我们打算如何使用它们,让我们准备一些简单的输入文本供变压器处理。最终我们会为文本中的每个标记得到一个上下文向量。它将包含我们在训练过程中学到的宝贵信息,这些信息将用于后续获取答案。
这里是我们的初始文本,只包含两句句子:
“一天一个苹果,医生远离我。”
“医生去度假了。”
传统的AI方法会试图列出医生、假期和苹果之间各种各样的联系,但在这里我们只需要列出两个句子中所有词的列表。虽然我在这里随意使用“词元”这个词来代表文本中的一个词,但实际上这些词元通常是字对,一种表示单词更小部分及其与标点符号组合的方法。从语料库中提取词元的过程称为分词。
这里是我们单词的标记在一个数组中,忽略大小写和标点符号。暂时我们将这称为输入序列,稍后会稍微修改一下这个定义。
["一个", "苹果", "一天", "保持", "医生", "远离", "医生", "远离", "在", "度假"]
如果我们删除所有重复项并按字母顺序排序,我们将得到:
["a", "an", "apple", "away", "day", "doctor", "is", "keeps", "on", "the", "vacation"]
这是词汇表。词汇表并不总是按字母顺序排序。通常,LLM会根据语料库中词元的频率对其进行排序。但是它必须按某种方式排序,因为我们需要用列表中的位置来跟踪它,称为词元ID。如果我们整个过程中都保留这个词汇表数组,我们就可以随时将这些ID号重新转换成英文单词。
嵌入
嵌入维度
矩阵
随机值
种子
注意力机制
一旦词汇表建立好,我们就可以为词汇表中的每个标记创建一个多维向量。这些向量被称为 嵌入,因为它们会将整个语料库的上下文信息嵌入到词汇表中的每个词中,这真是一个了不起的成就!
每个token的维度数量称为嵌入维度。为了处理我们词汇表中包含的每个token有300维度的11个token,我们需要一个 11 x 300 维度的矩阵。这需要很多存储箱,而我们仅仅写了两个句子。
你可以看到,这些“简单”的值类型(以及我们将对其执行的数学运算)在处理大量文本时会迅速变得难以控制。然而,今天三百维已经是小儿科了,你将使用的所有模型都远远超过这个数量。
无论我们选择什么样的嵌入维度,都需要在过程中将其扩展到原来的四倍,然后再收缩回来。很明显,训练一个具有大量文本和上下文解析能力的大型语言模型是一项昂贵的任务,通常由拥有庞大云端计算资源的数十亿美元公司来完成。
但是这些维度里装了什么呢?令人惊讶的是,我们从随机值开始。是的,你没有看错。无所不知、无所不晓的LLM实际上是从纯粹的随机性开始的,这也是本文标题的由来。
这些最初随机生成的值来源于一个种子,即随机数生成的起点,这个种子可以被保存并重复使用,以便再次生成相同的“随机”数。
这些值不会随机太久。通过至关重要的注意力机制,我们将收集关于输入序列中每个标记与其他标记之间关系的信息。然后,我们将调整这些值以嵌入这些上下文关系。
位于互联网发源地CERN的这台变压器用于为大型强子对撞机提供电力,进行亚原子粒子研究。虽然发明者在选择这个名字时可能指的是变形金刚系列,但这种变压器与大型语言模型中的变压器更为相关。在LLM中,变压器通过离散的数学步骤调整上下文中的令牌关系。
矩阵乘法
矩阵向量乘法
线性变换
非线性
激活函数
聚焦
变压器之所以被称为“变压器”,是因为发明者喜欢这个名字,这和任何其他理由一样好。虽然听起来很强大(实际上也是如此),但本质上,变压器在两个矩阵之间进行简单的数学运算,例如矩阵乘法——或者在一个矩阵和一个向量之间进行运算,就像矩阵与向量的乘法一样。
如果你对这些数学术语感兴趣,不妨查一查或让ChatGPT演示一下。它们不过就是乘法和加法。这些Transformer的厉害之处在于,它们可以将我们的向量扩展,从而为我们提供更多收集上下文的空间。它们还可以将向量之间的关系简化成更简单的表示形式,同时仍然包含原始信息中的所有内容。这真是一个令人惊叹的表演技巧,如果你只是想让自己印象深刻,也值得研究一下。
数学恐惧者们,不要害怕。在每一种情况下,我都会给出我们进行数学运算的_原因_以及我们期望得到的结果,因为这些是最重要的一部分。
Transformer有两种类型。线性变换是指输出与输入成比例的变换。如果一个线性变换将一个数乘以2
,那么输出总是与输入成比例——即输入的两倍。到目前为止我提到的所有变换都属于这种线性类型。
我们的训练过程会将词元向量提交给一系列这样的变换,每个变换都会对值进行微小的调整。这是一种通过一系列迭代来计算复杂问题的绝佳方法,但正如我们在杂货店收银台看到的那样,分别扫描三个不同的1美元商品,扫描同一个1美元商品3次,或者在收银机上按 QTY
3
然后扫描其中一个商品,最终的总价都是相同的。所有这些算术运算最终都会“坍缩”到一个相同的最终结果,只要输入的数值相同。
为了捕获更详细的信息,我们添加了一个非线性激活函数。非线性函数返回的结果与输入不成比例。一个流行的函数简单地将线性变换后的所有负结果重置为零。结果不成比例是因为 -2
和 -4
都会返回零。它被称为激活函数,因为它会在两个标记之间“激活”注意力,正如我们稍后将看到的。
回到棋盘的例子,如果我们说两个棋子之间的向量在一维上指向相同的方向,那么这一维上的两个值要么都是正数,要么都是负数。如果一个值是负数而另一个是正数,那么它们的方向就完全不同。
由于两个负数相乘的结果是正数,所以两个都指向负方向的向量实际上是朝同一个方向的。而且因为两个负数相乘的结果与两个正数相乘的结果相同,无论方向如何,我们得到的距离度量是相等的。
如果我们忽略负结果(即一个向量 x 中的负值与另一个向量中的正值),我们就忽略了多维空间中指向相反方向的向量之间的关系。这样做的效果是让模型只关注那些转换器产生正结果的值,从而使其能够捕捉到嵌入中的向量相似性。
在整个关于向量和空间的讨论中,请记住,这些只是思考(和数学处理)单词之间关系的一种视觉方式。事实证明,使用向量和矩阵来存储和操作文本的上下文信息很方便,但这里并没有像棋盘上那样的固有“空间关系”。相反,嵌入捕捉的是上下文信息,比如词义、语法,甚至风格。
埃里克·魏斯,艺名哈里·胡迪尼,喜欢揭露所谓的“灵媒”及其虚假表演。在这张照片中,胡迪尼似乎与林肯的鬼魂合影。他制作这张照片是为了驳斥其他声称展示与死后世界互动的照片。
下一个词预测
自动补全
微调
哈里·胡迪尼以魔术著称,但在20世纪20年代,他转而揭露灵媒的欺诈行为。他特别喜欢乔装打扮,带着一名警察侦探和记者参加灵异会,然后揭露灵媒的欺诈行为和他们编造的“预言”。这与我们从大型语言模型(LLM)中获取有用信息的方式颇为相似。
在我讨论LLM训练的过程中,我将暂停一会儿来解释为什么它会起作用。这并不明显,就像在Houdini的时代,即使是科学家们也不明白——直到他揭开了桌子上的秘密。相信魔法固然好,但了解其中的秘密更好。
许多GPTs最好的特性是下一个标记预测的应用。我们将仔细研究它是如何工作的,但它是为什么有效也同样重要。
当我们向ChatGPT提问时,看起来它是在“寻找”某个文本中的答案并将其写出来——可能还会在途中改写或从各种文本中拼凑出答案。实际上,事情并非如此。
真正的情况是,GPT 只是在预测下一个最有可能的词,然后将其写出来。接下来会预测什么呢?你可能会问,接下来是在你提供的提示的上下文中,预测下一个最有可能的词。
这并不像在语料库中查找你的提示并找到答案然后复述出来。你的提示是原创的,回复也是原创的。它们之前从未见过。回复中的每一个词都是通过逐词预测下一个词生成的,你可以看到GPT“逐字打出”回复的过程。
无论是你的提示是问题还是陈述,都没有关系。如果你写的是一个问题,那么接下来最有可能的词将是答案的第一个词。输出了那个词之后,接下来最有可能的词将是答案的第二个词,以此类推。
但是将这些称为“答案”对LLM来说无关紧要。陈述同样有效。如果你陈述你度过了糟糕的一天而不提问,接下来最有可能的词(从学习到的上下文中来看)会是“我”(“I’m”),再下一个词可能是“抱歉”(“sorry”)。
它对代码和 自动补全 也适用同样的原理。给定程序中某行的开头部分,LLM 可以预测下一个最有可能出现的词元,无论是语句、表达式、函数还是变量。
如果要求用海盗的口吻来写莎士比亚的作品,无需查找莎士比亚或海盗说话的方式,实际上也没有这样的数据存在。相反,模型会逐个词地预测,这样的诗可能会包含什么内容。
你输入的每个 token 以及 LLM 的输出都必须经过分词和训练步骤——而且这些工作是一次处理一个 token。LLM 的预训练是一次性收费的,但每次与你进行 token 交互时,还会产生计算成本,包括物理内存和处理器时间。这解释了为什么费用是基于计数和限制 token 来计算的,以及为什么更复杂的模型每个 token 的成本更高。
就像在预训练LLM时使用种子来提供随机性一样,在对您的输入进行训练时也会使用另一个种子,这被称为 微调。这就是为什么使用相同的提示多次运行LLM会产生不同的结果,但这些结果大多数(或全部)都是可行的响应。通过使用相同的种子反复调用LLM,当需要时,可以保持更可预测的一组输出。
在实践中,这些随机的起始点可以导致新的和令人惊讶的单词预测,使它们感觉更像人类。一个特定的回应可能包含有趣或有用的信息,这些信息在对同一提示的其他回应中缺失。这也是涌现行为的另一个例子。
在这部梅尔·布鲁克斯的《世界史:第一部分》中的一个场景中,玛德琳·凯恩审查了一支罗马男兵军团。被他们的短裙迷住了,在听到行进命令时却找不到合适的词来形容,她惊呼:“我爱你们向前迈步的 harch!”
前向传播
层
反向传播
前向传递是对词汇表中特定标记的嵌入进行的变换。它是前向的,因为当向量输入时,它们的值会随着函数的变化而变化,然后传递到下一个层。前向传递不会改变其之前的任何内容。
它也是“向前的”,因为它将构成一个_前瞻性的_预测,即用于找到下一个最有可能的词元的那个预测。
霍迪尼时代的灵媒(甚至直到今天)会抛出类似这样的猜测:“我听到一个以‘M’开头的名字。玛丽?玛莎?”并确保使用适合听众及其年龄(情境)的名字。当表演者听到“我母亲的名字叫莫林”时,他会退一步说:“啊,对了。我听到的是莫林的声音。她现在和我们在一起。”
类似地,在训练过程中,LLM最初(并且反复)会给出错误的预测。但与回退并更改其_最后一个_答案不同,LLM通过调整嵌入来提高其在_下一个_尝试中的准确性,这个过程被称为反向传播。
权重
加权
权重矩阵
处理 token 嵌入的 transformer 需要一些东西来进行操作,这些东西被称为 权重。权重告诉我们在 token 嵌入中的每个值需要调整多少,而嵌入本身则保留调整后的结果。
这种重量的比喻可以在我们的超市中找到。如果秤称出了1磅的糖果,并且促销活动说你可以获得50%的免费糖果,那么你原来的袋子会增加到原来的150%。也就是说,你原本的100%加上免费的50%,即 1
x 1.5
. 调整后的秤上显示的总重量将会是1.5磅的糖果。太棒了!
回想一下,词汇表中的每个标记都被分配了一个嵌入维度的向量,比如300。无论我们对什么进行加权,这都需要一个至少为300 x 300的权重矩阵,以便每个标记的每个维度都能与其他标记的每个维度进行加权比较。
如果觉得为每个维度与其他维度之间的比较添加权重会给我们提供更多捕捉上下文的机会,那么你已经走在正确的道路上了。事实上,为了不同的处理步骤,会创建多组这样的权重矩阵。首先,我们需要为每个词汇令牌创建一个权重矩阵。
数组索引
输入序列
一旦词汇表设置了初始嵌入和每个标记的权重,我们就可以开始在上下文中查看训练文本。换句话说,就是像我们最初得到的那样来审视语料库,而不仅仅是将其视为一组独特的词汇单词。
这里是我们使用的两个训练句子。
“一天一苹果,医生远离我。”
“医生去度假了。”
使用我之前提到的 token ID(每个 token 在排序后的词汇表中的位置),我可以将语料库重新写成一个 token 数字的列表。
[1,2,0,4,7,9,5,3,9,5,6,3,8,10]
你可能会注意到两件事。首先,单词“doctor”在这两个出现的地方都被赋予了相同的编号5
。同样,“away”这个词的两个出现也被记录为3
。这确保了每次这个词在语料库中出现时,无论它处于何种不同的上下文中,都会对同一个词汇表中的单词进行调整。
其次,单词“a”(列表中的第三个词)被赋予位置 0
。许多编程语言(但并非全部)使用 0
作为数组索引的起始位置。
正是这个精简的列表我们将用来处理输入文本,实际上这就是真正的 输入序列,而不是我之前展示的英文版本。
平壤的“人民大学习堂”是现代朝鲜建筑的一个宏伟例子(北朝鲜建筑),其运作方式与西方图书馆大不相同。所有书籍都存放在封闭的墙内,只有在请求时才会通过传送带送出来。尽管声称藏书量以百万计,但访客报告称常见的文学和科学教材却缺失了。输入大型语言模型(LLM)中的信息以及这些信息的输出方式,对于在AI应用中找到实用性至关重要。
机器学习
注意力机制
自注意力机制
就像人类学习一样,机器学习也涉及注意力的分配。特别是,我们希望机器能够关注那些高度相关的标记,也就是说,它们的向量在许多维度上是相似的。
自注意力 是用于确定这些关系的机制。“自注意力”中的“自”指的是我们仅使用文本本身来衡量各个词元向量的注意力或相似性,而不依赖其他任何内容。
注意力得分
查询
键
注意力权重
查询权重
说到底,我们希望为每个词元分配一个简单的数字,这个数字告诉我们它与其他词元的相关程度。当训练完成后,我们将使用这个数字来进行下一个词元的预测。
在实践中,这意味着我们需要在输入序列中的注意力得分之间建立——输入序列中的所有标记之间。为此,我们将遍历输入序列中的每个标记,称为查询,并将其与序列中的另一个标记进行比较,称为键。
了解计算每个查询和键之间的注意力分数只是对令牌嵌入进行一系列变换以及为这一目的创建的一些新权重(注意力权重)是否会令你感到惊讶?
对于输入序列中的每个词元,我们将从一个新的查询权重矩阵开始。和所有训练中的值一样,这些权重最初是随机的,但在每次迭代中都会进行调整。然后,我们在词汇表中查找该词元的嵌入向量,并将其与查询权重矩阵相乘。
需要注意的是,权重矩阵是为输入序列中的每个词元计算的,但来自词汇表的嵌入保持不变。在我们的样本语料库中,这意味着“doctor”这个词的两次出现在计算注意力分数时将使用相同的doctor
词元嵌入,但每次出现会有自己的权重矩阵。结果是,同一个词或词元在输入文本中的不同上下文可以被捕获在词本身中。
Q
K
标量
注意力矩阵
键权重
这个矩阵-向量乘法(嵌入 x 权重)的结果是一个新的向量,称为 Q。由于这个操作是在输入序列中的每个标记上执行的,因此 Q 的大小与输入序列长度相同。它现在包含了我们比较的每个标记的加权嵌入。
我们将要比较查询的 token 是我之前提到的 key。如果我们用每个 key 的 key 权重 矩阵乘以这些 token 的嵌入向量,我们将得到一个新的 K 向量,它代表了所有 key token 的加权嵌入。
我们追求的注意力得分仅仅是某个标记的Q向量(嵌入维度)与另一个标记的K向量(也是嵌入维度)的点积。这将所有维度上的向量比较压缩成一个单一的数值相似度度量。
这两个词之间的注意力得分既包含了词嵌入(来自词汇表),也包含了该词在语料库中的上下文权重,因为这些是计算Q和K时的一部分。在这个步骤中丢失的是关于每个嵌入维度的任何信息。我们仅仅计算了一个向量与另一个向量相似度的单一度量。
计算完每个Q和K的注意力得分后,我们得到了一个大小为Q x K的注意力矩阵——或者说输入序列长度 x 输入序列长度。通过调整词汇表中的令牌嵌入和基于稍后将要讨论的反馈步骤中的输入序列权重,最终的注意力得分能够更好地反映文本中令牌之间的上下文关系。
现代的轮盘赌桌,比如这个来自TCSJohnHuxley在保加利亚GoldenEye赌场的轮盘赌桌,配备了结果显示屏,位于右上角。这使得玩家可以看到最近几次旋转的实际结果,并据此预测下一个球会落在哪里。轮盘赌在每次旋转中都能获利,因为单个数字中奖的概率是1/38,但只赔付36:1。这个差额就是赌场的利润或称为vig。
softmax
概率分布
归一化
归一化注意力矩阵
敏锐的读者可能会回忆起,所有这些权重(甚至包括嵌入层)最初都是随机的。我们精心计算的注意力分数其实没有任何意义。我们还没有解释这些有意义的、非随机的分数是如何产生的。
我之前提到过灵媒通过抛出一些随机的信息来寻找答案,看看是否能抓住什么,然后在得知事实后调整他们的回答。这正是LLM学习的方式。这一切都关乎正确答案的概率。正确的答案是什么?就是下一个标记预测中应该出现的下一个标记。
利用我们现有的注意力矩阵,我们可以计算输入序列中任意一个token对另一个token具有高注意力的概率。执行这一计算的函数被称为 softmax。
现在在这里说“概率”可能听起来有些可笑,因为这两个向量要么相似,要么不相似。但这就是这些向量中数字的实际情况。这里的“概率”指的是一个 概率分布。我们将实际发生的数值转换为每种结果发生的频率百分比,就像我们可以通过观察实际的轮盘赌转盘来审计一个轮盘赌一样。
softmax的结果是归一化的,这样每个标记在序列中关注其他任何标记的概率加起来等于1。我们在玩任何概率游戏时都会在脑海中进行这样的计算。如果轮盘上有38个空间,你落在任何一个特定空间的概率就是1/38。由于球必定会落在某个地方,所有概率的总和等于1或100%。
这个计算结果被称为归一化注意力矩阵。任何一项分数越接近1,就表示在序列中这些标记之间分配的注意力越高。
加权值总和
值权重
值向量
上下文矩阵
我提到注意力得分通过将嵌入维度压缩成一个相似度的单一衡量指标来“舍弃”这些维度本身,并且对这些值进行归一化并不能让我们恢复出原始的嵌入。
为了建立每个嵌入维度对两个词元之间关系的影响,我们将使用加权值的总和。这些值来自一个新的向量,V。它类似于Q和K,并且以相同的方式创建,通过将词元的词汇向量与值权重矩阵相乘得到。
就像 Q 和 K 一样,V 向量的大小与输入序列相同。为了计算输入序列中单个 token 的加权和,我们将归一化注意力矩阵中的每个向量与 V 向量中对应的值相乘,然后将这些乘积相加。结果是一个大小为嵌入维度的向量。
这将输入序列中所有标记的注意力分数减少为每个嵌入维度上的单个加权和,展示了该维度对标记向量相似性以及因此对单词上下文的贡献程度。所有值向量(输入序列中的每个标记一个)组成的矩阵被称为上下文矩阵。
功能性磁共振成像 (fMRI) 是一种用于测量大脑特定区域神经活动的技术。颜色显示了每个区域的血液流动情况,这与标准的磁共振成像不同。扫描结果用于规划肿瘤手术和放射治疗。大型语言模型中使用的概念和术语源自我们对大脑活动的模型。
神经元
神经网络
前馈
FFNN
隐藏维度
瓶颈效应
ReLU
我们用来转换令牌向量中值的技术,例如通过乘法应用权重并求和其结果,旨在模拟大脑中的神经元如何相互传递信息。
嵌入维度中的每个位置都可以被认为像一个神经元一样传递信息。维度越多,我们可以捕获的信息就越多,但同时计算复杂性和时间成本也会增加。当我们执行模拟大脑神经元的矩阵运算时,我们实际上是将数据视为一个神经网络。
每个处理步骤称为一层。其中一个特定的层,即前馈神经网络或FFNN,通过为每个标记引入一个额外的隐藏维度权重,增强了模型捕捉上下文的能力。这个隐藏维度通常是嵌入维度的4倍,这是复杂性和性能之间的权衡。在我们原始的嵌入维度为300的情况下,隐藏维度将是1200。
一旦隐藏维度中的关系被捕获,全连接神经网络(FFNN)会将模型恢复到其原始大小,同时保留新的信息。这被称为瓶颈效应。宽漏斗顶部收集隐藏维度中的注意力信息,而狭窄的瓶颈部分将这些关系简化为嵌入维度中的数值摘要。
在两个阶段之间,使用了一个非线性激活函数来聚焦模型,使得只有期望的关系能够通过这一过程。在一种名为 ReLU 的非线性函数的情况下,只有正向的关系值(同方向的向量)被保留。
这些神经网络操作被称为前向传播,因为信息仅从前向后流动,从第一步到最后一步。这一部分不会修改或重新访问任何输入。这些操作稍后会进行。
在FFNN的第一部分,我们建立了一个新的权重矩阵,其大小为嵌入维度_x_隐藏维度。而之前的权重矩阵的大小为嵌入维度_x_嵌入维度,通过在这里使用新的隐藏维度,我们可以对每个标记与其他所有标记在所有原始维度上的权重进行更细致的调整。
我们之前建立的上下文矩阵然后与这个新的权重矩阵相乘,结果得到一个大小为输入序列长度 x 隐藏维度的矩阵。
激活水平
激活函数
在FFNN的下一步中,对转换后的上下文矩阵执行非线性激活函数。对于ReLU,这会“丢弃”所有负数乘积结果,使模型仅关注正注意力分数。
最初,分数既有正数也有负数,这是因为所有这些数据的随机来源。但在经过非线性激活后,保留的值使模型只关注正分数,忽略任何负值的结果。
这种方式省略某些值并不将它们传递到下一层,模仿了大脑中的神经元需要达到一定的激活水平才能放电,将信息传递给另一个神经元。这一步的非线性结果充当了激活函数的角色,只有当其水平超过零时才激活注意力。
在FFNN的最后一步,为输入序列中的每个令牌创建第二个权重矩阵,其大小为嵌入维度 x 隐藏维度。
应用了非线性激活的扩展上下文矩阵与第二个权重矩阵相乘,有效地将其压缩回原始大小,即输入序列长度乘以嵌入维度,同时捕获(并以数值形式总结)来自更高隐藏维度的所有聚焦信息。
赛马投注的互助式投注(parimutuel wagering)是在19世纪末由法国发明的,作为一种规避私人彩票法律的方法。这是赛马比赛中标准的系统,它根据每位赢家所占所有投注的比例公平地支付奖金——在扣除固定的佣金(vig)之后。该系统需要大量的实时计算,因为每一笔投注都会影响所有奖金的分配。产生这些信息的设备被称为总化器(totalizator),这里展示的是AmTote在20世纪60年代的一款设备。结果会显示在赛道上赛马后面的屏幕上。
最终线性层
预测步骤被称为最终线性层,就像一位舞台魔术师一样,我们已经把所有的东西“藏在袖子里”,以备随时表演。预测是从哪里来的呢?
我们已经看到,每对词元之间的注意力关系或向量相似性是通过一个概率分布来捕获的,该分布包含了词元在输入序列中的位置和上下文(以及词元本身)。这些信息存在于我们一直在精炼的上下文矩阵中。
如果我们取序列中的 最后一个词元 (上下文矩阵中的最后一个向量),并计算它与 词汇表中的每个词元 的相似度,然后将其转换为概率,得分最高的词元就是最有可能成为下一个词元的!如果我们对刚刚生成的词元执行相同的操作,我们就可以预测其后的下一个词元。
为了在整个词汇表的背景下看到最后一个词元,我们首先将其嵌入向量与一个新的权重矩阵相乘,该矩阵的大小为词汇表大小 x 嵌入维度。这将产生一个词汇表大小的向量,其中每个元素将词元的嵌入和其权重结合成一个单一的标量值。
logits
对数几率
对数
这些新向量中的值都称为 logits(发音为“低吉特”),这是对 log odds 的引用,即某个事件发生的 对数几率。在这种情况下,我们预测的事件是词汇表中每个词元成为序列中下一个词元的可能性,包括我们学到的所有上下文。
原始概率分数(即logits)代表词汇表中每个词元成为下一个词元的可能性。这些分数通过softmax函数进行归一化,使得它们在整个词汇表中相加为1。经过归一化后,得分最高的词汇表词元(最接近1)最有可能是下一个词元,因为它在输入序列中所有先前词元的上下文中具有最相似的加权嵌入。通过在我们保存的英语词汇表中查找该词元ID,我们可以返回LLM响应中的下一个词。
损失函数
信息论
熵
交叉熵损失
优化
为了计算预测的错误程度,我们使用了一个 损失函数。如果我们不是在输入序列的 最后一个 令牌上运行预测层(即最终的线性层),而是在倒数第二个令牌上运行呢?那么我们就可以查找序列中 实际的 最后一个令牌的概率,看看它是否得到了最高的分数。Et voilá, 我们就有了一个损失函数。
我们知道一开始我们没有任何机会做对任何事情,因为所有的数字都是随机的。这就像试图预测下一个无线电噪音一样。在信息论中,熵这个词指的是某些信息中存在的不确定性和随机性程度。
为了找出有关上下文的信息在随机性中丢失了多少,我们对分配给正确令牌的概率值取负对数,这一测量称为 交叉熵损失。
较低的交叉熵损失意味着模型做出了更准确的预测,或者说是“好命中”,而较高的损失则意味着预测不够准确或“差错失”。在接下来的优化步骤中,我们将看到模型如何在每次传递时调整嵌入和权重,以实现更低的损失并在下次做出更准确的预测。
回到我们的输入文本:
“一天一个苹果,医生远离我。”
“医生去度假了。”
如果我们提交了“一天一个苹果,医生”并要求预测,我们可能会在第一次尝试时得到“远离”——甚至可能是更离谱的结果。记住,这些输入一开始是没有任何关系信息的。
因为在该上下文或文本部分中,“doctor”之后的实际输入是“away”这个词,模型会调整“away”词的嵌入,使其在下次预测时更有可能被预测出来。
在实践中,这些步骤会对输入序列中的每个标记进行运行。所以我们先对“An”进行预测,然后对“An apple”进行预测,以此类推,在每个点上都进行相应的调整。
游戏Sakuna: Of Rice and Ruin中,种植水稻的过程非常详尽,需要经过几天和许多步骤。如果你的种植效果不佳,会导致收获的稻米质量差且数量少——这一点你只能在收获后才能发现,并且只能在下一个种植季节应用所学的经验。同样,LLM也会通过类似的反向传播技术从不良结果中学习,并在下一次调整自身。
参数梯度
学习率
反向传播
为了调整模型并提高预测准确性,我们首先检查每个token嵌入和权重矩阵中的值对“错误”或损失的贡献程度。这表明了每个维度的值或权重相对于其他维度应该调整多少,这一测量被称为参数梯度。
每次调整的目的是将参数值朝着减少损失的方向进行微调。为了确定调整的幅度,我们首先选择一个与梯度成比例的量,然后通过一个称为学习率的因子进行缩放。这影响了调整步长的大小或其对调整的影响。这种经过缩放的调整计算称为梯度下降。
每个微调都是朝着最小化损失的方向进行的。通过反复迭代,模型的准确性会随着时间的推移而提高,这个过程被称为 反向传播。
幻觉
此时你可能会想到,视角度不同,LLMs 的输出要么都不是幻觉——要么是全部都是。
从数学意义上讲,所有的输出都是100%正确的。从词汇表中选择的标记基于其嵌入值确实是正确的“下一个”标记。然而,这并不意味着该标记所代表的单词具有正确的含义,或者将几个这样的标记连在一起形成的整体输出具有正确的含义。
任何单一的输出令牌在人类意义上可能是正确的,这纯粹是偶然。它们都是幻觉,而这些幻觉有时会与现实一致。更好的模型和更好的提示可以提高现实世界与概率世界之间的对齐程度,但我们永远不会像在数据库中或读取文件内容时那样获得确定性。
回顾起来,我们将这个词语应用于这种现象是不幸的,因为它导致了一个错误的信念,认为所有幻觉都可以被消除。要做到这一点,我们必须完全放弃使用LLM。
epoch
训练模型
微调
主提示
通常,大规模语言模型的训练涉及从前向传播层到反向传播的步骤反复迭代,直到达到某个epoch数或计算成本等其他预设限制为止。
生成的产品称为 训练好的模型 ,然后就可以准备部署了。这足以用来创建一个聊天机器人或其他基于文本的应用程序,这些应用程序依赖于下一个标记的预测。
你将模型带回家后进行的额外训练称为 微调。它包括向语料库中添加新文本,通常使用较低的学习率以避免破坏原有的训练。在自定义的GPT或聊天会话中,如 主提示 这样的“设置”,在使用托管的LLM时即为微调。
1987年,苹果公司发布了一段名为Knowledge Navigator的概念视频,设想了一种虚构的设备,它可以协调参考信息(如已发表的论文)和个人信息(如约会和联系人),全部用简单的英语表达——甚至还配备了一个视频化身。这类应用程序今天可以被构建,但涉及到LLM与其他软件组件之间微妙且有时存在风险的连接,这导致了我们今天看到的像Apple Intelligence这样的产品所面临的限制。
函数调用
消息
AI应用
就这样,我们迅速从随机数跃升到了人工智能。当然,还差最后一步,那就是将大型语言模型(LLM)的自然语言能力(及其不可预测性)与需要可靠数值的传统应用程序(如银行余额或天气预报)连接起来。
当经过函数调用的高级微调训练后,模型可以调用用传统语言编写的编程语言程序。这些函数可以连接到服务器、在数据库中查找信息、执行数学和逻辑运算——而这些功能在训练模型时并不存在。
在一个神奇的镜像技巧中,LLM甚至可以被提示提前编写这些传统函数——当然,这需要人类的监督。在训练代码时,这是一项很好的下一令牌预测的应用。
需要注意的是,模型本身除了生成消息之外,不会执行任何计算任务,而这些消息只是对提示的单独响应,实际上是令牌的列表。为了实际启动一个函数调用,一个用传统语言编写的控制应用程序会检查每个消息,寻找一个标志,表明“这需要一个函数调用”。这些消息包含要调用的函数名称以及从用户的提示中提取的参数。
在我们的天气例子中,如果用户询问丹佛的温度,LLM 并不会随机选择一个较低的数字,因为丹佛通常很冷。开玩笑的。回复消息会包含一个温度函数的指示符,并带有参数“Denver”。
看到这条消息后,控制应用程序而不是LLM调用函数并传递消息中的参数。为了将函数结果包含在生成的回复中,必须将返回值通过自己的消息带回到LLM中,该消息包含上下文——实际上是包含该函数值的提示。
这种结合使用预训练的大型词汇和上下文模型,然后用你自己的行业或公司特定数据和功能调用进行微调,以创建一个自定义用户界面的方法,最终形成了一个AI应用。
虽然转换器背后的方法很简单,但可以看到,更复杂的AI应用需要大量的手工劳动和编写软件才能变得有用——至少在今天是这样。例如,为医生设计的AI应用需要非常谨慎地判断何时参考实际记录和数据库中的数据,何时使用下一个标记预测。我们不希望AI去 预测 某人被开的药物或这种药物可能致命的剂量。投入到这些应用中的努力会形成一个显著的竞争优势——一个 护城河 ,即使所有公司都从同一个语言模型开始,其他公司也很难跨越这个护城河。
这个解释对你澄清大语言模型(LLMs)和AI应用是否有帮助?写这个确实帮助我更好地理解了!
在我的下一篇文章中,我将介绍如何构建一个与这里描述的完全相同类型的AI应用——一个使用训练好的模型,并在Typescript(或JavaScript)应用中添加自定义的微调文档和函数调用的应用。
请随意在此处添加您的评论或直接与我联系。我期待您的反馈。我的联系方式可以在我的作品集网站davidbethune.com上找到。
一如既往,感谢您的阅读!
— D