Deep Learning Systems: 手动推导神经网络

297 阅读2分钟

从线性函数假设到非线性函数假设

线性函数存在的问题

前文中,我们通过一个线性假设函数把一个输入xRnx\in\mathbb R ^n映射到不同类别的输出yRky \in \mathbb R^k,也就是下面的线性假设函数:

hθ(x)=θTx,    θRn×kh_\theta(x)=\theta ^T x,\ \ \ \ \theta \in \mathbb R^{n \times k}

这个线性假设函数本质上是将输入线性划分为每个类别对应的区域,类似下图:

Screenshot from 2024-05-23 17-05-23.png

如果我们的数据不能被分成一系列线性的区域集合,该如何解决呢?

Screenshot from 2024-05-23 17-11-28.png

我们可以通过一个非线性的函数来分离不同的类别。

有一种想法是:提取数据更高维的特征,然后将高维特征应用于线性分类器

hθ(x)=θTϕ(x)θRd×k,ϕ:RnRdh_ \theta (x) = \theta ^T \phi(x) \\ \theta \in \mathbb R ^{d \times k}, \phi: \mathbb R ^n \rightarrow \mathbb R ^d

那么我们应该设计一个怎样的的特征提取函数ϕ\phi呢?

  1. 通过手动提取与问题相关的特征(这是以前机器学习中常用的方法)
  2. 让它自己从数据中学习如何提取特征(这是目前机器学习中用的方法)

首先,我们思考一个问题,如果我们的ϕ\phi函数还是使用线性函数行不行?

ϕ(x)=WTx \phi(x) = W^Tx

答案是不行的,其实理解起来很简单,因为一个线性函数再乘一个线性函数组合形式还是线性函数,那么提取特征和前面不提取特征的线性函数并没有本质的区别:

hθ(x)=θTϕ(x)=θTWTx=θ~xh_ \theta(x) = \theta ^T \phi(x)= \theta ^ T W^T x = \tilde \theta x

非线性特征

我们要怎样处理可以使这个特征起作用呢?实际上只需要在线性函数上加上任意一个非线性函数即可:

ϕ(x)=σ(WTx)\phi (x) = \sigma(W^Tx)

其中WRn×dW\in \mathbb R ^{n \times d},并且σ:RdRd\sigma : \mathbb R^d \rightarrow \mathbb R ^d是任意一个非线性函数。

如果让WW是一个(固定的)随机高斯样本的矩阵,让σ\sigmacosine函数,那么这个特征就是一个 “随机傅里叶特征”(在很多问题上这个特征能取得比较好的结果)

但是我们可能想训练WW参数以获得最小的损失,或者我们想将多种特征组合到一起,那我们应该怎么做呢?这就要用到神经网络了。

神经网络(或者说深度学习)

神经网络是指一种特定的假设函数,由多个参数可微的函数(又称为层layers)组合在一起形成输出。

神经网络这个术语来源于生物学,但是只要任何符合上述类型的函数都称为神经网络。

“深度网络”只是“神经网络”的同义词,而“深度学习”只是 意味着“使用神经网络假设函数的机器学习”(假设我们对深度的要求只有“非线性”的话)

但是现在的神经网络的确越来越复杂和庞大了,所以用“深度学习”这个术语也的确符合实际。

一个两层的神经网络

我们从最简单的神经网络形式开始,只是使用了前面提到的非线性特征,并且有两组可以学习权重参数。

Screenshot from 2024-05-23 19-35-03.png

hθ=W2Tσ(W1Tx)θ={W1Rn×d,W2Rd×k}h_\theta=W_2^T \sigma(W_1^T x) \\ \theta = \{ W_1 \in \mathbb R^{n \times d}, W_2 \in \mathbb R^{d \times k} \}

其中σ:RR\sigma :\mathbb R \rightarrow \mathbb R是对向量的每一个元素应用的非线性函数(例如:sigmoid, ReLU)

写成批量矩阵形式如下:

hθ(X)=σ(XW1)W2h_\theta(X)= \sigma (XW_1)W_2

全连接深度神经网络

一个更通用的LL层的神经网络,又叫做多层感知机、前馈网络、全连接网络。 Screenshot from 2024-05-23 19-51-07.png

用批量矩阵写法如下:

Zi+1=σi(ZiWi),i=1,,LZ1=X,hθ(X)=ZL+1[ZiRm×ni,WiRni×ni+1]Z_{i+1} = \sigma _i(Z_i W_i), i = 1, \ldots ,L \\ Z_1 = X,\\ h_{\theta}(X) = Z_{L+1} \\ [Z_i \in \mathbb R^{m \times n_i}, W_i \in \mathbb R^{n_i \times n_{i+1}}]

非线性函数σi:RR\sigma _i : \mathbb R \rightarrow \mathbb R应用于每个向量的元素和参数θ={W1,,WL}\theta = \{W_1, \ldots ,W_L \} (也可以给假设函数加上偏置项bias)

反向传播算法

回想一下上一篇文章中提到的机器学习算法三要素,神经网络只说明了三要素中的其中之一,还需要说明:

  • 损失函数:还是 cross entropy loss
  • 优化器:也还是SGD

也就是说,我们要解决的优化问题还是:

minimizeθ1mi=1mce(hθ(x(i)),y(i))\underset{\theta}{minimize} \frac{1}{m} \sum _{i=1}^m \ell_{ce}(h_{\theta}(x^{(i)}), y^{(i)})

还是可以使用SGD优化算法来求解,只不过这里的hθ(x)h_\theta(x)现在是神经网络了

需要对每一个θ\theta计算梯度θce(hθ(x(i)),y(i))\nabla_\theta \ell_{ce}(h_\theta(x^{(i)}),y^{(i)})

两层神经网络的梯度计算

我们用批量矩阵的形式来写对两层神经网络求梯度的式子:

{W1,W2}ce(σ(XW1)W2,y)\nabla_{\{ W_1,W_2\}} \ell_{ce}(\sigma(XW_1)W_2,y)

我们对W2W_2求偏导,求出来的形式类似softmax regression 的案例:

ce(σ(XW1)W2,y)W2=ce(σ(XW1)W2,y))σ(XW1)W2σ(XW1)W2W2=(SIy)σ(XW1),    [S=softmax(σ(XW1)W2)]\begin{align} \frac{\partial \ell_{ce}(\sigma (XW_1)W_2,y)}{\partial W_2} & = \frac{\partial\ell_{ce}(\sigma(XW_1)W_2,y))}{\partial \sigma(XW_1)W_2} \cdot \frac{\partial\sigma(XW_1)W_2}{\partial W_2} \\ & = (S - I_y) \cdot \sigma(XW_1), \ \ \ \ [S=softmax(\sigma(XW_1)W_2)] \end{align}

其中(SIy)(S-I_y)的维度为(m×k)(m \times k),而σ(XW1)\sigma(XW_1)的维度为(m×d)(m \times d) 为了使矩阵的维度匹配,最终梯度写成如下形式:

W2ce(σ(XW1)W2,y)=σ(XW1)T(SIy)\nabla_{W_2} \ell_{ce}(\sigma(XW_1)W_2,y)=\sigma(XW_1)^T(S-I_y)

下面我们对W1W_1来求偏导:

ce(σ(XW1)W2,y)W1=ce(σ(XW1)W2,y))σ(XW1)W2σ(XW1)W2σ(XW1)σ(XW1)XW1XW1W1=(SIy)W2σ(XW1)X\begin{align} \frac{\partial \ell_{ce}(\sigma (XW_1)W_2,y)}{\partial W_1} & = \frac{\partial\ell_{ce}(\sigma(XW_1)W_2,y))}{\partial \sigma(XW_1)W_2} \cdot \frac{\partial\sigma (XW_1)W_2}{\partial \sigma(XW_1)} \cdot \frac{\partial \sigma(XW_1)}{\partial XW_1} \cdot \frac{\partial XW_1}{\partial W_1} \\ & = (S-I_y) \cdot W_2 \cdot \sigma ^\prime(XW_1) \cdot X \end{align}

同样为了使矩阵维度相匹配,我们需要调换矩阵的顺序,其中(SIy)(S-I_y)的维度为(m×k)(m \times k)W2W_2的维度为(d×k)(d \times k)σ(XW1)\sigma ^\prime(XW_1)的维度为(m×d)(m \times d)XX的维度为(m×n)(m \times n),最终形式为:

W1ce(σ(XW1)W2,y)=XT((SIy)W2T  σ (XW1))\nabla_{W_1}\ell {ce}(\sigma (XW_1)W_2,y) = X^T((S-I_y)W_2^T \ \circ \ \sigma^\prime \ (XW_1) )

\circ 符号代表矩阵之间各元素相乘

更泛化的反向传播算法

有没有一种更加泛化的方法求参数的偏导数,我们以全连接网络为例:

Zi+1=σi(ZiWi),     i=1,,LZ_{i+1}= \sigma_i(Z_iW_i), \ \ \ \ \ i=1, \ldots,L

然后(我们用比较简洁的符号表示):

Screenshot from 2024-05-23 22-25-30.png

我们通过反向迭代计算Gi{G_i}

Gi=Gi+1Zi+1Zi=Gi+1σi(ZiWi)ZiWiZiWiZi=Gi+1σ(ZiWi)WiG_i=G_{i+1} \cdot \frac{\partial Z_{i+1}}{\partial Z_i} = G_{i+1} \cdot \frac{\partial \sigma_{i}(Z_iW_i)}{\partial Z_i W_i} \cdot \frac{\partial Z_iW_i}{\partial Z_i} = G_{i+1} \cdot \sigma^\prime(Z_iW_i) \cdot W_i

ZiZ_i表示正向计算的结果。

计算真正的梯度

要将这些式子转换为“真正的梯度”,我们需要考虑矩阵的维度大小

Gi=(ZL+1,y)Zi=Zi(ZL+1,y)Rm×niG_i = \frac{\partial \ell (Z_{L+1,y})}{\partial Z_i} = \nabla_{Z_{i}} \ell (Z_{L+1}, y) \in \mathbb R ^ {m \times n_i}

所以正确的矩阵操作应该是

Gi=Gi+1σ(ZiWi)Wi=(Gi+1  σ(ZiWi))WiTG_i=G_{i+1} \cdot \sigma ^\prime(Z_{i}W_i) \cdot W_i = (G_{i+1} \ \circ \ \sigma ^\prime(Z_iW_i))W_i^T

实际梯度的公式类似Wi(ZL+1,y)Rni×ni+1\nabla_{W_i}\ell(Z_{L+1}, y) \in \mathbb R ^{n_i \times n_{i+1}}

(ZL+1,y)Wi=Gi+1σi(ZiWi)ZiWiZiWiWi=Gi+1σ(ZiWi)ZiWi(ZL+1,y)=ZiT(Gi+1σ(ZiWi))\frac{\partial \ell(Z_{L+1}, y)}{\partial W_i} = G_{i+1} \cdot \frac{\partial \sigma _i(Z_iW_i)}{\partial Z_i W_i} \cdot \frac{\partial Z_iW_i}{\partial W_i} = G_{i+1} \cdot \sigma ^ \prime (Z_i W_i) \cdot Z_i \\ \Longrightarrow \nabla_{W_i} \ell(Z_{L+1}, y) = Z_i^T(G_{i+1} \circ \sigma ^\prime(Z_iW_i))

反向传播算法:正向和反向传递

把上述正向计算和反向计算的式子放在一起,我们可以有效地计算我们需要的所有梯度,神经网络遵循以下流程: Screenshot from 2024-05-23 22-56-48.png

我们可以通过下面的式子计算所有我们需要的梯度:

Wi(Zk+1,y)=ZiT(Gi+1σi(ZiWi))\nabla_{W_i} \ell(Z_{k+1},y) = Z_i^T(G_{i+1} \circ \sigma _i ^\prime(Z_iW_i))

"反向传播"就是使用链式法则+中间保存的结果

注意这个操作

Screenshot from 2024-05-23 23-01-39.png