卷积神经网络CNN相关代码注释

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

cnnexamples.m[plain]viewplaincopy1.clearall;closeall;clc;2.addpath('../data');3.addpath('../util');4.loadmnist_uint8;5.6.train_x=double(reshape(train_x',28,28,60000))/255;7.test_x=double(reshape(test_x',28,28,10000))/255;8.train_y=double(train_y');9.test_y=double(test_y');10.11.%%ex112.%willrun1epochinabout200secondandgetaround11%error.13.%With100epochsyou'llgetaround1.2%error14.15.cnn.layers={16.struct('type','i')%inputlayer17.struct('type','c','outputmaps',6,'kernelsize',5)%convolutionlayer18.struct('type','s','scale',2)%subsamplinglayer19.struct('type','c','outputmaps',12,'kernelsize',5)%convolutionlayer20.struct('type','s','scale',2)%subsamplinglayer21.};22.23.%这里把cnn的设置给cnnsetup,它会据此构建一个完整的CNN网络,并返回24.cnn=cnnsetup(cnn,train_x,train_y);25.26.%学习率27.opts.alpha=1;28.%每次挑出一个batchsize的batch来训练,也就是每用batchsize个样本就调整一次权值,而不是29.%把所有样本都输入了,计算所有样本的误差了才调整一次权值30.opts.batchsize=50;31.%训练次数,用同样的样本集。我训练的时候:32.%1的时候11.41%error33.%5的时候4.2%error34.%10的时候2.73%error35.opts.numepochs=10;36.37.%然后开始把训练样本给它,开始训练这个CNN网络38.cnn=cnntrain(cnn,train_x,train_y,opts);39.40.%然后就用测试样本来测试41.[er,bad]=cnntest(cnn,test_x,test_y);42.43.%plotmeansquarederror44.plot(cnn.rL);45.%showtesterror46.disp([num2str(er*100)'%error']);cnnsetup.m[plain]viewplaincopy1.functionnet=cnnsetup(net,x,y)2.inputmaps=1;3.%B=squeeze(A)返回和矩阵A相同元素但所有单一维都移除的矩阵B,单一维是满足size(A,dim)=1的维。4.%train_x中图像的存放方式是三维的reshape(train_x',28,28,60000),前面两维表示图像的行与列,5.%第三维就表示有多少个图像。这样squeeze(x(:,:,1))就相当于取第一个图像样本后,再把第三维6.%移除,就变成了28x28的矩阵,也就是得到一幅图像,再size一下就得到了训练样本图像的行数与列数了7.mapsize=size(squeeze(x(:,:,1)));8.9.%下面通过传入net这个结构体来逐层构建CNN网络10.%n=numel(A)返回数组A中元素个数11.%net.layers中有五个struct类型的元素,实际上就表示CNN共有五层,这里范围的是512.forl=1:numel(net.layers)%layer13.ifstrcmp(net.layers{l}.type,'s')%如果这层是子采样层14.%subsampling层的mapsize,最开始mapsize是每张图的大小28*2815.%这里除以scale=2,就是pooling之后图的大小,pooling域之间没有重叠,所以pooling后的图像为14*1416.%注意这里的右边的mapsize保存的都是上一层每张特征map的大小,它会随着循环进行不断更新17.mapsize=floor(mapsize/net.layers{l}.scale);18.forj=1:inputmaps%inputmap就是上一层有多少张特征图19.net.layers{l}.b{j}=0;%将偏置初始化为020.end21.end22.ifstrcmp(net.layers{l}.type,'c')%如果这层是卷积层23.%旧的mapsize保存的是上一层的特征map的大小,那么如果卷积核的移动步长是1,那用24.%kernelsize*kernelsize大小的卷积核卷积上一层的特征map后,得到的新的map的大小就是下面这样25.mapsize=mapsize-net.layers{l}.kernelsize+1;26.%该层需要学习的参数个数。每张特征map是一个(后层特征图数量)*(用来卷积的patch图的大小)27.%因为是通过用一个核窗口在上一个特征map层中移动(核窗口每次移动1个像素),遍历上一个特征map28.%层的每个神经元。核窗口由kernelsize*kernelsize个元素组成,每个元素是一个独立的权值,所以29.%就有kernelsize*kernelsize个需要学习的权值,再加一个偏置值。另外,由于是权值共享,也就是30.%说同一个特征map层是用同一个具有相同权值元素的kernelsize*kernelsize的核窗口去感受输入上一31.%个特征map层的每个神经元得到的,所以同一个特征map,它的权值是一样的,共享的,权值只取决于32.%核窗口。然后,不同的特征map提取输入上一个特征map层不同的特征,所以采用的核窗口不一样,也33.%就是权值不一样,所以outputmaps个特征map就有(kernelsize*kernelsize+1)*outputmaps那么多的权值了34.%但这里fan_out只保存卷积核的权值W,偏置b在下面独立保存35.fan_out=net.layers{l}.outputmaps*net.layers{l}.kernelsize^2;36.forj=1:net.layers{l}.outputmaps%outputmap37.%fan_out保存的是对于上一层的一张特征map,我在这一层需要对这一张特征map提取outputmaps种特征,38.%提取每种特征用到的卷积核不同,所以fan_out保存的是这一层输出新的特征需要学习的参数个数39.%而,fan_in保存的是,我在这一层,要连接到上一层中所有的特征map,然后用fan_out保存的提取特征40.%的权值来提取他们的特征。也即是对于每一个当前层特征图,有多少个参数链到前层41.fan_in=inputmaps*net.layers{l}.kernelsize^2;42.fori=1:inputmaps%inputmap43.%随机初始化权值,也就是共有outputmaps个卷积核,对上层的每个特征map,都需要用这么多个卷积核44.%去卷积提取特征。45.%rand(n)是产生n×n的0-1之间均匀取值的数值的矩阵,再减去0.5就相当于产生-0.5到0.5之间的随机数46.%再*2就放大到[-1,1]。然后再乘以后面那一数,why?47.%反正就是将卷积核每个元素初始化为[-sqrt(6/(fan_in+fan_out)),sqrt(6/(fan_in+fan_out))]48.%之间的随机数。因为这里是权值共享的,也就是对于一张特征map,所有感受野位置的卷积核都是一样的49.%所以只需要保存的是inputmaps*outputmaps个卷积核。50.net.layers{l}.k{i}{j}=(rand(net.layers{l}.kernelsize)-0.5)*2*sqrt(6/(fan_in+fan_out));51.end52.net.layers{l}.b{j}=0;%将偏置初始化为053.end54.%只有在卷积层的时候才会改变特征map的个数,pooling的时候不会改变个数。这层输出的特征map个数就是55.%输入到下一层的特征map个数56.inputmaps=net.layers{l}.outputmaps;57.end58.end59.60.%fvnum是输出层的前面一层的神经元个数。61.%这一层的上一层是经过pooling后的层,包含有inputmaps个特征map。每个特征map的大小是mapsize。62.%所以,该层的神经元个数是inputmaps*(每个特征map的大小)63.%prod:Productofelements.64.%Forvectors,prod(X)istheproductoftheelementsofX65.%在这里mapsize=[特征map的行数特征map的列数],所以prod后就是特征map的行*列66.fvnum=prod(mapsize)*inputmaps;67.%onum是标签的个数,也就是输出层神经元的个数。你要分多少个类,自然就有多少个输出神经元68.onum=size(y,1);69.70.%这里是最后一层神经网络的设定71.%ffb是输出层每个神经元对应的基biases72.net.ffb=zeros(onum,1);73.%ffW输出层前一层与输出层连接的权值,这两层之间是全连接的74.net.ffW=(rand(onum,fvnum)-0.5)*2*sqrt(6/(onum+fvnum));75.endcnntrain.m[plain]viewplaincopy1.functionnet=cnntrain(net,x,y,opts)2.m=size(x,3);%m保存的是训练样本个数3.numbatches=m/opts.batchsize;4.%rem:Remainderafterdivision.rem(x,y)isx-n.*y相当于求余5.%rem(numbatches,1)就相当于取其小数部分,如果为0,就是整数6.ifrem(numbatches,1)~=07.error('numbatchesnotinteger');8.end9.10.net.rL=[];11.fori=1:opts.numepochs12.%disp(X)打印数组元素。如果X是个字符串,那就打印这个字符串13.disp(['epoch'num2str(i)'/'num2str(opts.numepochs)]);14.%tic和toc是用来计时的,计算这两条语句之间所耗的时间15.tic;16.%P=randperm(N)返回[1,N]之间所有整数的一个随机的序列,例如17.%randperm(6)可能会返回[245613]18.%这样就相当于把原来的样本排列打乱,再挑出一些样本来训练19.kk=randperm(m);20.forl=1:numbatches21.%取出打乱顺序后的batchsize个样本和对应的标签22.batch_x=x(:,:,kk((l-1)*opts.batchsize+1:l*opts.batchsize));23.batch_y=y(:,kk((l-1)*opts.batchsize+1:l*opts.batchsize));24.25.%在当前的网络权值和网络输入下计算网络的输出26.net=cnnff(net,batch_x);

1 / 11
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功