本文为原创文章转载必须注明本文出处以及附上 本文地址超链接 以及 博主博客地址:http://blog.csdn.NET/qq_20259459 和 作者邮箱( [email protected] )。
(如果喜欢本文,欢迎大家关注我的博客或者动手点个赞,有需要可以邮件联系我)
在上一篇文章中我们已经介绍了自带的cifar-10的code。下面我将非常详细的一步一步的介绍如何训练自己的数据。
开始,新建编辑页 cnn_cifar_my :
这是外层调参和构建imdb结构体的code。
关于调参我会在后面单取一篇来介绍。
函数相互调用顺序:主函数 function [net, info] = cnn_cifar_my(varargin) :
1. 首先初始化网络如下:
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, 'data', ['cifar10-' sfx]) ; %选择数据存放的路径:data\cifar-baseline-simplenn
[opts, varargin] = vl_argparse(opts, varargin) ; %调用vl_argparse函数
opts.dataDir = fullfile(vl_rootnn, 'data', 'cifar10') ; %选择数据读取的路径:data\matconvnet-1.0-beta23\data\cifar
opts.imdbPath = fullfile(opts.expDir, 'imdb.mat'); %选择imdb结构体的路径:data\data\cifar-baseline-simplenn\imdb
opts.whitenData = true ;
opts.contrastNormalization = true ;
opts.train = struct() ; %选择训练集返回为struct型
opts = vl_argparse(opts, varargin) ; %调用vl_argparse函数
%选择是否使用GPU,使用opts.train.gpus = 1,不使用:opts.train.gpus = []。
%有关GPU的安装配置请看我的博客:http://blog.csdn.net/qq_20259459/article/details/54093550
if ~isfield(opts.train, 'gpus'), opts.train.gpus = [1]; end;
if isempty(opts.network) %如果原网络为空:
net = cnn_cifar_init_my('batchNormalization', opts.batchNormalization, ... % 则调用cnn_cifat_init网络结构
'networkType', opts.networkType) ;
else %否则:
net = opts.network ; % 使用上面选择的数值带入现有网络
opts.network = [] ;
end
if exist(opts.imdbPath, 'file') %如果cifar中存在imdb的结构体:
imdb = load(opts.imdbPath) ; % 载入imdb
else %否则:
imdb = getMnistImdb(opts) ; % 调用getMnistImdb函数得到imdb并保存
mkdir(opts.expDir) ;
save(opts.imdbPath, '-struct', 'imdb') ;
end
%arrayfun函数通过应用sprintf函数得到array中从1到10的元素并且将其数字标签转化为char文字型
net.meta.classes.name = arrayfun(@(x)sprintf('%d',x),1:10,'UniformOutput',false) ;
switch opts.networkType %选择网络类型:
case 'simplenn', trainfn = @cnn_train ; % 1.simplenn
case 'dagnn', trainfn = @cnn_train_dag ; % 2.dagnn
end
%调用训练函数,开始训练:find(imdb.images.set == 3)为验证集的样本
[net, info] = trainfn(net, imdb, getBatch(opts), ...
'expDir', opts.expDir, ...
net.meta.trainOpts, ...
opts.train, ...
'val', find(imdb.images.set == 3)) ;
下面以我自己的数据为例构建一个自己的imdb:
function imdb = getMnistImdb(opts)
%% --------------------------------------------------------------
% 函数名:getMnistImdb
% 功能: 1.从mnist数据集中获取data
% 2.将得到的数据减去mean值
% 3.将处理后的数据存放如imdb结构中
% ------------------------------------------------------------------------
% Preapre the imdb structure, returns image data with mean image subtracted
load('TR.mat');
load('TT.mat');
load('TRL.mat');
load('TTL.mat');
x1 = TR;
x2 = TT;
y1 = TRL;
y2 = TTL;
%set = 1 对应训练;set = 3 对应的是测试
set = [ones(1,numel(y1)) 3*ones(1,numel(y2))]; %numel返回元素的总数
data = single(reshape(cat(3, x1, x2),128,256,1,[])); %将x1的训练数据集和x2的测试数据集的第三个维度进行拼接组成新的数据集,并且转为single型减少内存
dataMean = mean(data(:,:,:,set == 1), 4); %求出训练数据集中所有的图像的均值
data = bsxfun(@minus, data, dataMean) ; %利用bsxfun函数将数据集中的每个元素逐个减去均值
%将数据存入imdb结构中
imdb.images.data = data ; %data的大小为[128 256 1 70000]。 (60000+10000) 这里主要看上面的data的size。
imdb.images.data_mean = dataMean; %dataMean的大小为[128 256]
imdb.images.labels = cat(2, y1', y2') ; %拼接训练数据集和测试数据集的标签,拼接后的大小为[1 70000]
imdb.images.set = set ; %set的大小为[1 70000],unique(set) = [1 3]
imdb.meta.sets = {'train', 'val', 'test'} ; %imdb.meta.sets=1用于训练,imdb.meta.sets=2用于验证,imdb.meta.sets=3用于测试
%arrayfun函数通过应用sprintf函数得到array中从0到9的元素并且将其数字标签转化为char文字型
imdb.meta.classes = arrayfun(@(x)sprintf('%d',x),0:9,'uniformoutput',false) ;
下面我将为大家介绍如何构建自己的网络:
1. Conv.layer:
net.layers{end+1} = struct('type', 'conv', ... %卷积层C,randn函数产生4维标准正态分布矩阵,设置偏置有20个
'weights', {{0.05*randn(3,3,1,32, 'single'), ...
zeros(1, 32, 'single')}}, ... %filter大小是3*3*1
'learningRate', lr, ...
'stride', 1, ... %stride = 1
'pad', 0) ;
2. Rule.layer:
net.layers{end+1} = struct('type', 'relu') ;
net.layers{end+1} = struct('type', 'pool', ... %池化层P
'method', 'max', ...
'pool', [2 2], ... %池化核大小为2*2
'stride', 2, ...
'pad', 0) ;
net.layers{end+1} = struct('type', 'dropout', 'name', 'dropout2', 'rate', 0.5) ;
注:这里我们给的drop rate 是0.5 。
5. softmax.layer:
net.layers{end+1} = struct('type', 'softmaxloss') ; %softmax层
关于网络参数的设置和调整我将在后面为大家介绍。虽然说了很多但是还是不能说尽所有。
本文为原创文章转载必须注明本文出处以及附上 本文地址超链接 以及 博主博客地址:http://blog.csdn.NET/qq_20259459 和 作者邮箱( [email protected] )。
(如果喜欢本文,欢迎大家关注我的博客或者动手点个赞,有需要可以邮件联系我)