找回密码
 立即注册
首页 业界区 科技 深度学习笔记-《动手学习深度学习》

深度学习笔记-《动手学习深度学习》

闰咄阅 3 天前

本笔记是作为复试应对面试回答做的一些笔记,后期还要去读一些论文加深理解,参考书为《动手学习深度学习》

作为一个研究者,我需要去读很多的文章,去总结很多不同的优秀的研究者对这个世界的认识,然后形成自己独特的观点是很重要的

读论文

  • 读论文的过程:Abstract、Introduction(讲个故事,我们研究的方向,要做什么,以及后面的几节会讲什么);之后给出实验数据,这里一般是做图表对比,刷刷榜;最后可能有 conclusion(少数有 discussion,如 AlexNet)

深度学习基础

损失函数

  • \(\hat{y}^{(i)} = \mathbf{w}^\top \mathbf{x}^{(i)} + b\), \(l^{(i)} = \frac{1}{2} (\hat{y}^{(i)} - y^{(i)})^2\), 根据链式法则,可以将其拆分为两步相乘:

\[\frac{\partial l^{(i)}}{\partial \mathbf{w}} = \frac{\partial l^{(i)}}{\partial \hat{y}^{(i)}} \cdot \frac{\partial \hat{y}^{(i)}}{\partial \mathbf{w}} \]

第一步:

\[\frac{\partial l^{(i)}}{\partial \hat{y}^{(i)}} = 2 \cdot \frac{1}{2} (\hat{y}^{(i)} - y^{(i)}) = \hat{y}^{(i)} - y^{(i)} = \mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)} \]

第二步:

\[\frac{\partial \hat{y}^{(i)}}{\partial \mathbf{w}} = \frac{\partial (\mathbf{w}^\top \mathbf{x}^{(i)} + b)}{\partial \mathbf{w}} = \mathbf{x}^{(i)} \]

将上面两步的结果相乘,就得到了完整的梯度表达式:

\[\partial_{\mathbf{w}} l^{(i)}(\mathbf{w}, b) = \mathbf{x}^{(i)} \left( \mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)} \right) \]

交叉熵损失也是基于 SoftMax:

\[\text{softmax}(\mathbf{X})_{ij} = \frac{\exp(\mathbf{X}_{ij})}{\sum_k \exp(\mathbf{X}_{ik})} \]

进行极大似然估计得出来的公式,交叉熵损失:

\[l(\mathbf{y}, \hat{\mathbf{y}}) = - \sum_{j=1}^q y_j \log \hat{y}_j \]

  • 为什么在做线性回归等任务时,我们通常会理所当然地选择"均方误差"作为损失函数
    \(y = \mathbf{w}^\top \mathbf{x} + b + \epsilon\), 假设噪音 \(\epsilon\) 符合正态分布,对 \(n\) 个样本的概率连乘,求极大似然估计,把无关紧要的常数项都抛开后,剩下的核心部分:

\[\sum_{i=1}^n \left( y^{(i)} - \mathbf{w}^\top \mathbf{x}^{(i)} - b \right)^2 \]

这正是我们非常熟悉的均方误差(MSE)公式的内核(即预测值与真实值差值的平方和)。也就是用均方误差去训练模型,本质上就是在做极大似然估计,是在寻找最能解释当前数据的最优参数。

  • 做分类任务的时候,采用交叉熵是一个不错的选择。
    1. 假设我们做一个二分类,模型输出前的逻辑值(Logits)为 \(z\),经过 Sigmoid 激活函数后得到预测概率 \(\hat{y} = \sigma(z)\)。真实标签为 \(y\)。
    2. 如果我们使用 MSE:\(L_{\text{MSE}} = \frac{1}{2}(\hat{y} - y)^2\),在分类问题中,我们预测的是各个标签的概率,于是在反向传播阶段,我们对 \(z\) 求导(也就是反向传播时传给上一层的梯度):

\[\frac{\partial L_{\text{MSE}}}{\partial z} = (\hat{y} - y) \cdot \sigma'(z) \]

\(\sigma'(z)\) 是 Sigmoid 的导数。
3. 如果模型预测 \(\hat{y}_i \approx 0\),此时 \(z\) 是一个很大的负数,但实际 \(y_i=1\),Sigmoid 在极值处的导数 \(\sigma'(z)\) 会极其接近于 0,那么梯度就接近 0 无法更新权重

          1. 如果使用交叉熵损失函数:

\[L_{\text{CE}} = - [y \ln \hat{y} + (1 - y) \ln (1 - \hat{y})] \]

同样对 \(z\) 求导:

\[\frac{\partial L_{\text{CE}}}{\partial z} = \hat{y} - y \]

梯度的物理意义变成了:预测值和真实值的单纯差值。

训练与反向传播

  • 分类问题的训练过程:定义一个 net,然后计算出 \(\hat{\mathbf{y}}\),通过损失函数计算出损失,然后反向传播(用于计算前面损失函数的偏导数),之后进行随机小批量梯度下降即可

    • 反向传播:\(L-1\) 神经元的输出值会受到应用于它们从 \(L-2\) 接收的输入的权重的影响。因此,我们可以对 \(L-1\) 中的激活函数进行微分,以找到应用于 \(L-2\) 贡献的权重的偏导数。这些偏导数将向我们展示 \(L-2\) 权重的任何变化会如何影响 \(L-1\) 的输出,进而影响 \(L_c\) 的输出值,并因此影响损失函数。递归重复这个过程,直到我们到达输入层。完成之后,我们会得到损失函数的梯度:网络中每个权重和偏差参数的偏导数向量。
    • 向下移动(下降)损失函数的梯度将减少损失。由于我们在反向传播期间计算的梯度包含每个模型参数的偏导数,因此我们知道向哪个方向"步进"每个参数以减少损失。
  • momentum 是防止个别极端数据会导致优化不平滑,你可以保持保持一个冲量,从过去的那个方向,沿着一个比较平滑的方向往前走

    • 须进一步观察

激活函数

  • 加入激活函数的原因是因为对于 hidden layer 来说,不加入激活函数实际上与线性层一样,考虑:\(\mathbf{H} = \mathbf{X}\mathbf{W}_1 + \mathbf{b}_1\),\(\mathbf{O} = \mathbf{H}\mathbf{W}_2 + \mathbf{b}_2\),我们把隐藏层 \(\mathbf{H}\) 的等式直接代入到输出层矩阵运算中:

\[\mathbf{O} = (\mathbf{X}\mathbf{W}_1 + \mathbf{b}_1)\mathbf{W}_2 + \mathbf{b}_2 \]

利用矩阵乘法的分配律将其展开:

\[\mathbf{O} = \mathbf{X}(\mathbf{W}_1\mathbf{W}_2) + (\mathbf{b}_1\mathbf{W}_2 + \mathbf{b}_2) \]

最终的等式变成了:

\[\mathbf{O} = \mathbf{X}\mathbf{W}' + \mathbf{b}' \]

  • ReLu 在 AlexNet 首次提出,当时大家觉得求导表现得特别好,其实后来发现都差不多,但是 ReLu 比较简单,就都用了

过拟合与欠拟合

  • 欠拟合:模型在 train 和 val 的 loss 都很差,误差较小,有理由相信是我们的网络过于简单;
  • 过拟合:模型在 train 的 loss 较小,但是 val 上面表现很差

正则化

  • Dropout:也就是对内部层注入噪音,随机的把一些 hidden layer 的 output 变成用固定概率设成零作为输出,能够做到一个正则的效果

    • 正则是什么?旨在减少学习算法的泛化误差(测试误差),而不是训练误差的任何修改。正则化就是所有用来"防止过拟合"的手段的总称
  • 权重衰减(weight decay)是最广泛使用的正则化的技术之一,它通常也被称为L2正则化。在我们没有加正则化之前,优化器的唯一目标是让"做题错误率"降到最低:

\[L_{\text{total}} = L_{\text{data}}(\mathbf{w}, b) \]

由于模型非常贪婪,为了让 \(L_{\text{data}}\) 趋近于 0,它会不择手段地调整 \(\mathbf{w}\),甚至把某些权重放大到成千上万,只为了迎合某个微小的噪声点(这就是过拟合)。现在,我们强行给目标函数加了一个"尾巴"(以 \(L_2\) 为例):

\[L_{\text{total}} = L_{\text{data}}(\mathbf{w}, b) + \frac{\lambda}{2} ||\mathbf{w}||^2 \]

优化器的目标依然是让整个 \(L_{\text{total}}\) 最小。这时候,博弈就产生了:
* 如果模型依然想把 \(\mathbf{w}\) 设得巨大无比来完美拟合数据(让 \(L_{\text{data}}\) 降为 0),那么后面的惩罚项 \(\frac{\lambda}{2} ||\mathbf{w}||^2\) 就会爆炸式增长,导致总分 \(L_{\text{total}}\) 极高。
* 为了拿到最低的总分,优化器被迫做出妥协:它宁愿让 \(L_{\text{data}}\) 稍微大一点(放弃完美拟合噪声),也要把权重 \(\mathbf{w}\) 的数值压下来,以此来换取惩罚项的大幅降低。

从微积分求导的过程来看,惩罚的作用更加直接:

\[\frac{\partial L_{\text{total}}}{\partial \mathbf{w}} = \frac{\partial L_{\text{data}}}{\partial \mathbf{w}} + \lambda \mathbf{w} \]

\[\mathbf{w} \leftarrow (1 - \eta\lambda)\mathbf{w} - \eta \frac{\partial L_{\text{data}}}{\partial \mathbf{w}} \]

这就是对权重的衰减

  • \(L_1\) vs \(L_2\) 的行为偏好:\(L_1\) 产生稀疏性,\(L_2\) 产生平滑性
    • \(L_2\) 惩罚(平方)的导数是 \(2\lambda w\):这意味着,惩罚的力度是和权重大小成正比的。当 \(w\) 是 100 的时候,惩罚力度是 \(200\lambda\),逼着它赶紧变小
    • \(L_1\) 惩罚(绝对值)的导数是 \(\lambda \cdot \text{sign}(w)\):无论你的 \(w\) 是巨大的 100,还是微小的 0.001,只要你不等于 0,惩罚项给你的推力永远是一个常数 \(\lambda\)

梯度问题与参数初始化

  • 梯度消失与梯度爆炸

    • 梯度消失:如 sigmoid 函数,值过大或过小都会导致梯度消失,可用 ReLu 解决
    • 梯度爆炸:由于梯度是前 \(l - 1\) 个矩阵与梯度向量的乘积,连乘可能导致爆炸,可用参数随机初始化尝试解决
  • 初始化有:随机(正态分布)初始化,Xavier 初始化(最常用于搭配 TanhSigmoid 这类具有 "S 型曲线" 激活函数的神经网络层中)

    • 不要把 Xavier 初始化和 ReLU 激活函数搭配使用

批量规范化

  • Batch Normalization:
    • 在深度神经网络中,由于层数很多,底层参数的微小变化,经过层层放大,会导致高层输入数据的分布发生剧烈震荡。高层网络被迫不断去"追赶"这种分布的变化,导致模型训练极慢。
    • 批量规范化就是在一些网络层中对前面的网络层进行标准化,标准化的参数也是可以学习的
    • 提升了训练速度,因为网络层的数据分布被稳定住了,对学习率不敏感了(大学习率也能快速收敛),同样的也不对初始化敏感了(如果开始初始化导致方差爆炸,BN 也能拉回来)

计算机视觉

卷积层

  • 卷积是 4 维是因为:如果是 Linear 的话,其实是 5 维,分别是 \([\mathbf{V}]_{i,j,a,b}\):意思是,针对输出图的 \((i,j)\) 这个位置,当偏移量是 \((a,b)\) 时,权重是多少,有 \(c\) 个 RGB

    • 由于平移不变性,我们意识到原始位置是没用的,这意味着权重张量 \([\mathbf{V}]_{i,j,a,b}\) 里的 \(i\) 和 \(j\) 完全成了摆设,我们可以直接把它俩踢掉,简化成 \([\mathbf{V}]_{a,b,c}\)
    • 局部性:你只需要看它周围一小圈的像素就行了,完全没必要去参考图片角落里距离它几千像素远的背景。它们不能超过一个很小的距离 \(\Delta\)(比如 \(\Delta=1\),也就是只看周围 \(3 \times 3\) 的九宫格)。
    • 剩下的一个维度就是通道了,\([\mathbf{V}]_{a,b,c,d}\)
  • 卷积核:为了实现"多输入 + 多输出",卷积核(权重张量)必须是一个四维(四阶)的数据结构。这非常关键: 假设输入有 \(c_i\) 个通道,输出想要 \(c_o\) 个通道,卷积核的高和宽分别是 \(k_h\) 和 \(k_w\)。 那么这个卷积核 K 的形状就是:\(c_o \times c_i \times k_h \times k_w\)。

特征映射与感受野

  • 特征映射其实就是上一层做卷积的时候对应的输出,可以被视为一个输入映射到下一层的空间维度的转换器

  • 感受野(receptive field):在卷积神经网络中,对于某一层的任意元素x,其感受野是指在前向传播期间可能影响x计算的所有元素(来自所有先前层)

    • 因此,当一个特征图中的任意元素需要检测更广区域的输入特征时,我们可以构建一个更深的网络。

汇聚层

  • 汇聚(pooling)层具有双重目的:降低卷积层对位置的敏感性,同时降低对空间采样表示的敏感性。

残差网络(ResNet)

  • ResNet 为什么有用?
    • 我们想要加深网络来提升性能,但事实上不一定会表现更好,如图,\(f'\) 我们设为最优解,那么 F6 的距离是要比 F3 更远的,而我们确实在向 F6 靠拢,那不如我们说是向右边一样,每次大模型都包含前面的小模型,这样最起码的不会变差![[Pasted image 20260310211425.png|684]]
    • ResNet 核心思想就是上述:每个附加层都应该更容易地包含原始函数作为其元素之一。于是,残差块(residual blocks)便诞生了。

转置卷积与全卷积网络(语义分割)

  • 转置卷积是好理解的,类似于卷积的逆变换,具体一张图其实就可以看懂
    ![[Pasted image 20260313235140.png|613]]
  • 对于语义分割,我们考虑先进行卷积神经网络,然后把输出为 1x1 特征图,这个小矩阵的感受野是整张图片的,随后我们再使用转置卷积对其进行放大分割,得到物体边界。
  • 对于转置卷积的初始化,我们使用双线性插值进行对特征图的放大,也就是上采样
  • 单线性插值:这个很简单,我们知道两点 \((x_0,y_0), (x_1, y_1)\),那么给定 \(x\),我们有:

\[y = \frac{x_1 - x}{x_1 - x_0} y_0 + \frac{x - x_0}{x_1 - x_0} y_1 \]

  • 双线性插值法:四个已知顶点(在图像中就是四个相邻的像素点):左上:\(Q_{11} = (x_1, y_1)\),其值为 \(f(Q_{11})\);右上:\(Q_{21} = (x_2, y_1)\),其值为 \(f(Q_{21})\);左下:\(Q_{12} = (x_1, y_2)\),其值为 \(f(Q_{12})\);右下:\(Q_{22} = (x_2, y_2)\),其值为 \(f(Q_{22})\);设目标点位 \(P(x, y)\),对应 \(f(x, y)\),我们对其在 \(x\) 轴做一次线性插值,对 \(y\) 轴再做一次即可(先 \(y\) 后 \(x\) 也可以),矩阵面积:\(S = (x_2 - x_1)(y_2 - y_1)\),那么我们有:

\[f(x, y) = \frac{(x_2 - x)(y_2 - y)}{S} f(Q_{11}) + \frac{(x - x_1)(y_2 - y)}{S} f(Q_{21}) + \frac{(x_2 - x)(y - y_1)}{S} f(Q_{12}) + \frac{(x - x_1)(y - y_1)}{S} f(Q_{22}) \]

自然语言处理

序列模型

  • 自回归模型:直接用观测序列 \(x_{t-1} \dots x_{t-\tau}\) 生成预测,这样的好处是参数的数量是不变的
    • 每次只根据前面的上文,预测下一个词:

\[P(x_1, \ldots, x_T) = \prod_{t=1}^T P(x_t \mid x_{t-1}, \ldots, x_1) \]

实际上就是多个条件概率连乘:

\[P(A, B, C) = P(A) \cdot P(B \mid A) \cdot P(C \mid A, B) \]

  • 接着,我们引用马尔科夫链,这里我们只用一阶马尔可夫模型(\(\tau = 1\)),然后我们对其化简:

\[P(x_1, \ldots, x_T) = \prod_{t=1}^T P(x_t \mid x_{t-1}) \]

如果我们要去预测下一个(即 \(x_{t+1}\)),那么我们需要把今天所有可能的情况算出来,有:

\[P(x_{t+1} \mid x_{t-1})= \sum_{x_t} P(x_{t+1} \mid x_t) P(x_t \mid x_{t-1}) \]

  • 隐变量自回归模型:我们总是保留一些对过去观测的总结 \(h_t\),并同时更新预测和总结,这样基于 \(x_t\) 和 \(h_t\) 更新的模型由于 \(h_t\) 从未被观测到,这类模型也被称为隐变量自回归模型

文本预处理与基本概念

  • 文本预处理的步骤:

    1. 将文本作为字符串加载到内存中。
    2. 将字符串拆分为词元(如单词和字符)。
    3. 建立一个词表,将拆分的词元映射到数字索引。
    4. 将文本转换为数字索引序列,方便模型操作。
  • 一些基本的概念:

    • 词元(token):就是数据集中的字或字符
    • 词表(vocabulary):本质是一个哈希表 map,对它们的唯一词元进行统计,得到的统计结果称之为语料(corpus)。然后根据每个唯一词元的出现频率,为其分配一个数字索引。很少出现的词元通常被移除,这可以降低复杂性。
    • 涉及一个、两个和三个变量的概率公式分别被称为一元语法(unigram)、二元语法(bigram)和三元语法(trigram)模型。(即 DeepDeep LearningDeep Learning is
    • 由于二元和三元词元数量很少,可以用拉普拉斯平滑来计数,但是我们需要存储所有的计数,这完全忽略了单词的意思

循环神经网络(RNN)

  • 循环神经网络(RNN),在时间步 \(t\) 引入了一个叫作隐状的变量 \(\mathbf{H}_t\),负责捕获并保留从序列开头一直到当前时间步的所有历史信息,那么我们更新状态就不是 MLP 那样更新了,而是:

\[\mathbf{H}_t = \phi(\mathbf{X}_t \mathbf{W}_{xh} + \mathbf{H}_{t-1} \mathbf{W}_{hh} + \mathbf{b}_h) \]

\(\phi\) 是激活函数

  • 困惑度(Perplexity)用于评估基于循环神经网络的模型:即使模型极好,它生成巨著《战争与和平》的总概率,也必定远小于生成短篇《小王子》的概率。这显然是不公平的。我们需要计算每个词元的平均损失(整个序列的负对数似然(交叉熵损失)取平均):

\[\text{Average Cross-Entropy}=\frac{1}{n} \sum_{t=1}^n -\log P(x_t \mid x_{t-1}, \ldots, x_1) \]

NLP 科学家为了让其特殊一点,就在这个交叉熵损失上面做了一次指数(吐槽一下哈哈哈):

\[\text{Perplexity} = \exp(\text{Average Cross-Entropy}) \]

  • 梯度裁剪(Gradient Clipping):为了克服梯度爆炸,最简单的办法就是设定一个速度上限(阈值 \(\theta\)):

\[\mathbf{g} \leftarrow \min\left(1, \frac{\theta}{\|\mathbf{g}\|}\right) \mathbf{g} \]

它只改变大小,不改变方向,确保了模型依然在朝着正确的方向优化,只是硬生生把步伐给缩小了,从而赋予了模型极大的稳定性。

  • 那么如何克服梯度消失?

    1. 利用 LSTM 或者 GRU,引入门控单元
    2. 利用残差连接将底层的输出直接跨层加到高层的输出上:\(\mathbf{O} = \mathcal{F}(\mathbf{x}) + \mathbf{x}\)
    3. 舍弃循环连乘,使用 Attention,因为 Attention 的复杂度不受序列长度影响,可以直接抓取目标位置的信息
  • 自回归语言模型(包括 ChatGPT 的底层逻辑)生成文本的标准:预热 + 预测

    • Warm-up:由于在生成文本的时候隐状态是空的,所以要更新模型的隐状态,要把序列开头喂给模型,但不理会其输出(即预测)
    • Predication:刚才预热好的隐状态,加上最后一个字,模型输出预测结果,然后模型自己生成的字作为下一个预测的 \(x_t\)
  • 时间反向传播(BPTT):

    • 在 RNN 中,情况变得极其复杂,因为当前的隐状态 \(h_t\) 不仅依赖于当前的输入,还依赖于上一个时间步的隐状态 \(h_{t-1}\)。
    • 这意味着,当我们要计算权重对当前输出的影响时,根据链式法则,沿着时间轴一步一步往回推导(从时间步 \(T\) 一直反推回时间步 1)。
    • 顺着链式法则把公式完全展开后,发现了一个极其恐怖的现象:隐状态的梯度中包含了一个极其致命的项:\((\mathbf{W}_{hh}^\top)^{T-t}\),这个矩阵需要被自己连续相乘 \((T-t)\) 次,使得模型极其不稳定
    • 于是不再苛求把链条反推到最开始的 \(t=1\) 时刻,而是设定一个步数上限 \(\tau\)。往前推了 \(\tau\) 步之后,我们就强行停止求导。在 Pytorch 中可利用 Detach 函数

门控循环单元(GRU)

  • GRU(门控循环单元),相对于 RNN 新增了两个门控单元:

\[\mathbf{R}_t = \sigma(\mathbf{X}_t \mathbf{W}_{xr} + \mathbf{H}_{t-1} \mathbf{W}_{hr} + \mathbf{b}_r) \]

\[\mathbf{Z}_t = \sigma(\mathbf{X}_t \mathbf{W}_{xz} + \mathbf{H}_{t-1} \mathbf{W}_{hz} + \mathbf{b}_z) \]

\(\sigma\) (Sigmoid)激活函数使得这两个门的输出在(0,1)之间,即什么时候放弃,什么时候用之前的记忆是可以学习的,接着我们有:

\[\tilde{\mathbf{H}}_t = \tanh(\mathbf{X}_t \mathbf{W}_{xh} + (\mathbf{R}_t \odot \mathbf{H}_{t-1}) \mathbf{W}_{hh} + \mathbf{b}_h) \]

\(\tilde{\mathbf{H}}_t\) 是候选隐状态,旧记忆 \(\mathbf{H}_{t-1}\) 被重置门 \(\mathbf{R}_t\) 拦截了:\((\mathbf{R}_t \odot \mathbf{H}_{t-1})\) 为什么这里必须使用 Hadamard 积(按元素相乘),而不是矩阵乘法?
* 隐状态 \(\mathbf{H}_{t-1}\) 不是一个单一的数字,而是一个高维向量(如256维度),把这 256 个维度想象成大脑里 256 个独立的神经元,分别记录着不同的信息
* 重置门 \(\mathbf{R}_t\) 也是一个一模一样长度为 256 的向量,里面全是 \((0, 1)\) 之间的数字。
* 当我们做元素相乘 (\(\odot\)) 时,发生的是:\(\mathbf{R}_t\) 的第 1 维只去乘 \(\mathbf{H}_{t-1}\) 的第 1 维,第 10 维只乘第 10 维,让模型拥有了选择性遗忘的能力

对于更新门,我们利用候选隐单元得到当前的隐单元:

\[H_t = \mathbf{Z}_t \odot{H_{t-1}} + (1 - \mathbf{Z}_t) \odot \tilde{\mathbf{H}}_t \]

这些设计可以帮助我们处理循环神经网络中的梯度消失问题,并更好地捕获时间步距离很长的序列的依赖关系![[Pasted image 20260311202827.png|886]]

长短期记忆(LSTM)

  • LSTM(长短期记忆):我们来细化一下长短期记忆网络的数学表达。时间步\(t\)的门被定义如下:输入门是\(\mathbf{I}_t \in \mathbb{R}^{n \times h}\),遗忘门是\(\mathbf{F}_t \in \mathbb{R}^{n \times h}\),输出门是\(\mathbf{O}_t \in \mathbb{R}^{n \times h}\)。它们的计算方法如下:

\[\begin{aligned} \mathbf{I}_t &= \sigma(\mathbf{X}_t \mathbf{W}_{xi} + \mathbf{H}_{t-1} \mathbf{W}_{hi} + \mathbf{b}_i),\\ \mathbf{F}_t &= \sigma(\mathbf{X}_t \mathbf{W}_{xf} + \mathbf{H}_{t-1} \mathbf{W}_{hf} + \mathbf{b}_f),\\ \mathbf{O}_t &= \sigma(\mathbf{X}_t \mathbf{W}_{xo} + \mathbf{H}_{t-1} \mathbf{W}_{ho} + \mathbf{b}_o), \end{aligned} \]

候选记忆单元为:

\[\tilde{\mathbf{C}}_t = \tanh(\mathbf{X}_t \mathbf{W}_{xc} + \mathbf{H}_{t-1} \mathbf{W}_{hc} + \mathbf{b}_c), \]

输入门\(\mathbf{I}_t\)控制采用多少来自\(\tilde{\mathbf{C}}_t\)的新数据,而遗忘门\(\mathbf{F}_t\)控制保留多少过去的记忆元\(\mathbf{C}_{t-1} \in \mathbb{R}^{n \times h}\)的内容。使用按元素乘法,得出:

\[\mathbf{C}_t = \mathbf{F}_t \odot \mathbf{C}_{t-1} + \mathbf{I}_t \odot \tilde{\mathbf{C}}_t. \]

最后,我们需要定义如何计算隐状态 \(\mathbf{H}_t \in \mathbb{R}^{n \times h}\),在 LSTM 中,它仅仅是记忆元的\(\tanh\)的门控版本。这就确保了\(\mathbf{H}_t\)的值始终在区间\((-1, 1)\)内:

\[\mathbf{H}_t = \mathbf{O}_t \odot \tanh(\mathbf{C}_t). \]

  1. <code>![[Pasted image 20260311211845.png|741]]
  2. </code>
复制代码
  • 为什么在循环神经网络中,tanh 和 sigmoid 混着用:
    • sigmoid 的作用是起到一个 mask 的作用,就是说我可以选择性的去记忆
    • tanh,对于 RNN 来说,如果不加 tanh 对于一个梯度更新,连乘会导致 H 的值指数级爆炸;对于 GRU 和 LSTM 这类存在记忆性的来说,tanh 的 \((-1, 1)\) 的范围允许记忆发生正负方向的相互抵消,内容的 \((-1, 1)\) 决定了吸收的信息是起正向促进作用,还是负向抑制作用。并且 tanh 在 backword 的时候也可以让梯度下降更加平滑

双向循环神经网络(Bi-RNN)

  • 双向 RNN(Bi-RNN):
    • 为了证明双向 RNN 的合理性,我们引出隐马尔可夫模型(HMM),我们有:

\[P(x_1, \ldots, x_T, h_1, \ldots, h_T) = \prod_{t=1}^T P(h_t \mid h_{t-1})P(x_t \mid h_t) \]

如果我们利用前面和后面的信息要预测中间某个位置的信息(类似于做完形填空)即求 \(P(x_j \mid x_{-j})\),其中 \(x_{-j}={x_1 \dots x_{j-1},x_{j+1} \dots x_t}\),由于 \(h\) 的信息是隐藏的,所以要枚举出所有情况,这样复杂度达到了 \(O(T \cdot k^2)\),考虑优化,我们首先提出 \(h_1\) 相关的项:

\[= \sum_{h_2, \ldots, h_T} \underbrace{\left[ \sum_{h_1} P(h_1)P(x_1 \mid h_1)P(h_2 \mid h_1) \right]}_{\text{定义为 } \pi_2(h_2)} P(x_2 \mid h_2) \prod_{t=3}^T \dots \]

接着我们提出 \(h_2\):

\[= \sum_{h_3, \ldots, h_T} \underbrace{\left[ \sum_{h_2} \pi_2(h_2)P(x_2 \mid h_2)P(h_3 \mid h_2) \right]}_{\text{定义为 } \pi_3(h_3)} P(x_3 \mid h_3) \prod_{t=4}^T \dots \]

最后有:

\[= \sum_{h_T} \pi_T(h_T)P(x_T \mid h_T) \]

于是我们把向前递归写为:

\[\pi_{T+1}(h_{T+1})= \sum_{h_T} \pi_T(h_T)P(x_T \mid h_T)P(h_{T+1}|{h_T}) \]

也可以写成:\(\pi_{T+1}=f(\pi_T,\,x_T)\) 于是我们可以把 \(f\) 看做可学习的函数,反向递归也如此,所以双向 RNN 是合理的
* 双向 RNN 不能用于文本生成,因为我们不知道后面的词元是什么
* 双向循环神经网络的计算速度非常慢。其主要原因是网络的前向传播需要在双向层中进行前向和后向递归,并且网络的反向传播还依赖于前向传播的结果。因此,梯度求解将有一个非常长的链。

编码器-解码器架构

  • 编码器解码器:

    • 编码器是对输入序列进行特征提取和信息压缩,转化成隐藏状态,称为上下文变量
    • 解码器在没有引入注意力机制之前,我们的解码器只引用编码器的最后一个隐藏状态
  • 预测过程:

    • 基础的序列生成策略是将原句子后面加入 ,然后填充,喂给编码器,得到最后的隐藏状态
    • 将隐藏状态和 送给解码器,然后得到第一个输出,之后把这个输出当作下次预测的输入,这个叫自回归

输出策略与评估

  • 输出策略:

    • 最简单的是贪心搜索,即我们在经过 softmax 层之后取最大概率的那一个;
    • 束搜索(beam search)是贪心搜索的一个改进版本,它有一个超参数,名为束宽(beam size)\(k\)。在时间步1,我们选择具有最高条件概率的 \(k\) 个词元![[Pasted image 20260312215526.png|983]]
  • BLEU 通过统计预测序列和真实序列重合的 N 元语法 (n-gram) 片段来打分。

\[\text{BLEU} = \exp\left(\min\left(0, 1 - \frac{\text{len}_{\text{label}}}{\text{len}_{\text{pred}}}\right)\right) \prod_{n=1}^k p_n^{1/2^n} \]

注意力机制

  • 一些基本定义
    • Query (查询 \(Q\)):代表你的“自主意愿”。比如你想找一本书,这个“找书”的念头就是 Query。
    • Key (键 \(K\)):代表环境中物品的“客观线索/特征”。比如红色的杯子、报纸的排版、书的封面。这是非自主的提示。
    • Value (值 \(V\)):代表物品的“实质内容”。与 Key 一一对应
  • 注意力汇聚(Attention Pooling)的工作逻辑:系统拿着你的意愿(Query),去和环境中所有物品的特征(Keys)一一比对。匹配度越高的 Key,系统就会给它对应的 Value 分配越大的权重(Attention Weight)。最后把你关注到的所有 Value 按权重加起来,就是模型的输出。

Bahdanau注意力

基于注意力机制的编码器-解码器架构,Decoder 仍然没变,在 Decoder 和 Encoder 中间接入了 Attention 机制, Decoder 在这里干三件事:把自己的输出传入 Attention、传入自己的隐状态(但只用到了最后一层)、传入有效字符长度;我们把要 Decoder 输入的最后一层的隐状态作为 \(Q\);对于 Decoder 的输出,我们称为 enc_outputs, 把其作为 \(K, V\);这里 hidden_state[-1] 作为 \(Q\) 是因为它有前面序列的信息,而它要预测下一个序列![[Pasted image 20260312231025.png|926]]

  • 这里,我们是 Decoder 拿着自己的 Q 去 Encoder 生成的 \(K, V\) 找线索,这个我们称之为交叉注意力

自注意力(Self-Attention)

  • 顾名思义就是自己看自己,也就是说,我们想要预测 \(i\) 位置的词 \(x_i\),那么就把其作为 \(Q\),在标准的注意力机制中,我们是:\(f(\text{Query}, (\text{Key}_1, \text{Value}_1), \dots, (\text{Key}_n, \text{Value}_n))\),自注意力要求自己理解自己,于是就有 \(\mathbf{y}_i = f(\mathbf{x}_i, (\mathbf{x}_1, \mathbf{x}_1), \dots, (\mathbf{x}_n, \mathbf{x}_n))\),这里的 \(x_1 \to x_n\) 为句子里的所有词,这种做法可以让模型更加深入的关注自身的句子,通过语境来给 \(x_i\) 一个不同的权重
  • 对于上述的理解,其实就是可以看为,我去抓取一个句子的其他 token,如果我们要预测苹果的真实意思,若句子中出现了 '水果','市场','好吃',等等,那么我们预测该苹果为吃的苹果,若出现了 '股票','芯片'等,那么理解为苹果手机,而这些东西是要自注意力去抓取上下文来理解的
  • 事实上,刚才对 \(x_i\) 作为 \(Q\) 的表述只是为了好理解,对于 '苹果' 一词,我们不想它只是一个定死的意思,它有多个语义,为此通过上述的方式更新它的向量表达
  • 上面提到上下文能力,由于我们是用 \(Q \times K\),然后利用评估函数对 \(V\) 做匹配,所以 \(x_i\) 与其他任何词的距离为 \(O(1)\),这就是自注意力与其他序列模型不同之处
  • 评估函数这里选择的是点积,但不是简单的 \(\text{Score} = X \cdot X_i\),因为这样是存在对称性的,即 \(X \cdot X_i = X_i \cdot X\),所以说我们引入一个可学习的参数,使得:\(\text{Score} = (X W_q) \cdot (X_i W_k)\),还有一个重要的原因,即上面的向量表达,由于 \(X\) 输入序列有很多的向量,我们需要利用可学习的 \(W\) 去进行特征提取以及语义匹配,其中 \(W_q, W_k\) 是特征提取,为了更优的相似度,\(W_v\) 是进行语义匹配
  • 有一个缺点,由于我们直接进行 \(Q\times K\),那么我们发现,其实 \(x_i\) 在哪不重要,因为即使整个句子是乱序的也可以正确得到结果,而位置信息往往比较重要,所以我们引入位置编码

Transformer

  • Transformer 也是基于编码器-解码器架构的,与视觉方面类似,引入了块的机制,其架构图如下:![[Pasted image 20260313224827.png]]
  • 对于其编码器,Q,K,V 均来自前一个编码层的输出,其中受到 ResNet 启发,采用了 Residual + LayerNorm,然后接入一个 FFN
  • 对于其解码器,Q 为前一个解码器的输出,K,V 来自编码器的最后一个输出,但是解码器中每个位置只能考虑该位置之前的所有位置(因为不能看到之后的信息),所以保留了自回归的性质
  • 这里的注意力评分机制是采用的点积注意力,为什么不采用加性注意力,原因有两个:
    1. 点积是矩阵乘法,速度较快,加性注意力要引入额外的权重矩阵和做一次 tanh,而且点积之后用一个标量除法 \(\frac{Q K^T}{\sqrt{d_k}}\) 可以有效地拉回分布方差
    2. 加性注意力计算时要用大量的广播机制,速度很慢,广播机制就是两个矩阵虽然形状不一样,但可以对矩阵做拓展使得可以相加
  • 对于位置编码,这里采用了固定位置编码,即三角函数性质的位置编码
  • 对于 LayerNorm,它是对一层做均一化,而 BatchNorm 是对一个小批次,例如对于一个 Batch 的数据 X = [[1, 2], [2, 3]], 那么对于 LayerNorm 来说,我们会得到 X = [[-1, 1], [-1, 1]], 它对一个 Layer,即 [1, 2], [2, 3] 做归一化;而 BathNorm 则是从一列,即 [[-1, 1], [1, -1]], 很明显的,token 的词向量特征与其他 token 无关,只与自身的向量特征有关,所以我们要做 LayerNorm
  • FFN(前馈网络)是干什么的?
    1. FFN 的作用在作者的 paper 说是类似于 1x1 卷积,对词元进行升降维度;
    2. 事实上,FFN 还起到了加入非线性变换的作用,可能的疑问:在计算注意力中有 \(\phi(Q \times K)\),这不就是一个 Softmax 的非线性运算吗?但后面的 \(V\) 是线性的问题没有被解决,所以本质还是引入了非线性变换
    3. 可以降低词元向量各向异性
  • 对于语言模型,应该使用 Transformer 的解码器,如果使用编码器(当它看到第 \(t\) 个位置的时候,它可以利用未来的答案来进行作弊)
  • Transformer 可以应用于对图像的分类,可以先用卷积神经网络进行图像的像素特征提取,之后这些像素块的感受野相当于 token,由 Transformer 来更新注意力权重,理解这些图像特征之间的关系,可以做到更好的分类,这个后面再详细看VIT

BERT

  • BERT输入序列的嵌入是词元嵌入、片段嵌入和位置嵌入的和,其中位置编码是可学习的。其输入形式为 segment1 segment2

  • 进行下一句预测的时候,我们提取出 作为输入,是因为我们判断两个句子是否连贯,是用宏观的全局语义表示,而 没有对应 token 语义,它负责吸收整个句子的全局逻辑(通过自注意力,提取全局特征),可以去做分类任务;还有一个原因就是,简洁通俗

  • 运用 Bert 的时候,Bert 的参数是 Pretrained(因为比 Random 要好),我们对此进行 fine-tune,从 开始做预测,之后的那个 Linear 是随机初始化的(如果做分类,评价的话)。

  • Bert 在做填空预测的时候(给定一定的80%的概率 mask,10%的概率 random,10%的概率不变)是非监督的,对 Bert 的 fine-tune 是监督性的,需要打 label,合起来是 semi-supervise

  • Q-A Robot 的输入为 question document , 输出是答案的起始和终止位置,唯一从头训练的是两个 tensor,尺寸和 Bert 的输出一样,两者分别代表起始位置和终止位置,对 document 做预测,两个 tensor 分别做 inner product 然后分别做 softmax,取 argmax 即可

  • Bert 在做预测(填空)的时候,吃的苹果和苹果电脑这两个完全不同的意思,Bert 在训练完之后,两者的余弦相似度是非常低的,原因可能是 Bert 的 Encoder 毕竟有 Transformer Block,所以可以抓取上下文,比如吃的苹果往往和树,味道相结合,苹果电脑则会和价格,性能结合在一起(但并不一定是对的,参考李宏毅,这个地方就是有待研究的,所以能力不完全在上下文能力中,还有很大研究空间)* 1. 1. 1.


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册