CNN:图像处理

RNN:循环神经网络,序列处理

大数据带来了人工智能的兴起,因为大规模的神经网络可以处理大量数据。而早期模型支持向量机等不擅长处理大数据。

神经网络和深度学习

神经网络基础和具有神经网络思维的logistics回归

  • 二分分类

    二分类问题:输出1或0

    目标:设计分类器对所给目标进行二分类。

    记号的规定: 表示一个样本及其输出,\(x\)\(n\) 维特征向量,\(y\) 是其分类结果

    用小写字母 \(m\) 表示样本数,\(m_{test}\) 表示测试样本数,\(m_{train}\) 表示训练样本数

    \(X\) 是一个 \(n\times m\) 矩阵,表示所有训练样本的输入;

    \(Y\) 是一个 \(1\times m\) 矩阵,表示样本的输出。

    \(\sigma(z)=\frac{1}{1+e^{-z}}\),可以将 \((-\infty,+\infty)\) 映射到 \((0,1)\) 的函数

    \(z^{(i)}=w^Tx^{(i)}+b\)

    记损失(误差)函数为 \(\mathcal L(\hat y,y)\) ,表示预测值和实际值的差距

    记成本函数为 \(J(w,b)=\frac{1}{m}\sum_{i=1}^m\mathcal L(\hat y^{(i)}-y^{(i)})\)

  • logistics 回归

    目标是设计 \(\hat y=P(y=1|x)\)

    \(\hat y=\sigma(w^Tx+b)=\sigma(z)\),然后通过训练集训练 \(w\)\(b\) 的取值。

    在logistics回归中,选用的是 \(\mathcal L(\hat y,y)=-(y\log \hat y+(1-y)\log (1-\hat y))\),这是sigmoid函数,记作 $$。

    注意到,当 \(y=0\) ,为了让误差函数为0,应该让 \(\hat y\) 尽可能接近0,即 \(z\) 越小越好;

    同理若 \(y=1\) ,则 \(z\) 越大越好

    则成本函数 \(J(w,b)=\frac{1}{m}\sum_{i=1}^m\mathcal L(\hat y^{(i)}-y^{(i)})\) 衡量了一堆 \((w,b)\) 对给定样本集的性能,且越小越好。

    logistics回归其实是一个很小的神经网络。

  • 梯度下降法

    用于训练 \(w\)\(b\)

    在logistics回归的设计中,\(J(w,b)\) 可以被证明为一个凸函数,即单峰,有最小值的函数。

    用某初始值初始化 \(w,b\) ,然后梯度下降。

    为了方便理解,假设 \(b\) 不存在 ,每次迭代使得 \(w=w-\alpha \frac{\mathrm{d}J(w)}{\mathrm{d}w}\)\(\alpha\) 是学习率),这样显然只要但是没推出这个公式 \(\alpha\) 的设置合理,最后 \(w\) 的值就会走向最低点。

    若考虑 \(b\) ,则: \[ \begin{cases} w= w -\alpha \frac{\partial J(w,b)}{\partial w}\\ b= b -\alpha \frac{\partial J(w,b)}{\partial b}\\ \end{cases} \]

  • 导数的计算

    假设 \(n=2,m=1\) (即,只有一个训练样本,每个样本的特征向量为二维),则有 \(\mathcal J(w,b)=\mathcal L(\sigma(w_1x_1+w_2x_2+b),y)\) ,需要用链式求导法则求导。 \[ \begin{align} \frac{\mathrm{d}J}{\mathrm{d}w_1} &=\frac{\mathrm{d}L}{\mathrm{d}w_1}\\&=\frac{\mathrm{d}L}{\mathrm{d}a} \times \frac{\mathrm{d}a}{\mathrm{d}z}\times\frac{\mathrm{d}z}{\mathrm{d}w_1}\\&=(-\frac{y}{a}+\frac{1-y}{1-a})(-\frac{1}{(1+e^{-z})^2})(-e^{-z})x_1\\&=\frac{a-y}{a(1-a)}a(1-a)x_1\\&=x_1(a-y) \end{align} \] 其中,\(a=\sigma(z),z=w_1x_1+w_2x_2+b\)

    同理,\(\frac{\mathrm{d}J}{\mathrm{d}w_2}=x_2(a-y)\)\(\frac{\mathrm{d}J}{\mathrm{d}b}=a-y\)。这个结果是容易推广到 \(n\) 更大的情况的。

    如果有 \(m\) 个训练样本,则对这 \(m\) 个关于 \(w_i\) (或 \(b\))的导数取均值就是 \(J\) 关于 \(w_i\) (或 \(b\))的导数。


    若利用 for 循环遍历加和所有导数,会使效率大幅降低,为了应对样本量极大的情况,引入向量化方法。

    对于连加式: \[ sum=\sum _{i=1} ^{n} a_ib_i \] 若将 \(a,b\) 视为向量相乘,即 \(sum=a\cdot b^T\) ,则计算速度会大大加快,这时因为向量的相乘在 python 中被实现在GPU上,且可以并行化。

    再如,对于连加式: \[ u_i=\sum_{j=1}^mA_{i,j}v_j \] 若将 \(A,v\) 写成矩阵乘法的形式,即 \(u=A\cdot v\) ,则计算速度会大大加快。

    在 numpy 宏包中,封装了很多支持并行计算的用于向量的函数,如 u=np.exp(v) 可以将向量 \(u\) 内所有的元素 \(u_i\) 赋值为 \(e^{v_i}\) 。在需要使用显式的 for 循环之前,应当检查 numpy 是否具有同样功能的函数以替换。

    有了以上的方法,已经可以节省一层大小为 \(n\) 的 for 循环,即遍历 \(w_i\) 进行更新的 for 循环。

    接下来继续使用向量化方法节省最外层的大小为 \(m\) 的,用于遍历样本计算导数均值的 for 循环。

    首先计算 \(Z\) ,注意 \(X\) 是由 \(m\) 个向量 \(x^{(i)}\) 组成的 \(n\times m\) 矩阵。而 \(Z\) 是一个 \(1\times n\) 矩阵。

    那么就有 \(Z=w^TX+[b,b,\dots,b]\),在 python 中,可以写作 Z=np.dot(w.T,X),然后可以直接使用 A=sigmoid(Z) 来计算所有 Z 的 $$ 值。

    而导数 \(\frac{\mathrm{d}J}{\mathrm{d}w_i}=x_i(a-y)\) 即为 \(\mathrm{d}b=\frac{1}{m}\sum (A-Y),\mathrm{d}w=\frac{1}{m}X(A-Y)\)

    1
    2
    3
    4
    5
    6
    7
    Z=np.dot(w.T,x)+b
    A=sigmoid(z)
    dZ=A-Y
    dw=1/m * X * dZ.T
    db=1/m * np.sum(dZ)
    w=w-a*dw
    b=b-a*db

浅层神经网络

在logistics回归中,使用一个 \(z\) 囊括了所有输入 \(x_i\) 的信息,在浅层神经网络中,我们将有多个由 \(z\) 组成的一层神经网络来处理输入,并将输出作为输入输入到另一个 \(z\) 中。因为节点数大幅度增加了,因此重新统一一下符号:

假设输入(样本)有 \(n^{[0]}\)

输入层为第 0 层,记为 \(a^{[0]}=X\) ,第一层为隐藏层,记为 \(a^{[1]}\) ,有 \(n^{[1]}\) 个节点,记为 \(a^{[1]}_i\) ,每个节点具有一对隐藏的 \(w\)\(b\)\(w\) 是一个 \(m\) 维向量,而 \(b\) 是一个值,因此 \(w^{[1]}\) 是一个 \(n^{[1]}\times n^{[0]}\) 的矩阵,\(b\) 是一个 \(n^{[1]}\times 1\) 的矩阵,第三层是输出层,记为 \(a^{[2]}\),具有参数 \(w^{[2]},b^{[2]}\) ,分别是 \(1\times n^{[0]}\) 的和 \(1\times 1\)

在上图所示的神经网络中,其第一层的计算如下: \[ z_1^{[1]}=w_1^{[1]T}x+b_1^{[1]},a_1^{[1]}=\sigma(z_1^{[1]})\\ z_2^{[1]}=w_2^{[1]T}x+b_2^{[1]},a_2^{[1]}=\sigma(z_2^{[1]})\\ z_3^{[1]}=w_3^{[1]T}x+b_3^{[1]},a_3^{[1]}=\sigma(z_3^{[1]})\\ z_4^{[1]}=w_4^{[1]T}x+b_4^{[1]},a_4^{[1]}=\sigma(z_4^{[1]})\\ \] 这样的计算是繁琐的,考虑向量化。 \[ Z^{[1]}=W^{[1]}x+b^{[1]}\\ A^{[1]}=\sigma(z^{[1]})\\ \] 这条两条算式可以推广到任意一层。

另外,也可以考虑将 \(\sigma\) 函数换成别的函数,如 $$ ,$$ 的取值是 \([-1,1]\),由于其均值为0,在一些情况下会方便神经网络下一层的学习。或者最常用的 \(\mathrm{ReLU}(z)=\max(0,z)\) 函数,以及 带泄露的ReLU函数 \(\text{Leaky\_ReLU}(z)=\max(0.01z,z)\)

在普通的 ReLU 中,当输入为负时,梯度变为零,这意味着在训练过程中,一旦某个神经元被激活为负值,它将不再更新其权重,这可能导致梯度消失问题。而在 Leaky ReLU 中,即使输入为负时,仍然有一个小的梯度存在。

若使用线性激活函数,意味着输出只能是线性激活函数相加,而线性函数相加仍然是线性函数的结果,隐藏层也就失去了意义。因此,必须使用非线性激活函数,多层神经网络才有意义。

考虑以上函数的导数: \[ g(z)=\sigma (z) & g'(z)=\sigma(z)(1-\sigma(z))\\ g(z)=\tanh(z)=\frac{e^x-e^{-x}}{e^x+e^{-x}}& g'(z)=1-(\tanh z)^2\\ g(z)=\mathrm{ReLU}(z)& g'(z)=\begin{cases}0,\quad \text{if z}<0\\1,\quad \text{if z}\geq 0\end{cases}\\ g(z)=\mathrm{Leaky\_ReLU}(z)& g'(z)=\begin{cases}0.01,\quad \text{if z}<0\\1,\qquad \text{ if z}\geq 0\end{cases}\\ \] 有了以上的工具,接下来就可以计算神经网络的正向传播和反向传播了,对于上文所示的隐藏层神经网络,假设各层节点数 \(n_x\),中间层具有一个 \(n_x\times n_{x-1}\)\(W\) 矩阵和 $n_x1 $ 的 \(b\) 矩阵。

故: \[ \begin{align} Z^{[1]}&=W^{[1]}X+b^{[1]}\\ A^{[1]}&=g^{[1]}(z^{[1]})\\ Z^{[2]}&=W^{[2]}A^{[1]}+b^{[2]}\\ A^{[2]}&=g^{[2]}(z^{[2]})=\sigma(z^{[2]})\\ dZ^{[1]}&=A^{[2]}-Y\\ dW^{[2]}&=\frac{1}{m}\mathrm{d}Z^{[2]}A^{[1]T}\\ \mathrm{d}b^{[2]}&=\frac{1}{m} \mathrm{np.sum}(\mathrm{d}Z^{[2]},axis=1,keepdims=1)\\ \mathrm{d}Z^{[1]}&=W^{[2]T}\mathrm{d}Z^{[2]}* g^{[1]'}(Z^{[1]})\\ \mathrm{d}W^{[1]}&=\frac{1}{m}\mathrm{d}Z^{[1]}X^{T}\\ \mathrm{d}b^{[1]}&=\frac{1}{m} \mathrm{np.sum}(\mathrm{d}Z^{[1]},axis=1,keepdims=1) \end{align} \]

另外,需要注意到,初始时每一层的每个节点参数 \(w,b\) 不能设置为相同,否则训练出来的结果将一模一样。因此需要随机化初始化方法。注意如果利用了sigmoid函数,随机的初始值绝对值不能太大,否则导数趋于0

深层神经网络

加入更多的隐藏层就能形成更深的神经网络。

前向传播: \[ \begin{align} Z^{[l]}&=W^{[l]}\times A^{[l-1]}+b^{[l]}\\ A^{[l]}&=g^{[l]}(Z^{[l]})\\ \end{align} \] 反向传播 \[ \begin{align} \mathrm{d}Z^{[l]}&=\mathrm{d}A^{[l]}*g^{[l]'}(Z^{[l]})\\ \mathrm{d}W^{[l]}&=\frac{1}{m}\mathrm{d}Z^{[l]}A^{[l-1]T}\\ \mathrm{d}b^{[l]}&=\frac{1}{m}\mathrm{np.sum}(\mathrm{d}Z,axis=1,keedims=true)\\ \mathrm{d}A^{[l-1]}&=W^{[l]T}\mathrm{d}Z^{[l]}\\ \end{align} \]

  • 调参:

    可以调的参数有各个 \(W,b\) 的初始值,学习率 \(\alpha\),循环次数,节点数,隐藏层数量和激活函数等。其中大部分需要多次尝试找到比较优的值,特别是学习率 \(\alpha\)

改善深层神经网络

最优参数和机器、时间、所有样本数量都有关。

  • 数据的选择:

    如果数据量较少,训练集,验证集和测试集可以考虑6:2:2

    如果数据量足够大,则10000条左右的数据也足以验证模型的精确性

    要注意为了优化性能,测试集和训练集应当来自同一个分布。

如果训练集误错误率为 1% ,验证集错误率为 11% ,则意味着低偏差,高方差,出现了过拟合

如果训练集误错误率为 15% ,验证集错误率为 16% ,则意味着高偏差,低方差,出现了欠拟合

如果训练集误错误率为 15% ,验证集错误率为 30% ,则意味着高偏差,高方差,训练非常失败。

当然,这是基于最优误差(目前已经实现的打tag方法,如肉眼判断)为0的。若最优误差为 15% ,错误率为15%也非常合理。

平衡方差和偏差是很重要的课题,如果方差过高,继续训练可能不一定有效,在增加训练量的同时,也要想办法收集训练样本,或者采用正则化。

正则化

正则化是一种避免过拟合的方法。

  • L2 正则化

    将 $J $ 改为: \[ \mathcal J(w,b)=\frac{1}{m}\sum_{i=1}^n\mathcal L(\hat y ^{[2]},y^{[2]})+\frac{\lambda}{2m}||w|| _2^2,\quad \text{(L2 regulation)}\\ (||w||_2^2=\sum_{j=1}^mw_j^2=w^Tw) \] \(\lambda\) 是正则化参数。

    经过正则化,\(\mathrm d w^{[l]}\) 的值加上了 \(\frac{\lambda}{m}w^{[l]}\),而在反向传播中, \(w^{[l]}=w^{[l]}-\alpha \mathrm dw^{[l]}\),因此反向传播过程中梯度下降的程度少了 \(\frac{\alpha\lambda}{m}w^{[l]}\)

    L2正则化在损失函数中添加了一个惩罚项,该项与模型参数的平方成正比。这意味着在优化过程中,模型会倾向于较小的参数值,因为较大的参数值会导致正则化惩罚增加,进而增加总损失。通过惩罚较大的参数值,L2正则化鼓励模型更平滑,防止极端的参数值,从而降低模型复杂性。

    正则化项可以被看作是对模型参数的额外约束,限制了参数值的范围。通过这种方式,在学习过程中,模型的参数空间受到限制,有助于防止对训练数据的过拟合,并提高其对未知数据的泛化能力。

  • dropout 正则化

    对于每个样本,对网络进行随机失活处理。即以随机的概率 keep-prob 选择一部分节点不纳入神经网络中。

    通过dropout正则化,神经网络会被迫学习到更加鲁棒的特征表示,因为每个神经元都需要适应其他神经元的缺失。这有助于减少神经元之间的复杂共适应(co-adaptation),从而降低模型对于训练数据的过拟合,提高了模型的泛化能力。

    过拟合可能性较大的层(节点数较多)应当减少 keep-prob 值,对于节点数较少的层,keep-prob值可以为1

    输入层基本不会产生过拟合,其keep-prob值可以为0.8~1,隐藏层为 0.5,输出层为1.

    对于更复杂的网络,可能需要更多的正则化,因此使用较低的keep-prob值;

    如果训练数据较少,可能会更容易过拟合,因此使用更大的keep-prob值。

    在dropout中,J失去了明确定义,会带来调试的不方便,一般只在计算机视觉领域,图像所含输入信息过大时且过拟合时使用。

  • Early Stopping

    在训练过程中监视模型在验证集上的性能,在性能不再提高时停止训练,从而防止模型继续拟合训练数据,避免出现过拟合。

  • 数据扩增

    通过对图像进行简单处理扩充样本。

优化方法

  • 归一化输入

    将所有输入的均值拉到1,并且将样本的各个维度的数值跨度放缩到同一范围内。

    若不归一化,由于样本不同维度的数据范围不同,J函数会呈现长条状,导致梯度下降法效率较低。归一化输入可以加速模型的收敛,减少训练过程中的梯度爆炸或消失问题。

    • 梯度爆炸和梯度消失:梯度是损失函数对参数的偏导数,它们在反向传播过程中通过链式法则传播。当网络层数较多时,如果每一层的偏导数都小于1或都大于1,在深度神经网络中,梯度的乘积可能会变得非常大或者非常小。
    • Leaky ReLU 通常比 ReLU 更能抵抗梯度消失问题。
  • 权重初始化

    用于缓解梯度爆炸和梯度消失的技术。

    让初始化权重从均值为0、方差为 \(\frac{1}{n^{[l-1]}}\) (Xavier初始化)或方差为 \(\frac{2}{n^{[l-1]}}\) (He初始化)的高斯分布中随机初始化。(ReLU函数或tanh函数)

    Xavier初始化根据前一层神经元的数量来控制权重的方差。通过将权重初始化为具有适当方差的高斯分布,Xavier初始化可以确保每一层的激活值在前向传播过程中保持在一个合适的范围内,有助于尽可能避免梯度消失和梯度爆炸问题的发生(此效果不绝对)。

  • 梯度检验(grad check)

    为了检验梯度,需要先数值上逼近梯度的值 \[ f'(\theta) \approx \frac{f(\theta+\varepsilon)-f(\theta-\varepsilon)}{2\varepsilon}\quad (\varepsilon\leq 10^{-3}) \] 计算损失函数相对于每参数的数值梯度,取 \(\frac{||\mathrm{d}\theta_{approx}-\mathrm{d}\theta||_2}{|\mathrm{d}\theta_{approx}||_2+||\mathrm{d}\theta||_2|}\),一般 \(1e-7\) 正常,\(1e-5\)需要检查,\(1e-3\)则大概率有误。

  • mini-batch 梯度下降法

    当样本数量 \(m\) 过大时,每次训练都要遍历全部训练样本,需要多次学习时,效率过低。

    将庞大的训练集分为多个小训练集,每次更新模型参数时不使用整个训练数据集,而是使用一个小训练集。

    因为每次训练集不同,J函数的走向可能不是一直向下的,而是有噪声地趋势向下。

    mini-batch的大小应当合理。过小会失去向量化的加速作用,过大则会退化为梯度下降法。因此应当取适中的mini-batch值

  • 动量梯度下降法(Momentum优化)

    先介绍指数加权平均

    • 指数加权平均

      用于对时间序列数据进行平滑处理。

      它通过对历史数据进行加权平均来生成平滑的序列,其中较新的数据具有较高的权重,而较旧的数据具有较低的权重。

      给定一个时间序列 \(\{x_1,x_2,x_3,\dots,x_n\}\)

      那么其质数加权平均 \(\{y_1,y_2,y_3,\dots,y_n\}\)\[ y_t=\beta y_{t-1}+(1-\beta)x_t\qquad (y_0=0,0<\beta<1) \]

      较大的 \(\beta\) 表示对历史数据的权重较高,平均值变化较缓慢,折线会更加平滑;而较小的 \(\beta\) 则表示对历史数据的权重较低,平均值更加灵活地跟随最新的数据。

      若将 \(y_t\) 的表达式从递归式拆开,可以写为: \[ \begin{align} y_t=&(1-\beta)x_t+\beta(1-\beta)x_{t-1}+\beta^2(1-\beta)x_{t-2}+\beta^3(1-\beta)x_{t-3}+\dots \\ =&(1-\beta)\sum_{i=0}^n \beta^i x_{t-i} \end{align} \]

      因为有 \(\lim _\limits{\varepsilon\rightarrow 0}(1-\varepsilon)^\frac{1}{\varepsilon}=\frac{1}{e}\) (自然对数底数 \(e\) 的定义式),所以若 \(\beta\) 比较大( \(>0.85\) ),当 \(i=\frac{1}{1-\beta}\) 时,实际上其加权平均之权值已经接近 \(e^{-1}\) ,因此可以说,其权值的 \(\frac{1}{e}\) 衰期为 \(\frac{1}{1-\beta}\)

      注意到,\(y_1=(1-\beta )x_1\) ,因此指数加权平均方式在前期对平均值的预测可能不准确。一种可行的修正方式是取 \(\frac{v_t}{1-\beta^t}\)

    考虑对梯度下降的梯度使用这一方法,每次保留一定前面的下降留下的动量,这样就可以很有效地消除震荡(这个震荡可能是某一维度已经到达最低点带来的,也可能是利用mini-batch梯度下降法带来的等等),并且在距离最低点较远处一直加速下降,在最低点附近步长会自适应地缩短。

    \(\beta\) 经常取 0.9

    可以写为: \[ \begin{align} \begin{cases} v_{\mathrm{d}W}=\beta v_{\mathrm{d}W}+(1-\beta){\mathrm{d}W}\\ v_{\mathrm{d}b}=\beta v_{\mathrm{d}b}+(1-\beta)\mathrm{d}b\\ W=W-v_{\mathrm{d}W}\\ b=b-v_{\mathrm{d}b} \end{cases} \end{align} \] 也可以将 \((1-\beta)\) 删去,写为

    \[ \begin{align} \begin{cases} v_{\mathrm{d}W}=\beta v_{\mathrm{d}W}+{\mathrm{d}W}\\ v_{\mathrm{d}b}=\beta v_{\mathrm{d}b}+\mathrm{d}b\\ W=W-v_{\mathrm{d}W}\\ b=b-v_{\mathrm{d}b} \end{cases} \end{align} \] 这两种方法基本只有学习率的调整不同,第二种更符合“保留初速度“的物理思想,第一种则更符合”加权平均“的数学思想。

  • RMSprop (Root Mean Square Propagation)

    也是一种用于优化神经网络的随机梯度下降算法的变体。

    对于每个参数 \(W\),计算梯度 \(\mathrm{d}W\)

    \(v=\beta' v+(1-\beta')(\mathrm{d}W)^2\)

    \(W=W-\frac{\eta}{\sqrt{v}+\varepsilon}\mathrm{d}W\)

    其中 \(\varepsilon\) 是一个很小的数 (\(1e-8\)),以防除以零,\(\beta'\) 通常也取 0.9,为了方便后文区分,这里采用了不同的记号。

    这也是一种自适应学习率的方法。RMSprop 使用每个参数的历史梯度信息来调整学习率,这使得每个参数的更新可以根据其梯度大小进行自适应调整。这有助于加速收敛并避免学习率衰减不合适的问题。

    如果一个参数的梯度一直很大,那么 \(v\) 也会变大,从而减小学习率;反之,如果梯度很小,那么 \(v\) 也会变小,学习率会增加,这有助于加速收敛。

  • Adam 优化算法

    Adam 优化算法结合 Momentum 和 RMSprop。

    • 计算梯度 \(\mathrm{d}W\)

    • \(m=\beta_1m+(1-\beta_1)\mathrm{d}W\)

      \(v=\beta_2v+(1-\beta _2)g^2\)

      通常情况下, \(\beta_1=0.9,\beta_2=0.999\) 具有良好的鲁棒性

    • \(\hat m=\frac{m}{1-\beta^t_1},\hat v=\frac{v}{1-\beta_2^t}\)

    • \(W=W-\frac{\eta}{\sqrt{\hat v}+\varepsilon}\hat m\)

  • 学习率衰减

    针对mini-batch不收敛,有噪声的情况,人为地在训练过程中动态地调低学习率来加快收敛速度。

    衰减方式可以是指数衰减,平方根衰减甚至手动衰减(训练时间较长的情况)。关于这些超参数的选择,后文会有全面的学习。

调参

最重要的是学习率 \(\alpha\) ,此外还有mini-batch的大小,隐藏单元(层数、每层的大小)和梯度下降法的 \(\beta\) 值等

随机撒点取值,在取值优秀的地方放大,再次密集地随机撒点取值试验效果。

有一些参数(如学习率或者加权平均系数 \(\beta\))的随机撒点可以考虑在对数数轴上随机撒点。\(\beta\in[0.0,0.999]\) ,显然也需要对数轴上撒点较为合理。

当计算资源较少时,可以边运行边更改参数;计算资源较多时,可以同时进行大量相同模型不同参数的计算,最终保留最有效的。

  • batch 归一化

    在logistics回归中,曾经使用归一化技术处理输入。在深层神经网络中,可能需要对每一层的输出也进行归一化,因为他们也是下一层的输入。 \[ \begin{align} \mu &= \frac{1}{m} \sum_i z^{(l)}\\ \sigma ^2&=\frac{1}{m} \sum_i (z_i-\mu)^2\\ z_{norm}^{(i)}&=\frac{z^{(i)}-\mu}{\sqrt{\sigma^2+\varepsilon}}\\ \end{align} \] 这时,隐藏单元平均值为0,方差为1,但是我们不希望每个隐藏单元的输出都是均值0,方差1的,不同的分布可能会带来更好的效果,因此: \[ \tilde z^{N(i)}=\gamma z_{norm}^{(i)}+\beta \] 用来重新平移和放缩。这时再将 \(\tilde z\) 输入到 \(g\) 函数中输出。

    注意到归一化已经 将 $ b$ 的影响消去,因此实际训练时,训练 $W{[l]}.{[l]},^{[l]} $。

    这一优化方法可以和上面各种梯度下降法一并使用。

    归一化的好处是,\([l]\) 层的各个参数是针对 \([l-1]\) 层的输出训练的。然而,\([l-1]\) 层由于前面参数变化的影响,其输出的特征及范围也在随之改变,这会使得 \([l]\) 层之前的训练的意义降低,因此,每层学习的独立性得到了增强。

    这样,内部协变量便宜减小,梯度的传播变得更快,就允许使用更高的学习率。同时,也有轻微的正则化的效果,正则化引入了一些噪声,可以防止模型过拟合。

softmax 回归

logistics回归是用于处理二分类问题的,softmax回归可用来处理多分类问题。

除了已有的 \(n\) 个可能的分类,softmax回归也可以给出拒绝判断的输出,即不属于任何一类。

这时,输出层应该有 \(n+1\) 个,表示对应每一项的概率,加起来应该是1。其中最大的就是预测值。 \[ t=e^{(z^{[l]})}\\ a^{[l]}_i=\frac{t_i}{\sum_{j=1}^{n+1} t_i}\\ \]\(a\) 作为激活函数,即 \(a^{[l]}=g^{[l]}(z^{[l]})\) ,与其他激活函数不同的是,\(a\) 输入一个 \(n+1\) 维向量,输出一个 \(n+1\) 维向量,且各维度和为1。

其损失函数和成本函数定义如下: \[ \mathcal L(\hat y,y)=-\sum_{j=1}^{n+1}y_j\log \hat y_j\\ \mathcal J(w,b,\dots)=\frac{1}{m}\sum_{i=1}^n\mathcal L(\hat y^{(i)},y^{(i)})\\ \] 从而可以计算导数,注意此时单个 \(\mathrm d z\) 已经是个 \(n+1\) 维向量。

一些神经网络框架

每个神经网络框架各有优点。比如开源性、高效性、便于编程等等

杂项

  • 评判一个系统有多个标准,寻找一个方式逐个调整·使得其满足标准,并且调整多个方式的过程互不影响

  • 单实数评估

    查准率/查全率:双指标评估,难以对好坏进行排序。

    因此取调和平均数 \(\frac{2}{\frac{1}{P}+\frac{1}{R}}\) 来兼顾查准率和查全率

  • 优化指标+满足指标

    eg. 时间小于100ms的前提下,准确度最高;一天内最多只出一次错的前提下,时间尽量快

    通常情况下,可以有多个满足指标,优化指标最好只有一个

  • 训练集,开发集和测试集的划分

    开发集和测试集应当尽可能来自同一分布。然而这并不一定总能实现。因为从最终投入使用的实际目标环境收集到的样本数量可能较少

    • 为了取得更优秀的成果,可以考虑将测试集和开发集全部设为实际环境得到的样本,以方便评估实际运用的真实效果

    • 当开发集和训练集取自不同分布时, 设置训练-开发集,与训练集同分布,以确认算法在开发集上错误率高是因为过拟合还是因为算法未学习开发集数据。

      也就是说,统计五个数据 人类错误率 - 训练集错误率 - 训练-开发集错误率 - 开发集错误率 - 测试集错误率,依次比较出四个指标:可避免误差、方差、数据不匹配带来的误差、对开发集过拟合的程度。

      收集与错误相关的数据进行分析有助于了解优化的方向。

      • 处理数据不匹配问题:做错误分析:考虑开发集和训练集的差异,尝试修改开发集(模拟类似开发集的噪声,多收集开发集常出现的数据等)

        收集数据时谨慎使用生成式AI的数据,或者其他模拟合成的数据,因为容易导致过拟合。

  • 数据扩充:在计算机视觉领域中,常常数据不足,此时可以翻转、剪切、旋转、扭曲、色彩转换等等方法来扩充数据集

  • 实时调整评估指标,对评估指标不满意时及时修正。

  • 对自然感知方面的任务(图像/声音识别)通常超过人类后增速变慢:学习资料基本来自人类(对数据的标记来自人类),且超过人类后难以想出能优化的方式。

    用人类水平估计最优水平,再考虑优化方差还是偏差。然后选择对应的方法去优化做法

  • 错误分析:观察被标记错误的数据,对于共同点想办法优化,并剔除标记错误的数据

  • 迁移学习:对于两个相似的任务AB,A的浅层知识可能对B也有用。这时可以直接从A的某个隐藏层甚至输出层开始对B的学习。

    在实际实践过程中,特别是计算机视觉方向,也常常使用别人已训练好的参数,对接到自己的模型上,只训练自己的模型。

  • 多任务学习:类似softmax地,输出多个值。但是每个样本可能对应多个标签,这意味着输出之和不为1。因此使用的不是softmax函数。如计算机视觉同时识别多个目标,多个目标的浅层特征是共用的。

卷积神经网络和计算机视觉

边缘检测

利用卷积核对图像进行卷积可以得到图像的边缘。卷积核(滤波器)是一个小的矩阵,它在图像上滑动并与图像进行逐元素相乘和求和的操作,从而产生一个新的输出图像。这个图像能蕴含边缘的信息。

卷积核可以是手动规划的,例如Sobel、Prewitt、Roberts等,也可以用机器学习去理解一个无法被人类直接理解的卷积核。

  • padding

    在输入图像的周围添加值为零的像素。可以在边缘处使得卷积核能够覆盖到输入图像的边界像素,从而避免信息丢失和输出尺寸的缩小。

  • 调整步长

    通过调整卷积核每次移动的步长,可以控制输出特征图的尺寸和网络的信息提取效率。较大的步长可以减少输出特征图的尺寸,从而降低模型的计算复杂度,加快模型的运行速度,而较小的步长可以增加输出特征图的尺寸,提高对图像特征的细节提取能力。

  • 三维卷积

    因为RGB图像是需要三个平面来描述的,因此卷积核也需要三个面,这样卷积之后就能变为平面。

卷积层

卷积的每一层拥有过滤器(\(f\times f\))的大小 \(f^{[l]}\),padding \(p^{[l]}\),步长 \(s^{[l]}\),过滤器的数量 \(n_c^{[l]}\)

输入 \(n_H^{[l-1]}\times n_W^{[l-1]} \times n_C^{[l-1]}\) ,输出 \(n_H^{[l]}\times n_W^{[l]} \times n_C^{[l]}\), 其中有 \[ n_{H/W}^{[l]}=\frac{n_{H/W}^{[l-1]}+2p^{[l]}-f^{[l]}}{s^{[l]}}+1 \] \(a^{[l]}\rightarrow n_H^{[l-1]}\times n_W^{[l-1]} \times n_C^{[l-1]},A^{[l]}\rightarrow m\times n_H^{[l-1]}\times n_W^{[l-1]} \times n_C^{[l-1]}\)

\(bias=n_C^{[l]}\)

能最大化地激活最浅层的通常是最简单的图案,层数越深,激活他们的图像便越复杂。

池化层和全连接层

最大池化:不使用卷积,而是对一定区域内的值取最大值代替,从而缩小图片。

平均池化:不使用卷积,而是对一定区域内的值取平均值代替,从而缩小图片。

最大池化常用的多,且通常 \(p=0,f=2,s=2\)。 因为其运算是取max,因此并没有进行反向传播修改参数的步骤。只是对特征的提取而已。

通常来讲,在训练过程中 \(n_H,n_W\) 逐渐减小至1,,而 \(n_C\) 逐渐增大,全连接层将最后的 \(n_c\) 维向量联系起来,进行 softmax

使用卷积的原因是,在普通神经网络中,每个节点都和上一层的所有节点相关,而在卷积神经网络中,每个节点只被上一层的等同于过滤器大小的节点相关。另外,卷积神经网络也有平移不变的特性,这使得他比普通神经网络更善于处理视觉问题,对于不同位置的同一物体可以类比辨别,这是普通神经网络难以学习到的。

经典神经网络结构

  • LeNet - 5

    卷积核为 \(5\times 5\) 。卷积层使得维数-4(当时还不使用padding),池化层使得维数减半,大致如下:

    \(32\times 32\times 1\longrightarrow 28\times 28\times 6\longrightarrow 14\times 14\times 6 \longrightarrow 10\times 10 \times 16\longrightarrow 5\times 5\times 16\)

    最后400个节点进入120个节点的全连接层,再进入84个节点的第二个全连接层,最后接入十个节点(手写数字识别)的输出(现在使用softmax)。

    约有6w个参数

  • AlexNet

    约有6000w个参数 $$ \[\begin{align} &227\times 227\times 32\times 3\stackrel{11\times 11}{\underset{s=4}\longrightarrow}55\times 55\times 96\stackrel{\small\text{MAX-POOL}}{\underset{3\times 3,s=2}\longrightarrow}27\times 27\times 96\stackrel{5\times 5}{\underset{\small\text{padding}}\longrightarrow}27\times 27\times 256\\ &\stackrel{\small\text{MAX-POOL}}{\underset{3\times 3,s=2}\longrightarrow}13\times 13\times 256\stackrel{\small\text{padding}}{\underset{3\times 3}\longrightarrow}13\times 13\times 384\stackrel{\small\text{padding}}{\underset{3\times 3}\longrightarrow}13\times 13\times 384 \stackrel{\small\text{padding}}{\underset{3\times 3}\longrightarrow}13\times 13\times 384 \\ &\stackrel{\small\text{padding}}{\underset{3\times 3}\longrightarrow}13\times 13\times 256 \stackrel{\small\text{MAX-POOL}}{\underset{3\times 3,s=2}\longrightarrow}6\times 6\times 256=9126\rightarrow 4096\rightarrow 4096\rightarrow \text{softmax} \end{align}\] $$

  • VGG-16

    16个卷积层和全连接层,包含1.38亿个参数,也是类似如此卷积层和全连接层交替的方式

  • 残差网络Res-Net(2015)

    深度网络的深度过深时,容易出现梯度消失和梯度爆炸问题,因此用远跳连接将当前节点的输出直接输入到几层之后,而不通过主路径逐个传递到达。

    非常容易训练 - 152层深度完成imagenet,复杂度却更低.

    原来的解决方法:中间做归一化,虽然可以让精度收敛,但是精度变差

    假设前面的输出为 \(X\) 某一些层输出为 \(F(x)\) ,学习的内容改为 \(F(X)=H(X)-X\) ,并且输出 \(F(X)+X\)

    为了避免计算量过大,使用了 \(1\times 1\) 卷积

    实际观测发现,梯度保持确实较好,可以一直保持下降的趋势。

  • Inception Net

    \(1\times 1\) 卷积:实际上是将 \(n_w\times n_c个\) \(1\times 1 \times n_c\) 的数据整合,起到一个类似全连接层的作用。减少卷积核的个数,就可以压缩 \(n_c\) 的大小;增加卷积核的个数,就可以放大 \(n_c\)

    对一个 \(n_w\times n_h\times n_c\) 的网络,用多个大小的卷积核和池化卷积核卷积后的结果堆叠在一起。

    考虑对一个 \(28\times 28\times 192\) 的网络作 \(5\times 5\),带 \(\text{same-padding}\) ,通道数为32的卷积的计算次数:\(28\times 28\times 32\times 5\times 5\times 192\),约为1.2亿,这是难以接受的。

    考虑先做 \(1\times 1\times 192\) ,通道数为16的卷积,再做 \(5\times 5\times 16\) ,通道数为32的卷积,此时计算次数变为:\(28\times28\times16\times1\times1\times192+28\times28\times32\times5\times5\times16\) 这约为0.12亿,计算时间缩小到了原来的 \(\frac{1}{10}\).

    (bottle neck)

    注意到池化层不会缩减通道数,因此需要将池化后的结果进行 \(1\times 1\) 卷积,以防止池化层的结果占据过多最后拼接矩阵的通道数。

    为了防止过拟合,inception net还在隐藏层的中间引出输出层,并用softmax预测,通过权衡多个softmax函数的预测值来得出最后的预测。

目标定位

  • 边界框

    神经网络的输出:物品分类和四个坐标(归一化的)。

    通常对边界框采用不同的误差函数计算方式:\(\mathcal L(\hat y,y)=\sum (\hat y_i-y_i)^2\)

    • (预测边框和实际边框面积的)交并比:\(IoU=\frac{\text{size of }\cap}{\text{size of }\cup}\)

      一般当其大于等于 \(0.5\) ,便可视为准确的识别。

  • 特征点

    此时,输出特征点坐标。

    相比之下,这一方法更应用与动作检测,人脸检测等。

  • 滑动窗口

    先训练网络辨识某目标,对图像适当剪切使得整个图像里都是该目标的图像。

    以固定步长在大图像上移动滑动窗口,调整滑动窗口大小,遍历整张图片来找到目标

    缺点:步长小计算成本高;步长大误差大。

    注意到,调整窗口大小,进行卷积时有一部分是重复计算的,其中的公有区域是可以只进行一次计算的,优化这一点即可。

    缺点:仍然不能得出精确的边界框

  • YOLO algorithm

    将图按网格区分,将目标分配给目标中点所在的网格内。

    • 非最大值抑制方法

      用于防止同个目标被识别多次。

      对于所有网格,取一个有车概率最大的网格,抑制(忽视)其他与其交并比较大的边框对应的网格。重复此操作直到有车概率最大的网格概率 \(p_c\leq 0.6\).

      注意:如果检测目标大于一个,对于每个目标应该做独立的非最大值抑制。

    • anchor box 算法

      用于处理多个目标处在同个格子内的情况。

      输出更多维数的向量,按处理的种类划分为各个box,对于不同种类目标交给不同box处理。

      利用交并比确定预测到的目标匹配哪一个实际目标,然后交给对应的box处理。

  • R-CNN 带区域卷积网络(候选区域方法)

    不针对每个滑动窗口都运行 CNN,而是预先通过某种方式预测某些区域是不可能有目标的。如分割色块,先运行CNN分割区域等。

人脸识别

困难:录入数据只有一个人脸。

  • One-shot learning

    训练网络实现目标:输入两个人脸,输出其相似度

    若相似度很低,视为同一个人。这样就容易获得训练样本

    • siamese 网络,triplet 损失

      训练一个模型,令模型对每张图片输出一个128维的向量,用两张图像的向量之差的范数衡量距离。

      将训练集图片分类为 A(Anchor), P(Positive), N(Negative),每次输入一个(A,P,N)三元组, A和P是同一个人,A和N不同。分别输入A-P和A-N,A-P应当被识别为同一个人,A-N应当被识别为不同的人。即

      \[ d(A,P)=||f(A)-f(P)||^2<||f(A)-f(N)||^2=d(A,N)\].

      则训练目标为:

      \[||f(A)-f(P)||^2-||f(A)-f(N)||^2<-\alpha\]

      \(\alpha\) 是一个阈值)。 \[ \begin{align} &\mathcal J(A,P,N)=\max(||f(A)-f(P)||^2-||f(A)-f(N)||^2+\alpha,0)\\ &\mathcal L=\sum_{i=1}^m\mathcal L(A^{(i)},B^{(i)},C^{(i)}) \end{align} \] 在训练集中选择 A,P,N 时,如果随机选择,可能N和A的区别太大,导致训练程度不够,应当尽量选择难分辨的A和N。

    • siamese 网络,二分类

      输入图片二元组,输出0或1,表示相似或不相似。

      同样也是训练一个网络,利用两张图片分别经过这个网络后得出的特征向量来进行比较。

神经风格迁移和其他运用

任务:将一张图片的风格修改为另一张,但内容不变。

对生成的图案定义一个代价函数,通过最小化代价函数来进行神经风格迁移。

代价显然要分为两部分:一部分是与第一张图片内容的相关度,一部分是与第二张图片风格的相似度。

CNN也可以用于其他的方面,如处理心电图等一维数据,或者B超等三维数据

循环神经网络RNN和序列模型

  • 示例问题:找到一句话里的人名。

    输出:对每个单词输出一个二分类标签1/0,来表示是不是人名的一部分。

    假设输入有 \(n\) 个单词,则输入为 \(T_x=n\),输出长度为 \(T_y=n\)

    \(x^{(i)}\) 表示第 \(i\) 个训练样本,用 \(x^{(i)<t>}\) 表示这个样本的第 \(t\) 个元素;同样地, \(T_X^{(i)}\) 表示这个训练样本的长度。\(y^{(i)<t>}\) 表示第 \(i\) 输出的第 \(t\) 个元素。

    表示一个词的方法可以是单词在词典里的序号,建立一个维度等同于词典长度的向量,其中将那个序号对于的维度标1,其他标0。这样,\(x^{(i)<t>}\) 就可以被写为一个 one-hot 向量。如果有不在词表里的单词,应当创造一个新的位置单词。

循环神经网络

因为每个句子长度不一样,因此将每个单词作为一个输入,一起输入神经网络是不合理的。

使用循环神经网络可以解决这个问题:

每次输入一个单词并进行预测,预测 \(y^{<n>}\) 时,继承 \(y^{<n-1>}\) 留下的一部分数据 \[ \cases{ a^{<t>}-g(W_{aa}a^{<t-1>}+W_{ax}x^{<t>}+b_a)\\ \hat y(y)=g(W_{ya}a^{<t>}+b_y)}\\ \] 为了方便处理,也可以写为 \(a^{<t>}=g(W_a[a^{<t-1>},x^{<t>}]+b_a)\)

反向传播:\(L^{<t>}(\hat y^{<t>},y^{<t>})=-\hat y^{<t>}\log \hat y^{<t>}-(1-y^{<t>})\log (1-\hat y^{<t>})\)

\(L(\hat y,y)=\sum L^{}(\hat y^{<t>},y^{<t>})\)

接下来处理输入输出的长度不一致的情况,如文本翻译,情感分类等。此时采用多对一结构:中途不输出对每个元素的预测,而是最后一起进行判断和输出。当然,输出单元也可以是多个的。

对于生成式问题,则会出现一对多情况。如输入关键词生成文本或者音乐。但无论如何,循环神经网络的每个输入或者输出单元,都会将其信息留给下一个单元。

  • 示例问题:音频转文本

    涉及到同音词的选择,此时可以对每个可能性输出一个概率,选择概率大的。

    对于输入输出长度的情况,每个单元的输出会参考前面单元留下的信息,而经过预训练,模型的第一个单元也会选择概率最大的开头单词。这样每个单词考虑到了上文,为了考虑下文,有一种方法是引入双向循环神经网络

    不提供 \(x\),而是每次只依靠上一个单元的信息来找到本单元概率最大的输出,就可以生成一个序列,直观地看出这个模型学到了什么。这一过程称为采样。

  • 梯度消失问题的处理

    考虑以下句子:

    \(\text{The cat, which has already ate ......, was full.}\)

    这时,\(\text{was}\) 这个单词是不是复数与前面很远的一个单词强相关,而由于神经网络过长,其影响很难传达到这里。这是RNN典型的梯度消失问题。

    当然,因为层数过高也会产生梯度爆炸问题,使得数值溢出,产生NaN。这只要在数据超过某个阈值时对数据进行缩放就能解决。

    • GRU 门控循环神经网络

      对于每个单元设计一个记忆单元 \(c\) ,在 GRU 中,这和 \(a\) 是一样的,即 \(c^{<t>}=a^{<t>}\)。注意这是一个向量,表示需要记忆的信息。

      用来更新 \(c\) 的是 \(\Gamma_r\) ,称为重置门,衡量了相关性,通常取到很接近0的值,使得 \(c\) 很少被更新。

      \[ \begin {align} &\widetilde{c}=\tanh (W_c[\Gamma_r*c^{<t-1>},x^{<t>}]+b_c)\\ &\Gamma_u=\sigma(W_u[c^{<t-1>,x^{<t>}}]+b_u)\\ &\Gamma_r=\sigma(W_u[c^{<t-1>,x^{<t>}}]+b_r)\\ &c^{<t>}=\Gamma_u\widetilde{c}^{<t>}+(1-\Gamma _u)+c^{<t-1>} \end{align} \]

    • LSTM 长短期记忆

      LSTM 的效果比GRU更加强大和具有普适性。但是计算成本稍高。 \[ \begin{align} \widetilde c^{<t>}&=\tanh (W_c[a^{<t-1>},x^{<t>}]+b_c)\\ \text{(update)}\Gamma_u&=\sigma(W_u[a^{<t-1>}],x^{<t>}+b_u)\\ \text{(forget)}\Gamma_f&=\sigma(W_f[a^{<t-1>}],x^{<t>}+b_f)\\ \text{(output)}\Gamma_o&=\sigma(W_o[a^{<t-1>}],x^{<t>}+b_o)\\ c^{<t>}&=\Gamma_u*\widetilde c^{<t>}+\Gamma_f*c^{<t-1>}\\ a^{<t>}&=\Gamma_o*c^{<t>} \end{align} \] 门值也可以与 \(c^{<t-1>}\) 相关,称为窥视孔连接。

  • 双向循环神经网络BRNN

    处理每个词后,复制当前的单元,新复制出来的单元留作用于处理反向传播来的信息,但也接受该单元的输入,最后通过这两个单元一同决定输出。

  • Deep RNN

    考虑到每个单元深度不够,可以往上继续添加单元。在RNN中,深度为3的计算规模就已经相当巨大了。

    image-20240328173751373
    image-20240328173751373

自然语言处理和词嵌入

one-hot表示方法让同类词(如苹果和橙子)的相关性不强,导致模型泛化能力不强。

考虑学习特征值:如性别、年龄、是否是实物、价格等等。假设有300个特征,就可以组成一个300维向量来表示一个词。如果能让算法自动生成特征向量,那么学习效率会高得多。这一方法称为词嵌入。因为这是由算法生成的,这写向量的含义并不容易被人为理解。

学习词嵌入就是学习每个词的这一特征向量

用 T-SNE算法可将高维特征投影到二维平面上,体现词语和词语之间的相似程度。通过读取大量文本资料,可以学习到不同词语之间的相近关系。这也很有利于迁移学习,方便个人的模型训练。

词嵌入对于类比推理也有很大的帮助。如通过比较特征向量,可以总结出男人之于女人的关系类似于皇帝之于女王(只有性别上的差异)。

衡量相似度一般使用余弦相似度,表示为 $(u,v)= $,有时也可以使用欧氏距离相似度 \(||u-v||^2\),但后者一般用于衡量相异度。有了这个工具,也可以判断两词之间的相似度:\(\mathrm{sim}(e_{w},e_{king}+e_{man}-e_{woman})\)

学习词嵌入的过程可以视为学习一个单词数 \(m\) (行)乘以特征数 \(n\) (列)的矩阵。

建立这样一个矩阵,则一个 one-hot 向量与该矩阵相乘(矩阵在前面),则输出会是该矩阵的一列,这一列是他的向量。

考虑问题:给定句子的前n个单词,预测下一个单词是什么

  • Word2vec等词嵌入算法

    • Skip-gram 模型

      通过一个中心词来预测其周围的上下文单词。具体而言,给定一个中心词,模型的目标是最大化周围上下文单词的条件概率。

      将各个one-hot向量输入给嵌入矩阵E,对于每个向量,嵌入矩阵E会输出一列特征值,将这些特征值送入softmax单元,让其作出决策。

      对于模型输出的一系列 \(y_i\),损失函数:\(\mathcal{L}(\hat y,y)=-\sum y_i\log \hat y_i\)

      考虑softmax模型:\(p(t|c)=\frac{e^{\theta_t^Te_c}}{\sum_{j=1}^{n} e^{\theta_t^Te_j}}\)

      因为n是词汇表长度的级别,所以计算加和是低效率的,可以考虑使用分级softmax分类器,每个softmax只完成二分类问题。形成一个树结构。

      这个树甚至可以用类似哈夫曼树的思路构造,不一定要是满的二叉树,而是将常用词直接作为叶子结点放在深度较浅的位置。

    • 负采样

      计算softmax的加和是低效率的。负采样这样方法改变了学习目标,可以避免这个问题。

      对于每个训练样本,只选择(生成)少量(k 个)的负样本来进行更新。具体来说,给定一个中心词和其周围的上下文单词,负采样方法会随机选择一些未出现在上下文中的单词作为负样本,然后通过最小化正样本的概率和负样本的概率之间的交叉熵损失来训练模型。

      这时候,我们对于每个训练样本只需要做(k+1)次logistics回归,这里的logistics回归一般使用sigmoid函数。

      注意到,随机从词典里抽取单词作为负样本是不实际的,通常要按照词频加权,一个受公众认可的数据是抽取 \(i\) 的概率为 \(P(w_i)=\frac{f(w_i)^{3/4}}{\sum f(w_j)^{3/4}}\)

    • GloVe (global vectors for word representation)

      给定单词 i 和单词 j 的共现次数 \(X_{ij}\),以及它们对应的词嵌入向量 \(\mathbf{v}_i\)\(\mathbf{u}_j\),GloVe 算法要最小化的目标函数可以表示为:

      \[ \sum_{i=1}^V \sum_{j=1}^V f(X_{ij}) (\mathbf{v}_i^T \mathbf{u}_j + b_i + b_j - \log X_{ij})^2 \]

      其中:

      • \(V\) 是词汇表的大小;
      • \(X_{ij}\) 是单词 i 和单词 j 的共现次数;
      • \(\mathbf{v}_i\)\(\mathbf{u}_j\) 分别是单词 i 和单词 j 的词嵌入向量;
      • \(b_i\)\(b_j\) 是偏置项;
      • \(f(X_{ij})\) 是权重函数,用于对共现次数进行加权,通常取值为 \(f(X_{ij}) = \min\{1, (\frac{X_{ij}}{X_{\max}})^\alpha\}\),其中 \(X_{\max}\) 是共现次数的最大值,\(\alpha\) 是一个超参数。

      该目标函数的含义是,通过最小化每一对单词之间的点积和对数共现概率之间的误差,来学习使得共现次数相近的单词在向量空间中距离较近的词嵌入向量。同时,通过权重函数 \(f(X_{ij})\) 对共现次数进行加权,可以使得低频词和高频词对损失的贡献更加均衡。

      通过优化上述目标函数,可以得到最优的词嵌入向量,实现更好的语义表示和语义相似度计算。

  • 情感分类

    有了词嵌入,情感分类变得简单。

    如果没有词嵌入,完全从以做好处理的 语言-情感训练集进行训练,会难以收集数据。

    如果已经训练过大量文本,便可以知道这些词的情感倾向,统一起来可以输出情感。

    但是忽视词序或者not等单词会导致错误,因此应当使用RNN来获取这些单词之外的信息。

  • 偏见消除

    实际情况下,由于学习语料的局限性,人们写作的偏见会出现在人工智能中,如性别歧视等。

    通过另外训练一个分类器,判断一个词语是否有性别指向,对于确实有性别指向的词,让他们在这一维度上取平均值。

    维度即是性别的维度,这一维度可以通过 \(e_{he}-e_{she}\) 或是 \(e_{woman}-e_{man}\) 得到。这不一定是一维的。

序列模型和注意力机制

RNN也可以用来实现其他语言处理功能如翻译(seq2seq),如与图像识别系统对接,来生成句子来描述图片(image to seq)。

任务:选择最可能的句子。注意到生成句子时,每次选择最可能的单词不一定是最优的,要将整个结合起来考虑,需要一种合适的搜索方法来搜索最可能的句子。

  • 集束搜索

    设置一个集束宽 \(K\),每层都保留可能性最大的 \(K\) 个及其目前概率。为了防止乘太多次导致的误差问题,可以改为记录对数和。另外,也应当加上关于词语数的平均,否则模型会倾向于输出短的句子。为了防止句子过长,也可以适当做一些调整让模型在翻译的准确度和长度上进行取舍。

  • Bleu 得分

    1. 首先,对于待评估的机器翻译结果和参考翻译,将它们分别切分成 n-gram 序列。

    2. 然后,计算机器翻译结果中与参考翻译中的 n-gram 重合的数量,并将其称为匹配数(matched n-gram)。

    3. 接下来,计算机器翻译结果的 n-gram 总数,以及参考翻译的 n-gram 总数,并将它们分别称为 candidate n-gram 总数和 reference n-gram 总数。

    4. 最后,根据匹配数、candidate n-gram 总数和 reference n-gram 总数,计算 BLEU 得分。BLEU 得分的计算公式为:

      \[\text{BLEU} = \text{BP} \times \exp(\sum_{n=1}^N w_n \log p_n)\]

      其中:

      • \(\text{BP}\) 是一种短句惩罚项(Brevity Penalty),用于惩罚机器翻译结果长度较短的情况。因为短的句子得分容易太高,因此需要取合适的值让模型在翻译的准确度和长度上进行取舍。
      • \(p_n\) 是 n-gram 的精确匹配率(Precision),定义为匹配数除以 candidate n-gram 总数。
      • \(w_n\) 是用于调整不同 n-gram 的权重,通常设置为 \(\frac{1}{N}\)

    BLEU 得分的取值范围通常在 0 到 1 之间,越接近 1 表示机器翻译结果与参考翻译越相似,质量越高。

    BLEU 得分是衡量句子贴合确切翻译的方式之一。

  • 注意力机制

    因为模型是读完整句话在进行翻译的,在实际情况下,翻译句子的前几个词并不需要用到后面的词,翻译后面几个词也不需要用到前面的词。因此会导致模型在处理长句子时表现欠佳。因此引入注意力模型。

    注意力机制可用于语音识别。语言识别常用CTC损失函数,这允许模型连续输出相同的单元,处理时将相同连续单元合并,方便语音的识别。

    语音识别可以完成触发字检测,这只需要对音频训练样本的词语处放置1,其他设为0即可。

对比学习模型简介

对比学习:

百花齐放

  • instdisc

    提出代理任务个体判别,提出无监督学习

    卷积神经网络,将特征向量在空间内尽可能分开

    memory bank存储大量负样本(在图片库里随机抽取),对每个正样本取负样本去对比

  • invariant and spreading

    基本对比学习:同个图片经过编码器特征应该保持不变。

    全部做数据增强,正样本 n 个,每个正样本 2(n-1) 个负样本(效果不够好:没有较好的数据增广和负样本)

  • CPC

    一种通用结构

    提出了用预测去做对比学习:让预测自己的结果接近自己

  • contrastive multiview coding

    用不同角度(不同的滤波器)观察物体,对应的输出应当一样,多视角对比学习,正样本扩充

simclr 和 moco

  • moco

    提出字典。用队列取代memory bank,提出动量编码器

    无监督 - 超越有监督模型

    将图片通过编码器,让相似图片的编码类似而不相似图片的编码不类似

    • 动量对比学习

      如果不采用minibatch,则需要同时存储大量样本

      如果采用minibatch,每个图片通过的编码器差异太大,模型可能趋于选择编码器相似的图片而不是图片内容相似的图片

      动量编码器利用动量使编码器缓慢更新。解决了这一问题,同时也可以在普通GPU上运行

    无监督:可迁移性强,下游任务数据量少也能有很好的效果

  • simclr:全部都做数据增强,一共正样本 n 个,每个正样本 2(n-1) 个负样本

    图片经过编码器 f 后加了一个 projecter g (mlp层、全连接+relu)再去对比学习,提升了十个点。

    需要更多的数据增强(剪切、旋转、噪声等等)。其中剪切+裁剪的效果最好

    (分类)

  • moco v2

    加入mlp层,数据增强加强,迭代次数增长。

    相比于端到端,内存用得少,时间用得少。

    (除了分类,还可以完成生成任务)

  • simclr v2

    先训练teacher模型,生成伪标签训练student

    提高的点:

    • 模型更大(152层的残差网络)

    • mlp变成两层
    • 动量编码器

  • Swav

    图片的输出不去跟每个负样本对比,而是去跟聚类的中心比(上万个随机的负样本变成3000个有语义含义的聚类中心)

    换位预测

    使用了multi crop:观察正样本的多个较小的切片,同时关注全局特征和局部特征,而不是一个负样本对应一个正样本。

不用负样本

  • BYOL

    对比自己的特征。

    为什么之前要使用负样本:如果不使用负样本,输出只要尽可能贴合样本就行,不需要躲避负样本(负样本防止了坍塌)。使得模型有学习的方向

    对一个样本用两个结构相同的编码器,但是参数不同:一个随梯度更新,一个使用动量编码器。然后通过两个结构相同,参数不同的projecter(此时,simclr的目标是让两个projecter尽量相同),在其中一条路径再加入predicter,其结构与projecter一致,让其输出预测另一条路径的输出

    image-20240331203026886
    image-20240331203026886

    博客:不坍塌依靠batch norm(均值方差后归一化):产生了数据泄露,因为均值和方差参考了其他样本,比较了样本和平均图片(其他图片的总结量),形成了隐式的对比学习

  • simsiam

    不用动量编码器也照样能训练,而且学的更快。

    目标函数的确认。

vision transformer

  • moco v3

    moco v2+simsiam

    将残差网络换成ViT,现象:batch太大了会多次突然掉落准确率,然后慢慢回升

    查梯度:大幅度衰减时梯度刚好有一个波峰。把patch projection layer冻住

  • DINO

    自监督训练vision transformer

    自注意力图能抓住每个物体的轮廓。

    对teacher网络的输出中心化