Andrew Ng机器学习课程笔记--week5(上)
Neural Networks: Learning 内容较多,故分成上下两篇文章。
一、内容概要
-
Cost Function and Backpropagation
- Cost Function
- Backpropagation Algorithm
- Backpropagation Intuition
-
Backpropagation in Practice
- Implementation Note:Unroll Parameters
- Gradient Checking
- Random Initialization
- Putting it Together
-
Application of Neural Networks
- Autonomous Driving
二、重点&难点
1.Cost Function and Backpropagation
1) Cost Function
首先定义一下后面会提到的变量
L: 神经网络总层数 Sl:l层单元个数(不包括bias unit) k:输出层个数
回顾正则化逻辑回归中的损失函数:
[J(theta) = - frac{1}{m} sum_{i=1}^m [ y^{(i)} log (h_theta (x^{(i)})) + (1 - y^{(i)}) log (1 - h_theta(x^{(i)}))] + frac{lambda}{2m}sum_{j=1}^n theta_j^2]
在神经网络中损失函数略微复杂了些,但是也比较好理解,就是把所有层都算进去了。 [ begin{gather*} J(Theta) = - frac{1}{m} sum_{i=1}^m sum_{k=1}^K left[y^{(i)}_k log ((h_Theta (x^{(i)}))_k) + (1 - y^{(i)}_k)log (1 - (h_Theta(x^{(i)}))_k)right] + frac{lambda}{2m}sum_{l=1}^{L-1} sum_{i=1}^{s_l} sum_{j=1}^{s_{l+1}} ( Theta_{j,i}^{(l)})^2end{gather*} ]
2)BackPropagation反向传播
更详细的公式推导可以参考http://ufldl.stanford.edu--反向传导算法
下面给出我自己对BP算法的理解以及ufldl上的推导:
假设神经网络结构如下
- 1. FP
- 利用前向传导公式(FP)计算(2,3……) 直到 ({n_l})层(输出层)的激活值。 计算过程如下:
- 2. BP
- 权值更新
首先需要知道的是BP算法是干嘛的?它是用来让神经网络自动更新权重(W)的。 这里权重(W)与之前线性回归权值更新形式上是一样:
那现在要做的工作就是求出后面的偏导,在求之前进一步变形:
注意(J(W,b;x^{(i)},y^{(i)}))表示的是单个样例的代价函数,而(J(W,b))表示的是整体的代价函数。
所以接下来的工作就是求出(frac{∂J(W,b;x,y)}{∂W_{ij^{(l)}}}),求解这个需要用到微积分中的链式法则,即
[ begin{align*} frac{∂J(W,b;x,y)}{∂W_{ij^{(l)}}} = frac{∂J(W,b;x,y)}{∂a_{i^{(l)}}} frac{∂a_{i^{(l)}}}{∂z_{i^{(l)}}} frac{∂z_{i^{(l)}}}{∂w_{ij^{(l)}}} = a_j^{(l)}δ_i^{(l+1)} end{align*} ]
更加详细运算过程可以参考[一文弄懂神经网络中的反向传播法——BackPropagation],这篇文章详细的介绍了BP算法的每一步骤。
上面的公式中出现了(δ)(误差error),所以后续的目的就是求出每层每个node的(δ),具体过程如下:
- 计算δ
对于第 (n_l)层(输出层)的每个输出单元(i),我们根据以下公式计算残差:
对 (l = n_l-1, n_l-2, ……,3,2)的各个层,第 (l) 层的第 (i) 个节点的残差计算方法如下:
将上面的结果带入权值更新的表达式中便可顺利的执行BackPropagation啦~~~
但是!!!需要注意的是上面式子中反复出现的 (f '(z_i^{(l)})) ,表示激活函数的导数。这个在刚开始的确困惑到我了,因为视频里老师在演示计算(δ)的时候根本就乘以这一项,难道老师错了?其实不是的,解释如下: 常用的激活函数有好几种,但使用是分情况的:
- 在线性情况下:f(z) = z
- 在非线性情况下:(只举一些我知道的例子)
- sigmoid
- tanh
- relu
所以这就是为什么老师在视频中没有乘以 (f '(z_i^{(l)})) 的原因了,就是因为是线性的,求导后为1,直接省略了。
另外sigmoid函数表达式为(f(z)=frac{1}{1+e^{-z}}),很容易知道(f'(z)=frac{-e^{-z}}{ (1+e^{-z}) ^2 } = f(z)·(1-f(z)))这也就解释了Coursera网站上讲义的公式是这样的了:
所以现在总结一下BP算法步骤:
- 进行前馈传导计算,利用前向传导公式,得到(L_2, L_3, ldots)直到输出层 (textstyle L_{n_l})的激活值。
- 对输出层(第 (textstyle n_l)层),计算: (delta^{(n_l)}= - (y - a^{(n_l)}) bullet f'(z^{(n_l)}))
- 对于 (textstyle l = n_l-1, n_l-2, n_l-3, ldots, 2) 的各层,计算: (delta^{(l)} = left((W^{(l)})^T delta^{(l+1)}right) bullet f'(z^{(l)}))
- 计算最终需要的偏导数值: [ begin{align} nabla_{W^{(l)}} J(W,b;x,y) &= delta^{(l+1)} (a^{(l)})^T, \ nabla_{b^{(l)}} J(W,b;x,y) &= delta^{(l+1)}. end{align} ]
使用批量梯度下降一次迭代过程:
- 对于所有(textstyle l),令 (textstyle Delta W^{(l)} := 0 , textstyle Delta b^{(l)} := 0) (设置为全零矩阵或全零向量)
- 对于(textstyle i = 1) 到(textstyle m) , 使用反向传播算法计算(textstyle nabla_{W^{(l)}} J(W,b;x,y)) 和(textstyle nabla_{b^{(l)}} J(W,b;x,y)) 。 计算(textstyle Delta W^{(l)} := Delta W^{(l)} + nabla_{W^{(l)}} J(W,b;x,y)) 。 计算(textstyle Delta b^{(l)} := Delta b^{(l)} + nabla_{b^{(l)}} J(W,b;x,y)) 。
- 更新权重参数: [ begin{align} W^{(l)} &= W^{(l)} - alpha left[ left(frac{1}{m} Delta W^{(l)} right) + lambda W^{(l)}right] \ b^{(l)} &= b^{(l)} - alpha left[frac{1}{m} Delta b^{(l)}right] end{align} ]
3) Backpropagation Intuition
本小节演示了具体如何操作BP,不再赘述。
具体可参考Coursera讲义。
- JavaScript 数据类型
- 3361: [Usaco2004 Jan]培根距离
- Java NIO
- 1342: [Baltic2007]Sound静音问题
- 加深理解HTTP请求---网络基础TCP/IP
- BZOJ2199: [Usaco2011 Jan]奶牛议会(2-SAT)
- 数据结构之链表、栈和队列 java代码实现
- 洛谷P3209 [HNOI2010]PLANAR(2-SAT)
- javascript 面向对象(多种创建对象的方式)
- 1711: [Usaco2007 Open]Dingin吃饭
- 1574: [Usaco2009 Jan]地震损坏Damage
- HTTPS科普(转) 为什么需要https
- 1590: [Usaco2008 Dec]Secret Message 秘密信息
- 1751: [Usaco2005 qua]Lake Counting
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法