matconvnet环境下训练自己的数据集及模型测试-mnist网络结构-cifar10部分数据集
2017-10-27 15:17
971 查看
摘要
网络结构:mnist的LeNet结构数据集:cifar10中的batch1和batch2
准确率:测试集测试51.37%
我将下载好的cifar-10数据可视化为图片后,这样就可以假装是自己的数据集了,毕竟以后任何的图片数据集我都会操作了。将batch1和batch2做成和mnist的mat数据结构一样的mat结构(其实就是依样画葫芦,mnist怎么存储的我就怎么存储的,保持所有格式一致),我用batch1的10000张图片做训练集,用batch2的10000张图片做验证集。然后修改mnist网络的数据参数(conv、pooling层的参数要自己计算),这样就训练出自己数据的模型了,然后写程序测试模型的准确率。
制作数据集
cifar10可视化,之前说过matlab环境下的cifar10数据可视化参照mnist的数据格式:mnist的imdb.mat文件包含一个images和一个meta
data中为28*28*1*70000的数据集,其中60000为训练集,10000为验证集
sets中是三个标签,set = 1为训练集,set = 2为测试集,set = 3为验证集
class中是10个类别
前面说过cifar10中共20000张图片,训练验证各一半,每张大小为32*32*3,制作数据集的时候会在第四维上进行联结,所以我们的data大小为32*32*3*20000,其它不变
制作数据集代码如下:
%将cifar10的图像构建成和mnist相似的数据体格式 % 读取一个文件夹的多幅图片,如果为单通道图片则为I(:,:,k) imgpath1 = ('E:\2-科研\2-实验\cifar-10-batches-mat\image\data_batch_1\'); di1 = dir(fullfile(imgpath1,'*.png')); for k= 1:length(di1) I(:,:,:,k) = imread([imgpath1,di1(k).name]); end %读一张图片验证 %I1 = imread(fullfile(imgpath,'batch_label_0_116.png')); %将其转为double型 data1 = im2double(I); for k= 1:length(di1) label1(1,k) = str2num(di1(k).name(13:13)); end % --------------------------------------------------------------------- imgpath2 = ('E:\2-科研\2-实验\cifar-10-batches-mat\image\data_batch_2\'); di2 = dir(fullfile(imgpath1,'*.png')); for k= 1:length(di2) I2(:,:,:,k) = imread([imgpath1,di2(k).name]); end data2 = im2double(I2); for k= 1:length(di2) label2(1,k) = str2num(di2(k).name(13:13)); end % ---------------------------------------------------------------------------- % imdb结构体: % 1. 这是用于cnn_train中的结构体,也就是实际训练的部分。 % 2. 该结构体内共有4个部分,由data,label,set,class组成。 % data:包含了train data和test data。 % label:包含了train label和test label。 % set:set的个数个label的个数是相等的,set=1表示这个数据是train data,set=3则表示这个数据是test data。 以此方法用于计算机自己判断的标准。 % class:于数据中的class完全一样。 % 3. imdb构造时遵循train在上层,test在下层的顺序。 % 4. 相关的data需要进行泛化处理。 % -------------------------------------------------------------------- %计算出训练数据集中所有图像的均值 %set = 1 对应训练;set = 3 对应的是测试 set = [ones(1,numel(label1)) 3*ones(1,numel(label2))];%numel返回元素的总数 data = single(cat(4,data1,data2)); %将x1的训练数据集和x2的测试数据集的第三个维度进行拼接组成新的数据集,并且转为single型减少内存 dataMean = mean(data1(:,:,:,:), 4);%求出训练数据集中所有的图像的均值 dataMean = single(dataMean); data = bsxfun(@minus, data, dataMean) ; %利用bsxfun函数将数据集中的每个元素逐个减去均值 % --------------------------------------------------------------------- %将数据存入imdb结构中 mycifar_batch1_2_imdb.images.data = data ;%data的大小为[32 32 3 20000]前10000训练,后10000测试 mycifar_batch1_2_imdb.images.data_mean = dataMean; %dataMean的大小为[32 32 3] mycifar_batch1_2_imdb.images.labels = cat(2, label1, label2) ; %拼接训练数据集和测试数据集的标签,拼接后的大小为[1 20000] mycifar_batch1_2_imdb.images.set = set ; %set的大小为[1 20000],unique(set) = [1 3] mycifar_batch1_2_imdb.meta.sets = {'train', 'val', 'test'} ; %imdb.meta.sets=1用于训练,imdb.meta.sets=2用于验证,imdb.meta.sets=3用于测试 %读入类别 mycifar_batch1_2_imdb.meta.class = {'airplane' 'automobile' 'bird' 'cat' 'deer' 'dog' 'frog' 'horse' ' 4000 ship' 'truck'}; %imdb.meta.classes = arrayfun(@(x)sprintf('%d',x),0:9,'uniformoutput',false) ;%arrayfun函数通过应用sprintf函数得到array中从0到9的元素并且将其数字标签转化为char文字型
训练模型
三个函数说明:cnn_mnist_experiments_cifar_my:主函数,主要调用下一个函数,并将结果画图显示
cnn_mnist_cifar_my:最主要的函数,包括各种函数及训练验证的过程
cnn_mnist_init_cifar_my:初始化网络结构的函数,主要是网络参数的设定
1.cnn_mnist_experiments_cifar_my
% Experiment with the mycnn_mnist_fc_bnorm [net_bn, info_bn] = cnn_mnist_cifar_my(... 'expDir', 'data/mnist-bnorm', 'batchNormalization', true); [net_fc, info_fc] = cnn_mnist_cifar_my(... 'expDir', 'data/mnist-baseline', 'batchNormalization', false); figure(1) ; clf ; subplot(1,2,1) ; semilogy([info_fc.val.objective]', 'o-') ; hold all ; semilogy([info_bn.val.objective]', '+--') ; xlabel('Training samples [x 10^3]'); ylabel('energy') ; grid on ; h=legend('BSLN', 'BNORM') ; set(h,'color','none'); title('objective') ; subplot(1,2,2) ; plot([info_fc.val.top1err]', 'o-') ; hold all ; plot([info_fc.val.top5err]', '*-') ; plot([info_bn.val.top1err]', '+--') ; plot([info_bn.val.top5err]', 'x--') ; h=legend('BSLN-val','BSLN-val-5','BNORM-val','BNORM-val-5') ; grid on ; xlabel('Training samples [x 10^3]'); ylabel('error') ; set(h,'color','none') ; title('error') ; drawnow ;
2.cnn_mnist_experiments_cifar_my
function [net, info] = cnn_mnist_cifar_my(varargin) run('E:\2-科研\MatConvNet\matconvnet-1.0-beta25\matconvnet-1.0-beta25\matlab\vl_setupnn.m') ; opts.batchNormalization = false ; %选择batchNormalization的真假 opts.network = [] ; %初始化一个网络 opts.networkType = 'simplenn' ; %选择网络结构 %%% simplenn %%% dagnn [opts, varargin] = vl_argparse(opts, varargin) ; %调用vl_argparse函数 sfx = opts.networkType ; %sfx=simplenn if opts.batchNormalization, sfx = [sfx '-bnorm'] ; end %这里条件为假 opts.expDir = fullfile(vl_rootnn,'my','1025','data',['cifar10-' sfx]) ; %选择数据存放的路径:data\cifar-baseline-simplenn [opts, varargin] = vl_argparse(opts, varargin) ; %调用vl_argparse函数 opts.dataDir = fullfile(vl_rootnn,'my','1025','data', 'cifar10') ; opts.mycifar_batch1_2_imdbPath = fullfile(opts.expDir, 'mycifar_batch1_2_imdb.mat'); %选择mycifar_batch1_2_imdb结构体的路径:data\data\cifar-baseline-simplenn\mycifar_batch1_2_imdb %------------------------------新增加的两句 opts.whitenData = true ; opts.contrastNormalization = true ; %------------------------------------------ opts.train = struct() ; %选择训练集返回为struct型 opts = vl_argparse(opts, varargin) ; %调用vl_argparse函数 % -------------------------------------------------------------------- % Prepare data % -------------------------------------------------------------------- if isempty(opts.network) %如果原网络为空: net = cnn_mnist_init_cifar_my('batchNormalization', opts.batchNormalization, ... % 则调用cnn_cifat_init网络结构 'networkType', opts.networkType) ; else %否则: net = opts.network ; % 使用上面选择的数值带入现有网络 opts.network = [] ; end if exist(opts.mycifar_batch1_2_imdbPath, 'file')%如果cifar中存在mycifar_batch1_2_imdb的结构体: mycifar_batch1_2_imdb = load(opts.mycifar_batch1_2_imdbPath) ; % 载入mycifar_batch1_2_imdb else %否则: mycifar_batch1_2_imdb = getMnistmycifar_batch1_2_imdb(opts) ; % 调用getMnistmycifar_batch1_2_imdb函数得到mycifar_batch1_2_imdb并保存 mkdir(opts.expDir) ; save(opts.mycifar_batch1_2_imdbPath, '-struct', 'mycifar_batch1_2_imdb') ; end %arrayfun函数通过应用sprintf函数得到array中从1到10的元素并且将其数字标签转化为char文字型 net.meta.classes.name = arrayfun(@(x)sprintf('%d',x),1:10,'UniformOutput',false) ; % -------------------------------------------------------------------- % Train % -------------------------------------------------------------------- switch opts.networkType %选择网络类型: case 'simplenn', trainfn = @cnn_train ; % 1.simplenn case 'dagnn', trainfn = @cnn_train_dag ; % 2.dagnn end %调用训练函数,开始训练:find(mycifar_batch1_2_imdb.images.set == 3)为验证集的样本 [net, info] = trainfn(net, mycifar_batch1_2_imdb, getBatch(opts), ... 'expDir', opts.expDir, ... net.meta.trainOpts, ... opts.train, ... 'val', find(mycifar_batch1_2_imdb.images.set == 3)) ; % -------------------------------------------------------------------- function fn = getBatch(opts) %% -------------------------------------------------------------- % 函数名:getBatch % 功能: 1.由opts返回函数 % 2.从imdb结构体取出数据 % 相对于正常数据集,如果Batch_Size过小,训练数据就会非常难收敛,从而导致underfitting。 % 增大Batch_Size,相对处理速度加快。 % 增大Batch_Size,所需内存容量增加(epoch的次数需要增加以达到最好结果)。 % 这里我们发现上面两个矛盾的问题,因为当epoch增加以后同样也会导致耗时增加从而速度下降。因此我们需要寻找最好的batch_size。 % 再次重申:batchsize 的正确选择是为了在内存效率和内存容量之间寻找最佳平衡。 %%-------------------------------------------------------------------- switch lower(opts.networkType) %根据网络类型使用不同的getBatcch case 'simplenn' fn = @(x,y) getSimpleNNBatch(x,y) ; case 'dagnn' bopts = struct('numGpus', numel(opts.train.gpus)) ; fn = @(x,y) getDagNNBatch(bopts,x,y) ; end % -------------------------------------------------------------------- function [images, labels] = getSimpleNNBatch(mycifar_batch1_2_imdb, batch) %% -------------------------------------------------------------- % 函数名:getSimpleNNBatch % 功能: 1.由SimpleNN网络的批得到函数 % 2.batch为样本的索引值 % ------------------------------------------------------------------------ images = mycifar_batch1_2_imdb.images.data(:,:,:,batch) ; labels = mycifar_batch1_2_imdb.images.labels(1,batch) ; % -------------------------------------------------------------------- function inputs = getDagNNBatch(opts, mycifar_batch1_2_imdb, batch) %% -------------------------------------------------------------------- images = mycifar_batch1_2_imdb.images.data(:,:,:,batch) ; labels = mycifar_batch1_2_imdb.images.labels(1,batch) ; if opts.numGpus > 0 images = gpuArray(images) ; end inputs = {'input', images, 'label', labels} ; function mycifar_batch1_2_imdb = getMnistmycifar_batch1_2_imdb(opts) %% -------------------------------------------------------------- % 函数名:getMnistmycifar_batch1_2_imdb % 功能: 1.从mnist数据集中获取data % 2.将得到的数据减去mean值 % 3.将处理后的数据存放如mycifar_batch1_2_imdb结构中 % ------------------------------------------------------------------------ % Preapre the mycifar_batch1_2_imdb structure, returns image data with mean image subtracted load('E:\2-科研\2-实验\mycifar_batch1_2_imdb.mat');
3.cnn_mnist_init_cifar_my
%cifar数据集batch1和batch2 运用mnist的网络来训练 function net = cnn_mnist_init_cifar_my(varargin) % CNN_MNIST_LENET Initialize a CNN similar for MNIST opts.batchNormalization = true ; opts.networkType = 'simplenn' ; opts = vl_argparse(opts, varargin) ; rng('default');%设置随机数发生器,重现每次运行结果? rng(0) ; % 开始构建网络结构,这里是LeNet5 f=1/100 ; net.layers = {} ; net.layers{end+1} = struct('type', 'conv', ... 'weights', {{f*randn(5,5,3,32, 'single'), zeros(1, 32, 'single')}}, ... 'stride', 1, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'pool', ... 'method', 'max', ... 'pool', [2 2], ... 'stride', 2, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'conv', ... 'weights', {{f*randn(5,5,32,50, 'single'),zeros(1,50,'single')}}, ... 'stride', 1, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'pool', ... 'method', 'max', ... 'pool', [2 2], ... 'stride', 2, ... 'pad', 0) ; net.layers{end+1} = struct c0a9 ('type', 'conv', ... 'weights', {{f*randn(5,5,50,500, 'single'), zeros(1,500,'single')}}, ... 'stride', 1, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'relu') ; net.layers{end+1} = struct('type', 'conv', ... 'weights', {{f*randn(1,1,500,10, 'single'), zeros(1,10,'single')}}, ... 'stride', 1, ... 'pad', 0) ; net.layers{end+1} = struct('type', 'softmaxloss') ; % optionally switch to batch normalization if opts.batchNormalization %如果opts.batchNormalization为真: net = insertBnorm(net, 1) ; %在原网络第一层后添加Bnorm net = insertBnorm(net, 4) ; %在原网络第四层后添加Bnorm net = insertBnorm(net, 7) ;%在原网络第七层后添加Bnorm end % Meta parameters结构元参数 net.meta.inputSize = [32 32 3] ; %大小为28*28*1的input data net.meta.trainOpts.learningRate = 0.001 ; %学习率为0.001 net.meta.trainOpts.numEpochs = 2 ; %Epoch为20 net.meta.trainOpts.batchSize = 100 ;%批的大小为100 % Fill in defaul values net = vl_simplenn_tidy(net) ;%添加默认的属性值 % Switch to DagNN if requested switch lower(opts.networkType) case 'simplenn' % done case 'dagnn' net = dagnn.DagNN.fromSimpleNN(net, 'canonicalNames', true) ; net.addLayer('top1err', dagnn.Loss('loss', 'classerror'), ... {'prediction', 'label'}, 'error') ; net.addLayer('top5err', dagnn.Loss('loss', 'topkerror', ... 'opts', {'topk', 5}), {'prediction', 'label'}, 'top5err') ; otherwise assert(false) ; end % -------------------------------------------------------------------- function net = insertBnorm(net, l) % -------------------------------------------------------------------- assert(isfield(net.layers{l}, 'weights')); %断言以确保第l层有权重项 ndim = size(net.layers{l}.weights{1}, 4); %第l层的神经元的个数(卷积核个数) layer = struct('type', 'bnorm', ... 'weights', {{ones(ndim, 1, 'single'), zeros(ndim, 1, 'single')}}, ... 'learningRate', [1 1 0.05], ... 'weightDecay', [0 0]) ;%Bnorm层的权值=上一层的神经元个数 net.layers{l}.weights{2} = [] ; % eliminate bias in previous conv layer net.layers = horzcat(net.layers(1:l), layer, net.layers(l+1:end)) ;
4.测试模型的准确率
这里用的是验证集的图片,accurcy = 51.37%%% 测试所有图片 run('E:\2-科研\MatConvNet\matconvnet-1.0-beta25\matconvnet-1.0-beta25\matlab\vl_setupnn.m') ; load('E:\2-科研\MatConvNet\matconvnet-1.0-beta25\matconvnet-1.0-beta25\my\1025\data\mnist-bnorm1\net-epoch-20.mat') ; mycifar_batch1_2_imdb = load('E:\2-科研\MatConvNet\matconvnet-1.0-beta25\matconvnet-1.0-beta25\my\1025\data\mnist-bnorm\mycifar_batch1_2_imdb.mat'); test_index = find(mycifar_batch1_2_imdb.images.set==3); test_data = mycifar_batch1_2_imdb.images.data(:,:,:,test_index); test_label =mycifar_batch1_2_imdb.images.labels(test_index); net = vl_simplenn_tidy(net) ; net.layers{1,end}.type = 'softmax'; for i = 1:length(test_label) i im_ = test_data(:,:,:,i); im_ = im_ - mycifar_batch1_2_imdb.images.data_mean; res = vl_simplenn(net, im_,[], [], ... 'accumulate', 0, ... 'mode', 'test', ... 'backPropDepth', Inf, ... 'sync', 0, ... 'cudnn', 1); scores = squeeze(gather(res(end).x)) ; [bestScore, best] = max(scores) ; pre(i) = best; end % 计算准确率 accurcy = length(find(pre==test_label))/length(test_label); disp(['accurcy = ',num2str(accurcy*100),'%']);
致谢
在这一整个网络的折腾中其实参考了很多的博客,但尤其是这两个博客的帮助最大:深度学习12:能力提升, 一步一步的介绍如何自己构建网络和训练,利用MatConvNet
MatConvNet框架下mnist数据集测试
想说
这个系列折腾了两天多,终于出成果了,虽说最后结果是51%但十分类的问题如果盲猜的准确率才10%,作为第一个自己训练的网络已经很满足很开心了!接下去会再继续努力的。接下去想探究三个问题:1.数据集的图片不是正方形该如何处理,在哪块进行改动;2.在数据集没有那么大的情况下是否能支持;3.探究其它网络结构
相关文章推荐
- 深度学习-CAFFE利用CIFAR10网络模型训练自己的图像数据获得模型-1.制作自己的数据集
- 深度学习-CAFFE利用CIFAR10网络模型训练自己的图像数据获得模型-3结合caffe中的CIFAR10修改相关配置文件并训练
- 【深度学习】笔记6:使用caffe中的CIFAR10网络模型和自己的图片数据训练自己的模型(步骤详解)
- 深度学习-CAFFE利用CIFAR10网络模型训练自己的图像数据获得模型-4应用生成模型进行预测
- Caffe 用自己的数据集在ImageNet网络结构上训练测试
- Caffe初试(三)使用caffe的cifar10网络模型训练自己的图片数据
- Caffe深度学习入门—— caffenet 微调网络 训练自己的数据并测试训练的模型
- Matconvnet学习——利用mnist网络训练自己的数据分辨左右手
- 深度学习-CAFFE利用CIFAR10网络模型训练自己的图像数据获得模型-2生成图像库的均值文件
- caffe之利用mnist数据集训练好的lenet_iter_10000.caffemodel模型测试一张自己的手写体数字
- caffe-MobileNet-ssd环境搭建及训练自己的数据集模型
- Ubuntu14.04+caffe+cuda7.5 环境搭建以及MNIST数据集的训练与测试
- caffe之利用mnist数据集训练好的lenet_iter_10000.caffemodel模型测试一张自己的手写体数字
- mnist训练的cnn模型测试自己的手写数字
- TensorFlow——训练自己的数据(四)模型测试
- Mnist数据集下载、转换为lmdb,训练、测试、生成mean文件、生成label.txt、单张图片分类测试、可视化网络、可视化loss和accurate
- 利用tensorflow训练自己的图片数据(5)——测试训练网络
- mnist数据集在caffe(windows)上的训练与测试及对自己手写数字的分类
- YOLO模型训练自己数据-VOC格式数据集制作-ubuntu c++文件夹内图片批量读取与重命名
- 利用tensorflow训练自己的图片数据(3)——建立网络模型