斯坦福大学《Machine Learning》第5周学习笔记

Neural Networks: Learning神经网络:学习

Cost Function and Backpropagation代价函数和反向传播

Cost Function代价函数

假设我们有一个如左边所示的 神经网络结构 我用大写字母 L 来表示 这个神经网络结构的总层数 这里 L等于4 用 sl表示 第L层的单元的数量 也就是神经元的数量 这其中不包括L层的偏差单元 这里s1 = 3 是输入层 s2 =5 输出层s4 = 4 把K看作 输出层的 单元数目 我们只有在K大于 或者等于3个类的时候 才会使用这种 一对多的方法 因为如果只有两个类别 我们就只需要一个输出单元就可以了

以上是神经网络的代价函数  h(x)带下标i 来表示第i个输出 也就是h(x)是一个K维向量 下标 i 表示 选择了神经网络输出向量的 第i个元素 这里的第二项 这就是类似于我们在逻辑回归里所用的 正则化项  它所做的就是把这些项全部相加也就是对所有i j和l 的θji的值都相加 这里要除去那些对应于偏差值的项 

Backpropagation Algorithm反向传播算法

反向传播算法 :最小化神经网络的代价函数

为了使用梯度下降法或者 其他某种高级优化算法 我们需要做的就是 写一个函数,传入参数 θ 然后计算 J(θ) 和偏导数项 

如何计算这些 偏导数项?

我们假设只有一个训练样本记为 (x, y) 首先应用前向传播方法来它的输出 这里的a(1) ~a(4) 都是向量

然后用反向传播(Backpropagation)的算法计算导数项    反向传播的式子太多,参考《反向传播算法几个重要公式的详细推导》有这些重要公式的详细推导过程

反向传播算法从直观上说 就是对每一个结点 我们计算这样一项 δ下标 j 上标(l)  代表了第 l 层的第 j 个结点的 误差  a 上标 (l) 下标 j 表示的是第 l 层第 j 个单元的 激励值 所以这个 δ 项就表示在这个神经节点的激励值的误差 

注意这里 δ(4) a(4) 和 y 都是一个向量 并且向量维数等于 输出单元的数目 也就是4维  

我们首先计算出 网络结构的 误差项 δ(4) 然后根据 δ(4) 计算 δ(3),以此类推,注意这里的点乘  这个例子中我们的 δ 项就只有 第2层和第3层   

反向传播法这个名字 源于我们从 输出层开始计算 δ项 然后我们返回到上一层 计算第三隐藏层的 δ项 接着我们 再往前一步来计算 δ(2)所以说 我们是类似于把输出层的误差 反向传播给了第3层 然后是再传到第二层 这就是反向传播的意思  

这里总结了反向传播算法的流程

有 m 个样本的训练集 正如此处所写 首先初始化Δ = 0 (这里的Δ就是δ)  Δ(l)ij 会被用来计算 J(θ) 关于 θ 上标(l) 下标 i j 的 偏导数  这些 δ 会被作为累加项 慢慢地增加 以算出这些偏导数   

接下来我们将遍历我们的训练集 首先设定a(1) 也就是 输入层的激励函数 设定它等于 x(i)  接下来我们运用正向传播 来计算第二层的激励值 然后是第三层 第四层 一直这样 到最后一层 L层 接下来 用样本的 输出值 y(i) 计算这个输出值 所对应的误差项 δ(L) 继续运用反向传播算法 来计算 δ(L-1) δ(L-2) 一直这样直到 δ(2) 

最后用 Δ 来累积偏导数项 然后跳出这个 for 循环 然后计算下面这些式子 注意 在 j=0 的情况下 对应偏差项 所以没有额外的正则化项  

Backpropagation Intuition

前向传播流程,输入层是第i个训练样本x(i),进行前向传播传播到第一个隐藏层时 我们的做法是 算出 z(2)1   和 z(2)2  这两个值 是输入单元的加权总和 接下来 将S型的逻辑函数应用到z值上 得到 a(2)1 和 a(2)2 的值 然后 再做一次前向传播 最后我们得到 z(4)1 应用逻辑函数 得到 a(4)1 这也是这个网络的输出单元的值  这里观察z的计算,后面会和反向传播对比,它们实质是一样的,只有计算的方向不同而已

   

为了更好地理解 反向传播算法的原理 我们把目光转向代价函数 这个代价函数 对应的情况是只有一个输出单元 我们用同一个样本同时来做正向和反向传播 不考虑正则化 这个求和运算括号里面 与第i个训练样本对应的 代价项 所扮演的角色 可以看作是平方误差 这里的cos(i) 表征了该神经网络 是否能准确地预测样本i的值 也就是输出值 和实际观测值y(i)的接近程度 

反向传播算法就是在计算 所有这些δ(i)j项 它的计算和前面前向传播z的计算过程是一样的

δ 项实际上是 关于 z(l)j 的 偏微分 也就是 cost 函数 因此 它们度量着 我们对神经网络的权值 做多少的改变 对中间的计算量 影响是多少 进一步地 对整个神经网络的输出 h(x) 影响多少 以及对整个的代价值影响多少 

我们先算出了 δ(4)1等于 y(i) 减去 a(4)1   接下来我们要对这些值进行反向传播 我们计算出 δ(3)1 和 δ(3)2 然后同样的 再进行下一层的反向传播 这一次计算出 δ(2)1 以及 δ(2)2   反向传播的计算,这里注意我们计算出这些  δ的过程,和之前计算z是一样的,是后一层的δ乘以权重θ的和

Backpropagation in Practice反向传播练习

Implementation Nonrolling Parameters实现参数向量化

代价函数costFunction  输入参数是theta  返回值是代价函数以及导数值  将返回值 传递给高级最优化算法fminunc 这个算法是假设theta和gradient是向量 而对于神经网络 我们的参数都是矩阵θ(1) θ(2) θ(3) 

如图,上面是取出这些矩阵 并且将它们展开成向量 下面是从向量表达 返回到矩阵表达式

学习算法:   

1. 假设说你有一些 初始参数值 θ(1) θ(2) θ(3) 我们要做的是 取出这些参数并且将它们 展开为一个长向量 我们称之为initialTheta 

2. 将initialTheta作为theta参数的初始设置 传入函数fminunc   

3. 执行代价函数costFunction 参数thetaVec 也是向量  函数实现部分 首先使用 thetaVec和重组函数reshape 重组以得到参数矩阵 θ(1) θ(2) θ(3) 这样就能以更方便的形式执行前向传播 和反向传播 来计算出导数 以求得代价函数的J(θ) 函数最后 取出这些导数值展开D1 D2 D3 来得到gradientVec 它是代价函数的返回值 而且是一个向量 

Gradient Checking梯度检测

实现反向传播时 会遇到很多细小的错误 你把它和梯度下降法 或者其他优化算法一起运行时 可能看起来它运行正常 并且 你的代价函数J 最后可能 在每次梯度下降法迭代时 都会减小 即使在实现反向传播时有一些小错误 可能也会检查不出来 所以它看起来是 J(θ)在减小但是可能你最后得到的 神经网络误差 较高 但是很难找出原因 有一个叫梯度检验 (Gradient Checking) 的方法可以解决

考虑上面这个例子 假如我有一个 函数J(θ) 我想估计这个函数在实数 θ点的导数 

我们可以用这条 红色线的斜率 来作为我 导数的近似值 真正的导数是这边这条 蓝色线的斜率 这条红线的斜率等于 J(θ+ε)-J(θ-ε) 除以2ε 给ε取很小的值 比如可能取 10的-4次方 右边蓝色这个求导方式叫做单侧拆分 左边这个公式叫做双侧 双侧差分更精确

现在θ是n维向量 是神经网络参数的 展开形式 我们可以用类似的想法 来估计所有的偏导数项 如图所示

在Octave里的实现如上 最后将gradApprox 与我们从反向传播得到的DVec 比较 如果结果非常近似 那么你就可以非常确信 你实现的反向传播时正确的

总结梯度检验 

1,将计算得到的D(1),D(2),D(3)展开为DVec向量
2,实现数值梯度检验 计算出gradApprox
3,确定DVec和gradApprox给出接近的结果 
4,关掉梯度检验 不再使用 使用DVec来计算,因为gradApprox计算量 非常大

Random Initialization随机初始化

当你运行一个算法 例如梯度下降算法 或者其他高级优化算法时 我们需要给变量 θ 一些初始值 是否可以 将 θ 的初始值设为 全部是0的向量  在逻辑回归时 初始化所有变量为0 是可行的 但在训练神经网络时这样做是不可行的   

如果将所有变量初始化为0 (这里可以考虑从每一个输入出发的θ都是相等的,即x1到a(2)的θ相等,即x2到a(2)的θ相等...那么对于第二层的z = θ‘x 就都相等了) 那么就有每一个隐藏层的a和δ都是相等的 同时 如果你更深入地挖掘一下 你不难得出 这些变量对参数的偏导数互为相等 即使更新一个梯度下降 最后这些权重也会互为相等 所以每次更新后 隐藏单元的输入对应的参数 将是相同的  因此 第l层的a(l)都是相等的 这也就意味着 这个神经网络 的确不能计算更有价值的东西 想象一下 不止有两个隐藏单元 而是 有很多很多的隐藏单元 这就是说 所有的隐藏单元 都在计算相同的特征 所有的隐藏单元都通过完全相同的输入函数计算出来 这是完全多余的表达   

为了解决这个问题 神经网络变量 初始化的方式 采用随机初始化  范围在 -ɛ 到 +ɛ 之间 Octave实现如下 rand 就是用来得出一个任意的 二维矩阵   矩阵中的所有值 都介于0到1之间

总结来说 为了训练神经网络 应该对权重进行随机初始化 初始化为  --ε到+ε间 接近于0的小数 然后进行反向传播 执行梯度检查 或者 使用高级的优化算法 试着使代价函数 J  达到最小 从某个随机选取的 参数 θ 开始   来打破对称性

Putting It Together总结

当我们在训练一个神经网络时 我们要做的第一件事 就是搭建网络的大体框架 这里我说的框架 意思是 神经元之间的连接模式 这里有如下几种结构

那么我们该如何做出选择呢? 对于输入和输出层的单元数是已经确定的,我们只需要考虑  隐藏单元的个数 以及隐藏层的数目 

规则一:只使用单个隐藏层 

规则二:如果你使用 不止一个隐藏层的话 每一个隐藏层 通常都应有相同的单元数   

规则三:隐藏单元越多越好 (计算量一般会比较大)

规则四:隐藏单元的数目应该和输入x 的维度即特征的数目匹配 (数量相同 或者是它的二倍 或者三倍 四倍 取为稍大于 输入特征数目 都是可以接受的)

实现神经网络的 训练过程 这里一共有六个步骤 

第一步 构建一个 神经网络 然后随机初始化权值 

第二步 执行前向传播算法 也就是 对于该神经网络的 任意一个输入x(i) 计算出对应的h(x)值 也就是一个输出值y的向量

第三步 通过代码 计算出代价函数J(θ) 

第四步 执行 反向传播算法   来算出这些偏导数 或偏微分项 也就是 J(θ)关于参数θ的偏微分

具体来说 我们要对所有训练集数据 使用一个for循环进行遍历 一些比较先进的分解方法 可能不需要像这里一样使用 for循环来对所有 m个训练样本进行遍历 但是 这是你第一次进行反向传播算法 所以我建议你最好还是 使用一个for循环来完成程序 对每一个训练样本进行迭代执行前向传播和反向传播算法 具体来说就是 我们把x(i) 传到输入层 然后执行前向传播和反向传播   这样我们就能得到 该神经网络中 每一层中每一个单元对应的 所有这些激励值a(l) 和delta项 记得考虑使用 正则化项lambda值 

第五步 梯度检查

第六步 使用一个最优化算法 比如说梯度下降算法 或者说是更加高级的优化方法 比如说BFGS算法 共轭梯度法 或者其他一些已经内置到fminunc函数中的方法 将所有这些优化方法 和反向传播算法相结合 这样我们就能计算出使得J(θ)最小的θ;

对于神经网络 代价函数 J(θ)是一个非凸函数 就是说不是凸函数 因此理论上是能够停留在 局部最小值的位置 实际上 梯度下降算法 和其他一些高级优化方法 理论上都能收敛于局部最小值   但一般来讲 这个问题其实 并不是什么要紧的事 尽管我们不能保证 这些优化算法一定会得到 全局最优值 但通常来讲 像梯度下降这类的算法 在最小化代价函数 J(θ)的过程中 还是表现得很不错的 通常能够得到一个很小的局部最小值 尽管这可能不一定是全局最优值 

 

参考资料

https://www.coursera.org/learn/machine-learning/

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值