欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MatConvNet的excise 3改为网络配置文件形式

程序员文章站 2022-06-09 12:26:09
...
MatConvNet为vlFeat作者写的matlab下的卷积神经网络工具包,可以使用GPU。
主页:http://www.vlfeat.org/matconvnet/
教程:http://www.robots.ox.ac.uk/~vgg/practicals/cnn/index.html

注意:需要下载新版的MatConvNet替换掉教程中工具包中的matconvnet:http://www.vlfeat.org/matconvnet/download/matconvnet-1.0-beta12.tar.gz


本文程序和excise3效果一致,但使用了MatConvNet的examples中类似的网络结构进行定义,可以使用cnn_train函数进行训练。
内容:
  • 演示了自定义网络层、自定义误差函数的方法
  • 演示了自定义errorFunction的方法
  • 演示了对于不同参数分别设置learning rate和weight decay 的方法


不多说,上代码,注释很详细:

function LC_Ex3_usingNetStructure
clc
% -------------------------------------------------------------------------
% Part 3: Learning a simple CNN  改为了使用网络定义
% -------------------------------------------------------------------------
% 改写http://www.robots.ox.ac.uk/~vgg/practicals/cnn/index.htm  的 exercise 3为一个网络
%  注意:MatConvNet工具包已经替换为新版:http://www.vlfeat.org/matconvnet/download/matconvnet-1.0-beta12.tar.gz


setup ;
%%

doSmooth=false;
subMean=false;

doSmooth=true;
subMean=true;


wSize=9;
% -------------------------------------------------------------------------
% Part 3.1: Load an example image and generate its labels
% -------------------------------------------------------------------------
%%
% Load an image
im = rgb2gray(im2single(imread('data/dots.jpg'))) ;

% Compute the location of black blobs in the image
[pos,neg] = extractBlackBlobs(im) ;

%%
% -------------------------------------------------------------------------
% Part 3.2: Image preprocessing
% -------------------------------------------------------------------------

% Pre-smooth the image
if(doSmooth)
    im = vl_imsmooth(im,3) ;
end
%%
% Subtract median value
if(subMean)
    im = im - median(im(:)) ;
end



%% Create pixel-level labels to compute the loss
y = zeros(size(pos),'single') ;
y(pos) = +1 ;
y(neg) = -1 ;


%%  转换为imdb格式

imdb.images.data = {im} ;
imdb.images.labels = {y} ; %labels的数据结构完全由自己决定,与getBatch函数以及误差层的backward函数兼容即可(在backward函数中以layer.class形式出现,layer.class等于getBatch函数的返回值labels);对于分类问题,一般为[1,1,2,2]等类别信息
imdb.images.set = [1];%  样本类型,1为训练样本,2为validation样本,3为测试样本,,但是cnn_train函数只会对训练样本和测试样本进行计算
imdb.meta.sets = {'train', 'val', 'test'} ;%集合名称,即1代表训练集,2代表val集(validation)
imdb.meta.classes ={'1'}; %类别名称




%% -------------------------------------------------------------------------
% Part 3.3: Learning with stochastic gradient descent
% -------------------------------------------------------------------------

trainOpts.batchSize = 1 ;
trainOpts.numEpochs = 500 ; %运行多少轮
trainOpts.continue = false ;%如果trainOpts.expDir已经有对应epoch的网络,是否直接载入
trainOpts.gpus=[]; %gpu下标,不使用GPU则设为[],,如果有两个GPU可以设为 [1 2]
trainOpts.learningRate =.5 ;
trainOpts.expDir = 'data/ex3-experiment' ; %输出的网络结果、实验结果图存在哪儿
trainOpts.momentum=0.9;
trainOpts.weightDecay = 0.0001 ;

trainOpts.errorFunction=@error_ErrPixels; %用于显示误差的自定义函数
trainOpts.errorLabels ={'错误率'};

net=LC_CNN_Ex3('wSize',wSize); %将pos,neg均传给网络,记录到输出层的结构中,便于根据之前的公式计算误差





trainOpts.val=   imdb.images.set==1;  %验证集下标,,必须有验证集,否则报错。。。只好把训练集当成验证集了
[net, info] = cnn_train(net, imdb, @getBatch, ...
    trainOpts) ;

end


%只有一幅图片,直接返回就行了
function  [im, labels]=getBatch(imdb,batch)
   im= imdb.images.data{1};
   im=reshape(im,[size(im) 1]);
   labels=imdb.images.labels{1};
end


%绘图用,用于检测不同epoch下网络的性能,这里返回的指标为分类错误率
function err = error_ErrPixels(opts, labels, res)
% -------------------------------------------------------------------------
resX=res(end-1).x;
y=labels;
        fp = resX >0 & y < 0 ;
        fn = resX < 1 & y > 0 ;
        tn = resX <= 0 & y < 0 ;
        tp = resX >= 1 & y > 0 ;
% err=[fp;fn;tn;tp]; %可以设置多个指标,对应的trainOpts.errorLabels 也要改为多个标签
err=100*(1-sum(sum(tp|tn))/sum(sum(fp|fn|tp|tn)));
end



function net=LC_CNN_Ex3(varargin)
% 改写http://www.robots.ox.ac.uk/~vgg/practicals/cnn/index.html  的 exercise 3为一个网络

opts.wSize=3;
opts=vl_argparse(opts,varargin);


net.layers = {} ;

lr=ones(1,10); 
weightDecay=[1 0];
w = 10 * randn(opts.wSize,opts.wSize, 1) ;  %最后一个表示输出只有一个通道
w = single(w - mean(w(:))) ;
b = single(0) ;
pad1 = ([size(w,1) size(w,1) size(w,2) size(w,2)] - 1) / 2 ;
net.layers{end+1}= struct('type', 'conv', ...
    'weights', {{w, b}}, ...
    'learningRate', [1 2], ...  %自定义learning rate相对于全局的learning rate 的比率,[1 2] 表示w的学习率与全局学习率一致,而偏置b的学习率则为全局学习率的两倍
    'weightDecay',weightDecay,...;%自定义weightDecay相对于全局的weightDecay的比率,[1 0]表示只对w矩阵进行weight decay,而不对偏置b进行weight decay
    'stride', 1, ...
    'pad', pad1) ;

rho2 = 3 ;
pad2 = (rho2 - 1) / 2 ;
net.layers{end+1}= struct('type', 'pool', ...
    'method', 'max', ...
    'pool', rho2, ...
    'stride', 1, ...
    'pad', pad2) ;



%% 自定义的误差函数层
net.layers{end+1}= struct('type', 'custom', ...
    'forward', @forwardFunc , ...  %
    'backward', @backwardFunc) ;
end


function resIp1= forwardFunc(layer, resI, resIp1)   % 计算数据项误差
pos=layer.class==1;
neg=layer.class==-1;
resIp1.x=  mean(max(0, 1 - resI.x(pos))) + ...
    mean(max(0, resI.x(neg)));
end

%后向传播,,求导;;;注意layer.class为该batch内图片的labels。
function resI = backwardFunc(layer, resI, resIp1)  %计算导数

pos=layer.class==1;
neg=layer.class==-1;
resI.dzdx=- single(resI.x < 1 & pos) / sum(pos(:)) + ...
    + single(resI.x > 0 & neg) / sum(neg(:)) ;
end
相关标签: matlab