《Notes on Convolutional Neural Networks》中详细讲解了CNN的BP过程,下面结合Deep learn toolbox中CNN的BP源码对此做一些解析

 卷积层:

卷积层的前向传导:

误差反传:

当卷基层的下一层是pooling层时,如果pooling层的误差敏感项为时,那么卷基层的误差敏感项为:

其中,upsample表示对进行上采样,表示激活函数对输入的导数,代表点积操作

upsample根据pooling时采用方法来定,大概思想为:pooling层的每个节点是由卷积层中多个节点(一般为一个矩形区域)共同计算得到,所以pooling层每个节点的误差敏感值也是由卷积层中多个节点的误差敏感值共同产生的,只需满足两层的误差敏感值总和相等即可,下面以mean-pooling和max-pooling为例来说明。

假设卷积层的矩形大小为4×4, pooling区域大小为2×2, 很容易知道pooling后得到的矩形大小也为2*2(本文默认pooling过程是没有重叠的,卷积过程是每次移动一个像素,即是有重叠的,后续不再声明),如果此时pooling后的矩形误差敏感值如下:

  

  则按照mean-pooling,首先得到的卷积层应该是4×4大小,其值分布为(等值复制):

  

  因为得满足反向传播时各层见误差敏感总和不变,所以卷积层对应每个值需要平摊(除以pooling区域大小即可,这里pooling层大小为2×2=4)),最后的卷积层值

分布为:

  

  如果是max-pooling,则需要记录前向传播过程中pooling区域中最大值的位置,这里假设pooling层值1,3,2,4对应的pooling区域位置分别为右下、右上、左上、左下。则此时对应卷积层误差敏感值分布为:

  

  求得后,我们就要求卷积层的导数了,论文中给出的公式为:

上式中表示的(u,v)项的值,表示进行卷积的结果的(u,v)项所对应的的patch。

上述公式和下面的公式是等价的:

损失函数对b的导数为:

deep learn toolbox就是按照上述2个公式计算的。

pooling层

      pooling层的前向传导:

down(.)表示一个下采样函数。典型的操作一般是对输入图像的不同nxn的块的所有像素进行求和。这样输出图像在两个维度上都缩小了n倍。每个输出map都对应一个属于自己的乘性偏置β和一个加性偏置b。

已知卷积层的误差敏感项时,那么pooling层的误差敏感项为:

得到误差敏感项后,由于pooling只有两个参数,分别求导:

但在deep learn toolbox中,只是简单地进行subsampling,并没有加sigmoid激活函数,因而pooling层没有参数,不需要对pooling层求导,也不

需要对其参数进行更新。

下面是deep learn toolbox 中CNN BP算法的代码:

[cpp] view plaincopy
  1. function net = cnnbp(net, y)
  2. n = numel(net.layers);
  3. //  error
  4. net.e = net.o - y;
  5. //  loss function
  6. net.L = 1/2* sum(net.e(:) .^ 2) / size(net.e, 2);
  7. //从最后一层的error倒推回来deltas
  8. //和神经网络的bp有些类似
  9. backprop deltas
  10. net.od = net.e .* (net.o .* (1 - net.o));   //  output delta
  11. net.fvd = (net.ffW' * net.od);              //  feature vector delta
  12. if strcmp(net.layers{n}.type, 'c')         //  only conv layers has sigm function
  13. net.fvd = net.fvd .* (net.fv .* (1 - net.fv));
  14. end
  15. //和神经网络类似,参看神经网络的bp
  16. //  reshape feature vector deltas into output map style
  17. sa = size(net.layers{n}.a{1});
  18. fvnum = sa(1) * sa(2);
  19. for j = 1 : numel(net.layers{n}.a)
  20. net.layers{n}.d{j} = reshape(net.fvd(((j - 1) * fvnum + 1) : j * fvnum, :), sa(1), sa(2), sa(3));
  21. end
  22. //这是算delta的步骤
  23. //这部分的计算参看Notes on Convolutional Neural Networks,其中的变化有些复杂
  24. //和这篇文章里稍微有些不一样的是这个toolbox在subsampling(也就是pooling层)没有加sigmoid激活函数
  25. //所以这地方还需仔细辨别
  26. //这这个toolbox里的subsampling是不用计算gradient的,而在上面那篇note里是计算了的
  27. for l = (n - 1) : -1 : 1
  28. if strcmp(net.layers{l}.type, 'c')
  29. for j = 1 : numel(net.layers{l}.a)
  30. net.layers{l}.d{j} = net.layers{l}.a{j} .* (1 - net.layers{l}.a{j}) .* (expand(net.layers{l + 1}.d{j}, [net.layers{l + 1}.scale net.layers{l + 1}.scale 1]) / net.layers{l + 1}.scale ^ 2);
  31. end
  32. elseif strcmp(net.layers{l}.type, 's')
  33. for i = 1 : numel(net.layers{l}.a)
  34. z = zeros(size(net.layers{l}.a{1}));
  35. for j = 1 : numel(net.layers{l + 1}.a)
  36. z = z + convn(net.layers{l + 1}.d{j}, rot180(net.layers{l + 1}.k{i}{j}), 'full');
  37. end
  38. net.layers{l}.d{i} = z;
  39. end
  40. end
  41. end
  42. //参见paper,注意这里只计算了'c'层的gradient,因为只有这层有参数
  43. calc gradients
  44. for l = 2 : n
  45. if strcmp(net.layers{l}.type, 'c')
  46. for j = 1 : numel(net.layers{l}.a)
  47. for i = 1 : numel(net.layers{l - 1}.a)
  48. net.layers{l}.dk{i}{j} = convn(flipall(net.layers{l - 1}.a{i}), net.layers{l}.d{j}, 'valid') / size(net.layers{l}.d{j}, 3);
  49. end
  50. net.layers{l}.db{j} = sum(net.layers{l}.d{j}(:)) / size(net.layers{l}.d{j}, 3);
  51. end
  52. end
  53. end
  54. //最后一层perceptron的gradient的计算
  55. net.dffW = net.od * (net.fv)' / size(net.od, 2);
  56. net.dffb = mean(net.od, 2);
  57. function X = rot180(X)
  58. X = flipdim(flipdim(X, 1), 2);
  59. end
  60. end

Deep learn toolbox:CNN BP求导解析相关推荐

  1. 非线性优化Ceres手动求导数值求导解析求导使用示例

    参考Ceres官方文档http://www.ceres-solver.org/nnls_tutorial.html#hello-world 实现手动求导进行非线性优化. 1.问题描述 假设下面曲线 y ...

  2. pythonmath反三角函数的导数_Pytorch反向求导更新网络参数的方法

    方法一:手动计算变量的梯度,然后更新梯度 import torch from torch.autograd import Variable # 定义参数 w1 = Variable(torch.Flo ...

  3. BP算法双向传_链式求导最缠绵(深度学习入门系列之八)

    摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...

  4. 深度学习(三十)——Deep Speech, 自动求导

    CTC 推断计算(续) 上图是一个Beam Width为3的Beam Search.Beam Search的细节可参见<机器学习(二十三)>. 由于语音的特殊性,我们实际上用的是Beam ...

  5. 矩阵求导与BP的证明的建议

    前言 在有些博客推导神经网络的BP时,涉及到多次矩阵求导运算,尤其是反向传播时候,求的梯度结果被转置了,比如假设最后一层的输出为 y=σ(w⋅x+b) y=\sigma\left(w\cdot x+b ...

  6. BP算法双向传,链式求导最缠绵(深度学习入门系列之八)

    摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...

  7. 【深度学习之美】BP算法双向传,链式求导最缠绵(入门系列之八)

    8.1 BP神经网络极简史 在神经网络(甚至深度学习)参数训练中,BP(Back Propagation)算法非常重要,它都占据举足轻重的地位.在提及BP算法时,我们常将它与杰弗里•辛顿(Geoffr ...

  8. 机器学习BP算法及矩阵求导

    除了基本导数公式,本文介绍的矩阵求导方法不涉及任何公式的套用. 本文以neural network中最常见的一种计算单元为例,详细介绍了BP算法中涉及到的矩阵求导过程.刚接触机器学习时,曾被BP算法中 ...

  9. DL之BP:利用乘法层/加法层(forward+backward)算法结合计算图(CG)求解反向求导应用题

    DL之BP:利用乘法层/加法层(forward+backward)算法结合计算图(CG)求解反向求导应用题 导读 计算图中层的实现(加法层/乘法层),其实非常简单,使用这些层可以进行复杂的导数计算.可 ...

最新文章

  1. k8s,nginx备份日志脚本
  2. DCMTK:dcmseg模块的辅助功能
  3. webservice linux 杀进程
  4. 小甲鱼 OllyDbg 教程系列 (一) :二进制破解科普系列之 ReverseMe
  5. 从事前到事后,云数据库 Redis MongoDB 安全体系全揭秘!
  6. Web前端笔记-修改element ui中表格样式(透明、去横纵线等含修改思路)
  7. LeetCode 5364. 按既定顺序创建目标数组
  8. 微信开发(一)SAE环境搭建
  9. 列出场景对象Lightmap属性
  10. 北京邮电大学计算机专业录取名单,祝福!“跪地谢母”考生被北京邮电大学计算机类专业录取...
  11. Microsoft Edge闪退问题解决方案:
  12. u盘乱码怎么办?数据丢失如何恢复?(详解)
  13. LS1021A 调试问题记录
  14. python爬虫进阶-1688工厂信息(JS逆向-sign签名验证)
  15. 易飞ERP和钉钉办公集成——ERP移动审批解决方案
  16. 【面试题】对闭包的理解?什么是闭包?
  17. MySQL数据库之数据库约束,一文带你了解
  18. 02操作符(Operators)操作符
  19. java 设计模式 路由器_java设计模式2————工厂模式
  20. 股票查询系统,模糊查询,判断数值,字典,列表,字符串的运用python

热门文章

  1. how to rank conferences or journals?
  2. 为什么一定要好好睡觉?
  3. UNITY 内存问题资料收集
  4. python中引用上层路径
  5. JSF Tree学习...
  6. 洛谷 1858 多人背包
  7. 外媒炒作中国黑客入侵美保险公司 并无相关证据
  8. 走进AngularJs(六) 服务
  9. 不用回调方法捕获数据包
  10. python list遍历