前言
将2024年诺贝尔物理学奖授予John J.Hopfield和Geoffrey E.Hinton,以表彰他们"为利用人工神经网络进行机器学习做出的基础性发现和发明"。
我们可以这样建立一个大picture, 语言模型给语言建模,语言给整个世界建模,所以大模型也可以认为给整个世界建模了。
上一个对物理世界建模成功建模的祖师爷级人物是牛顿,他只用了3个定律就对大千世界完成建模。牛顿三大定律现在高中生也可以理解掌握了。
而目前大模型的基础transformer也很简单,大神karpathy写的nanoGpt实现的模型,才400多行,其中还包含了很多优化加速的代码了,比如按批计算什么的。真正原理性的代码,估计就两三百行。这种复杂度的代码高中生也能轻松掌握的。
但是目前transformer比起牛顿力学,大家会觉得难很多,还没有去魅。这是因为我们对牛顿世界观已经建立了物理图像,而transformer在很多人脑海里就还没有统一的物理图像。
本文就试图建立自己的transformer的物理图像,希望抛砖引玉,大神们将自己的物理图像分享出来。
什么是物理图像
物理图像就是就是物理意义,属于定性分析,是对一些公式的理解,有时候不一定有很强的证据或逻辑式一种直觉,有点哲学的味道。但是物理图像能够指明方向提供灵感,真正理解一个问题必须要建立起这个事物的物理图像,否则就是我们经常批评小朋友的死记硬背公式了。所以理科的尽头是文科,理科生也要学点文科。
由于物理图像这样的有点超科学的性质,这些物理图像不一定会记录到正式的论文里面。这些图像会在非正式论坛,当面交谈,非正式讲座里面可能出现的反而比较多,所以当面的交流往往效果更好。
后面我们就详细的分析Transformer模型,同时建立我们的物理图像。我从最最基础的地方开始讲起,希望高中生也能掌握。
Transformer 总体图像
Transformer的开始的时候,主要是用于进行翻译。比如英译中。比如《Attention is All you need》就是一个翻译的场景。在这个场景中一种语言先先用一个encoder翻译成一种中间的表示方式,然后将这个中间表达方式输入到一个decoder将这个中间表达方式翻译成目标语言。那为啥到了GPT的时候,明明是同一种语言,是生成式的,为啥还是能用翻译呢?其实是这样,作为一个翻译,有时候只要理解了语义,你不一定将话说得很完整,也能翻译出来,因此生成式可以认为是将隐含得语义翻译出来。
另一个问题是,GPT根本就没有用到了encoder部分,只用了一个decoder,但为啥仍然是Tranformer结构呢?要回答这个问题,首先我们看看原始Transformer的架构图:
从上面的结构图可以看到Transformer是将一个序列转成了一个中间序列,然后再将这个中间序列转成了目标序列,而GPT则是将源序列直接转换到目标序列。那么中间序列到底是啥呢?这就好比将中文翻译为英文的时候,先将中文翻译成日文,再从日文翻译为英文一样。但是如果我们有一个同时懂中文和英文的翻译,是完全不需要中间再隔一层来翻译的。
有了这样的物理图像,我们知道为啥GPT当时会想到只用decoder就可以了。而decoder和encoder本质上就是懂不同语言的翻译而已,本质是完全相同的,所以都叫transformer没有问题。
Transformer里面Token和Embedding的物理意义
语言本身是一个整体,token是将语言剁成的一个一个块,方便处理。embedding是如何如何在数学上和电脑上表示这个Token。
由于语言模型的成本都比较大,通过实验的方式寻找到最好的分割策略和表示方式可能需要很大代价,这里我们的物理图像就能为我们提供一个思考的方向。
首先我们的翻译,肯定是一个语义级别的翻译,所以按照语义来分割token是比较好的,因此我们一般在英语用单词作为token,在中文用字比较好。而如果用字母或者笔划来分割token估计就没这么好。这可以说是大语言模型中的"归纳偏置",类似于卷积是图像处理中的"归纳偏置"一样。
embedding代表什么呢?由于我们认为token是有语义基础的,所以我们考虑其表达方式的时候,就要考虑用什么数据结构来表达语义比较好呢?我们再一次可以参考的我们的物理图像,比如我们在物理上描述一个系统的时候,会用一个基来描述物理量,用前面一个系数代表这个物理量的大小,比如 有0.5个电荷,0.3个上自旋,0.5个下自旋等等,我们可以写成 【0.5,0.3,0.5】乘以【电荷,上自旋,下自旋】,我们约定第一维度代表电荷,第二维度代表上自旋,第三维度代表下自旋的话,后面的量纲可以不写了。我们就可以用【0.5,0.3, 0.5】来代表一个子系统的状态了。
我们可以看到,描述一个物理粒子的维度代表的是整个宇宙所有的物理量的数量,如果没有这个物理量可以将其设为0。与此类比,我们的语言模型中的每一个token,一可以用一个数组来表示,而后面的量纲就是一些最基本的语义单位,只是这些单位我们可能还没有研究过,识别出来,并且命名。但是这个不影响我们使用这些概念。我们就称呼这个数组为embedding。 embedding的维度应该是和这个语言能表达的语言的丰富程度相关的,也就是这个语言表达的宇宙的所有基本的不可再细分的属性的数量。这样就能理解,embedding的维度和我们选择tokenize方式是无关的。比如我们用字母作为token,那么一个语言的token数也就是几十个,如果我们将字母继续细化,用一个0,1序列来代表字母,比如0001表示A,0002表示B那么我们甚至可以用0,1序列来代表整个语言,token的数量只有2个,但是按照我们的物理图像,我们不会应为token的数量多少而改变embedding的维度。
Transformer的流程图我们归纳如下::
从序列号到embedding的变换,可以认为是一个1 hot vector 到 一个 embeding维度的vector的线性换,因此也是可以在模型的训练阶段训练出来,不需要预先计算。
transformer的物理图像
transformer就是将语义从一种表达方法转成另一种表达方式。
我们这样思考,一种语言是一语义的空间,所以,我们应该有一个语素空间的变换矩阵。如原本[0.3,0.5,0.7]是对应后面的一个量纲数组而言的,量纲数组可以成为基,我们就说现在两种语言的语素的基变了,因此需要有一个变换矩阵。这是一个d维到d维的变换矩阵。
所以这里应该就有一个矩阵,对embeding序列里面的每个embedding进行坐标系变换。这就对应了Transformer里面对应的每个 block里面的Linear层。所以Transformer里面的Linear层相当于一个语义空间的相当于语素为基的坐标变换。因为这里是一个系统的基的变换,所以这里的转换矩阵只和基的数量有关,不和输入的token的长度相关。所以这里的矩阵的维度是d*d,只和embeding的维度相关,因为我们知道embeding就是基的系数。
当然,语言的翻译不可能只是一个一个字的逐字的翻译,必须是整体的参考上下文。Transformer中的attern模块做起的就是这个作用。
为了考虑上下文的相互作用,首先我们会考虑输出为输入的组合。先是最简的线性组合,也就是每一个输出的Token都是所有其他Token 的线性组合,这就相当于输入和一个n*n的矩阵相乘,其中那为输入的Token序列的长度的长度,可以看到这里的矩阵是和embeding的维度d无关,只和输入的长度n相关有关。
通常我们的语言翻译的时候,不仅仅只是对整体的语义做解读,也需要逐字的进行翻译才能得到最好的最精确的结果,这就需要引入注意力机制了。注意力机制就是某个位置的输出,只会和某个局部的输入相关。也就是当我们翻译某个词的时候,只会将我们的注意力集中到输入的某段。
我们如何实现这个注意力机制呢?有很多数学的解释方法去理解,我们也可以用物理图像的方式进行理解。假设我们的一对一翻译是可行的,理想情况下我们就一定能在语义空间中找到两种语言,这两种语言之间就是可以一对一的翻译的。我们能找到两个语义的坐标系,其中某个位置的输出只和输入的某个位置相关。我们可以通过一个变换来学习这两个语义空间的。所以Q,K,V中的Q,K可以理解为我们用来学习这的两个语义空间的变换。
因此将输入x,变换到这两个空间的话,就有Q = xwq 和 K = xwk, 我们记得作为语义空间变换的矩阵只和空间的维度有关,所以这两个变换矩阵都是d*d。
在Q,K空间中的embeding两两进行点积,只有相关的位置是非零的,理想情况是1(归一化后),其他位置为0。由于根据我们的常识,语言一般不是理想情况,但是有很强的局域性,所以我们可以预计,QK应该是很多0,很少1的一个nn的矩阵。可以称为是一个低秩的矩阵。这个矩阵刚好代表了embed ing之间的相关性程度,可以作为我们上文的变换矩阵。但是这个相关性是是Q空间和K空间的相关性,不是原输入空间的相关性。因此我们需要将原输入控件变换到Q或者K空间才有意义。这里我们要记住,Q,K都是理想状态,实际上并不可能真正找到完美的 Q,K都是一个逐步逼近的近似值,所以我们不是直接采用wq或者wk,而是用一个wv将原空间变换到一个近似于理想空间的一个位置。(我怀疑用wk或wq,说不定也是可以的,可以节约一点可训练参数,我没有做过实验,有做过的同学吗?如果我能找到做实验的资源,我想下一篇文章写一下这个,不知道能不能入围)。这部分的操作就是所谓的注意力机制了。
总结一下,我们通过attention机制,实现token之间的互相关系。然后用一个全连接层转换到目标语义空间上。然而我们实际的语言复杂,真实的转换函数很可能不是线性的。我们的模型应该只是一个近似,参考我们物理上常用的傅里叶展开和泰利展开,如果我们不能一下子获得精确的结果,我们可以相同的结构重复多层来无限的逼近,因此我们可以用一个多层的结构来实现这两个语义空间的转换。因此我们的语言模型将会是一个多层的Transformer结构。也就是transformer叠加多次。我们在概念上可以理解为入股如果两个语义空间相差比较大,一次性转不过来,我们可以通过很多次的转换,一步一步的转过来,像拧螺丝一样。每一层就是转一定角度。multihead在我们的图像里面会起到一个什么的作用呢?可能的作用有两个,第一个就是采用了multihead最大的作用就是可续连参数一下子加大了,相当于扩大了语义空间,也就是相当于增加embedding的维度。如果一开始选择的embedding维度不够大,可以通过multihead来弥补。另外的可能是multihead等于跑了多个搜索小队到语义空间里面去搜索合适的Q和K空间,派的小队越多,搜索到合适的空间的可能性就会越高。到底是哪个其他作用更大,可以通过一些实验来进行探索。有没有人想组队或捐算力来研究?
最后讲一下pos encoding的作用,在我们的模型里面没有pos encoding 的位置。因为位置编码在attention变换里面是完全考虑进去的。不需要pos encoding来增加位置的信息。很可能pos encoding的作用是不重要的,这点需要通过一些实验探索一下。
总结
建立了物理图像以后,物理学和ai是不是真的很像,是不是都是对宇宙的建模,一个用语言建模一个用物理定理建模,实际上很可能物理定律只是近似?诺贝尔物理学奖颁给AI也没有这么难以理解了。
我们的宇宙还有一个大bug,量子纠缠。我们的物理量居然是矢量,是可以线性叠加的。我们知道线性一般只是一个小范围近似的手段,应该不会在大范围都使用才对,为啥我们宇宙最基础的规则是线性的呢 ?这就很离谱。但是我们的线性的量子力学还留了一个非线性的部分----量子纠缠。他会坍缩。这个坍缩也就很难理解。但是我们记得我们Ai模型的ReLu?我们的变换都用线性的,但我们会用一个ReLu函数,在某个点之前一直都是线性的,突然没有斜率了,变成了0。这不就是坍缩吗?
到底是我们的AI模型是给宇宙建模,所以会这样相似,还是我们宇宙本身就是一个AI?说到底还是那个庄周梦蝶的问题。