ML Note 1.4 - Neural Networks

MP 模型

人工神经元是神经网络中的逻辑基础。一个神经元可以有多个输入 x 1 , x 2 , … , x n x_1, x_2, \dots, x_n x1,x2,,xn 但只能有一个输出 h ( x ) h(x) h(x) 。神经元状态定义为输入信号的线性组合
z ≡ ∑ i = 0 n w i x i z \equiv \sum\limits_{i = 0}^n w_ix_i zi=0nwixi

因为截距项 x 0 x_0 x0 恒为 1 1 1 ,有时也将 w 0 w_0 w0 称为 bias unit 。得到了神经元状态后,还需要经过 activation function 的映射才能得到输出。一般情况下,激活函数选用 sigmoid 函数
h ( x ) = g ( z ) h(x) = g(z) h(x)=g(z)

Perceptron Learning Algorithm

对于单个 MP 模型,如果选择激活函数为阶跃函数,即可得到感知器模型。
g ( z ) = s i g n ( z ) g(z) = sign(z) g(z)=sign(z)

这一模型可以将样本逐个加入模型,根据输出结果和标签的差别调整模型内部的权重大小,和人类的学习过程较为类似。首先定义规范化样本
x i ′ = y ( i ) x ( i ) x_i' = y^{(i)}x^{(i)} xi=y(i)x(i)

其中 x x x 为增广样本向量,标签 y ∈ { 1 , − 1 } y \in \{1, -1\} y{1,1} 。这一操作相当于对标签为负的样本做一次中心对称。

规范化样本

可以看出,左侧原样本集是线性可分的。右侧的规范化样本虽然变得线性不可分,但是所有样本都到了分界线的一侧。也就是说,为了使 h ( x ) = s i g n ( w T x ) = y h(x) = sign(w^Tx) = y h(x)=sign(wTx)=y 只需要 w T x ′ > 0 w^Tx' > 0 wTx>0 。此时参数 w w w 的变化范围被样本集相对原点张角最大的数据所限制,模型训练时很可能使样本落在分界线上。为了避免这种情况,引入 b > 0 b > 0 b>0 并规定
w T x ′ ≥ b w^Tx' \ge b wTxb

训练过程中,超平面需要尽可能多的将被错分的样本分对,而那些已经分对的样本则不再参与迭代。因此定义错分样本集合
η = { i ∣ w T x i ′ < b } \eta = \{i|w^Tx'_i < b\} η={iwTxi<b}

和准则函数
J ( w ) = ∑ i ∈ η w T x i ′ J(w) = \sum\limits_{i \in \eta} w^Tx'_i J(w)=iηwTxi

对于一组线性可分的样本,必然存在一个 w w w 使所有样本被正确分类。这时有 η = ϕ \eta = \phi η=ϕ J = 0 J = 0 J=0 ,训练终止。如果样本集线性不可分,模型有可能不收敛。迭代过程中可以用梯度下降求解 max ⁡ w J ( w ) \max\limits_w J(w) wmaxJ(w) 其中
∇ w J = ∑ i ∈ η x i ′ \nabla_wJ = \sum\limits_{i \in \eta} x'_i wJ=iηxi

Artificial Neural Network

单个感知器可以实现二分类的功能,也就是判断样本是否属于某个类。如果对于所有可能的类别都建立一个感知器,即可实现多分类的功能。但是这样的多输出感知器还有一个问题,就是不能处理线性不可分的数据集。对于这个问题,其中的一种解决办法是增加感知器的层数。有理论证明了下述结论

三层感知器可以实现任意的逻辑运算。当激活函数为 sigmoid 时,可以逼近任何多元函数。

人工神经网络就是利用这样的思想实现的。一个 ANN 由以下几部分组成

名称数量符号功能
input layer 1 1 1 x x x a 0 a^0 a0存储输入数据
hidden layers L L L a i a^i ai计算输出与反向传播误差
output layer 1 1 1 h ( x ) h(x) h(x)将输出向量归一化

一般来说,神经网络会逐个检查输入样本,并对每个样本执行下述算法
for  l ∈ [ 1 , L ]   { z l = forward propagation of  a l − 1 a l = g ( z l ) } h ( x ) = a L / ∣ ∣ a L ∣ ∣ initialize  δ L for  l ∈ [ 1 , L ] .reversed  { δ l − 1 = back propagation of  a l  and  δ l update  a l  according to  δ l } \begin{aligned} & \text{for }l \in [1, L]\ \{\\ & \qquad z^l = \text{forward propagation of }a^{l - 1}\\ & \qquad a^l = g(z^l)\\ & \}\\ & h(x) = a^L / ||a^L||\\ & \text{initialize }\delta^L\\ & \text{for }l \in [1, L]\text{.reversed }\{\\ & \qquad \delta_{l - 1} = \text{back propagation of }a^l\text{ and }\delta_l\\ & \qquad \text{update }a^l\text{ according to }\delta_l\\ & \}\\ \end{aligned} for l[1,L] {zl=forward propagation of al1al=g(zl)}h(x)=aL/aLinitialize δLfor l[1,L].reversed {δl1=back propagation of al and δlupdate al according to δl}

其中反向传播算法是整个学习过程的核心。其基本思想是:将输出层的误差反向传播至中间各层,每层对应的参数梯度均可由当前层的误差计算出来。误差的形式化定义如下
δ j = ∂ J ∂ z j ∈ R s j + 1 \delta_j = \frac{\partial J}{\partial z^j} \in \mathbb{R}^{s_j+1} δj=zjJRsj+1

下文中将会以层为单位进行推导。为了方便起见,将前一层的激活函数的导数记为 f f f 。在没有特别说明的情况下,激活函数取 sigmoid 。因此有
f ( a ) = a ( 1 − a ) f(a) = a(1 - a) f(a)=a(1a)

可以将误差项化为1
δ j = ∂ J ∂ a j ⊙ f ( a j ) \delta_j = \frac{\partial J}{\partial a^j} \odot f(a^j) δj=ajJf(aj)

对于第 l l l 层来说,只需要计算 ∂ J / ∂ a l − 1 \partial J / \partial a^{l - 1} J/al1 即可完成反向传播的计算。下面将会按不同层的种类来讨论前向传播和反向传播的具体算法,设当前层为 j j j

输出层

输出层的前向传播公式已经包含在前面的伪代码中了,此处主要推导其误差项的公式。本文使用的代价函数是带 l 2 l_2 l2 正则化的交叉熵函数
J ( w ) = − [ ∑ k = 1 K y k log ⁡ h k ( x ) + ( 1 − y k ) log ⁡ ( 1 − h k ( x ) ) ] + λ 2 ∑ θ ∈ w θ 2 J(w) = -\left[\sum\limits_{k=1}^Ky_k\log h_k\left(x\right) + (1-y_k)\log\left(1-h_k(x)\right) \right] + \frac{\lambda}{2} \sum_{\theta \in w} \theta^2 J(w)=[k=1Kykloghk(x)+(1yk)log(1hk(x))]+2λθwθ2

其中 w w w 表示全部在模型中出现的参数。对于输出层来说,我们有
h ( x ) = g ( z L ) h(x) = g\left(z^L\right) h(x)=g(zL)

首先对代价函数进行改写
J ( Θ ) ≡ − [ ∑ k = 1 K log ⁡ ( 1 − g ( z k L ) ) + y k log ⁡ g ( z k L ) log ⁡ ( 1 − g ( z k L ) ) ] = − [ ∑ k = 1 K log ⁡ ( 1 − g ( z k L ) ) + y k z k L ] = ∑ k = 1 K − y k z L − log ⁡ ( 1 − g ( z k L ) ) \begin{array}{rcl} J(\Theta) &\equiv& -\left[\sum\limits_{k=1}^K \log\left(1-g\left(z_k^L\right)\right) + y_k\frac{\log g\left(z_k^L\right)}{\log\left(1-g\left(z_k^L\right)\right)} \right]\\ &=& -\left[\sum\limits_{k=1}^K \log\left(1-g\left(z_k^L\right)\right) + y_kz_k^L \right]\\ &=& \sum\limits_{k=1}^K -y_kz^L - \log\left(1-g\left(z_k^L\right)\right) \end{array} J(Θ)==[k=1Klog(1g(zkL))+yklog(1g(zkL))logg(zkL)][k=1Klog(1g(zkL))+ykzkL]k=1KykzLlog(1g(zkL))

直接对上式求导可得
δ L = − y + g ( z L ) = h ( x ) − y \delta_L = -y + g(z^L) = h(x) - y δL=y+g(zL)=h(x)y

Fully Connected Layers

全连接层将上一层的输入按照一定的权重输出,其参数为二维矩阵 Θ \Theta Θ 。其前向传播的算法如下
add  a 0 j − 1 = 1 z j = Θ j − 1 a j − 1 a j = g ( z j ) \begin{aligned} & \text{add }a^{j - 1}_0 = 1\\ & z^j = \Theta^{j - 1}a^{j - 1}\\ & a^j = g\left(z^j\right)\\ \end{aligned} add a0j1=1zj=Θj1aj1aj=g(zj)

a x a^x ax 的长度为 s x s_x sx 则参数 Θ \Theta Θ 的大小为 s j × ( s j − 1 + 1 ) s_j \times (s_{j - 1} + 1) sj×(sj1+1) ,其中 Θ 23 j \Theta^j_{23} Θ23j 表示第 j j j 层第 3 3 3 个神经元对第 j + 1 j + 1 j+1 层第 2 2 2 个神经元的贡献。有了前向传播的公式,可以很方便的推出反向传播算法
∂ J ∂ a j − 1 = ( ∂ z j ∂ a j − 1 ) T ∂ J ∂ z j = ( Θ j − 1 ) T δ j \frac{\partial J}{\partial a^{j - 1}} = \left(\frac{\partial z^j}{\partial a^{j - 1}}\right)^T \frac{\partial J}{\partial z^j} = \left(\Theta^{j - 1}\right)^T \delta_j aj1J=(aj1zj)TzjJ=(Θj1)Tδj

因此
δ j − 1 = ( Θ j − 1 ) T δ j ⊙ f ( a j − 1 ) \delta_{j - 1} = (\Theta^{j - 1})^T\delta_j \odot f(a^{j - 1}) δj1=(Θj1)Tδjf(aj1)

由误差项计算梯度时可以使用下面的公式
∂ J ∂ Θ j = δ j ( a j − 1 ) T + λ Θ j \frac{\partial J}{\partial \Theta^j} = \delta_j \left(a^{j - 1}\right)^T + \lambda\Theta^j ΘjJ=δj(aj1)T+λΘj

需要注意这里的 a i a^i ai 是包含偏移项的,但 δ i + 1 \delta_{i + 1} δi+1 是不含偏移项误差的,否则向量维数不匹配。

Convolutional Layers

卷积层的输入和输出都是图片,用二维矩阵来表示。卷积层中每个神经元负责提取一个 local receptive field 的区域特征2
local receptive field

举例来说,上图中的神经元负责一个 5 × 5 5 \times 5 5×5 的区域。可以看出,在上面这个 28 × 28 28 \times 28 28×28 的图像中最多可以找到 24 × 24 24 \times 24 24×24 各不同的窗口,也就对应着 24 × 24 24 \times 24 24×24 个神经元。设各个矩阵的大小为

  • 窗口 s × s s \times s s×s
  • 输入图像 s j − 1 × s j − 1 s_{j - 1} \times s_{j - 1} sj1×sj1
  • 输出图像 s j × s j s_j \times s_j sj×sj

可以看出他们有如下关系
s j = s j − 1 − s + 1 s_j = s_{j - 1} - s + 1 sj=sj1s+1

Kernel

卷积层的参数包括权重 w w w 和偏移 b b b 两部分。一般来说 w w w 是一个二维矩阵,大小为 s × s s \times s s×s 。定义神经元状态
z j = b j + a j − 1 ⊗ w j z^j = b^j + a^{j - 1} \otimes w^j zj=bj+aj1wj

可以看出,不同位置的神经元对应的参数却是相同的,这一性质被称为 shared weights and bias 。正是因为这个性质的存在,卷积层的参数个数远小于全连接层,所以可以更有效的防止过拟合。

Padding

从上面的讨论中可以看到两件事

  1. 经过一次卷积就会使图像变小一点
  2. 输入图像中不同的像素被覆盖的次数不同

为了解决这两个问题,卷积层引入了填充的概念。设填充数为 p p p 则意味着输入图像在卷积前,会被 p p p 0 0 0 所包裹。例如
[ 1 2 3 4 ] ⟶ p = 2 [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] \left[\begin{array}{cc} 1 & 2\\ 3 & 4 \end{array}\right] \mathop\longrightarrow\limits^{p = 2} \left[\begin{array}{cccccc} 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 2 & 0 & 0\\ 0 & 0 & 3 & 4 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ \end{array}\right] [1324]p=2000000000000001300002400000000000000

反向传播

δ j ′ \delta'_j δj δ j \delta_j δj 经过 s − 1 s - 1 s1 层填充后得到的矩阵,可以证明3
δ j − 1 = δ j ′ ⊗ rot180 ( w j ) \delta_{j - 1} = \delta'_j \otimes \text{rot180}(w^j) δj1=δjrot180(wj)

由当前层的误差矩阵可以计算出核矩阵的梯度
∂ J ∂ w j = a j − 1 ⊗ δ j + λ w j \frac{\partial J}{\partial w^j} = a^{j - 1} \otimes \delta_j + \lambda w^j wjJ=aj1δj+λwj

如果当前层进行了填充,那么还需要对 a j − 1 a^{j - 1} aj1 进行裁剪。对偏移项有
∂ J ∂ b j = ∣ ∣ δ j ∣ ∣ 1 + λ b j \frac{\partial J}{\partial b^j} = ||\delta_j||_1 + \lambda b^j bjJ=δj1+λbj

Stride Length

上文中,我们对于每个可能的窗口都用一个神经元加以记录。实际操作中也可以每隔 k − 1 k - 1 k1 个窗口设置一个神经元。这里 k k k 也可以理解为窗口每次滑动的距离。前向传播中步长可以缩小输出图像的大小,因此在进行反向传播前,需要先把被跳过的神经元加入矩阵。例如矩阵
A = [ 1 2 3 4 ] A = \left[\begin{array}{cc} 1 & 2\\ 3 & 4 \end{array}\right] A=[1324]

使经过步长为 2 2 2 的卷积得到的。那么恢复后就应该变成
A = [ 1 0 2 0 0 0 3 0 4 ] A = \left[\begin{array}{ccc} 1 & 0 & 2\\ 0 & 0 & 0\\ 3 & 0 & 4 \end{array}\right] A=103000204

多通道

卷积层的输入和输出可以是一个多通道的图片,这时就需要用三维矩阵来表示。设 a x a^x ax 所表示的矩阵有 c x c_x cx 个通道,那么 w w w 将会是一个四维矩阵大小为
s × s × c j − 1 × c j s \times s \times c_{j - 1} \times c_j s×s×cj1×cj

在进行前向传播时 c j c_j cj 个三维卷积核会分别与 a j − 1 a^{j - 1} aj1 进行卷积运算。每个卷积核可以求出一个二维图片,最终组成一个 c j c_j cj 个通道的输出。对于每个三维卷积核,其 c j − 1 c_{j - 1} cj1 层会分别与输入的 c j − 1 c_{j - 1} cj1 层卷积,并将得到的图像求和。

对于反向传播,可以先假设 c j − 1 = 1 c_{j - 1} = 1 cj1=1 进行说明。此时 δ j \delta_j δj 每一层的误差都来自于这一层。因为 δ j \delta_j δj 的层与层之间相互独立,所以只需要将其反向传播的误差相加即可得到 δ j − 1 \delta_{j - 1} δj1

计算 w j w^j wj 的梯度时,总可以找到一个输入中的通道和一个输出中的通道与 w j w^j wj 中的任意一个二维矩阵相对应。而 b j b^j bj 与输出图像的通道相对应。因此二者原公式都不需要改变。

Pooling Layer

为了缩小卷积层输出的尺寸,池化层将二维图像分割成一系列不相交的区域,并选取一个代表元素来替换这个区域。需要注意的是,池化层的输出并不经过激活函数。常用的池化层主要有两种,一种选择区域内的最大值,另一种选择平均值。反向传播时,最大池化层可以将误差全部传递给最大值出现的位置,而平均值池化层可以将误差平均分配给区域内的全部神经元。因为池化层本身并没有参数,所以不需要计算梯度。

随机初始化

上述算法可以应用于梯度下降以训练模型。需要注意的是,各个权重的初始值如果相同,则所有神经元都是对称的,无法区分。因此实际上一般在 0 0 0 的一个小临域内随机选取初始值
Θ i j l ∈ ( − ϵ , ϵ ) \Theta_{ij}^l \in (-\epsilon,\epsilon) Θijl(ϵ,ϵ)

由于初始值会对模型的收敛性造成影响,因此在模型不收敛时可以考虑更换初始值。


  1. 符号 ⊙ \odot 表示矩阵的 Hadamard 乘积,也就是 Matlab 里的点乘。 ↩︎

  2. 图片来源:Neural Networks and Deep Learning ↩︎

  3. 【深度学习系列】卷积神经网络详解(二)——自己手写一个卷积神经网络 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LutingWang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值