HanyNet – 卷积神经网络的初步实现

 全部代码已经发布在https://github.com/johnhany/HanyNet


        开发环境

        Windows 7 x64 Ultimate

        Visual Studio 2012 Ultimate

        OpenCV 3.1

        RapidXML 1.13


        模型

        基于经典的LeNet卷积网络模型,该网络结构如下图所示:

HanyNet – 卷积神经网络的初步实现        包含输入层,卷积层,降采样层,全连通层以及输出层。

        以手写数字为例,网络分类过程如下图所示:

HanyNet – 卷积神经网络的初步实现HanyNet – 卷积神经网络的初步实现HanyNet – 卷积神经网络的初步实现


        网络结构在parameters.xml文件内定义,各参数的含义如下:

        group_samples – 输入层包含的样本数。推荐人脸识别采用10;MNIST手写字体识别采用50、64等大一些的值。

        epoch_num – 训练的总迭代次数。依据样本量而定,若训练样本较少,则设为几百上千量级的值;若是MNIST这种很大的样本库,则设为10即可。

        gradient_alpha – 训练收敛速度。采用默认的1.0即可。

        sample_width – 输入样本图像的宽度。其值由网络的层数决定,如果包含2卷积层和2降采样层,则设为28;若包含3卷积层和3降采样层,则设为60。

        sample_height – 输入样本图像的高度。其值由网络的层数决定,如果包含2卷积层和2降采样层,则设为28;若包含3卷积层和3降采样层,则设为60。

        net_struct – 规定网络的结构。其中的layer定义每一层的属性,具体如下,

                type="i" – 输入层;

                type="c" – 卷积层,其中func为**函数(可为relusigmoid),maps为卷积核的数量,size为卷积核的尺寸(最好为奇数);

                type="s" – 降采样层,其中scale为缩小的比例;

                type="o" – 输出层,其中func为**函数(只能为softmax),classes为类别数。

        第一层必须为输入层;最后一层必须为输出层;中间隐层由一对对卷积层加降采样层构成。结构如下:

                i | c | s | c | s | o

        或

                i | c | s | … | c | s | o


       HanyNet-run.cpp文件的一些说明:

       1. 17-19行的以下三个宏只允许一个有定义:

              _HANY_NET_LOAD_MNIST – 载入MNIST训练集

              _HANY_NET_LOAD_SAMPLE_FROM_PIC – 载入图像训练集

              _HANY_NET_CAPTURE_FACE_FROM_CAMERA – 从摄像头捕捉训练集

       2. 21-24行的以下四个宏只允许一个有定义:

              _HANY_NET_PREDICT_MNIST – 载入MNIST测试集

              _HANY_NET_PREDICT_IMAGE_SERIES – 载入图像测试集

              _HANY_NET_PREDICT_VEDIO_SERIES – 将视频文件作为测试集

              _HANY_NET_PREDICT_CAMERA – 从摄像头捕捉测试集

       3. 如果每一类有单独的字符串名称,请准备好一个标签文本文件,并使第36行的label_file指向该文件,取消26行_HANY_NET_WITH_LABEL_NAMES的注释。

       4. 29行的pretrained_cnn_file指向预训练好的xml文件。

       5. 35行的sample_file_pre指向样本集目录(包含图像或者视频文件)。

       6. 42行的sample_num为每个类别包含的样本数。我们规定所有类别所包含的样本数是相同的。


       HanyNet.h文件的一些说明:

       1. 36行的_HANY_NET_TRAIN_FROM_SCRATCH有定义时,完成网络训练和测试样本分类两个步骤;_HANY_NET_TRAIN_FROM_SCRATCH未定义时,跳过训练步骤,只完成测试样本分类一个步骤。

       2. 39行的_HANY_NET_LIMIT_SAMPLE_NUM规定训练样本数量的上限,在调试代码阶段会比较有帮助。


       MNIST手写数字识别

       在这里下载MNIST数据库,并把t10k-images.idx3-ubyte, t10k-labels.idx1-ubyte, train-images.idx3-ubyte, train-labels.idx1-ubyte四个文件拷贝到HanyNet-run.cpp同一目录下。

       保持_HANY_NET_LOAD_MNIST_HANY_NET_PREDICT_MNIST有定义。


       自定义样本库

       1. 训练样本为图像。保持_HANY_NET_TRAIN_FROM_SCRATCH有定义。保持_HANY_NET_LOAD_SAMPLE_FROM_PIC有定义,设置sample_file_pre为样本目录,设置sample_num为每个类别包含的样本数。样本图像文件名称需按照a_b.jpg的格式,其中a为类别号,b为类内样本号,a和b均以0开始。

       2. 从摄像头捕捉训练样本(仅限人脸识别)。保持_HANY_NET_TRAIN_FROM_SCRATCH有定义。保持_HANY_NET_CAPTURE_FACE_FROM_CAMERA有定义。HanyNet利用Haar级联分类器从画面中检测人脸,再将检测到的人脸片元作为样本。每个人采集sample_num幅样本,采集满sample_num幅图像之后,程序暂停样本录入,将摄像头对准下一个人,按空格键开始捕捉第二个人的图像。所有人的样本录入完毕后,按ESC键开始训练网络。

       3. 测试样本为图像。保持_HANY_NET_PREDICT_IMAGE_SERIES有定义,设置sample_file_pre为样本目录,设置sample_num为每个类别包含的样本数。样本图像文件名称需按照a_b.jpg的格式,其中a为类别号,b为类内样本号,a和b均以0开始。

       4. 从视频文件捕捉测试样本(仅限人脸识别)。保持_HANY_NET_PREDICT_VEDIO_SERIES有定义。设置sample_file_pre为样本目录。样本图像文件名称需按照a.wmv的格式,其中a为类别号,以0开始。

       5. 从摄像头捕捉测试样本(仅限人脸识别)。保持_HANY_NET_PREDICT_CAMERA有定义。


       分类精度

       MNIST:采用双隐层网络,测试集精度在83~88%之间。训练耗时1546.98s(60000样本,10次迭代),测试耗时392.15s(10000样本)。

       人脸识别:4人情况下,正确率100%;10人以上正确率欠佳。

       车辆分类:4种车型(轿车,SUV,货车,客车),每种车型30个样本,正确率最高97%(客车),其余为67%(轿车),87%(SUV),73%(货车)。


       未来计划

       一个更完备的项目正在开发之中,使HanyNet支持更复杂的深度学习模型,并加入多线程支持和CUDA支持。

转载http://johnhany.net/2016/04/naive-implementation-of-cnn/