机器学习 —— 深度学习 —— 基于DAGNN的MNIST NET

  DAGNN 是Directed acyclic graph neural network 缩写,也就有向图非循环神经网络。我使用的是由MatConvNet 提供的DAGNN API。选择这套API作为工具的原因有三点,第一:这是matlab的API,相对其他语言我对Matlab比较熟悉;第二:有向图非循环的网络可以实现RPN,Network in Network 等较为复杂的功能,可以随意的引出各层的输入和输出,有利于针对三维视觉任务改造网络结构。MNIST 是手写数字的图片集,也是机器学习网络最简单的试金石。

1、定义层

 1 conv_layer1 = dagnn.Conv('size',single([5,5,1,30]),'hasBias',true);
 2 relu_layer2 = dagnn.ReLU();
 3 
 4 conv_layer3 = dagnn.Conv('size',single([5,5,30,16]),'hasBias',true);
 5 relu_layer4 = dagnn.ReLU();
 6 pooling_layer5 = dagnn.Pooling('poolSize',[2,2],'stride',[2 2]);
 7 
 8 fullConnet_layer6 = dagnn.Conv('size',single([4,4,16,256]),'hasBias',true);
 9 relu_layer7 = dagnn.ReLU();
10 fullConnet_layer8 = dagnn.Conv('size',single([1,1,256,10]),'hasBias',true);
11 SoftMat_layer9 = dagnn.SoftMax();
12 Loss_layer = dagnn.Loss();
View Code

首先是利用API构造各层网络,定义网络结构类型。所有的Layer 都继承自dagnn.Layer类,子类中定义了输入输出,前向传播,反向传播的行为。

其中包括卷积层,激活层,池化层,Softmax 分类层,以及计算Loss层。值得注意的是全连接层是通过大卷积层来实现的。本质上全连接就是“输入的等尺寸卷积”。全连接层的作用是将卷积层提取的特征进行高度非线性的映射,将其映射到输出空间中。

2、定义网络

 1 mynet = dagnn.DagNN();
 2 mynet.addLayer('conv1',conv_layer1,{'input'},{'x2'},{'filters_conv1','bias_conv1'});
 3 mynet.addLayer('relu1',relu_layer2,{'x2'},{'x3'});
 4 mynet.addLayer('pool1',pooling_layer5,{'x3'},{'x4'});
 5 
 6 mynet.addLayer('conv2',conv_layer3,{'x4'},{'x5'},{'filters_conv2','bias_conv2'});
 7 mynet.addLayer('relu2',relu_layer4,{'x5'},{'x6'});
 8 mynet.addLayer('pool2',pooling_layer5,{'x6'},{'x7'});
 9 
10 mynet.addLayer('full1',fullConnet_layer6,{'x7'},{'x8'},{'filters_fc1','bias_fc1'});
11 mynet.addLayer('relu3',relu_layer7,{'x8'},{'x9'});
12 mynet.addLayer('full2',fullConnet_layer8,{'x9'},{'x10'},{'filters_fc2','bias_fc2'});
13 mynet.addLayer('Cls1',SoftMat_layer9,{'x10'},{'pred'});
14 mynet.addLayer('Loss',Loss_layer,{'pred','label'},{'loss'});
15 mynet.initParams();
16 mynet.meta.inputs = {'data',[28,28,1,1]};
17 mynet.meta.classes.name = {1,2,3,4,5,6,7,8,9,10};
18 mynet.meta.normalization.imageSize = [28,28,1,1];
19 mynet.meta.interpolation = 'bicubic';
View Code

定义网络调用了addLayer方法,与其他API的网络构建方法不同的是,DAGNN的API需要针对每层定义输入和输出,以及网络中的待求得参数。当然,作为初学者我先实现了链式网络,在下周的工作中会尝试实现Faster R-CNN。

net.addLayer('full1',fullConnet_layer6,{'x7'},{'x8'},{'filters_fc1','bias_fc1'});

以此为例,代表该层的名字是full1 , 该层的结构是fullConnect_layer6,输入为x7、输出x8,参数名为filters_fc1 和 bias_fc1。其中loss 层最为特殊,其具有来自softmax层的pred 和 label (ground truth) 两种输入。

最重要的是一定要initParams()!!!!这会生成初始参数。

3、定义数据输入函数

为了训练网络,我们需要定义一个输入函数。数据量小,可存在内存中,但当数据量大的时候全部存在内存里是不现实的,这就需要一个数据输入函数来对你定义的数据库进行操作。本例中我仅使用5000幅图片进行训练,所以可以把图片放在内存中。getBatch函数如下所示:

1 function inputs = getBatch(imdb, batch)
2 % --------------------------------------------------------------------
3 images = imdb.images.data(:,:,:,batch) ;
4 labels = imdb.images.labels(1,batch) ;
5 
6 %  images = gpuArray(images) ;
7 
8 inputs = {'input', images, 'label', labels} ;
View Code

其中 imdb 是image data base. 其中包括:

imdb.images.data  图片 W*H*C*N 的4-D  single Array

imdb.images.label  标签 N*1  的 single Array

imdb.images.data_mean 图片平均值 用于预处理时去中心

imdb.images.set    集合号 N*1 的 single Array, 其中1 代表训练集 2 代表测试集 3 代表验证集

imdb.meta 存放类型名称等和训练关系不太密切的东西

4、开始训练

直接调用 cnn_train_dag 的API 开始对整个集合进行训练,注意getBatch 输入的是函数句柄。

cnn_train_dag(mynet,imdb_sub,@getBatch);

  训练了30个epoch,但是learningRate好像给太高了,掉局部最小里了。。。。。。。不过结果不错,在验证集中拿到了4998/5000.

 

posted @ 2016-11-13 10:46  IronStark  阅读(4716)  评论(0编辑  收藏  举报