caffe学习笔记(二)--MNIST实例

来源:互联网 发布:linux git 安装 编辑:程序博客网 时间:2024/05/18 11:49

LeNet MNIST实例
MNIST手写数字数据库是另外一个更大的手写体数据库NIST的子集,现在已成为图像识别领域用来测试自己的算法的一个基准数据库,它的训练集由60000张手写数字图片样本组成,测试集包含了10000个样本,其中所有的图片样本都经过了尺寸标准化和中心化,图片的大小固定为28*28。
据说该数据集中的图片是由美国中学生手写的数字,所以非常贴近实际,如果你的模型在该测试集上的测试精度能达到一定的程度,那么就可以说明你的模型的使用价值还是挺高的,说不定就可以用于手写邮政编码识别上。

这里写图片描述

Yann LeCun等人做的MNIST网站上,有MNIST数据集的介绍、下载链接及各种算法在MNIST数据集上的测试误差统计及相应的论文汇总。需要的请点击此链接:http://yann.lecun.com/exdb/mnist/
接下来让我们正式进入caffe中的MNIST实例环节
整个流程是这样的:先准备数据,接着定义分类模型和模型网络,然后是定义solver,最后对模型进行训练和测试。听着挺复杂,不过caffe都替你做好了,你只需要运行下相应的脚本程序就好了。
1.准备数据
首先要下载数据并将下载的MNIST数据转换为leveldb或lmdb格式的。caffe训练和测试的数据都需要转化为这两种格式中的一种,本文默认使用lmdb格式。(leveldb是老版本caffe默认的格式。lmdb是新版本caffe默认的格式)
打开caffe安装目录,官网文档中用‘CAFFE_ROOT’表示caffe安装目录。我的caffe安装在/home/hhwang/caffe-master/目录中。
先进入caffe的安装目录,切换到caffe-master目录下后运行脚本程序获取MNIST数据集,让后将其转换为lmdb格式。具体步骤如下(./是linux中用于运行脚本程序的一种方式):

cd $CAFFE_ROOT./data/mnist/get_mnist.sh./examples/mnist/create_mnist.sh

如果运行无误的话就会生成两个文件mnist_train_lmdb和mnist_test_lmdb。感兴趣的可以详细了解下get_mnist.sh和create_mnist.sh这两个脚本文件的内容。在这里我们只对比下新老版本的caffe中生成MNIST数据的shell脚本的不同点。

这里写图片描述

新版本的caffe中默认将MNIST数据集转换为lmdb格式的文件。当然,你也可以根据需要用它生成leveldb格式的文件,只需要修改BACKEND=“leveldb”即可。

这里写图片描述

老版本的caffe中将MNIST数据集转换为leveldb格式的文件。
2.定义分类模型
如果你只是为了跑个MNIST例子,测试下caffe是否正常工作的话,那么在运行上面的两个脚本文件生成lmdb格式的文件后,你可以直接跳到训练和测试部分,对模型进行训练和测试了。中间这几部分只是为了说明caffe中的模型是怎么定义的,需要修改参数的话去哪个文件中进行设置。
首先需要说明的一点是,caffe中的LeNet与原始的LeNet并不完全一样,在caffe中用ReLU激活函数取代了原始的sigmoid激活函数。
LeNet的模型结构是一个卷积层接一个pooling层,然后又是一个卷积层接一个pooling层,之后是两个全连接层,所谓的全连接层就是类似传统的多层感知器的结构,不同层之间的神经元之间采用全连接的方式。各层的定义见文件:$*CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt.*
从文件名就可以看出,caffe中使用google的protobuf定义模型,这就使得我们修改模型时非常方便,具体怎么个方便法,进lenet_train_test.prototxt中看看他是怎么定义模型的吧。(protobuf是什么东西,在这里先不讲,放到文末介绍了,感兴趣的,可以去看看)
数据层定义如下图,需要注意的是source和backend,batch_size也可以根据需要自己调整。其中,参数scale用于对输入的像素进行缩放,将所有的像素值缩放到[0,1]区间内。0.00390625=1/256。最后该层会生成两个blob,一个是data,一个是label。

这里写图片描述

卷积层如下图,卷积过程中的相应参数都在这里设置,例如kernel_size和stride,num_output应该就是filter的个数,决定生成的feature maps个数。送入该层的blob是上一层产生的data,该层输出的blob是conv1。

这里写图片描述

pooling层如下所示,可以修改pooling的方式(在这里使用的是最大值),以及相应的kernel_size和stride。送入该pooling层的blob是conv1,该层输出的blob是pool1。

这里写图片描述

其它部分与此类似,不再赘述。需要的请参考官网文档。
关于层的定义和连接对应到图上应该是什么样呢?
若我们以下图表示输入blob和输出blob的关系,那么我们就可以将protobuf中定义的网络以图的形式表示出来,这样整个模型的网络结构就更加清晰明了了。
这里写图片描述
将下图左边文本定义转化为图形模式就如下面右图所示。
该网络的名字为“LogReg”,其结构有3层,分别为mnist、ip和loss。mnist层的类型为DATA,该层产生两个blob,一个是data,一个是label。第2层为ip层,类型为INNER_PRODUCT,输入blob为data,输出blob为ip(别与层的名字混淆了)。第3层为loss层,类型为SOFTMAX_LOSS,输入blob为ip和label,输出blob为loss,在图中没有画出来。

name: "LogReg"layers {  name: "mnist"  type: DATA  top: "data"  top: "label"  data_param {    source: "input_leveldb"    batch_size: 64  }}layers {  name: "ip"  type: INNER_PRODUCT  bottom: "data"  top: "ip"  inner_product_param {    num_output: 2  }}layers {  name: "loss"  type: SOFTMAX_LOSS  bottom: "ip"  bottom: "label"  top: "loss"}

这里写图片描述
请根据该例子画出LeNet MNIST实例的网络结构图以加深理解。
3.定义MNIST solver
打开该文件:$CAFFE_ROOT/examples/mnist/lenet_solver.prototxt,内容如下图所示:

这里写图片描述

在该文件中定义了一些与模型训练有关的参数,包括初始学习率、momentum、权重衰减系数、最大迭代数、使用cpu还是gpu等参数。可根据需要进行修改。
在这里需要提的一点是,如果你在使用自己的参数进行训练的过程中发现,loss的值或者输出值非常大或者显示成NaN或inf的时候,那说明你的学习过程发散了,这是应该降低base_lr重新训练,知道你找到了一个合适的base_lr为止。
4.训练和测试模型
在设置好网络定义的protobuf文件(lenet_train_test.prototxt)和设置solver的protobuf文件(lenet_solver.prototxt)后,接下来的训练过程就非常简单了。只需要运行train_lenet.sh就可以开始训练了。
protobuf简介
protobuf是google公司开发的,并在Google内部久经考验的一个东西,在08年google把它贡献给了开源社区,随后便有越来越多的人使用它。protobuf是一个结构化信息传递的工具,主要用于数据存储、传输协议格式等场合。

0 0
原创粉丝点击