来源:https://mp.weixin.qq.com/s/vt8YpMDnj-bfu9x2-CPvjQ
学了这么多年英语,翻译英语的途径也有了很多变化。在 10 年前,我们常常用谷歌翻译、金山翻译,翻译效果差强人意,有时让人啼笑皆非。但如今用大模型翻译的文本非常自然流畅,几乎不需要修改。也因此有很多人在拿到英语原版电子书后,都会第一时间用沉浸式翻译翻译成中文,Github 上也有很多利用大模型(OpenAI、Gemini、Deepseek)的 API 来翻译电子书的项目(repo)。
今天,我想尝试着揭秘一下,过去 10+年来语言翻译背后技术的变迁,按照时间顺序分为三个部分:第一个部分是 RNN,第二个部分是 RNN + attention,而第三部分(也就是现在的翻译所使用的技术背后的模型)介绍当前主流大模型背后的底层结构——Transformer。
我们先定义一下翻译任务,之后会用三个模型来执行同样的任务:
将英语短句I love llamas翻译为荷兰语( Dutch)。
一、RNN
RNN 全称是 Recurrent Neural Networks,RNN 分为两部分 Encoder(RNN) 和 Decoder(RNN)。
步骤:
总的来说,RNN模型是 autoregressive的,即这一步的输入和输出,会合并在一起成为下一步的输入。
具体来说,分为如下几个步骤:
1.根据词典(vocalbulary)对输入进行分词(切分成 token),用附录中提到的Word2Vec 技术将每个 token进行向量化,取得输入中每个 Word 对应的向量化表示(word2vec embeddings)。
2.将输入的向量化表示输入给 Encoder(RNN),得到 context embedding(上下文向量),也就是说这一组 向量中包含了输入的文本的上下文信息。
3.包含了上下文的向量再作为输入传给 Decoder(RNN),便得到了翻译后的荷兰语。
RNN 用于翻译的局限性:
由于 Encoder 产生的 context embedding只是单个大变量,当要翻译的句子比较长,句式也复杂后,这个单一大变量难以捕捉到输入中所包含的所有上下文信息。因此RNN模型在翻译长句子、复杂句子时,效果表现不佳。
二、RNN + attention
第一部分,我们提到了 RNN 模型的局限性(难以捕捉到长句子、复杂句子中全部的上下文信息),那么如何解决呢?2014 年,一个名叫注意力(attention)的方案被提出来,在原来 RNN 的基础上,Encoder 保持不变,但是 Decoder 变为 Attention Decoder。
注意力机制使得模型可以更聚焦在与其关联性更大的一些词语上。以如下输入为例,带有相同含义的词语I和荷兰语Ik是同义词,它们之间会有更高的注意力权重(attention Weight)。同理,love 与 hou(荷兰语) 之间相关性也更大。
具体来说,RNN + Attention 模型进行翻译的流程如下:
1.首先,是对输入进行 Word2vec 技术处理,得到词向量,这一步和上面 RNN 模型一致。
2.然后将词向量作为输入,给到 RNN Encoder 做处理,这一步的输出不再是一个大的包含上下文的向量,而是输入中的每一个词向量,都会对应输出一个对应的向量,包含了输入中这个 Word 及之前所有的 word的相关信息。
3.Attention Decoder利用注意力机制查看整个输入的句子,然后输出对应的翻译。
RNN + Attention 模型比原来的 RNN 模型翻译效果更好的原因是:
注意力机制(Decoder)可以利用输入中每个 token 或者 word 的 embeddings,来查看整个输入的句子,也就是在翻译的时候,会从全局的角度去调优,使得翻译效果更佳。而 RNN 模型中 decoder 只能根据唯一的一个 context embedding 来翻译,离当前词语比较远的词语很难照顾到,句子变长后整体翻译效果不太好。
三、Transformer 模型
与第二部分中提到的 RNN + Attention 模型不同,Transformer 模型的架构去掉了 RNN 模块,只留下了 Attention 模块。相比于 RNN,只有注意力机制的 Transformer 非常适合并行训练。
Transformer 底层主要是由很多个 Encoder 和 Decoder 模块组成,这些模块内部的结构与第二部分中 Attention Decoder 结构类似。
Encoder 模块拆解
以其中的一个 Encoder 为例,同样的输入I love llamas,形成向量序列(但是此时的向量表示不是用Word2vec 技术,而是用随机的数值),再传给 Encoder模块作为输入。Encoder 中首先经过自注意力机制(Self-attention)处理,使得输出后的向量(下图右边 encoder 模块中 Self-attention 与 Feed-forward Neural Network 模块中间,绿色的部分)涵盖有上下文相关的信息,这个更新后的向量进一步传输给前馈神经网络(Feed-forward Neural Network),最后形成包含上下文信息的词向量(下图中右边蓝色部分)。
Self-Attention 模块拆解
其中的 Self-Attention 机制与第二部分的 Attention 不一样的地方在于,第二部分的 Attention 机制处理的是两个独立的序列之间的相关性。而 Self-attention 顾名思义就是 自相关性,处理自己与自己之间的相关性。
Decoder 拆解
假设Transformer 模型已经生成了lk和hou两个词语,现在的任务是:基于生成的词语,推断并生成下一个词语。
在Decoder 中,先将之前已经生成的输出(lk 和 hou)经过一层 masked self-attention,生成中间层向量(图中绿色部分);然后和 Encoder 生成的向量(上图蓝色部分),一并传给另一个注意力网络(下图右边 decoder 中的 Encoder attention 部分),处理之后的值又传给前馈神经网络,最后输出了下一个词语——van。
什么是 masked self-attention呢?
Masked self-attention 与之前的self-attention 不一样的地方在于,它是一个下三角矩阵,在主对角线以上的元素(右上角区域)全为 0,而对角线及其以下的元素可能非零。这样带来的结果是:在生成 van之前,我们只能看到 van 之前的lk和hou,不能看到之后的词语(lama's),因此参与计算的时候在 van之后的词语不参与运算。这个相当于在金融量化中避免了未来函数。
四、Transformer 模型的变形
大家应该都或多或少听说过,2017 年《Attention is all you need》这篇论文横空出世,开启了新的生成式 AI 时代的序幕。那么,当前的 ChatGPT、Llama 、DeepSeek V3等主流模型与这篇论文有啥关系呢?
原来,《Attention is all you need》这篇论文中提到的Transformer 模型对于翻译任务可以胜任得很好,但是换一个场景,譬如文本分类可能就不太擅长。但是这篇论文启发了后面的研究学者,其中提出的 encoder 和 decoder 对于研究者们来说就像乐高积木,在他们手中又重构出了新的效果更好的模型。
其中一类就是 OpenAI、Anthropic、Meta 等厂商推出的模型,这些模型中只有 decoder 模块,没有 encoder 模块,实际上它是用 decoder 模块 替代了 transformer 中 encoder 的功能。另一类典型代表是BERT 模型,只有 encoder 模块,没有 decoder 模块,使得其可以胜任文本分类等更多任务。
介于文章篇幅原因,这两类衍生模型具体的介绍这里就不表了。
好,以上就是关于语言翻译背后技术的演变历程,希望对大家有启发。
后记
最早在2023 年公司内部做行业研究分享时,笔者讲到了ChatGPT 背后的原理,但是个人并没有很满意,部分原因是当时 ChatGPT 刚出来没多久,相关介绍材料不多,笔者个人理解有限。
这两年笔者在油管博主视频、书籍、大学相关课程中寻找对于 transformer 的解读,譬如台湾李宏毅老师、油管 3BlurBrown、Andrew Karparthy 的相关视频都很不错,但是对于我来说,还是感觉隔着一层窗户纸。直到看到Jay Alammar 和 Maarten Grootendorst 两位作者写的《Hands-On Large Language Models Language Understanding and Generation 》,才算找到了钥匙。后面这两位作者又在吴恩达的 deeplearning.ai 上面开了一门简明课程《How Transformer LLMs Work》,我如获至宝。
本文主要的内容解读及截图均是来自于《How Transformer LLMs Work》这门课程,重点从语言翻译这个视角来解读。如有整理不太到位的地方,欢迎大家批评指正。
附录——word2vec 技术
首先要产生一个包含 token 的词典(vacabulary),这个词典包含了几乎所有的 input 中的词语对应的 token。
(1)如何产生词典呢?
第一步,把所有的英文单词一个个按照字母拆开,假如输入是a caring teddy bear is playing with other bears
这里面单个字母去重后,会添加到词典中。
第二步,将相邻的两个字母一一组合,然后数其中的两字母组合中,出现频率最高的词汇,然后加入到词典中。譬如这一步中,ar组合出现了 3 次,频率最高,因此把ar也加入到字典中。
此时,字典中的词汇如下:
第三步,重新根据更新后的字典,将当前的输入进行分组,譬如下文中ar合并在了一起。
接下来,可以看到出现频率为 2 次的组合有in、be、th等,继续添加到词典中。
如此往复,直到词典的条目大小达到设想的值。同时,也要考虑加入一些特殊的字符,用于处理特殊情况,譬如[UNK]。
(2)有了字典后,接下来就要根据字典,把输入进行分词(也就是下方中的Split input into tokens)
注意:分词不一定是根据单词间的空格来划分,在下图中,vocalization 被分成了 vocal 和 ization 两个 token。
(3)切分成 token 之后,就要将每个 token 映射为一组变量。
这组变量的 dimension 可以自定义,在 GPT-2 中,变量多达 1024 个,我们其实很难推断出这 1024 个数字对应的准备含义,但我们可以这么理解:其中每个数字代表了它和其他的字母的关联程度(从 -1 到 +1,值越靠近 1,相关性越大)。
假设存在一个 1024 维的坐标轴,我们把这些 token 放在坐标轴中,各个 token 间相关性会一目了然。下图中,我们可以看到,apple 和 banana 两个 token 之间的向量距离比较相近,而从含义上它们都是水果,比较相近。同理 building和 houses 同属于房屋的一种称谓,它们之间的向量距离也比较相近。
那么token 的向量表示是如何产生的?这个是根据优质的语料库(譬如维基百科的文本语料库)训练出来的。
(4)映射为一组向量后,我们将 token 进行组合( average the tokens),即可以得到 word embedding,即每个单词的向量化表示。