深度学习Matlab工具箱代码注释之cnnbp.m

%%=========================================================================  
%函数名称:cnnbp()  
%输入参数:net,呆训练的神经网络;y,训练样本的标签,即期望输出  
%输出参数:net,经过BP算法训练得到的神经网络  
%主要功能:通过BP算法训练神经网络参数  
%实现步骤:1)将输出的残差扩展成与最后一层的特征map相同的尺寸形式  
%         2)如果是卷积层,则进行上采样  
%         3)如果是下采样层,则进行下采样  
%         4)采用误差传递公式对灵敏度进行反向传递  
%注意事项:1)从最后一层的error倒推回来deltas,和神经网络的BP十分相似,可以参考“UFLDL的反向传导算法”的说明  
%         2)在fvd里面保存的是所有样本的特征向量(在cnnff.m函数中用特征map拉成的),所以这里需要重新换回来特征map的形式,  
%            d保存的是delta,也就是灵敏度或者残差  
%         3)net.o .* (1 - net.o))代表输出层附加的非线性函数的导数,即sigm函数的导数  
%%=========================================================================  
function net = cnnbp(net, y)  
n     = numel(net.layers);                         %网络层数  
net.e = net.o - y;                                 %实际输出与期望输出之间的误差  
net.L = 1/2* sum(net.e(:) .^ 2) / size(net.e, 2);  %代价函数,采用均方误差函数作为代价函数  
net.od = net.e .* (net.o .* (1 - net.o));          %输出层的灵敏度或者残差,(net.o .* (1 - net.o))代表输出层的激活函数的导数  
net.fvd = (net.ffW' * net.od);                     %残差反向传播回前一层,net.fvd保存的是残差  
if strcmp(net.layers{n}.type, 'c')                 %只有卷积层采用sigm函数  
    net.fvd = net.fvd .* (net.fv .* (1 - net.fv)); %net.fv是前一层的输出(未经过simg函数),作为输出层的输入  
end  
 
%%%%%%%%%%%%%%%%%%%%将输出的残差扩展成与最后一层的特征map相同的尺寸形式%%%%%%%%%%%%%%%%%%%%  
sa    = size(net.layers{n}.a{1});           %最后一层特征map的大小。这里的最后一层都是指输出层的前一层  
fvnum = sa(1) * sa(2);                      %因为是将最后一层特征map拉成一条向量,所以对于一个样本来说,特征维数是这样  
for j = 1 : numel(net.layers{n}.a)          %最后一层的特征map的个数  
    net.layers{n}.d{j} = reshape(net.fvd(((j - 1) * fvnum + 1) : j * fvnum, :), sa(1), sa(2), sa(3));  
end  
 
for l = (n - 1) : -1 : 1                    %对于输出层前面的层(与输出层计算残差的方式不同)  
 if strcmp(net.layers{l}.type, 'c')      %如果是卷积层,则进行上采样  
 for j = 1 : numel(net.layers{l}.a)  %该层特征map的个数  
            %%=========================================================================  
            %主要功能:卷积层的灵敏度误差传递  
            %注意事项:1)net.layers{l}.d{j} 保存的是 第l层 的 第j个 map 的 灵敏度map。 也就是每个神经元节点的delta的值  
            %            expand的操作相当于对l+1层的灵敏度map进行上采样。然后前面的操作相当于对该层的输入a进行sigmoid求导  
            %            这条公式请参考 Notes on Convolutional Neural Networks  
            %%=========================================================================  
            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);  
        end  
 
    elseif strcmp(net.layers{l}.type, 's')            %如果是下采样层,则进行下采样  
        %%=========================================================================  
        %主要功能:下采样层的灵敏度误差传递  
        %注意事项:1)这条公式请参考 Notes on Convolutional Neural Networks  
        %%=========================================================================  
 for i = 1 : numel(net.layers{l}.a)            %第i层特征map的个数  
            z = zeros(size(net.layers{l}.a{1}));  
 for j = 1 : numel(net.layers{l + 1}.a)    %第l+1层特征map的个数  
                z = z + convn(net.layers{l + 1}.d{j}, rot180(net.layers{l + 1}.k{i}{j}), 'full');  
            end  
            net.layers{l}.d{i} = z;  
        end  
    end  
end  
 
%%=========================================================================  
%主要功能:计算梯度  
%实现步骤:  
%注意事项:1)这里与Notes on Convolutional Neural Networks中不同,这里的子采样层没有参数,也没有  
%            激活函数,所以在子采样层是没有需要求解的参数的  
%%=========================================================================  
for l = 2 : n  
 if strcmp(net.layers{l}.type, 'c')  
 for j = 1 : numel(net.layers{l}.a)  
 for i = 1 : numel(net.layers{l - 1}.a)  
 
                %%%%%%%%%%%%%%%%%%%%dk保存的是误差对卷积核的导数%%%%%%%%%%%%%%%%%%%%  
                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);  
            end  
 
            %%%%%%%%%%%%%%%%%%%%db保存的是误差对于bias基的导数%%%%%%%%%%%%%%%%%%%%  
            net.layers{l}.db{j} = sum(net.layers{l}.d{j}(:)) / size(net.layers{l}.d{j}, 3);  
        end  
    end  
end  
 
%%%%%%%%%%%%%%%%%%%%最后一层perceptron的gradient的计算%%%%%%%%%%%%%%%%%%%%  
net.dffW = net.od * (net.fv)' / size(net.od, 2);  
net.dffb = mean(net.od, 2);  
 
    function X = rot180(X)  
        X = flipdim(flipdim(X, 1), 2);  
    end  
end  

量化投资与机器学习

知识、能力、深度、专业

勤奋、天赋、耐得住寂寞

原文发布于微信公众号 - 量化投资与机器学习(ZXL_LHTZ_JQXX)

原文发表时间:2015-11-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨熹的专栏

详解 LSTM

今天的内容有: LSTM 思路 LSTM 的前向计算 LSTM 的反向传播 关于调参 ---- LSTM 长短时记忆网络(Long Short Term Mem...

5115
来自专栏深度学习那些事儿

利用pytorch实现神经网络风格迁移Neural Transfer

载入图像输入大小无要求,最终会被剪裁到相同大小,这是因为神经网络设计了一个特定的输入大小,因此内容图像和风格图像必须大小一致。

3537
来自专栏决胜机器学习

机器学习(十一) ——神经网络基础

机器学习(十一)——神经网络基础 (原创内容,转载请注明来源,谢谢) 一、概述 神经网络,可以理解为输入的内容,经过一系列的内部的处理,得到输出的假设函数。简...

3836
来自专栏PPV课数据科学社区

TensorFlow基本操作 实现卷积和池化

之前已经提到过图像卷积的操作和意义,并且用OpenCV中的filter2D函数实现了一些例子。OpenCV中的filter2D函数仅仅是用一个卷积核去卷积单个的...

1082
来自专栏深度学习那些事儿

利用pytorch实现神经网络风格迁移Neural Transfer

载入图像输入大小无要求,最终会被剪裁到相同大小,这是因为神经网络设计了一个特定的输入大小,因此内容图像和风格图像必须大小一致。

4242
来自专栏ATYUN订阅号

一文带你认识深度学习中不同类型的卷积

卷积(convolution)现在可能是深度学习中最重要的概念。靠着卷积和卷积神经网络(CNN),深度学习超越了几乎其它所有的机器学习手段。 ? 这篇文章将简要...

4599
来自专栏瓜大三哥

竞争型神经网络续1

1.竞争神经网络函数 1.1创建函数 1.1.1 newc函数 newc函数用于创建一个竞争层,这是一个旧版本的函数,现在用competlayer函数代替。函数...

40910
来自专栏人工智能LeadAI

黑猿大叔-译文 | TensorFlow实现Batch Normalization

原文:Implementing Batch Normalization in Tensorflow(https://r2rt.com/implementing-...

5538
来自专栏机器学习算法工程师

趣谈深度学习核心----激活函数

作者:詹晓辉 编辑:王抒伟 当你在苦扒图像处理方法得时候 他在用深度学习 当你在干瞪切片像素得时候 他在用深度学习 当你在愁思小偷是谁得时候 他在用深度学习 当...

3817
来自专栏Pytorch实践

Pytorch实现Logistic回归二分类

? 摘要:本文主要介绍使用深度学习框架Pytorch实现简单的Logistic回归模型,进而实现简单的分类问题。 一.逻辑回归简述 逻辑回归实质上是线性回...

1.3K14

扫码关注云+社区

领取腾讯云代金券