"); //-->
神经网络 —— 至少在它们目前的设置中 —— 从根本上说是基于数字的。因此,如果我们要用它们来处理像文本这样的东西,我们就需要一种方法来用数字表示我们的文本。当然,我们可以开始(基本上就像 ChatGPT 那样)为字典中的每个词分配一个数字。但是,有一个重要的想法 —— 例如,它是 ChatGPT 的核心 —— 超出了这个范围。这就是 “嵌入” 的概念。我们可以把嵌入看作是一种尝试用数字阵列来表示事物 “本质” 的方式 —— 其特性是 “附近的事物” 由附近的数字来表示。
因此,举例来说,我们可以把一个词的嵌入看作是试图在一种 “意义空间” 中排列词语,在这个空间中,以某种方式 “在意义上接近” 的词语在嵌入中出现。实际使用的嵌入 —— 例如在 ChatGPT 中 —— 往往涉及大量的数字列表。但是如果我们把它投射到二维空间,我们就可以显示出嵌入的单词是如何排列的例子:
而且,是的,我们看到的东西在捕捉典型的日常印象方面做得非常好。但是,我们怎样才能构建这样一个嵌入呢?大致的想法是查看大量的文本(这里是来自网络的 50 亿个词),然后看不同的词出现的 “环境” 有多相似。因此,例如,“鳄鱼” 和 “鳄鱼” 经常会在其他类似的句子中互换出现,这意味着它们在嵌入中会被放在附近。但是 “萝卜” 和 “老鹰” 不会出现在其他类似的句子中,所以它们在嵌入中会被放在很远的地方。
但是,如何使用神经网络实际实现这样的东西呢?让我们先来讨论一下不是针对单词的嵌入,而是针对图像的嵌入。我们想找到某种方法,通过数字列表来描述图像,使 “我们认为相似的图像” 被分配到相似的数字列表中。
我们如何判断我们是否应该 “认为图像相似”?好吧,如果我们的图像是,例如,手写的数字,我们可能会 “认为两个图像是相似的”,如果它们是相同的数字。早些时候,我们讨论了一个被训练来识别手写数字的神经网络。我们可以认为这个神经网络被设置成在其最终输出中把图像放入 10 个不同的仓,每个数字一个仓。
但是,如果我们在做出 “这是一个 ‘4’” 的最终决定之前,“****” 神经网络内部发生的事情呢?我们可能会想到,在神经网络中,有一些数字将图像描述为 “大部分是 4,但有一点是 2” 或类似的情况。而我们的想法是挑选出这样的数字作为嵌入的元素。
所以这里有一个概念。我们不是直接试图描述 “什么图像在什么其他图像附近”,而是考虑一个定义明确的任务(在这种情况下是数字识别),我们可以获得明确的训练数据 —— 然后利用这样一个事实,即在做这个任务时,神经网络隐含地要做出相当于 “接近度决定” 的决定。因此,我们不需要明确地谈论 “图像的接近性”,而只是谈论一个图像代表什么数字的具体问题,然后我们 “把它留给神经网络” 来隐含地决定这意味着什么 “图像的接近性”。
那么,这对数字识别网络来说是如何更详细地工作的呢?我们可以认为这个网络是由 11 个连续的层组成的,我们可以用图标来概括它(激活函数显示为独立的层):
在开始时,我们向第一层输入实际的图像,用像素值的二维阵列表示。在最后一层,我们得到了一个由 10 个值组成的数组,我们可以认为这表示网络对图像对应于 0 到 9 的每个数字的 “确定程度”。
输入图像 4,最后一层的神经元的值就是:
换句话说,神经网络此时已经 “非常确定” 这个图像是 4,为了实际得到输出 “4”,我们只需挑选出数值最大的神经元的位置。
但是,如果我们再往前看一步呢?网络中的最后一个操作是一个所谓的 softmax,它试图 “强制确定”。但在这之前,神经元的值是:
代表 “4” 的神经元仍然有最高的数值。但在其他神经元的数值中也有信息。我们可以期望这个数字列表在某种意义上可以用来描述图像的 “本质”,从而提供我们可以用作嵌入的东西。因此,例如,这里的每一个 4 都有一个稍微不同的 “签名”(或 “特征嵌入”) —— 都与 8 的非常不同:
在这里,我们基本上是用 10 个数字来描述我们的图像特征。但通常情况下,使用比这更多的数字会更好。例如,在我们的数字识别网络中,我们可以通过挖掘前一层得到一个 500 个数字的阵列。而这可能是一个合理的数组,作为 “图像嵌入” 使用。
如果我们想对手写数字的 “图像空间” 进行明确的可视化,我们需要 “降低维度”,有效地将我们得到的 500 维向量投射到,例如,三维空间:
我们刚刚谈到为图像创建一个特征(从而嵌入),有效地基于识别图像的相似性,确定(根据我们的训练集)它们是否对应于同一个手写数字。如果我们有一个训练集,比如说,确定每张图片属于 5000 种常见类型的物体(猫、狗、椅子…… ),我们就可以更普遍地对图片做同样的事情。通过这种方式,我们可以制作一个图像嵌入,它被我们对常见物体的识别所 “锚定”,但然后根据神经网络的行为 “围绕它进行概括”。关键是,只要这种行为与我们人类感知和解释图像的方式相一致,这将最终成为一个 “对我们来说是正确的” 的嵌入,并在实践中做 “类似人类判断” 的任务时有用。
好吧,那么我们如何遵循同样的方法来寻找单词的嵌入呢?关键是要从一个我们可以随时进行训练的关于单词的任务开始。而标准的任务是 “单词预测”。假设我们得到了 “the ___ cat”。基于一个大型的文本语料库(比如说,网络上的文本内容),可能 “填空” 的不同单词的概率是多少?或者说,给定 “_____ 黑 _____”,不同的 “侧翼词” 的概率是多少?
我们如何为神经网络设置这个问题?归根结底,我们必须用数字来表述一切。做到这一点的一个方法就是为英语中 5 万个左右的常用词中的每一个分配一个独特的数字。因此,例如,“the” 可能是 914,而 “cat”(前面有一个空格)可能是 3542。(这些是 GPT-2 所使用的实际数字。)所以对于 “the ___ cat” 问题,我们的输入可能是{914, 3542}。输出应该是什么样子的呢?好吧,它应该是一个由 50000 个左右的数字组成的列表,有效地给出了每个可能的 “填充” 单词的概率。再一次,为了找到一个嵌入,我们要在神经网络 “达到结论” 之前 “****” 它的 “内部” —— 然后捡起在那里出现的数字列表,我们可以把它看作是 “每个词的特征”。
好吧,那么这些表征是什么样子的呢?在过去的 10 年里,已经有一系列不同的系统被开发出来(word2vec, GloVe, BERT, GPT, …… ),每一个都是基于不同的神经网络方法。但最终,所有这些系统都是通过数百到数千个数字的列表来描述单词的特征。
在它们的原始形式中,这些 “嵌入向量” 是相当无信息的。例如,这里是 GPT-2 产生的三个特定词的原始嵌入向量:
如果我们做一些事情,比如测量这些向量之间的距离,那么我们就可以发现像单词的 “接近性” 这样的东西。稍后我们将更详细地讨论我们可能认为这种嵌入的 “认知” 意义。但现在主要的一点是,我们有一种方法可以有效地将单词变成 “神经网络友好” 的数字集合。
但实际上,我们可以更进一步,不仅仅是用数字的集合来描述单词;我们还可以对单词的序列,或者整个文本块进行描述。在 ChatGPT 中,它就是这样处理事情的。它把目前得到的文本,生成一个嵌入矢量来表示它。然后,它的目标是找到接下来可能出现的不同词汇的概率。它将其答案表示为一个数字列表,该列表基本上给出了 50,000 个左右的可能词汇的概率。(严格地说,ChatGPT 不处理单词,而是处理 “符号” —— 方便的语言单位,可能是整个单词,也可能只是 “pre” 或 “ing” 或 “ized” 这样的片段。使用代币使 ChatGPT 更容易处理罕见的、复合的和非英语的词汇,有时,无论好坏,都可以发明新的词汇。)
好了,我们终于准备好讨论 ChatGPT 内部的内容了。是的,最终,它是一个巨大的神经网络 —— 目前是所谓的 GPT-3 网络的一个版本,有 1750 亿个权重。在许多方面,这是一个非常像我们讨论过的其他神经网络。但它是一个特别为处理语言问题而设置的神经网络。它最显著的特征是一个叫做 “转化器” 的神经网络架构。
在我们上面讨论的第一个神经网络中,任何给定层的每个神经元基本上都与前一层的每个神经元相连(至少有一些权重)。但是,如果一个人在处理具有特殊的、已知的结构的数据时,这种全连接的网络(大概)是过剩的。因此,例如,在处理图像的早期阶段,典型的做法是使用所谓的卷积神经网络(“convnets”),其中的神经元被有效地布置在一个类似于图像中的像素的网格上 —— 并且只与网格上附近的神经元相连。
变换器的想法是为构成一段文本的标记序列做一些至少有点类似的事情。但是,转化器并不只是在序列中定义一个可以有连接的固定区域,而是引入了 “注意” 的概念 —— 以及对序列的某些部分比其他部分更 “注意” 的概念。也许有一天,仅仅启动一个通用的神经网络并通过训练进行所有的定制是有意义的。但至少到现在为止,将事情 “模块化” 在实践中似乎是至关重要的,就像变压器那样,可能也像我们的大脑那样。
好吧,那么 ChatGPT(或者说,它所基于的 GPT-3 网络)实际上是做什么的?回想一下,它的总体目标是以 “合理” 的方式延续文本,基于它所看到的训练(包括从网络上查看数十亿页的文本等),所以在任何时候,它都有一定数量的文本,它的目标是为下一个要添加的标记提出适当的选择。
它的操作分为三个基本阶段。首先,它获取与迄今为止的文本相对应的标记序列,并找到代表这些标记的嵌入(即一个数字阵列)。然后,它以 “标准的神经网络方式” 对这一嵌入进行操作,数值 “通过” 网络中的连续层,产生一个新的嵌入(即一个新的数字阵列)。然后,它从这个数组的最后一部分,生成一个大约 50,000 个值的数组,这些值变成了不同的可能的下一个标记的概率。(而且,是的,恰好使用的标记的数量与英语中的常用词的数量相同,尽管只有大约 3000 个标记是整个单词,其余的是片段。)关键的一点是,这个管道的每一部分都是由一个神经网络实现的,其权重是由网络的端到端训练决定的。换句话说,实际上,除了整体架构之外,没有任何东西是 “明确设计的”;所有东西都是从训练数据中 “学习” 的。
然而,在架构的设置方式上有很多细节,反映了各种经验和神经网络的传说。而且,尽管这肯定是进入了杂草丛中,但我认为谈论其中的一些细节是有用的,尤其是为了了解建立像 ChatGPT 这样的东西所需要的东西。
首先是嵌入模块。下面是 GPT-2 的 Wolfram 语言示意图:
输入是一个由 n 个标记组成的向量(如上一节所述,由 1 到 50,000 的整数表示)。这些标记中的每一个都被(通过单层神经网络)转换成一个嵌入向量(GPT-2 的长度为 768,ChatGPT 的 GPT-3 为 12,288)。同时,还有一个 “二级路径”,它将标记的(整数)位置序列,并从这些整数中创建另一个嵌入向量。最后,来自令牌值和令牌位置的嵌入向量被加在一起 —— 产生嵌入模块的最终嵌入向量序列。
为什么只是把令牌值和令牌位置的嵌入向量加在一起?我不认为这有什么特别的科学依据。只是各种不同的东西都被尝试过,而这是一个似乎有效的方法。这也是神经网络传说的一部分,从某种意义上说,只要你的设置是 “大致正确的”,通常就可以通过做充分的训练来确定细节,而不需要真正 “在工程层面上理解” 神经网络最终是如何配置它的。
下面是嵌入模块所做的工作,对字符串 “hello hello bye bye bye”:
每个标记的嵌入向量的元素都显示在页面下方,在整个页面上,我们首先看到的是 “hello” 的嵌入,然后是 “bye” 的嵌入。上面的第二个数组是位置嵌入 —— 其看起来有点随机的结构只是 “碰巧学到的”(在这种情况下是 GPT-2)。
好了,在嵌入模块之后,是转化器的 “主要事件”:一连串所谓的 “注意块”(GPT-2 为 12 个,ChatGPT 的 GPT-3 为 96 个)。这一切都很复杂 —— 让人想起典型的难以理解的大型工程系统,或者,生物系统。但无论如何,这里是一个单一的 “注意块” 的示意图(对于 GPT-2):
在每个这样的注意力块中,有一系列的 “注意力头”(GPT-2 有 12 个,ChatGPT 的 GPT-3 有 96 个) —— 每一个都是独立操作嵌入向量中的不同数值块的。(是的,我们不知道为什么分割嵌入向量是个好主意,或者它的不同部分有什么 “意义”;这只是 “被发现可行” 的事情之一)。
好吧,那么注意头是做什么的?基本上,它们是一种在标记序列中 “回顾” 的方式(即在迄今为止产生的文本中),并将过去的内容 “打包” 成有助于寻找下一个标记的形式。在上面的第一节中,我们谈到了使用 2-gram 概率来根据它们的直接前身来挑选单词。变换器中的 “注意” 机制所做的是允许 “注意” 甚至更早的词 —— 因此有可能捕捉到,比如说,动词可以指代在句子中出现在它们之前的许多词的名词的方式。
在更详细的层面上,注意力头所做的是以一定的权重重新组合与不同标记相关的嵌入向量中的大块。因此,例如,在第一个注意力区块中的 12 个注意力头(在 GPT-2 中)对上面的 “hello, bye” 字符串有如下(“look-back-all-the-way-beginning-the-sequence-of-tokens”)模式的 “重组权值”:
在经过注意力头的处理后,产生的 “重新加权的嵌入向量”(GPT-2 的长度为 768,ChatGPT 的 GPT-3 的长度为 12288)被传递到一个标准的 “全连接” 神经网层。很难掌握这个层在做什么。但这里是它使用的 768×768 权重矩阵的图(这里是 GPT-2):
采用 64×64 的移动平均数,一些(随机漫步式的)结构开始出现:
是什么决定了这种结构?最终,它可能是人类语言特征的一些 “神经网络编码”。但到现在为止,这些特征可能是什么还很不清楚。实际上,我们正在 “打开 ChatGPT 的大脑”(或至少是 GPT-2),并发现,是的,里面很复杂,而且我们不了解它 —— 尽管最终它产生了可识别的人类语言。
好吧,在经历了一个注意力区块之后,我们得到了一个新的嵌入向量 —— 然后它又被连续地传递到其他的注意力区块中(GPT-2 共有 12 个;GPT-3 有 96 个)。每个注意力区块都有自己特定的 “注意力” 和 “完全连接” 权重模式。这里是 GPT-2 的 “hell,bye” 输入的注意权重序列,用于第一个注意头(attention head):
这里是全连接层的(移动平均)“矩阵”:
奇怪的是,尽管这些 “权重矩阵” 在不同的注意力块中看起来很相似,但权重的大小分布可能有些不同(而且不总是高斯的):
那么,在经历了所有这些注意力区块之后,转化器的净效果是什么?从本质上讲,它是将原始的符号序列的嵌入集合转化为最终的集合。而 ChatGPT 的具体工作方式是在这个集合中提取最后一个嵌入,并对其进行 “解码”,以产生一个关于下一个标记应该是什么的概率列表。
这就是 ChatGPT 的概要内容。它可能看起来很复杂(尤其是因为它有许多不可避免的、有点武断的 “工程选择”),但实际上,所涉及的最终元素非常简单。因为最终我们要处理的只是一个由 “人工神经元” 组成的神经网络,每个神经元都在进行简单的操作,即接受一组数字输入,然后将它们与某些权重相结合。
ChatGPT 的原始输入是一个数字数组(到目前为止符号的嵌入向量),当 ChatGPT“运行” 以产生一个新的符号时,所发生的只是这些数字 “通过” 神经网的各层,每个神经元 “做它的事”,并将结果传递给下一层的神经元。没有循环或 “回头”。一切都只是通过网络 “前馈”。
这是一个与典型的计算系统 —— 如图灵机 —— 非常不同的设置,在图灵机中,结果是由相同的计算元素反复 “再处理” 的。在这里,至少在生成一个特定的输出符号时,每个计算元素(即神经元)只被使用一次。
但在某种意义上,即使在 ChatGPT 中,仍然有一个重复使用计算元素的 “外循环”。因为当 ChatGPT 要生成一个新的标记时,它总是 “读取”(即作为输入)它之前的整个标记序列,包括 ChatGPT 自己之前 “写” 的标记。我们可以认为这种设置意味着 ChatGPT —— 至少在其最外层 —— 涉及到一个 “反馈循环”,尽管在这个循环中,每一次迭代都明确地显示为一个出现在其生成的文本中的标记。
但让我们回到 ChatGPT 的核心:反复用于生成每个标记的神经网络。在某种程度上,它非常简单:一整个相同的人工神经元的集合。网络的某些部分只是由(“完全连接”)的神经元层组成,其中某一层的每个神经元都与前一层的每个神经元相连(有一定的权重)。但是,特别是它的变压器结构,ChatGPT 有更多的结构部分,其中只有不同层的特定神经元被连接。(当然,人们仍然可以说,“所有的神经元都是连接的” —— 但有些神经元的权重为零)。
此外,ChatGPT 中的神经网的某些方面并不是最自然地被认为是由 “同质” 层组成的。例如,正如上面的图标摘要所示,在一个注意力区块中,有一些地方对传入的数据进行了 “多份拷贝”,然后每个拷贝经过不同的 “处理路径”,可能涉及不同数量的层,然后才重新组合。但是,虽然这可能是对正在发生的事情的一种方便的表述,但至少在原则上总是可以考虑 “密集地填入” 层,但只是让一些权重为零。
如果我们看一下 ChatGPT 的最长路径,大约有 400 个(核心)层参与其中 —— 在某些方面不是一个巨大的数字。但是有数以百万计的神经元 —— 总共有 1750 亿个连接,因此有 1750 亿个权重。需要认识到的一点是,每当 ChatGPT 生成一个新的令牌时,它都要进行涉及这些权重中每一个的计算。在实现上,这些计算可以 “按层” 组织成高度并行的阵列操作,可以方便地在 GPU 上完成。但是,对于产生的每一个标记,仍然要进行 1750 亿次计算(最后还要多一点) —— 因此,是的,用 ChatGPT 生成一个长的文本需要一段时间,这并不令人惊讶。
但最终,最了不起的是,所有这些操作 —— 它们各自都很简单 —— 能够以某种方式共同完成如此出色的 “类似人类” 的文本生成工作。必须再次强调的是,(至少到目前为止,我们知道)没有任何 “最终的理论理由” 来解释这样的工作。事实上,正如我们将要讨论的那样,我认为我们必须把这看作是一个潜在的令人惊讶的科学发现:在像 ChatGPT 这样的神经网络中,有可能捕捉到人类大脑在生成语言方面的本质。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。