机器学习笔记 Week5 神经网络:学习

学习笔记(Machine Learning) Week5

全部笔记PDF版:http://vdisk.weibo.com/s/J4rRX/1373287206

Week5 神经网络:学习

神经网络:学习

1.1神经网络代价函数

首先引入一些便于稍后讨论的新标记方法:

  • L代表一个神经网络中的层数
  • Sl代表第l层的处理单元(包括偏见单元)的个数。
  • SL代表最后一层中处理单元的个数。
  • K代表我们希望分类的类的个数,与SL相等。

我们回顾逻辑回归问题中我们的代价函数为:

在逻辑回归中,我们只有一个输出变量,又称标量(scalar),也只有一个因变量y,但是在神经网络中,我们可以有很多输出变量,我们的hθ(x)是一个维度为K的向量,并且我们训练集中的因变量也是同样维度的一个向量,因此我们的代价函数会比逻辑回归更加复杂一些,为:

抓图12

这个看起来复杂很多的代价函数背后的思想还是一样的,我们希望通过代价函数来观察算法预测的结果与真实情况的误差有多大,唯一不同的是,对于每一行特征,我们都会给出K个预测,基本上我们可以利用循环,对每一行特征都预测K个不同结果,然后在利用循环在K个预测中选择可能性最高的一个,将其与y中的实际数据进行比较。

归一化的那一项只是排除了每一层θ0后,每一层的 Θ矩阵的和。最里层的循环j循环所有的行(由sl+1层的激活单元数决定),循环i则循环所有的列,由该层(sl层)的激活单元数所决定。

1.2反向传播算法(Backpropagation Algorithm

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

现在,为了计算代价函数的偏导数抓图13,我们需要采用一种反向传播算法,也就是首先计算最后一层的误差,然后再一层一层反向求出各层的误差,直到倒数第二层。

以一个例子来说明反向传播算法。

假设我们的训练集只有一个实例(x(1),y(1)),我们的神经网络是一个四层的神经网络,其中K=4,SL=4,L=4:

抓图14

我们从最后一层的误差开始计算,误差是激活单元的预测(daum_equation_1372579231428)与实际值(yk)之间的误差,(k=1:K)。我们用δ来表示误差,则:

daum_equation_1372579837430

我们利用这个误差值来计算前一层的误差:

daum_equation_1372580000259

其中g'(z(3))是S形函数的导数,g'(z(3))=a(3).*(1-a(3))。而(Θ(3))Tδ(4)则是权重导致的误差的和。

一下步是继续计算第二层的误差:

daum_equation_1372580797226

因为第一层是输入变量,不存在误差。我们有了所有的误差的表达式后,便可以计算代价函数的偏导数了,假设λ=0,即我们不做任何归一化处理时有:

daum_equation_1372581201202

重要的是清楚地知道上面式子中上下标的含义:

l代表目前所计算的是第几层
j代表目前计算层中的激活单元的下标,也将是下一层的第j个输入变量的下标。
i代表下一层中误差单元的下标,是受到权重矩阵中第i行影响的下一层中的误差单元的下标。

如果我们考虑归一化处理,并且我们的训练集是一个特征矩阵而非向量。在上面的特殊情况中,我们需要计算每一层的误差单元来计算代价函数的偏导数。在更为一般的情况中,我们同样需要计算每一层的误差单元,但是我们需要为整个训练集计算误差单元,此时的误差单元也是一个矩阵,我们用daum_equation_1372582015317来表示这个误差矩阵。第l层的第i个激活单元受到第j个参数影响而导致的误差。

我们的算法表示为:

daum_equation_1372582703224

即首先用正向传播方法计算出每一层的激活单元,利用训练集的结果与神经网络预测的结果求出最后一层的误差,然后利用该误差运用反向传播法计算出直至第二层的所有误差。

在求出了daum_equation_1372582015317之后,我们便可以计算代价函数的偏导数了,计算方法如下:

抓图15

在Octave中,如果我们要使用fminuc这样的优化算法来求解求出权重矩阵,我们需要将矩阵首先展开成为向量,在利用算法求出最优解后再重新转换回矩阵。

假设我们有三个权重矩阵,Theta1,Theta2和Theta3,尺寸分别为10*11,10*11和1*11

下面的代码可以实现这样的转换:

1.3梯度检验(Gradient Checking)

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

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

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

QQ截图20130630191648

Octave中代码如下:

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

daum_equation_1372591667928

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

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

QQ截图20130630193429

1.4随机初始化(Random Initialization)

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

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

1.5综合起来

小结一下使用神经网络时的步骤:

网络结构:

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

  • 第一层的单元数即我们训练集的特征数量。
  • 最后一层的单元数是我们训练集的结果的类的数量。
  • 如果隐藏层数大于1,确保每个隐藏层的单元个数相同,通常情况下隐藏层单元的个数越多越好。

我们真正要决定的是隐藏层的层数和每个中间层的单元数。

训练神经网络:

  1. 参数的随机初始化
  2. 利用正向传播方法计算所有的hθ(x)
  3. 编写计算代价函数J的代码
  4. 利用反向传播方法计算所有偏导数
  5. 利用数值检验方法检验这些偏导数
  6. 使用优化算法来最小化代价函数

课程地址:https://class.coursera.org/ml-003/class/index