神经网络表述

模型表示

大脑中每一个神经元可以认为是一个处理单元/神经核,它含有许多输入/树突,并且有一个输出/轴突。神经网络是大量神经元相互链接并通过电脉冲来交流的一个网络。

神经网络模型建立在很多神经元之上,神经元(也叫激活单元(activation unit)采纳一些特征作为输出,根据本身的模型提供一个输出。参数被称为权重(weight)。

一个神经网络结构如图所示:

上面是一个 3 层的神经网络,第一次为输入层(Input Layer),最后一层为输出层(Output Layer),中间一层为隐藏层(Hidden Layers),我们为每一层都增加一个偏差单位(bias unit)。每个神经元都对它的输入和权重进行点积,然后加上偏差,最后使用非线性函数(或称为激活函数)。

下面引入一些标记法来帮助描述模型:
ai(j)a_i^{(j)} 代表第jj 层的第 ii 个激活单元。θ(j)\theta^{(j)}代表从第 jj 层映射到第j+1j+1 层时的权重的矩阵,例如θ(1)\theta^{(1)}代表从第一层映射到第二层的权重的矩阵。其尺寸为:以第 j+1j+1层的激活单元数量为行数,以第 jj 层的激活单元数加一为列数的矩阵。例如:上图所示的神经网络中θ(1)\theta^{(1)}的尺寸为 3*4。

对于上图所示的模型,激活单元和输出分别表达为:

a1(2)=g(Θ10(1)x0+Θ11(1)x1+Θ12(1)x2+Θ13(1)x3)a2(2)=g(Θ20(1)x0+Θ21(1)x1+Θ22(1)x2+Θ23(1)x3)a3(2)=g(Θ30(1)x0+Θ31(1)x1+Θ32(1)x2+Θ33(1)x3)hΘ(x)=g(Θ10(2)a0(2)+Θ11(2)a1(2)+Θ12(2)a2(2)+Θ13(2)a3(2))\begin{array}{l}{a_{1}^{(2)}=g\left(\Theta_{10}^{(1)} x_{0}+\Theta_{11}^{(1)} x_{1}+\Theta_{12}^{(1)} x_{2}+\Theta_{13}^{(1)} x_{3}\right)} \\ {a_{2}^{(2)}=g\left(\Theta_{20}^{(1)} x_{0}+\Theta_{21}^{(1)} x_{1}+\Theta_{22}^{(1)} x_{2}+\Theta_{23}^{(1)} x_{3}\right)} \\ {a_{3}^{(2)}=g\left(\Theta_{30}^{(1)} x_{0}+\Theta_{31}^{(1)} x_{1}+\Theta_{32}^{(1)} x_{2}+\Theta_{33}^{(1)} x_{3}\right)} \\ {h_{\Theta}(x)=g\left(\Theta_{10}^{(2)} a_{0}^{(2)}+\Theta_{11}^{(2)} a_{1}^{(2)}+\Theta_{12}^{(2)} a_{2}^{(2)}+\Theta_{13}^{(2)} a_{3}^{(2)}\right)}\end{array}

由上面可以看出每一个 α\alpha 都是由上一次所有的 xx 和对应的权重 ww 决定的。把这样从左到右的算法称为前向传播算法(FORWARD PROPAGATION) 。

xx, θ\theta, aa 分别用矩阵表示:

X=x0x1x2x3,θ=θ10θ13θ30θ33,a=a1a2a3X = \begin{matrix} x_{0}\\ x_{1}\\ x_{2}\\ x_{3} \end{matrix}, \theta = \begin{matrix} \theta_{10} &\cdots &\theta_{13} \\ \cdots & \cdots &\cdots \\ \cdots & \cdots &\cdots \\ \theta_{30} & \cdots & \theta_{33} \end{matrix}, a = \begin{matrix} a_1\\ a_2\\ a_3 \end{matrix}

可以得到θX=a\theta \cdot X=a

前线传播算法利用向量化的方法计算更方便。以上面的神经网络为例,计算第二层的值:

x=[x0x1x2x3]x = \begin{bmatrix} x_0\\ x_1\\ x_2\\ x_3 \end{bmatrix} z(2)=[z1(2)z2(2)z2(2)]z^{(2)} = \begin{bmatrix} z_{1}^{(2)}\\ z_{2}^{(2)}\\ z_{2}^{(2)} \end{bmatrix}

z(2)=Θ(2)xz^{(2)} = \Theta^{(2)}x

a(2)=g(z(2))a^{(2)} = g(z^{(2)})

g([θ10(1)θ11(1)θ12(1)θ13(1)θ20(1)θ21(1)θ22(1)θ23(1)θ30(1)θ31(1)θ32(1)θ33(1)]×[a0(2)a1(2)a2(2)a3(2)])=g([θ10(1)x0+θ11(1)x1+θ12(1)x2+θ13(1)x3θ20(1)x0+θ21(1)x1+θ22(1)x2+θ23(1)x3θ30(1)x0+θ31(1)x1+θ32(1)x2+θ33(1)x3])=[a1(2)a2(2)a3(2)]g\left ( \begin{bmatrix} \theta_{10}^{(1)} & \theta_{11}^{(1)} &\theta_{12}^{(1)} & \theta_{13}^{(1)}\\ \theta_{20}^{(1)} & \theta_{21}^{(1)} &\theta_{22}^{(1)} & \theta_{23}^{(1)}\\ \theta_{30}^{(1)} & \theta_{31}^{(1)} &\theta_{32}^{(1)} & \theta_{33}^{(1)} \end{bmatrix} \times\begin{bmatrix} a_0^{(2)}\\ a_1^{(2)}\\ a_2^{(2)}\\ a_3^{(2)} \end{bmatrix} \right ) = g\left ( \begin{bmatrix} \theta_{10}^{(1)}x_0 + \theta_{11}^{(1)}x_1+\theta_{12}^{(1)}x_2+\theta_{13}^{(1)}x_3\\ \theta_{20}^{(1)}x_0 + \theta_{21}^{(1)}x_1+\theta_{22}^{(1)}x_2+\theta_{23}^{(1)}x_3\\ \theta_{30}^{(1)}x_0 + \theta_{31}^{(1)}x_1+\theta_{32}^{(1)}x_2+\theta_{33}^{(1)}x_3 \end{bmatrix} \right ) = \begin{bmatrix} a_1^{(2)}\\ a_2^{(2)}\\ a_3^{(2)} \end{bmatrix}

我们令 z(2)=θ(1)xz^{\left( 2 \right)}=\theta ^{\left( 1 \right)}x,则 a(2)=g(z(2))a^{(2)}=g(z^{(2)}) ,计算后添加 a0(2)=1a_0^{\left( 2 \right)}=1。 计算输出的值为:

g([θ10(2)θ11(2)θ12(2)θ13(2)]×[a0(2)a1(2)a2(2)a3(2)])=g(θ10(2)a0(2)+θ11(2)a1(2)+θ12(2)a2(2)+θ13(2)a3(2))=hθ(x)g\left(\left[\begin{array}{ccc}{\theta_{10}^{(2)}} & {\theta_{11}^{(2)}} & {\theta_{12}^{(2)}} & {\theta_{13}^{(2)}}\end{array}\right] \times\left[\begin{array}{c}{a_{0}^{(2)}} \\ {a_{1}^{(2)}} \\ {a_{2}^{(2)}} \\ {a_{3}^{(2)}}\end{array}\right]\right)=g\left(\theta_{10}^{(2)} a_{0}^{(2)}+\theta_{11}^{(2)} a_{1}^{(2)}+\theta_{12}^{(2)} a_{2}^{(2)}+\theta_{13}^{(2)} a_{3}^{(2)}\right)=h_{\theta}(x)

我们令z(3)=θ(3)a(2)z^{\left( 3 \right)}=\theta ^{\left( 3 \right)}a^{(2)},则 hθ(x)=a3=g(z(3))h_{\theta }(x) = a^3=g(z^{(3)})

若对整个训练集进行计算,则z(2)=Θ(1)×XTz^{(2)} = \Theta ^{(1)}\times X^T a(2)=g(z(2))a^{(2)} = g(z^{(2)})

为了更好了解 Neuron Networks 的工作原理,我们把左半部分遮住:

可以看出右半部分是以 a0a_0,a1a_1, a2a_2,a3a_3,按照 Logistic Regression 的方式输出 hθ(x)h_\theta(x)

hθ(x)=g(Θ10(2)a_0(2)+Θ11(2)a1(2)+Θ12(2)a2(2)+Θ13(2)a3(2))h_{\theta}(x) = g(\Theta_{10}^{(2)}a\_0^{(2)}+\Theta_{11}^{(2)}a_1^{(2)}+\Theta_{12}^{(2)}a_2^{(2)}+\Theta_{13}^{(2)}a_3^{(2)})

a0,a1,a2,a3a_0, a_1, a_2, a_3看成更为高级的特征值,也就是x0,x1,x2,x3x_0, x_1, x_2, x_3的进化体,并且它们是由 xxθ\theta决定的,因为是梯度下降的,所以aa是变化的,并且变得越来越厉害,所以这些更高级的特征值远比仅仅将 xx次方厉害,也能更好的预测新数据。这是神经网络相比于逻辑回归和线性回归的优势。

特征和直观理解

从本质上讲,神经网络能够通过学习得出其自身的一系列特征,在普通的逻辑回归中,我们被限制为使用数据的原始特征x1,x2,...,xnx_1,x_2,...,x_n,虽然可以使用二项式特征,但是仍然受限于原始特征。在神经网络中,原始特征数据只是输入层,第三层做出的预测是利用第二层的特征,而非原始数据特征。可以认为第二层是神经网络通过学习后自己得出的一系列用于预测输出变量的新特征。

神经网络中,单层神经元(无中间层)的计算可用来表示逻辑运算,比如与(AND),或(OR)。

用神经网络表示AND函数:

其中 θ0=30,θ1=20,θ2=20\theta_0 = -30, \theta_1 = 20, \theta_2 = 20,输出函数 hθ(x)h_{\theta}(x) 为:hΘ(x)=g(30+20x1+20x2)h_\Theta(x) = g(-30+20x_1+20x_2)

g(x)g(x)的图像是

所以我们有:hΘ(x)x1ANDx2h_\Theta(x)\approx x_1ANDx_2

用神经网络表示OR函数:

二元逻辑运算符当输入特征为布尔值时,一个单元的激活层可以作为二元逻辑运算符,为了表示不同的运算符,需要选择不同的权重即可。

下图的神经元(三个权重分别为-30,20,20)可以被视为作用同于逻辑与(AND):

下图的神经元(三个权重分别为-10,20,20)可以被视为作用等同于逻辑或(OR):

下图的神经元(两个权重分别为 10,-20)可以被视为作用等同于逻辑非(NOT):

我们可以利用神经元来组合成更为复杂的神经网络以实现更复杂的运算。例如我们要实现XNOR 功能(输入的两个值必须一样,均为1或均为0),即 XNOR=(x1ANDx2)OR((NOTx1)AND(NOTx2))\text{XNOR}=( \text{x}_1\, \text{AND}\, \text{x}_2 )\, \text{OR} \left( \left( \text{NOT}\, \text{x}_1 \right) \text{AND} \left( \text{NOT}\, \text{x}_2 \right) \right)
首先构造一个能表达(NOTx1)AND(NOTx2)\left( \text{NOT}\, \text{x}_1 \right) \text{AND} \left( \text{NOT}\, \text{x}_2 \right)部分的神经元:

然后将表示 AND 的神经元和表示(NOTx1)AND(NOTx2)\left( \text{NOT}\, \text{x}_1 \right) \text{AND} \left( \text{NOT}\, \text{x}_2 \right)的神经元以及表示 OR 的神经元进行组合:

我们就得到了一个能实现 XNOR\text{XNOR} 运算符功能的神经网络。按这种方法我们可以构造出越来越复杂的函数,也能得到更加厉害的特征值。

多类的分类问题

输入向量 xx 有三个维度,两个中间层,输出 4 个神经元分别用来表示 4 类,也就是每个数据在输出层都会出现[abcd]T\begin{bmatrix} a & b & c & d \end{bmatrix}^T ,且 aa,bb,cc,dd 中仅有一个为 1,表示当前类。下图为可能的结构示例:

神经网络算法的输出结果为四种可能之一:[1000],[0100],[0010],[0001]\begin{bmatrix} 1\\ 0\\ 0\\ 0 \end{bmatrix}, \begin{bmatrix} 0\\ 1\\ 0\\ 0 \end{bmatrix}, \begin{bmatrix} 0\\ 0\\ 1\\ 0 \end{bmatrix}, \begin{bmatrix} 0\\ 0\\ 0\\ 1 \end{bmatrix}

神经网络的学习

代价函数

假设神经网络的训练样本有 mm 个,每个包含一组输入 xx 和一组输出信号 yy ,LL 表示神经网络层数,SIS_I 表示每层的 neuron 个数(SlS_l 表示输出层神经元个数,不包括偏置单元),SLS_L 代表最后一层中处理单元的个数。

神经网络的分类定义为两种情况:二类分类和多类分类,

二类分类:SL=0,y=0or1S_L = 0, y = 0 or 1 表示哪一类;

K类分类:SL=k,yi=1S_L = k, y_i = 1 表示分到第 ii 类;(k>2k > 2)。

在逻辑回归中的代价函数为:

J(θ)=1m[j=1ny(i)loghθ(x(i))+(1y(i))log(1hθ(x(i)))]+λ2mj=1nθj2J(\theta) = -\frac{1}{m}\left [ \sum_{j=1}^{n}y^{(i)}logh_\theta(x^{(i)}) + (1 - y^{(i)}) log(1 - h_\theta(x^{(i)}))\right ] + \frac{\lambda }{2m}\sum_{j=1}^{n}\theta _{j}^{2}

在逻辑回归中,只有一个输出变量,又称标量(scalar),也只有一个因变量 yy,但是在神经网络中,我们可以有很多输出变量,hθ(x)h_\theta(x) 是一个维度为 KK 的向量,并且训练集中的因变量也是同样维度的一个向量,此时代价函数更加复杂:hθ(x)RKh_\theta(x)\subseteq \mathbb{R}^K(hθ(x))i=ithoutput(h_\theta(x))_i = i^{th} output

J(Θ)=1m[i=1mk=1kyk(i)log(hΘ(x(i)))k+(1yk(i))log(1(hΘ(x(i)))k)]+λ2ml=1L1i=1slj=1s_l+1(Θji(l))2J(\Theta )=-\frac{1}{m}\left [ \sum_{i=1}^{m}\sum_{k=1}^{k}y_{k}^{(i)}log\left ( h_\Theta \left ( x_{(i)} \right ) \right )_k + \left ( 1-y_{k}^{(i)} \right )log\left ( 1-\left ( h_\Theta \left ( x^{(i)} \right ) \right )_k \right ) \right ]+\frac{\lambda }{2m}\sum_{l=1}^{L-1}\sum_{i=1}^{s_l}\sum_{j=1}^{s\_l+1}\left ( \Theta _{ji}^{(l)} \right )^2

其背后的思想与逻辑回归算法是一致的,希望通过代价函数来观察算法预测的结果与真实情况的误差有多大,唯一不同的是,对于每一行特征,都会给出 KK 个预测,利用循环,对每一行特征都预测 KK 个不同结果,然后利用循环在 KK 个预测中选择可能性最高的一个,将其与 yy 中的实际数据进行比较。

正则化的那一项只是排除了每一层 θ0\theta_0 后,每一层的 θ\theta 矩阵的和。最里面的循环 jj 循环所有的行(由 sl+1s_l + 1 层的激活单元数决定)循环 ii 则循环所有的列,由该层(sls_l 层)的激活单元数决定。即:hθ(x)h_\theta(x) 与真实值之间的距离为每个样本-每个类输出的加和,对参数进行 regularizationbias 项处理所有参数的平方和。

反向传播算法

Backpropagation Algorithm

在计算神经网络预测结果的时候采用了一种正向传播的方法,从第一层开始正向一层一层进行计算,直到最后一层的 hθ(x)h_\theta(x)

为了计算代价函数的偏导数 Θij(l)J(Θ)\frac{\partial }{\partial \Theta _{ij}^{(l)} }J(\Theta) ,我们需要一种反向传播算法,先计算最后一层的误差,然后在一层一层反向求出各层的误差,直到倒数第二层。举例说明:

假设训练集只有一个实例 (x(1),y(1))(x^{(1)}, y^{(1)}) ,神经网络为4层,K=4K = 4,SL=4S_L = 4,L=4L = 4,前向传播算法(Forward propagation):

a(1)=xa^{(1)} = x

z(2)=Θ(1)a(1)z^{(2)} = \Theta^{(1)}a^{(1)}

a(2)=g(z(2))a^{(2)} = g(z^{(2)}) (add a0(2)a_0^{(2)})

z(3)=Θ(2)a(2)z^{(3)} = \Theta^{(2)}a^{(2)}

a(3)=g(z(3))a^{(3)} = g(z^{(3)}) (add a0(3)a_0^{(3)})

z(4)=Θ(3)a(3)z^{(4)} = \Theta^{(3)}a^{(3)}

a(4)=hΘ(x)=g(z(4))a^{(4)} = h_\Theta(x) = g(z^{(4)})

δj(l)\delta _{j}^{(l)} 表示第 ll 层的第 jj 个节点的误差 “error”,误差是激活单元的预测 (ak(4))(a_k^{(4)}) 与实际 yky_k 的误差,其中 k=1:Kk=1:Kδ(4)=a(4)y\delta^{(4)} = a^{(4)} - y对于每个输出单元(layer L = 4)
δj(4)=aj(4)yj\delta_j^{(4)} = a_j^{(4)} - y_j 表示第4层的第 jj 个单元的误差 δ\delta ,其中 aj(4)a_j^{(4)} 可以写作 (hΘ(x))j(h_\Theta(x))_j 写出向量化的表达式为 $\delta^{(4)}= a^{(4)} - y $ 。

计算前几项误差的公式为:

δ3=(Θ(3))Tδ(4)g(z(3))\delta_{3}=\left(\Theta^{(3)}\right)^{T} \delta^{(4)} \cdot * g^{\prime}\left(z^{(3)}\right)

δ2=(Θ(2))Tδ(3)g(z(2))\delta_{2}=\left(\Theta^{(2)}\right)^{T} \delta^{(3)} \cdot * g^{\prime}\left(z^{(2)}\right)

..* 是两个向量的元素间对应相乘,g(z(3))g'(z^{(3)}) 是激励函数在输入值为 z(3)z^{(3)} 的时候求的导数。

f(z)=11+ezf(z) = \frac{1}{1+e^{-z} } ,则f(z)=f(z)(1f(z))f'(z) = f(z)(1 - f(z)),推到过程:

f(z)=(11+ez)=ez(1+ez)2=1+ez1(1+ez)2=11+ez(11(1+ez))=f(z)(1f(z))\begin{aligned} f^{\prime}(z) &=\left(\frac{1}{1+e^{-z}}\right)^{\prime} \\ &=\frac{e^{-z}}{\left(1+e^{-z}\right)^{2}} \\ &=\frac{1+e^{-z}-1}{\left(1+e^{-z}\right)^{2}} \\ &=\frac{1}{1+e^{-z}}\left(1-\frac{1}{\left(1+e^{-z}\right)}\right) \\ &=f(z)(1-f(z)) \end{aligned}

根据以上的公式,可以得到g(z(3))=a(3)(1a(3))g^{\prime}\left(z^{(3)}\right)=a^{(3)} *\left(1-a^{(3)}\right),而则(Θ(3))Tδ(4)\left(\Theta^{(3)}\right)^{T} \delta^{(4)}是权重导致的误差的和,下一步是继续计算第二层的误差: 。δ2=(Θ(2))Tδ(3)g(z(2))\delta_{2}=\left(\Theta^{(2)}\right)^{T} \delta^{(3)} \cdot * g^{\prime}\left(z^{(2)}\right)因为第一层是输入变量,不存在误差。反向传播算法源于我们从输出层开始计算误差δ\delta,然后返回上一层,计算第三隐藏层的,然后在计算第二层的δ\delta。类似把输出层的误差传递给第三层然后传递给第二层。

若不考虑正则化,经过复杂的推导,可以得到:

Θij(l)J(Θ)=aj(l)δil+1\frac{\partial}{\partial \Theta_{i j}^{(l)}} J(\Theta)=a_{j}^{(l)} \delta_{i}^{l+1}

ll 代表所计算的第几层

jj 代表目前计算层中激活单元的下标,也是下一层的第 jj 个输入变量的下标

ii 代表下一层中误差单元的下标,是受到权重矩阵中第 ii 行影响的下一层中的误差单元的下标。

若考虑正则项,且训练集是一个矩阵而非向量,此时整个训练集的的误差单元也是一个矩阵,使用Δij(l)\Delta {_{ij} }^{(l)} 来表示这个误差矩阵,第 ll 层的第 ii 个激活单元受到第 jj 个参数影响而导致的误差。

假设训练集为 {(x(1),y(1)),...,(x(m),y(m))}\left\{ (x^{(1)}, y^{(1)}),...,(x^{(m)}, y^{(m)}) \right\}

Δij(l)=0(foralll,i,j)\Delta {_{ij} }^{(l)} = 0 (for\,all\,l,i,j)Δij(l)\Delta {_{ij} }^{(l)} 用来计算偏导数项Θij(l)J(Θ)\frac{\partial}{\partial\Theta_{ij}^{(l)} }J(\Theta) 的)

即首先用正向传播方法计算出每一层的激活单元,利用训练集的结果与神经网络预测的结果求出最后一层的误差,然后利用该误差反向传播法计算出直至第二层的所有误差。求出 Δij(l)\Delta {_{ij} }^{(l)} 后,可以计算代价函数的偏导数:

Dij(l):=1mΔij(l)+λΘij(l) if j0Dij(l):=1mΔij(l) if j=0\begin{array}{l} D_{i j}^{(l)}:=\frac{1}{m} \Delta_{i j}^{(l)}+\lambda \Theta_{i j}^{(l)} \text { if } j \neq 0 \\ D_{i j}^{(l)}:=\frac{1}{m} \Delta_{i j}^{(l)} \quad \text { if } j=0 \end{array}

即若考虑正则化,可以得到 Θij(l)J(Θ)=Dij(l)\frac{\partial}{\partial\Theta _{ij}^{(l)} }J(\Theta)= D_{ij}^{(l)}

未正则化的神经网络的BP算法推导

假设现在有一个三层的神经网络,如图:

参数含义:

  • θ(i)\theta^{(i)}ii 层的参数矩阵
  • z(l)z^{(l)}ll 层的输入
  • a(l)a^{(l)}ll 层的输出

传递过程

  • a(1)=xa^{(1)} = x
  • z(2)=θ(1)a(1)z^{(2)} = \theta^{(1)}a^{(1)}
  • a(2)=g(z(2))a^{(2)} = g(z^{(2)}) add a0(2)a_0^{(2)}
  • z(3)=θ(2)a(2)z^{(3)} = \theta^{(2)}a^{(2)}
  • h=a(3)=g(z(3))h = a^{(3)} = g(z^{(3)})

其中 gg 为 sigmoid 激活函数

δ(l)\delta^{(l)} 表示每层的”误差“,yy 为每个样本的标签,hh 为每个样本的预测值,从后往前计算每层的”误差“。这里”误差“不是真正的误差。

  • δ(3)=hy(1)\delta^{(3)} = h - y(1)
  • δ(2)=(θ(2))Tδ(3)g(z(2))\delta^{(2)} = (\theta^{(2)})^T\delta^{(3)}g'(z^{(2)})

吴恩达在课里面提到,”误差“的实质是δ(l)=z(l)\delta^{(l)} = \frac{\partial}{\partial z^{(l)} },具体见后面的推导过程。然后计算每层参数矩阵的梯度,用 Δ(l)\Delta^{(l)} 表示:

  • Δ(2)=a(2)δ(3)\Delta^{(2)} = a^{(2)}\delta^{(3)}
  • Δ(1)=a(1)δ(2)\Delta^{(1)} = a^{(1)}\delta^{(2)}

最后网络的总梯度为:D=1m(Δ(1)+Δ(2))D = \frac{1}{m}(\Delta^{(1)}+\Delta^{(2)})。到这里反向传播算法完成了,接下来就可以利用梯度下降法或更高级的优化算法来训练网络。

推导过程:

假设只有一个输入样本,则代价函数为 J(θ)=ylogh(x)(1y)log(1h)J(\theta)=-ylogh(x)-(1-y)log(1-h)

由前面可知正向的传递过程为:

  • a(1)=xa^{(1)} = x
  • z(2)=θ(1)a(1)z^{(2)} = \theta^{(1)}a^{(1)}
  • a(2)=g(z(2))a^{(2)} = g(z^{(2)}) add a0(2)a_0^{(2)}
  • z(3)=θ(2)a(2)z^{(3)} = \theta^{(2)}a^{(2)}
  • h=a(3)=g(z(3))h = a^{(3)} = g(z^{(3)})

利用到的一个公式:若g(z)=11+ezg(z) = \frac{1}{1+e^{-z} } ,则g(z)=g(z)(1g(z))g'(z) = g(z)(1 - g(z))

根据链式求导法则可以计算得到:

Jθ(2)=Ja(3)a(3)z(3)z(3)θ(2)=(hy)a(2)\frac{\partial J}{\partial \theta^{(2)} } = \frac{\partial J}{\partial a^{(3)} }\frac{\partial a^{(3)} }{\partial z^{(3)} } \frac{\partial z^{(3)} }{\theta^{(2)} }=(h-y)a^{(2)}

其中:

Ja(3)=Jh=yh+1y1h=hyh(1h))\frac{\partial J}{\partial a^{(3)} }=\frac{\partial J}{\partial h}=\frac{-y}{h}+\frac{1-y}{1-h} = \frac{h-y}{h(1-h))}

a(3)z(3)=g(z(3))z(3)=g(z3)(1g(z(3)))=h(1h)\frac{\partial a^{(3)} }{\partial z^{(3)} } = \frac{\partial g(z^{(3)})}{\partial z^{(3)} }=g(z^{3})(1-g(z^{(3)}))=h(1-h)

z(3)θ(2)=a(2)\frac{\partial z^{(3)} }{\theta^{(2)} }=a^{(2)}

由上图可以得到反向传播公式 Δ(2)=a(2)δ(3)\Delta^{(2)} = a^{(2)}\delta^{(3)}

同样可以得到:Δ(1)=a(1)δ(2)\Delta^{(1)} = a^{(1)}\delta^{(2)}

得到这个规律后,便可以应用到深层次的网络中,计算反向传播时就很方便。

反向传播算法的直观理解

前向传播算法:

反向传播算法做的是:

梯度检验

当对一个较为复杂的模型(例如神经网络)使用梯度下降算法时,可能会存在一些不容易察觉的错误,意味着,虽然代价看上去在不断减小,但最终的结果可能并不是最优解。

为了避免这样的问题,我们采取一种叫做梯度的数值检验(Numerical Gradient Checking)方法。这种方法的思想是通过估计梯度值来检验我们计算的导数值是否真的是我们要求的。

对梯度的估计采用的方法是在代价函数上沿着切线的方向选择离两个非常近的点然后计算两个点的平均值用以估计梯度。即对于某个特定的 θ\theta,我们计算出在 θ\theta-$\varepsilon $ 处和 θ\theta+$\varepsilon $ 的代价值($\varepsilon $是一个非常小的值,通常选取 0.001),然后求两个代价的平均,用以估计在 θ\theta 处的代价值。

Octave 中代码如下:

gradApprox = (J(theta + eps) – J(theta - eps)) / (2*eps)

θ\theta是一个向量时,我们则需要对偏导数进行检验。因为代价函数的偏导数检验只针对一个参数的改变进行检验,下面是一个只针对θ_1\theta\_1进行检验的示例:

θ1=J(θ1+ε1,θ2,θ3θn)J(θ1ε1,θ2,θ3θn)2ε\frac{\partial}{\partial \theta_{1}}=\frac{J\left(\theta_{1}+\varepsilon_{1}, \theta_{2}, \theta_{3} \ldots \theta_{n}\right)-J\left(\theta_{1}-\varepsilon_{1}, \theta_{2}, \theta_{3} \ldots \theta_{n}\right)}{2 \varepsilon}

最后我们还需要对通过反向传播方法计算出的偏导数进行检验。

根据上面的算法,计算出的偏导数存储在矩阵 Dij(l)D_{ij}^{(l)} 中。检验时,我们要将该矩阵展开成为向量,同时我们也将 θ\theta 矩阵展开为向量,我们针对每一个 θ\theta 都计算一个近似的梯度值,将这些值存储于一个近似梯度矩阵中,最终将得出的这个矩阵同 Dij(l)D_{ij}^{(l)} 进行比较。

随机初始化

任何优化算法都需要一些初始的参数。到目前为止我们都是初始所有参数为0,这样的初始方法对于逻辑回归来说是可行的,但是对于神经网络来说是不可行的。如果我们令所有的初始参数都为0,这将意味着我们第二层的所有激活单元都会有相同的值。同理,如果我们初始所有的参数都为一个非0的数,结果也是一样的。

我们通常初始参数为正负ε之间的随机值,假设我们要随机初始一个尺寸为10×11的参数矩阵,代码如下:

Theta1 = rand(10, 11) * (2*eps) – eps

总结

选择网格结构

第一件要做的事就是选择网格结构,即决定选择多少层以及决定每层分别有多少个单元。

第一层的单元数即训练集的特征数量,最后一层的单元数是训练集的结果的类的数量,如果隐藏层数大于1,确保每个隐藏层的单元个数相同,通常情况下隐藏单元的个数越多越好。真正需要决定的是隐藏层的层数以及每个中间层的单元数。

训练神经网络

  1. 参数的随机初始化
  2. 利用正向传播方法计算所有的 hθ(x(i))h_\theta(x^{(i)}) for any x(i)x^{(i)}
  3. 编写计算代价函数 J(Θ)J(\Theta) 的代码
  4. 利用反向传播算法计算所有的偏导数 Θjk(l)J(Θ)\frac{\partial}{\partial \Theta_{jk}^{(l)} }J(\Theta)
  5. 利用数值检验的方法检验这些偏导数
  6. 使用优化算法来最小化代价函数

应用机器学习的建议

下一步如何做

当我们运用训练好了的模型来预测未知数据时发现较大的误差,我们下一步如何做呢?可以考虑下面的方法:

  1. 尝试减少特征的数量
  2. 尝试获取更多的特征
  3. 尝试增加多项式的特征
  4. 尝试减少正则化程度λ\lambda
  5. 尝试增加正则化程度λ\lambda

模型选择和交叉验证集

一般使用交叉验证集来选择模型,使用60%的数据集作为训练集,使用20%的数据作为交叉验证集,使用20%作为测试集。模型选择的方法:

  • 使用训练集训练出10个模型
  • 用10个模型分别对交叉验证集计算得出交叉验证误差(代价函数的值)
  • 选取代价函数最小值的模型
  • 用上述步骤选出的模型对测试集计算得出推广误差(代价函数的值)

诊断偏差和方差

若算法效果不好,多半会出现两种情况:偏差较大或方差较大,即欠拟合或过拟合。我们通常会将训练集和交叉验证集的代价函数误差与多项式的次数绘制在同一张图表上来帮助分析:

ml_notes36

当交叉验证集误差较大时,如何判断偏差还是方差呢?

训练集误差和交叉验证集误差近似时:偏差/欠拟合

交叉验证集误差远大于训练集误差时:方差/过拟合

对于正则化参数λ\lambda,其与代价函数的关系

λ\lambda较小时,训练集误差较小(过拟合)而交叉验证集误差较大

λ\lambda增加时,训练集误差不断增加(欠拟合)而交叉验证集误差则是先减小后增大。

决定下一步做什么

  • 获得更多的训练实例–解决高方差(过拟合)
  • 尝试减少特征的数量–解决高方差(过拟合)
  • 尝试获得更多的特征–解决高偏差(欠拟合)
  • 尝试增加多项式特征–解决高偏差(过拟合)
  • 尝试减少正则化程度–解决高偏差(过拟合)
  • 尝试增加正则化程度–解决高方差(欠拟合)

对于神经网络中的隐藏层的层数的选择,通常从一层开始逐渐增加层数,可以把数据分为训练集、交叉验证集和测试集,针对不同隐藏层层数的神经网络训练神经网络,然后选择交叉验证集代价最小的神经网络。

聚类和降维

聚类

K-Means算法

K-Means是一个迭代算法,假设要将数据聚类为n个组,其方法为:

  • 选择K个随机的点,称为聚类中心(cluster centroids)
  • 对于数据集中每一个数据,按照距离K个中心点的距离,将其与距离最近的中心点关联起来,与同一个中心点关联的所有点聚成一类
  • 计算每一个组的平均值,将该组所关联的中心移到平均值的位置
  • 重复步骤2-4直至中心点不再变化

降维

动机

  • 数据压缩
  • 数据可视化

主成分分析问题

主成分成分分析(PCA)是最常见的降维算法。

在PCA中我们要做的是找到一个方向向量,当我们把所有的数据都投射到该向量上时,希望投射平均均方误差尽可能的小。方向向量是一个经过原点的向量,而投射误差是从特征向量向该方向向量作垂线的长度。

主成分分析问题是将 nn 维数据降至 kk 维,目标是找到向量 u(1),u(2)...u(k)u^{(1)},u^{(2)}...u^{(k)} 使得总的投射误差最小。

PCA将 nn 个特征降维到 kk 个,可以用来数据压缩。PCA技术一大好处是对数据进行降维处理,可以对新求出的主元向量的重要性进行排序,根据需要取前面重要的部分,将后面的维数省去,可以简化模型同时最大程度保持原有的数据信息。一大优点是完全无参数限制的。

PCA算法:

  1. 均值归一化,计算出所有特征的均值,然后令 xj=xjujx_j = x_j - u_j 。如果特征在不同数量集上,还需要除以标准差 σ2\sigma^2
  2. 计算协方差矩阵(covariance matrix) Σ\SigmaΣ=1mi=1n(x(i))(x(i))T\Sigma=\frac{1}{m} \sum_{i=1}^{n}\left(x^{(i)}\right)\left(x^{(i)}\right)^{T}
  3. 计算协方差矩阵 Σ\Sigma 的特征向量(eigenvectors),可以利用奇异值分解(singular value decomposition)来求解 [U, S, V]=svd(sigma)

对于一个 n×nn \times n 维度的矩阵成的矩阵。上面的 UU 是一个具有与数据之间最小投射误差的方向向量构成的矩阵。如果我们希望将数据从 nn 维降至𝑙维,我们只需要从 UU 中选取前 kk 个向量,获得一个 n×kn \times k 维度的矩阵,我们用 UreduceU_{\text {reduce}} 表示,然后通过如下计算得到新特征向量 z(i)z^{(i)}z(i)=UreduceTx(i)z^{(i)}=U_{\text {reduce}}^{T} * x^{(i)}

选择主成分的数量

主要成分分析是减少投射的平均均方误差:训练集的方差为:1mi=1mx(i)2\frac{1}{m} \sum_{i=1}^{m}\left\|x^{(i)}\right\|^{2}

我们希望在平均均方误差与训练集方差的比例尽可能小的情况下选择尽可能小的 kk 值。

先令 k=1k=1 ,然后进行主要成分分析,获得 UreduceU_{\text {reduce}}zz ,然后计算比例是否小于1%。如果不是的话再令k=2k=2,如此类推,直到找到可以使得比例小于 1%的最小 kk 值(原因是各个特征之间通常情况存在某种相关性)。

应用

随机梯度下降法

对于大规模的训练集,可以使用随机梯度下降法(SGD)来代替批量梯度下降法。在随机梯度下降法中,我们定义代价函数为一个单一训练实例的代价:

cost(θ,(x(i),y(i)))=12(hθ(x(i))y(i))2\operatorname{cost}\left(\theta,\left(x^{(i)}, y^{(i)}\right)\right)=\frac{1}{2}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right)^{2}

随机梯度下降算法每在一次计算之后便更新参数 θ\theta ,而不需要首先将所有的训练集求和。
/Volumes/Projects/zhkuo/blog/source/_posts/pytorch-notes.md

小批量梯度下降

小批量梯度下降法是介于批量梯度下降算法和随机梯度下降算法之间的算法,每计算常数 bb 次训练实例,便更新一次 θ\theta