functiontest_example_CNNloadmnist_uint8;train_x=double(reshape(train_x',28,28,60000))/255;test_x=double(reshape(test_x',28,28,10000))/255;train_y=double(train_y');test_y=double(test_y');%%ex1Traina6c-2s-12c-2sConvolutionalneuralnetwork%willrun1epochinabout200secondandgetaround11%error.%With100epochsyou'llgetaround1.2%errorcnn.layers={struct('type','i')%inputlayerstruct('type','c','outputmaps',6,'kernelsize',5)%convolutionlayerstruct('type','s','scale',2)%subsamplinglayerstruct('type','c','outputmaps',12,'kernelsize',5)%convolutionlayerstruct('type','s','scale',2)%subsamplinglayer};cnn=cnnsetup(cnn,train_x,train_y);opts.alpha=1;opts.batchsize=50;opts.numepochs=1;cnn=cnntrain(cnn,train_x,train_y,opts);[er,bad]=cnntest(cnn,test_x,test_y);%plotmeansquarederrorfigure;plot(cnn.rL);assert(er0.12,'Toobigerror');functionnet=cnnsetup(net,x,y)inputmaps=1;mapsize=size(squeeze(x(:,:,1)));forl=1:numel(net.layers)%layerifstrcmp(net.layers{l}.type,'s')mapsize=mapsize/net.layers{l}.scale;assert(all(floor(mapsize)==mapsize),['Layer'num2str(l)'sizemustbeinteger.Actual:'num2str(mapsize)]);forj=1:inputmapsnet.layers{l}.b{j}=0;endendifstrcmp(net.layers{l}.type,'c')mapsize=mapsize-net.layers{l}.kernelsize+1;fan_out=net.layers{l}.outputmaps*net.layers{l}.kernelsize^2;forj=1:net.layers{l}.outputmaps%outputmapfan_in=inputmaps*net.layers{l}.kernelsize^2;fori=1:inputmaps%inputmapnet.layers{l}.k{i}{j}=(rand(net.layers{l}.kernelsize)-0.5)*2*sqrt(6/(fan_in+fan_out));endnet.layers{l}.b{j}=0;endinputmaps=net.layers{l}.outputmaps;endend%'onum'isthenumberoflabels,that'swhyitiscalculatedusingsize(y,1).Ifyouhave20labelssotheoutputofthenetworkwillbe20neurons.%'fvnum'isthenumberofoutputneuronsatthelastlayer,thelayerjustbeforetheoutputlayer.%'ffb'isthebiasesoftheoutputneurons.%'ffW'istheweightsbetweenthelastlayerandtheoutputneurons.Notethatthelastlayerisfullyconnectedtotheoutputlayer,that'swhythesizeoftheweightsis(onum*fvnum)fvnum=prod(mapsize)*inputmaps;onum=size(y,1);net.ffb=zeros(onum,1);net.ffW=(rand(onum,fvnum)-0.5)*2*sqrt(6/(onum+fvnum));endfunctionnet=cnntrain(net,x,y,opts)m=size(x,3);numbatches=m/opts.batchsize;ifrem(numbatches,1)~=0error('numbatchesnotinteger');endnet.rL=[];fori=1:opts.numepochsdisp(['epoch'num2str(i)'/'num2str(opts.numepochs)]);tic;kk=randperm(m);forl=1:numbatchesbatch_x=x(:,:,kk((l-1)*opts.batchsize+1:l*opts.batchsize));batch_y=y(:,kk((l-1)*opts.batchsize+1:l*opts.batchsize));net=cnnff(net,batch_x);net=cnnbp(net,batch_y);net=cnnapplygrads(net,opts);ifisempty(net.rL)net.rL(1)=net.L;endnet.rL(end+1)=0.99*net.rL(end)+0.01*net.L;endtoc;endendfunctionnet=cnnff(net,x)n=numel(net.layers);net.layers{1}.a{1}=x;inputmaps=1;forl=2:n%foreachlayerifstrcmp(net.layers{l}.type,'c')%!!belowcanprobablybehandledbyinsanematrixoperationsforj=1:net.layers{l}.outputmaps%foreachoutputmap%createtempoutputmapz=zeros(size(net.layers{l-1}.a{1})-[net.layers{l}.kernelsize-1net.layers{l}.kernelsize-10]);fori=1:inputmaps%foreachinputmap%convolvewithcorrespondingkernelandaddtotempoutputmapz=z+convn(net.layers{l-1}.a{i},net.layers{l}.k{i}{j},'valid');end%addbias,passthroughnonlinearitynet.layers{l}.a{j}=sigm(z+net.layers{l}.b{j});end%setnumberofinputmapstothislayersnumberofoutputmapsinputmaps=net.layers{l}.outputmaps;elseifstrcmp(net.layers{l}.type,'s')%downsampleforj=1:inputmapsz=convn(net.layers{l-1}.a{j},ones(net.layers{l}.scale)/(net.layers{l}.scale^2),'valid');%!!replacewithvariablenet.layers{l}.a{j}=z(1:net.layers{l}.scale:end,1:net.layers{l}.scale:end,:);endendend%concatenateallendlayerfeaturemapsintovectornet.fv=[];forj=1:numel(net.layers{n}.a)sa=size(net.layers{n}.a{j});net.fv=[net.fv;reshape(net.layers{n}.a{j},sa(1)*sa(2),sa(3))];end%feedforwardintooutputperceptronsnet.o=sigm(net.ffW*net.fv+repmat(net.ffb,1,size(net.fv,2)));endfunctionnet=cnnbp(net,y)n=numel(net.layers);%errornet.e=net.o-y;%lossfunctionnet.L=1/2*sum(net.e(:).^2)/size(net.e,2);%%backpropdeltasnet.od=net.e.*(net.o.*(1-net.o));%outputdeltanet.fvd=(net.ffW'*net.od);%featurevectordeltaifstrcmp(net.layers{n}.type,'c')%onlyconvlayershassigmfunctionnet.fvd=net.fvd.*(net.fv.*(1-net.fv));end%reshapefeaturevectordeltasintooutputmapstylesa=size(net.layers{n}.a{1});fvnum=sa(1)*sa(2);forj=1:numel(net.layers{n}.a)net.layers{n}.d{j}=reshape(net.fvd(((j-1)*fvnum+1):j*fvnum,:),sa(1),sa(2),sa(3));endforl=(n-1):-1:1ifstrcmp(net.layers{l}.type,'c')forj=1:numel(net.layers{l}.a)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}.scalenet.layers{l+1}.scale1])/net.layers{l+1}.scale^2);endelseifstrcmp(net.layers{l}.type,'s')fori=1:numel(net.layers{l}.a)z=zeros(size(net.layers{l}.a{1}));forj=1:numel(net.layers{l+1}.a)z=z+convn(net.layers{l+1}.d{j},rot180(net.layers{l+1}.k{i}{j}),'full');endnet.layers{l}.d{i}=z;endendend%%calcgradientsforl=2:nifstrcmp(net.layers{l}.type,'c')forj=1:numel(net.layers{l}.a)fori=1:numel(net.layers{l-1}.a)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);e