cs224n学习笔记
词嵌入
我们学习过 cs231n,了解了神经网络的本质是将数据进行线性变换为我们所需要的数据模式(如分类等等)。
但是在自然语言处理这个领域,我们的语言难以直接被计算机所理解,所以我们要对我们的语言进行编码,注意这里的编码并不是像unicode那样无序编码,而是为了让计算机“理解”词意而编码,所以在这里引入词嵌入方法(PS:词嵌入在之后的 transformer 中仍然有一席之地)
词嵌入其实也是模型的一个学习阶段,拿现实来举一个例子,我们学习语言的时候,通过理解单词的实际意义来学习,词嵌入类似,但是我们无法让计算机通过五感来理解词义,所以我们对相同或者有类似词义的单词进行分类,所以每个单词对于计算机来说都是抽象概念,我们将在之后的训练中让各种抽象概念相互依存、连接。
词嵌入的实际操作非常简单,cs224n_a1 已经有详细的步骤拆分,这里不做赘述,我们只需要知道词嵌入是将语言的编码的重要工具即可。
依存句法分析器
这个模块的功能在 Transformer 中会集成在注意力机制中,但是学习这个模块这是我们理解语言分析的一个重要阶段。
在上文我们提到过计算机所理解的概念都是抽象的,但是人们的语言会有着不同的风格、歧义甚至是语法错误,为了让计算机依然能“看懂”我们的语言,便有了这个模块。
这个模块将我们的语言拆分为最简单的树形结构,让计算机理解起来不会有歧义。
那么现在的问题来到了怎么合理拆分构造我们的树形结构,首先不同的语言有不同的语法规范,其次我们要对这个依存句法分析器进行训练,让其能合理地处理任何句子。
在 cs224n 中我们采用神经网络对其进行训练,并且使用 pytorch 减少代码难度,写起来其实没多少东西。
神经机器翻译
这部分的代码实在是太乱了,我按照自己的理解进行讲解,如果有错误请联系我改正。
在这里我们引入了注意力机制和 LSTM 架构,那么我们所需训练的矩阵数便涉及了注意力机制的注意力模块和LSTM的遗忘门、输入门、输出门。
在笔记中我们只通过抽象概念来理解,并不会说明具体代码实现。
LSTM(长短期记忆网络)是为了解决长对话的理解而诞生的,主要模块有遗忘门、输入门、输出门。
遗忘门是解决过远的记忆,优化性能且防止过久记忆。
输入门便是对某些数据进行记忆。
输出门便是对现有的记忆进行编码,而后传导到下一个循环。
那么我们现在发现了一个问题,如果真的有一个问题需要我们长久记忆怎么办,我们的遗忘门在每一次循环都会按照时间步对之前的权重进行削减,那么我们在这里引入注意力机制,我们在遗忘之前对原始数据进行注意力机制的应用,令超长期记忆成为可能。
注意这里的注意力机制和 Transformer 中的自注意力机制有所不同,这里的注意力机制只会告诉模型应该注意前文的某某方面,而不会分析更多。
这部分的实现变得更为抽象,但是我们要明确一点,就像上文提到的,计算机所有点一切概念都是数字,都是抽象的,我们为模型实现任何的模块只是提供了模型分析某个方面的功能,具体的模块间的嵌合性以及那些矩阵权重数据的实际都不是我们需要考虑的,这些问题会在实际数据的训练中进行自拟合,这也提供了一个知识点便是我们不能将某一模块的权重单独拿出来放在另一个模型上,这是不合理的。
Attention is All You Need
Transformer 的知识点很多,我们按照架构数据处理主要模块来讲解。
自注意力机制
这是 Transformer 架构最具有革命性的模块。
首先从单一自注意力入手,这里我们将为每一个词元(这个待会解释)设置三个键值,分别为查询键值Q,自身键值K,本质键值V,这便是自注意机制要学习的三个主要参数,这里引用一下deepseek给我的例子
- 查询 Q :每个词发出的"问题":我该关注谁?
- 键 K :每个词提供的"答案":我有什么特点值得关注?
- 值 V :每个词的"本质内容",将被加权求和
之后我们便要计算注意力分数,计算方法不重要,重要的是我们的注意力分数代表了我们对这个词的关注度。
但是考虑到对语言分析不够全面,并且联想到卷积神经网络中卷积核的概念,我们便引入了多头注意力机制,本质是对原本的单一自注意力机制的三个键值进行拆解,拆成 3$\times$N 个键值(设有N个头),之后对所有的头进行整合即可。
前馈神经网络(FFN)
这是 Transformer 中很有趣的一部分,正如我上文说的,我们实现的每一个模块都是为了提供给模型学习的能力,而不是单纯的功能。
前馈神经网络为模型提供了学习更复杂特征的能力,因为FFN将传统神经网络的线性变换替换为了非线性变换
$$ \text{FFN}(\mathbf{x}) = \sigma(\mathbf{x}\mathbf{W}_1 + \mathbf{b}_1)\mathbf{W}_2 + \mathbf{b}_2 $$
根据数学定理,我们可以知道这种形式的变换可以逼近任何的连续函数,这提供了 FFN 强大的学习分析能力。
残差连接与层归一化
这其实不是一个重要的模块,但是这是一个重要的小优化。
在我们刚刚接触神经网络时便知道学习的实际便是通过反向传播不断优化我们的各种矩阵超参数,但是如果我们需要深度学习,我们便需要增加层数,那么我们会遇到数学上的问题,比如梯度消失或无效学习,那么我们便要引入残差连接这个模块。
说直白一点,这个模块其实就是将我们的输出权重与原始权重加在一起,这防止了某一参数学着学着没了,也防止了过于激进的变换。
但是我们又发现,单纯相加之后又会过于破坏我们原本的矩阵,甚至导致越加越大难以计算,所以我们引入了层归一化(LayerNormalization)来进行“还原”操作。
感性理解一下,我认为这个模块令我们的 Transformer 变得优雅。
自然语言文本生成器
注意这里我并不是在讲解整个解码器,我相信理解上述模块后已经可以理解编码器,而解码器需要生成自然语言,我曾在这部分疑惑过,所以单独拿出来讲解。
在Transformer中,我们使用自回归解码器,解码器通过理解上文生成预测词向量,然后通过束搜索进行词汇预测。
那么什么是束搜索?
我们来回顾一下我们的起点——knn算法,我们查找前k个相似的图像,束搜索与此类似。
束搜索搜索k前相似,而后再每个相似后再搜索k前相似,在一定循环后选择得分(概率)最大的词列。
这种方法有些丑陋,于是有了许多剪枝和优化方法,在这里不过多赘述。
补充解释
- 词元:在生成式人工智能导论中,我们知道chatGPT并不是以每个单词进行编码,而是分为若干词元,比如一个词可以由许多词元构成,故此在上文使用词元概念