“ 介绍神经网络的基本概念和结构,讨论训练实践、技巧以及网络规模的大小对模型能力的影响。同时介绍嵌入(Embeddings)概念,将高维数据映射到低维空间。通过本文,您将对神经网络有更深入的理解,有助于后面理解 ChatGPT 是怎么做的,为什么它有效。”
01
—
神经网络
那么我们用于图像识别等任务的典型模型实际上是如何工作的呢?当前最流行且最成功的方法是使用神经网络。神经网络发明于 20 世纪 40 年代,其形式与今天的使用非常接近,可以被认为是大脑工作方式的简单理想化。
人脑中约有 1000 亿个神经元(神经细胞),每个神经元每秒能够产生高达一千次的电脉冲。神经元连接在一个复杂的网络中,每个神经元都有树状分支,使其能够将电信号传递给可能数以千计的其他神经元。粗略地估计,任何给定的神经元是否在给定时刻产生电脉冲取决于它从其他神经元接收到的脉冲——不同的连接贡献不同的“权重”。
当我们“看到图像”时,发生的情况是,当来自图像的光子落在我们眼睛后部的(“光感受器”)细胞上时,它们会在神经细胞中产生电信号。这些神经细胞与其他神经细胞相连,最终信号通过一系列神经元层。正是在这个过程中,我们“识别”了图像,最终“形成了我们正在“看到 2”的想法(也许最终会大声说出“二”这个词)。
上一节中的“黑盒”函数是此类神经网络的“数学化”版本。它恰好有 11 层(尽管只有 4 个“核心层”):
(注:虽然上图有 11 层,但是主要的就是前四种核心层,最后一个输出用的层。各层的大致作用简单了解如下:
Convolutional layers 卷积层,就是使用一系列过滤器对图片做卷积计算,提取特征。并且典型的卷积层会使用ReLU激活函数来引入非线性因数。
Ramp 激活函数,一种斜面函数。激活函数是构建神经网络过程中的重要环节,若神经元的净激活net为正,称该神经元处于激活状态或兴奋状态(fire),若净激活net为负,则称神经元处于抑制状态。
激活函数有三种线性函数:线性函数 ( Liner Function ),斜面函数 ( Ramp Function ),阈值函数 ( Threshold Function ),两个非线形函数:S形函数 ( Sigmoid Function ) ,双极S形函数)
Pooling layers 池化层:池化这个概念相对简单,类似于压缩图片。
Flatten层的功能:Flatten层是把一个输入的大小为n * c * h * w变成一个简单的向量,其大小为 n * (chw)。可以用reshape代替~,相当于第一维不变,后面的自动计算。
LinearLayer 线性层:对一维信号(向量)进行线性组合,所以它挨着 Fatten 层。
Softmax 层:将多个标量映射为一个概率分布,其输出的每一个值范围在(0,1)。用在神经网络的最后一层,作为输出层,进行多分类。)
这个神经网络没有什么特别的“理论推导”;它只是1998 年作为一项工程而构建的东西,并且被发现可以工作。(当然,这与我们描述的通过生物进化过程产生的大脑没有太大不同。)
(注:因为是模仿人类大脑的工作原理,所以它叫神经网络。它提出来很久了,经过三个阶段,直到最近,算法进步和算力的增长,深度学习的神经网络才迎来它的爆发期)
好的,但是像这样的神经网络如何“识别事物”呢?关键是吸引子的概念。想象一下我们有 1 和 2 的手写图像:
我们希望所有 1 都“被一个地方吸引”,而所有 2 都“被另一个地方吸引”。或者,换句话说,如果图像在某种程度上“更接近 1 ”而不是 2,我们希望它最终位于“1 位”,反之亦然。
作为一个简单的类比,假设我们在平面上有某些位置,用点表示(在现实生活中,它们可能是咖啡店的位置)。然后我们可能会想象,无论从平面上的哪个点开始,我们总是希望到达最近的点(也就是我们总是去最近的咖啡店)。我们可以通过将平面划分为由理想化“分水岭”分隔的区域(“吸引盆地”)来表示:
我们可以将其视为实现一种“识别任务”,我们不是在做像识别给定图像最接近哪个数字之类的事情,而是直接确定一个给定的点最靠近哪个点。(我们在这里展示的“Voronoi 图”,将平面欧几里德空间中的点分开;可以将数字识别任务看作是在由每个图像中所有像素的灰度级组成的 784 维空间中进行非常类似的操作。)
(注:784 维空间 784-dimensional space 是一个矩阵,不用纠结为什么是784 维,这也是为什么人工智能受制于算力的原因:计算量大。现在优化计算量也是正在研究的方向之一。)
那么,如何使神经网络“执行识别任务”呢?让我们考虑这个非常简单的案例:
我们的目标是获取与位置 { x , y } 相对应的“输入”,然后将其“识别”为最接近的三个点之一。换句话说,我们希望神经网络计算一个关于 { x , y } 的函数,类似于:
那么如何使用神经网络实现这个功能呢?实际上,神经网络是由理想化的“神经元”组成的连接集合,通常以层的方式排列。一个简单的示例如下所示:
(注:这个图就是神经网络的基本结构,一共四层,更复杂的神经网络也是在这个基础上演变而来,组合了多层)
每个“神经元”实际上被设置为评估一个简单的数值函数。为了“使用”网络,我们只需在顶部输入数字(如坐标x和y),然后让每个层上的神经元“评估其函数”并将结果沿网络向前传递,最终在底部产生最终结果。
在传统的(受生物启发的)设置中,每个神经元从前一层的神经元那里有效地获得一定数量的“传入连接”,每个连接都被赋予一定的“权重”(可以是正数或负数)。给定神经元的值由将“前一层神经元”的值乘以它们对应的权重,然后加总并加上一个常数来确定,并最终应用“阈值化”(或“激活”)函数来确定。在数学上,如果一个神经元具有输入x = {x1,x2 ...},我们计算f[w . x + b],其中权重w和常数b通常对于网络中的每个神经元选择不同;函数f通常是相同的。
计算w . x + b只是矩阵乘法和加法的问题。激活函数f引入了非线性(最终导致非平面的行为)。常用的激活函数有很多种;在这里,我们将使用斜坡函数(或ReLU):
对于我们希望神经网络执行的每个任务(或者等效地说,我们希望它评估的每个整体函数),我们将有不同的权重选择。(正如我们将在后面讨论的那样,这些权重通常通过使用机器学习从我们希望的输出的示例来“训练”神经网络来确定。)
最终,每个神经网络只对应某个整体的数学函数,尽管可能很复杂。对于上面的示例,它可能如下所示:
ChatGPT的神经网络也只对应类似的数学函数,但实际上有数十亿个项。
让我们回到单个神经元。下面是一个具有两个输入(表示坐标x和y)的神经元在各种权重和常数选择下可以计算的函数的示例(使用斜坡函数作为激活函数):
那么关于上面的较大网络呢?嗯,它计算的是这个:
它不完全“正确”,但接近我们上面展示的“最近点”函数。
让我们看看其他一些神经网络的情况。在每种情况下,我们将在稍后解释,我们使用机器学习找到最佳的权重选择。然后在这里展示具有这些权重的神经网络计算的结果:
更大的网络通常更好地逼近我们的目标函数。在每个吸引子盆地的“中间”,通常我们会得到我们想要的答案。但在边界处,神经网络“很难下定决心”的地方,情况可能会比较混乱。
在这个简单的数学风格的“识别任务”中,很明显“正确答案”是什么。但在识别手写数字的问题中,情况就不那么清楚了。如果有人把“2”写得像“7”呢?等等。尽管如此,我们可以询问神经网络如何区分数字,这给出了一些线索:
我们能否“从数学上”解释网络是如何作出区分的?实际上不能。它只是“按照神经网络的方式进行”。但事实证明,这通常与我们人类所作出的区分相当一致。
让我们举一个更复杂的例子。假设我们有猫和狗的图像,并且我们有一个经过训练以区分它们的神经网络。以下是它在一些示例上的表现:
现在,“正确答案”变得更加不明确了。那么穿着猫装的狗怎么办?等等。无论输入什么样的图像,神经网络都会生成一个答案,并且在某种程度上与人类的判断相当一致。正如我之前所说,这不是我们可以“从第一原理”推导出来的事实。这只是经验上被发现在某些领域中成立的一种情况。但这是神经网络有用的一个关键原因:它们以某种方式捕捉到了一种“类似于人类”的处理方式。
给自己看一张猫的图片,然后问“这是一只猫的原因是什么?”也许你会说:“嗯,我看到了它尖尖的耳朵等等。”但很难解释你是如何将图像识别为猫的。只是不知怎么地,你的大脑就能弄清楚。但对于大脑来说,目前没有办法“进入内部”并看到它是如何解决这个问题的。对于(人工)神经网络呢?当你给它展示一张猫的图片时,很容易看到每个“神经元”在做什么。但即使是基本的可视化通常也非常困难。
在上面用于“最近点”问题的最终网络中,有17个神经元。在用于识别手写数字的网络中,有2190个神经元。在我们用于识别猫和狗的网络中,有60,650个神经元。通常很难将60,650维空间可视化。但由于这是一个用于处理图像的网络,它的许多神经元层都组织成像它所看到的像素数组一样的数组。
如果我们拿一个典型的猫的图像来看
然后,我们可以通过一系列派生图像来表示第一层神经元的状态,其中许多图像我们可以很容易地解释为“没有背景的猫”或“猫的轮廓”等等:
到了第10层,就很难解释正在发生的事情:
但总的来说,我们可以说神经网络在“挑选出某些特征”(也许尖尖的耳朵是其中之一),并使用这些特征来确定图像的内容。但这些特征是否是我们有名称的特征,比如“尖尖的耳朵”?大多数情况下并不是。
我们的大脑是否使用类似的特征?我们大多数时候并不知道。但值得注意的是,像我们在这里展示的这种神经网络的前几层似乎挑选出了图像的某些方面(如物体的边缘),这些方面似乎与我们知道的大脑视觉处理的第一层所挑选出的方面相似。
但假设我们想要一个关于神经网络中猫识别的“理论”。我们可以说:“看,这个特定的网络可以做到”——这立即让我们对问题的“难度”有了一些概念(例如,需要多少个神经元或层)。但至少目前我们没有办法“提供一个叙述描述”来解释网络在做什么。也许这是因为它确实是计算上不可简化的,并且除了通过明确追踪每一步之外,没有通用的方法可以找出它的功能。或者也许只是因为我们还没有“弄清楚科学”,并且还没有确定能够概括正在发生的事情的“自然法则”。
当我们谈论使用ChatGPT生成语言时,我们将遇到同样的问题。再次强调,目前尚不清楚是否有办法“总结它在做什么”。但是语言的丰富性和细节(以及我们对它的经验)可能使我们在这方面取得更进一步的进展。
(注:这也是大模型的魅力所在,创造它的人也无法用准确的语言描述它到底在干了些什么,也不明白它怎么做到的,所以人工智能出现了一个词:“涌现”,来表示大模型的这种能力。
有点类似至今我们也无法理解大脑到底是怎么工作的。
那人工智能会“涌现”出创造力吗?
有一种观点认为大模型只是按某种概率产生回答,它受限于人类目前已有的多模态(文字、声音、视频)资料,并不会创造。
有一种观点认为也许有一天,它会产生自己的意识,并认为它会变得很危险,需要加以限制。
你觉得哪种观点对?)
02
—
机器学习与神经网络的训练
迄今为止,我们讨论的是“已经知道”如何执行特定任务的神经网络。但神经网络之所以如此有用(也适用于大脑),是因为它们不仅原则上可以执行各种任务,而且可以逐步地从示例中“训练”以执行这些任务。
当我们制作一个可以区分猫和狗的神经网络时,我们不需要有效地编写一个程序来直白的找到(猫狗的)触须;相反,我们只需要展示很多关于什么是猫和什么是狗的示例,然后让神经网络从中“机器学习”,学会区分它们。
关键在于,经过训练的神经网络可以从它所展示的特定示例中“泛化”。就像我们之前看到的那样,网络并不仅仅是识别它所展示的特定猫图像的像素模式;而是神经网络以某种方式根据我们认为的某种“一般猫的特征”来区分图像。
那么神经网络的训练实际上是如何工作的呢?基本上,我们始终试图找到一组权重,使神经网络能够成功地复现我们给定的示例。然后,我们依赖于神经网络以一种“合理”的方式在这些示例之间进行“插值”(或“泛化”)。
让我们看一个比上面的最近点问题更简单的问题。我们只是尝试让神经网络学习函数:
对于这个任务,我们将需要一个只有一个输入和一个输出的网络,如下所示:
但是,我们应该使用什么权重等?对于每组可能的权重,神经网络都会计算一些函数。例如,以下是使用几组随机选择的权重时的情况:
是的,我们可以明显看到,在这些情况下,它都没有接近我们想要的函数。那么如何找到能够复现函数的权重呢?
基本思想是提供大量的“输入→输出”示例供其“学习”,然后尝试找到能够复现这些示例的权重。以下是使用逐渐增加的示例进行训练的结果:
在这个“训练”过程的每个阶段,网络中的权重逐渐调整,我们看到最终获得了一个成功复现所需函数的网络。那么我们如何调整权重呢?基本思想是在每个阶段看看“离我们想要的函数有多远”,然后以一种使之更接近的方式更新权重。
为了找出“离我们想要的函数有多远”,我们计算通常称为“损失函数”(有时称为“代价函数”)的函数。在这里,我们使用一个简单的(L2)损失函数,即获取的值与真实值之间差异的平方和。我们看到,随着训练过程的进行,损失函数逐渐减小(根据不同任务的不同“学习曲线”),直到达到一个点,网络(至少在很好的近似情况下)成功复现了我们想要的函数:
最后一个需要解释的关键部分是如何调整权重以减小损失函数。正如我们所说,损失函数给出了我们得到的值与真实值之间的“距离”。但是,“我们得到的值”在每个阶段都由当前版本的神经网络决定,并由其中的权重确定。现在假设权重是变量,比如wi。我们想要找出如何调整这些变量的值以最小化依赖于它们的损失。
例如,想象一下(这是对实际应用中典型神经网络的极度简化),我们只有两个权重w1和w2。那么我们可能会有一个以w1和w2为函数的损失函数如下所示:
在这种情况下,数值分析提供了多种寻找最小值的技术。但一种典型的方法是沿着最陡下降的路径逐步前进,从之前的w1和w2开始:
就像水流下山一样,唯一保证的是这个过程最终会达到曲面的某个局部最小值(“山中湖泊”),但未必会达到最终的全局最小值。
在“权重空间”上找到最陡下降路径并不明显可行。但微积分可以解决这个问题。我们可以将神经网络视为计算一个依赖于输入和权重的数学函数。现在考虑对这些权重进行微分。事实证明,微积分的链式法则实际上使我们能够“解开”神经网络中连续层所进行的操作。结果是,我们可以至少在某种局部近似下“反演”神经网络的操作,并逐步找到最小化与输出相关的损失的权重。
上面的图片展示了我们在仅有两个权重的,不现实的简单情况下可能需要进行的最小化过程。但是事实证明,即使在有更多权重的情况下(ChatGPT使用了1750亿个权重),仍然有可能进行最小化,至少在某种程度上得到近似结果。实际上,围绕2011年左右出现的“深度学习”重大突破与一种发现相关,即在某种意义上,当涉及大量权重时,进行(至少近似)最小化可能比涉及相当少的权重更容易。
换句话说,有些违反直觉的是,用神经网络解决更复杂的问题可能比解决更简单的问题更容易。粗略的原因似乎是,当有很多“权重变量”时,高维空间中有“很多不同的方向”可以引导我们达到最小值,而如果变量较少,很容易陷入局部最小值(“山中湖泊”),无法“找到出口的方向”。
值得指出的是,在典型情况下,有很多不同的权重组合都可以得到几乎具有相同性能的神经网络。通常在实际的神经网络训练中会进行许多随机选择,这会导致“不同但等效的解”,就像下面这些:
然而,每个这样的“不同解”都会有至少稍微不同的行为。如果我们要求在我们给出训练样例之外的“外推”区域进行预测,我们可能会得到截然不同的结果。
但是哪个结果是“正确”的?实际上没有办法说。它们都“与观察到的数据一致”。但它们对应于不同的“内在”思考方式,以确定如何在“盒子外部”进行操作。其中一些可能对我们人类来说比其他解更“合理”。
(注:这段相当的硬核,比较难以理解,多读几遍就好了。
这个是人工智能的核心,模拟大脑的思维过程:建模,训练,反馈 - 看看是否符合现实情况,调整,再训练。)
03
—
神经网络训练的实践和技巧
在过去的十年中,神经网络训练的技术取得了许多进展。没错,它基本上是一门艺术。有时候事后回顾,我们可以看到对于某个正在进行的事情,至少有一些“科学解释”的端倪。但大多数情况下,这些技术都是通过试错方法发现的,逐渐积累了关于如何处理神经网络的丰富经验。
其中有几个关键部分。首先,对于特定任务,应该使用什么样的神经网络结构。然后,关键问题是如何获取用于训练神经网络的数据。而且,现在往往不是从头开始训练一个新的神经网络,而是新的网络要么直接包含另一个已经训练好的网络,要么至少可以利用那个网络为自己生成更多的训练样本。
之前我们可能会认为,对于每种特定的任务,都需要一种不同的神经网络结构。但事实上发现,即使是看起来非常不同的任务,同样的结构通常也能奏效。在某种程度上,这让人联想到了通用计算的概念(以及我提出的计算等价性原理),但正如我之后将讨论的,我认为这更多地反映了我们通常试图让神经网络完成的任务是“类似人类”的任务,而神经网络可以捕捉到相当通用的“类人过程”。
(注:在通用型人工智能 ChatGPT 未出现之前,就是这类处理思路。针对图像识别,有专门图像识别的神经网络模型。针对商品的客户评价,有文字的处理模型。翻译方面,有专门翻译的模型,曾经最好的翻译是谷歌翻译 - 现在是之一。)
在神经网络的早期阶段,人们倾向于认为“让神经网络尽可能少地做事情”是一个好主意。例如,在将语音转换为文本时,人们认为应该先分析语音的音频,将其分解为音素等。但后来发现,至少对于“类人任务”来说,通常更好的方法是只需尝试对“端到端问题”进行神经网络训练,让它“发现”必要的中间特征、编码等。
还有一个观点认为,应该向神经网络引入复杂的单个组件,以实际上“明确实施特定的算法思想”。但同样地,这大多数情况下都不值得。相反,最好只使用非常简单的组件,并让它们“自行组织”(尽管通常是以我们无法理解的方式)来实现(推测上)等效的算法思想。
这并不意味着神经网络没有相关的“结构化思想”。例如,在处理图像的早期阶段,拥有具有局部连接的二维神经元阵列似乎至少非常有用。而在处理诸如人类语言(例如ChatGPT中)之类的事物时,具有“向后查看序列”的连接模式似乎也很有用,我们稍后会看到。
但神经网络的一个重要特点是,就像计算机一样,它们最终只是在处理数据。而当前的神经网络(以及神经网络训练的当前方法)专门处理数字数组。但在处理过程中,这些数组可以完全重新排列和重塑。以前面我们用于识别数字的网络为例,它从一个二维的“类似图像”的数组开始,迅速“加厚”为许多通道,然后“集中”为一个一维数组,最终包含代表不同可能输出数字的元素:
如何确定在特定任务中需要多大的神经网络呢?这是一种艺术。在某种程度上,关键是了解“任务有多难”。但对于类似人类的任务,通常很难估计。是的,可能有一种机械地通过计算机完成任务的系统方法。但很难知道是否存在可以以至少“类似人类水平”更轻松地完成任务的技巧或捷径。机械地枚举一个巨大的游戏树可能会“机械地”玩某个游戏,但可能存在一种更简单(“启发式”)的方法来实现“人类水平的游戏”。
当处理微小的神经网络和简单的任务时,有时可以明确看到“无法从这里到达那里”。例如,下面是使用几个小型神经网络在前面章节中的任务上能够做到的最好结果:
然后我们会发现,如果网络太小,它就无法重现我们想要的功能。但是在某个尺寸以上,它就没有问题,至少在训练时间足够长且使用足够的示例时如此。顺便提一下,这些图片展示了神经网络传统中的一部分:如果在中间有一个“挤压”,迫使所有信号通过较少数量的中间神经元,通常可以用更小的网络来解决问题。(值得一提的是,“无中间层”或所谓的“感知器”网络只能学习基本上是线性的函数,但只要有一个中间层,原则上总是可以以任意好的精度近似任何函数,至少如果有足够的神经元,尽管为了使其可训练性可行,通常需要一些正则化或归一化方法。)
假设我们已经确定了特定的神经网络架构。现在的问题是获取用于训练网络的数据。神经网络和机器学习的许多实际挑战都集中在获取或准备必要的训练数据上。在许多情况下(“监督学习”),我们希望获得输入的显式示例以及对应的期望输出。例如,我们可能希望对图像进行标记,标记其中包含的内容或其他属性。也许我们必须明确地进行标记,通常需要花费大量精力。但很多时候,我们可以利用已经完成的工作,或将其用作某种代理。因此,例如,我们可以使用网络上提供的alt标签来进行图像标记。或者,在不同领域中,我们可以使用为视频创建的闭路字幕。或者,在语言翻译训练中,我们可以使用以不同语言存在的网页或其他文档的平行版本。
为了训练特定任务的神经网络,需要展示多少数据给它?同样,很难从第一原理进行估计。当然,使用“迁移学习”将已经在另一个网络中学到的重要特征列表“迁入”可以大大减少需求。但通常神经网络需要“看到很多示例”才能进行良好的训练。至少对于某些任务而言,神经网络的传统认识是示例可以极其重复。事实上,一个标准的策略是反复向神经网络展示所有已有的示例。在每个“训练轮次”(或“周期”)中,神经网络的状态至少会略有不同,并且以某种方式“提醒它”特定的示例有助于让它“记住那个示例”。(是的,也许这类似于人类记忆中重复的有用性。)
然而,仅仅重复相同的示例并不足够。还需要向神经网络展示示例的变化。神经网络的传统认识是,这些“数据增强”的变化并不需要很复杂就能发挥作用。只需使用基本图像处理稍微修改图像,就可以使其在神经网络训练中变得“一样好”。类似地,当用于训练自动驾驶汽车的实际视频等数据用尽时,可以继续在类似于模拟游戏的环境中运行模拟,并从中获取数据,而无需关注实际现实场景的所有细节。
那么类似 ChatGPT 这样的模型呢?它有一个好的特点,即它可以进行“无监督学习”,从而更容易为其提供训练示例。回想一下,ChatGPT 的基本任务是弄清楚如何继续给定的一段文本。因此,要获得“训练示例”,我们只需要获取一段文本,将其结尾部分屏蔽,并将其用作“训练输入”,同时将完整的、未屏蔽的文本作为“输出”。我们稍后会更详细地讨论这一点,但主要观点是,与学习图像内容不同,ChatGPT不需要“显式标记”;它实际上可以直接从任何给定的文本示例中进行学习。
那么神经网络的实际学习过程是如何进行的呢?最终的目标是确定哪些权重能够最好地捕捉到给定的训练示例。有各种各样的详细选择和“超参数设置”(称为超参数,因为权重可以被视为“参数”),可以用来微调这个过程。有不同的损失函数选择(平方和、绝对值和等)。有不同的损失最小化方式(每步在权重空间中移动多远等)。然后还有一些问题,例如每次展示多少个“批次”的示例来获得对要最小化的损失的每个连续估计。是的,可以应用机器学习(例如我们在Wolfram语言中所做的)来自动化机器学习,并自动设置超参数等。
但最终,整个训练过程可以通过观察损失如何逐步减小来描述(如用于小型训练的 Wolfram 进度监视器中所示):
(注:Wolfram 是一种由沃尔夫勒姆研究公司开发的多模态编程语言 。主要特点是符号计算、函数式编程和基于规则的编程。它可以用来创建和表示任何结构和数据,内置了用于生成和运行图灵机、创建图形和音频、分析三维模型、矩阵操作、求解微分方程的内置函数。)
通常情况下,损失会先减小一段时间,但最终会趋于某个常数值。如果这个值足够小,那么训练可以被认为是成功的;否则,这可能是改变网络架构的信号。
能否确定“学习曲线”趋于平稳需要多长时间?与许多其他事物一样,似乎存在与神经网络大小和使用的数据量有关的近似幂律关系。但总的结论是,训练神经网络是困难的,并且需要大量的计算工作量。而实际上,绝大部分工作量是在对数字数组进行运算,而这正是 GPU 擅长的领域,这也是神经网络训练通常受到 GPU 可用性限制的原因。
在未来,是否会出现基本上更好的训练神经网络的方法,或者说执行神经网络的任务的方法?我认为几乎可以肯定会有。神经网络的基本思想是利用大量简单(本质上相同)的组件创建一个灵活的“计算结构”,并使这个“结构”可以通过逐渐修改来从示例中学习。在当前的神经网络中,我们基本上使用了微积分的思想(应用于实数)来进行这种逐步修改。但越来越明显的是,高精度的数字并不重要;即使在当前方法下,8位或更少的精度可能已经足够。
神经网络——或许有点像大脑——被设置为具有基本固定的神经元网络,其中被修改的是它们之间的连接强度("权重")。(或许在至少是年轻的大脑中,完全新的连接数量也可以增长。)但是,虽然这对生物学来说可能是一种方便的设置,但它并不明确是实现我们所需功能的最佳方式。而涉及逐步重写网络的某种方法(或许类似于我们的物理项目)可能最终会更好。
但即使在现有神经网络的框架内,目前存在一个重要的限制:目前的神经网络训练基本上是顺序进行的,每个批次的示例效果被传播回去更新权重。实际上,即使考虑到GPU,当前的计算机硬件在训练过程中大部分时间都是“闲置”的,只有一部分在被更新。从某种意义上说,这是因为我们当前的计算机倾向于具有与CPU(或GPU)分离的内存。但在大脑中,这可能是不同的——每个“存储元素”(即神经元)也是一个潜在的主动计算元素。如果我们能够以这种方式设置未来的计算机硬件,可能能够更高效地进行训练。
(注:我理解人的大脑神经是可以并行的,而现在的大模型还做不到并行训练。其次,大脑的神经元是计算&存储,也就是说如果把大脑看成电脑,它每一个神经元都是CPU+内存+硬盘,而目前的计算机这几部分是分开的,导致计算和存储分离,效率大大下降。)
04
—
足够大的网络可以做任何事情!
类似 ChatGPT 这样的系统的能力如此令人印象深刻,以至于人们可能会想象,如果能够继续训练更大、更大的神经网络,那么它们最终将能够“做任何事情”。如果我们关注那些容易被即时人类思维所接触到的事物,这种想法可能是正确的。但过去几百年科学的教训是,有些事情可以通过形式化的过程来解决,但对于即时人类思维来说并不容易。
非平凡的数学就是一个很好的例子。但一般情况下是关于计算的。最终问题在于计算不可约性的现象。有些计算可能需要很多步骤才能完成,但实际上可以被“化简”为相当直接的形式。但是计算不可约性的发现意味着这种情况并非总是成立。相反,存在一些过程(可能类似于下面的过程),为了弄清楚发生了什么,不可避免地需要基本上追踪每个计算步骤:
(注:数学中,术语平凡或平凡的经常用于结构非常简单的对象 -- 比如群或拓扑空间。
非平凡解在数学中具有重要意义,包括代数、几何和分析等领域。在代数中,非平凡解意味着有多种方式能够满足方程,这可以导致所研究的结构的有趣性质。在几何中,解决问题的非平凡解通常涉及发现形状或对象之间意外的关系,这可以导致对所研究的几何学的新见解。
在物理学中,非平凡解通常用于描述不太明显或难以解释的物理现象。例如,在量子力学中,薛定谔方程的非平凡解用于描述复杂系统(如原子和分子)中粒子的行为。
总的来说,非平凡解之所以重要,是因为它们通常需要创造性的思维和洞察力,这可以在给定领域中带来新的发现和见解。它们还可以用于测试现有方法和理论的限制,并确定需要新方法或技术的领域。)
我们通常用大脑进行的活动可能是有意避免计算不可约性的。在大脑中进行数学运算需要特殊的努力。实际上,仅凭脑中的思考几乎不可能“思考透”任何非平凡程序的操作步骤。
但是,当然我们有计算机。通过计算机,我们可以轻松地进行长时间的计算不可约性任务。关键是,对于这些任务通常没有捷径可走。
我们可以记住许多关于某个特定计算系统中发生的特定例子。也许我们甚至可以看到一些(“计算上可化简”的)模式,使我们能够进行一些泛化。但是关键是,计算不可约性意味着我们永远无法保证不会发生意外情况,只有通过显式计算才能确定在任何特定情况下会发生什么。
最终,学习和计算不可约性之间存在一种根本的张力。学习实际上是通过利用规律性来压缩数据。但是计算不可约性意味着最终可能存在规律性的限制。
作为实际问题,可以设想在可训练的系统(如神经网络)中构建类似元胞自动机或图灵机的小型计算设备。实际上,这样的设备可以作为神经网络的良好“工具”,就像 Wolfram|Alpha 对 ChatGPT 有益一样。但是,计算不可约性意味着不能指望“进入”这些设备并让它们学习。
或者换句话说,能力与可训练性之间存在着根本的权衡:你越希望系统能够真正利用其计算能力,它就越会展现计算不可约性,而可训练性就会越弱。而如果系统从根本上可训练,它就越难以进行复杂的计算。
(对于当前的 ChatGPT,情况实际上更为极端,因为用于生成每个输出符号的神经网络是纯粹的“前馈”网络,没有循环,因此无法进行任何涉及非平凡“控制流”的计算。)
当然,人们可能会想知道是否实际上能够进行不可约计算并不重要。实际上,在人类历史的大部分时间里,这并不特别重要。但是我们现代的技术世界是建立在利用数学计算(至少如此)和越来越多的更一般计算的工程基础上的。如果我们观察自然界,它充满了不可约计算,我们正在逐步理解如何模拟和利用它们来满足我们的技术需求。
神经网络当然可以注意到自然界中的那些我们可能用“未经辅助的人类思维”也能轻易注意到的规律。但是,如果我们想解决数学或计算科学领域的问题,神经网络将无法做到这一点,除非它有效地将一个“普通”的计算系统作为“工具”来使用。
但是,这其中可能存在一些潜在的混淆。在过去,有许多任务(包括写作文章)被认为在某种程度上对计算机来说“基本上太难”。而现在我们看到像 ChatGPT 这样的系统完成这些任务后,我们往往突然认为计算机一定变得非常强大,特别是超过了它们已经基本能够做到的事情(比如逐步计算元胞自动机等计算系统的行为)。
但这不是正确的结论。计算不可约性的过程仍然是计算不可约的,对于计算机来说仍然是基本困难的,即使计算机可以轻松计算它们的各个步骤。我们应该得出的结论是,像写作文章这样的任务,我们人类能够做到,但我们认为计算机无法做到的任务,在某种意义上实际上比我们想象的计算上更容易。
换句话说,神经网络在写作文章方面能够取得成功,是因为写作文章的问题比我们想象的“计算上更浅”。从某种意义上说,这使我们更接近“拥有一个理论”,即我们人类如何成功地完成写作文章等任务,或者如何处理语言问题。
(注:最新的新闻显示, ChatGPT 可以帮助论证数学定理:“加州理工和MIT研究者用ChatGPT证明数学定理的论文在数学圈引发了极大关注”,不知道 GPT 是怎么做到这一点的,OpenAI 也没有公开他们的论文和模型的秘密。)
如果你拥有足够大的神经网络,那么你可能能够做到人类能够轻松完成的任务。但是你无法捕捉到自然界总体所能做到的事情,或者说我们从自然界塑造出来的工具所能做到的事情。正是通过使用这些工具——无论是实用工具还是概念工具——我们在最近几个世纪里超越了“纯粹无辅助人类思维”的限制,从而为人类目的更好地利用了物理和计算宇宙中的资源。
05
—
嵌入(Embeddings)的概念
神经网络——至少在目前的设置中——基本上是基于数字的。因此,如果我们要将其用于处理文本等任务,就需要一种用数字表示文本的方式。当然,我们可以从简单的方法开始(就像ChatGPT一样),只需给字典中的每个单词分配一个数字。但还有一个重要的思想——例如ChatGPT的核心——超越了这一点。这就是“嵌入”(Embeddings)的概念。我们可以将嵌入看作是通过一系列数字来尝试表示某个事物的“本质”,并且具有“相近事物”用相近的数字表示的属性。
例如,我们可以将词嵌入视为一种试图在某种“意义空间”中布置单词的方式,在该空间中,意义上相近的单词在嵌入中靠近。实际使用的嵌入(比如在ChatGPT中)往往涉及大量的数字列表。但如果我们将其投影到二维空间,我们可以展示单词在嵌入中的布局示例:
然而,我们该如何构建这样的嵌入呢?大致的思路是观察大量的文本(比如来自网络的50亿个单词),然后看不同单词出现在哪些“环境”中时有多相似。举个例子,"alligator"和"crocodile"在其他相似的句子中几乎可以互换,这意味着它们在嵌入中会被放置在附近。但"萝卜"和"老鹰"在其他相似的句子中不太可能同时出现,因此它们会在嵌入中被放置得很远。
那么,如何使用神经网络来实现这样的嵌入呢?让我们首先讨论图像的嵌入,而不是单词的嵌入。我们希望找到一种方式,通过一系列数字来描述图像,以便“我们认为相似的图像”被分配相似的数字列表。
我们如何判断是否应该“认为图像相似”呢?嗯,如果我们的图像是手写数字的图像,我们可能会“认为两个图像相似”,如果它们是相同的数字。之前我们讨论过一个被训练用于识别手写数字的神经网络。我们可以将这个神经网络设置为将图像分为10个不同的类别,每个类别对应一个数字,在其最终输出中。
但如果我们在最终“它是一个‘4’”的决策被做出之前“拦截”神经网络内部发生的情况呢?我们可能会预期,在神经网络内部存在一些数字,用于描述图像“在很大程度上类似于‘4’,但有点像‘2’”或类似的情况。这个想法是选择这些数字作为嵌入中的元素。
所以,这是个概念。我们不直接尝试描述“哪个图像靠近哪个图像”,而是考虑一个明确定义的任务(在这种情况下是数字识别),我们可以获得明确的训练数据,然后利用这个事实,在执行这个任务时,神经网络隐含地做出了类似于“靠近性决策”的决策。所以,我们不必明确讨论“图像的靠近性”,我们只是在讨论关于图像所代表的具体问题,然后我们“交给神经网络”隐含地确定这对于“图像的靠近性”意味着什么。
那么,对于数字识别网络,具体是如何工作的呢?我们可以将该网络看作由11个连续的层组成,我们可以将其以如下方式进行图示总结(其中激活函数显示为单独的层):
在开始时,我们将实际图像输入到第一层,图像由像素值的二维数组表示。在最后一层,我们得到一个包含10个值的数组,可以理解为表示网络对图像对应于数字0到9的确定程度。
输入图像后,最后一层神经元的值为:
换句话说,到这一步,神经网络对这个图像是数字4非常确定,而要得到输出的“4”,我们只需选出具有最大值的神经元的位置。
但是如果我们再往前看一步呢?网络中的最后一个操作是所谓的softmax,它试图“强制确定性”。但在应用softmax之前,神经元的值是:
仍然有一个神经元代表着数字“4”,并具有最高的数值。但其他神经元的值中也包含了信息。我们可以预期,这个数字列表可以在某种程度上用来表征图像的“本质”,从而提供我们可以用作嵌入的东西。例如,这里的每个数字“4”都有略微不同的“特征签名”(或“特征嵌入”),而与数字“8”完全不同:
在这里,我们基本上使用了10个数字来描述我们的图像。但通常最好使用更多的数字。例如,在我们的数字识别网络中,通过访问前一层,我们可以得到一个包含500个数字的数组。这可能是一个合理的用作“图像嵌入”的数组。
如果我们想对手写数字的“图像空间”进行明确的可视化,我们需要“降低维度”,通过将我们得到的500维向量投影到,比如,3D空间中:
我们刚刚讨论了如何根据图像的相似性来创建图像的特征化(从而形成嵌入),通过确定它们是否(根据我们的训练集)对应于相同的手写数字。如果我们有一个训练集,能够确定每个图像是5000个常见物体类型(猫、狗、椅子等)中的哪一种,我们也可以更一般地对图像进行相同的操作。通过这种方式,我们可以创建一个图像嵌入,它以我们对常见物体的识别为“锚点”,然后根据神经网络的行为“在此基础上进行泛化”。关键在于,只要该行为与人类对图像的感知和解释方式相符,这将成为一个“看起来正确”的嵌入,并且在实践中对于执行“类似人类判断”的任务非常有用。
好的,那么我们如何按照相同的方法为单词找到嵌入呢?关键是从一个关于单词的任务开始,我们可以很容易地进行训练。标准的任务是“单词预测”。想象一下,我们得到了“the ___ cat”。基于大量的文本语料库(比如网络文本内容),不同可能“填空”的单词的概率是多少?或者,另一种情况是,给定“___ black ___”,不同“两侧单词”的概率是多少?
我们如何为神经网络设置这个问题?最终,我们必须用数字来表示所有内容。一种方法是为英语中的大约5万个常见单词分配唯一的数字。因此,例如,“the”可能是914,“ cat”(前面有一个空格)可能是3542。(这些是GPT-2使用的实际数字。)因此,对于“the ___ cat”的问题,我们的输入可能是{914, 3542}。输出应该是一个包含大约5万个数字的列表,有效地给出了每个可能的“填充”单词的概率。再次提到,为了找到嵌入,我们希望“截取”神经网络在“得出结论之前”的“内部状态”,然后获得在那里出现的列表,我们可以将其视为“描述每个单词”的列表。
那么,这些描述是什么样的?在过去的10年中,已经开发出一系列不同的系统(word2vec、GloVe、BERT、GPT等),每个系统都基于不同的神经网络方法。但归根结底,它们都是通过数百到数千个数字的列表来描述单词。
这些“嵌入向量”在原始形式下并不具备信息量。例如,下面是GPT-2为三个特定单词生成的原始嵌入向量的示例:
通过测量这些向量之间的距离,我们可以找到单词之间的“相似度”。稍后我们将详细讨论这些嵌入的“认知”意义。但目前的重点是我们有一种有效的方法,可以将单词转化为“神经网络友好”的数字集合。
实际上,我们不仅可以将单词表示为数字集合,还可以将单词序列或整个文本块表示为数字集合。在ChatGPT内部,它正是这样处理的。它使用当前已有的文本生成一个嵌入向量来表示它。然后,它的目标是找到可能出现在接下来的单词中的不同单词的概率。它将其答案表示为一个数字列表,这些数字基本上给出了大约5万个可能单词的概率。
(严格来说,ChatGPT并不处理单词,而是处理“标记”——方便的语言单位,可以是整个单词,也可以只是像“pre”、“ing”或“ized”这样的部分。使用标记使得ChatGPT更容易处理罕见的、复合的和非英语的单词,并且有时可以更好地或更糟地创造新词。)
(注:这部分内容涉及深度学习的概念和技术太多,极其不好消化,大致了解一下即可,也不影响使用大模型。)
往期热门文章推荐:
为什么对ChatGPT、ChatGLM这样的大语言模型说“你是某某领域专家”,它的回答会有效得多?(一)
与ChatGPT媲美的大模型试用:免费体验 Claude 手把手的保姆级教程!
快捷部署清华大模型 ChatGLM2-6B,一键搞定 HuggingFace Space 空间
终于部署成功!GPU 云环境搭建 ChatGLM2-6B 坎坷路
拥抱未来,学习 AI 技能!关注我,免费领取 AI 学习资源。