用Caffe在MNIST上训练LeNet

来源:互联网 发布:科技公司网站源码 编辑:程序博客网 时间:2024/05/19 12:11
博客参考:Caffe官方Training LeNet on MNIST with Caffe

数据准备

首先从MNIST网站下载数据集并转换获取的数据格式,运行以下简单的命令脚本

cd $CAFFE_ROOT #$CAFFE_ROOT指的是caffe所在根目录./data/mnist/get_mnist.sh #从脚本中提供的网址下载数据(.gz格式)并解压、删除已下载的原件,仅保留解压后的数据(如train-images-idx3-ubyte、train-labels-idx1-ubyte)./examples/mnist/create_mnist.sh #将上述数据转化成lmdb格式

lmdb格式讲解
简述:Caffe中的lmdb数据大约有两类:1. 输入DataLayer的训练/测试数据集;2.extract_feature输出的特征数据。

lmdb,文件结构简单,一个文件夹里面包含一个数据文件,一个锁文件。数据随意复制,随意传输。访问简单,不需要运行单独的数据库管理进程,只要在访问数据的代码里引用LMDB库,访问时给文件路径即可。


运行完上述的脚本文件后,会在/examples/mnist目录下面得到mnist_train_lmdb和mnist_test_lmdb两个文件夹,每个文件夹下包含有一个数据文件data.lmdb和一个锁文件lock.lmdb。

LeNet:MNIST分类模型

在初始版本的LeNet上稍稍改变:用ReLU替换sigmoid激活函数。已经在$CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt中定义了网络结构。

caffe中的protobuf定义,见$CAFFE_ROOT/src/caffe/proto/caffe.proto,官方的protobuf documents参考Google Protobuf,另参考博客protobuf文件的简单使用

定义MNIST网络

在LeNet的示例中,lenet_train_test.prototxt文件描述了LeNet网络的结构:

首先,给网络一个名字

name:"LeNet"

数据层Data Layer

layer {  name: "mnist" #本层的名字自取  type: "Data" #层类型  top: "data"  top: "label"  include {    phase: TRAIN  }  transform_param {    scale: 0.00390625  }  data_param {    source: "examples/mnist/mnist_train_lmdb"    batch_size: 64    backend: LMDB  }}
从所指定的lmdb中读取数据;batch size为64,scal输入的像素值到[0,1)256分之1=0.00390625;最后产生(输出)两个blob(data blob和label blob)用于下层。

卷积层Convolution Layer

第一个卷积层:

layer {  name: "conv1" # 本层的名字自取  type: "Convolution" # 层类型  bottom: "data" # 接受来自data layer的data  top: "conv1" # 输出/产生conv1 blob  param {    lr_mult: 1#学习率  }  param {    lr_mult: 2  }  convolution_param {    num_output: 20 #输出的channels数为20    kernel_size: 5    stride: 1    weight_filler {      type: "xavier"    }    bias_filler {      type: "constant"    }  }}
fillers可以随机的初始化weights和bias值。在本层中,对于weights fillers,使用xavier算法根据输入输出的神经节点数目自动决定初始化的尺度;对于bisa fillers,采用constant常数填充,这里用0填充。
lr_mults是层中可学习参数的学习率。在该例子中,weight的学习率与运行期间由solver给定的学习率相同,bias学习率是weight学习率的两倍大,这样做通常有更好的收敛率。

池化层Pooling Layer

layer {  name: "pool1"  type: "Pooling"  bottom: "conv1"  top: "pool1"  pooling_param {    pool: MAX    kernel_size: 2    stride: 2  }}
pooling层相对简单,这里的解释是对来自conv1的blob以max-pooling的方式处理,然后产生名为pool1的blob。如此,可以近似地编写conv2和pool2层。

全连接层Fully Connected Layer

layer {  name: "ip1"  type: "InnerProduct" #全连接方式  bottom: "pool2"  top: "ip1"  param {    lr_mult: 1  }  param {    lr_mult: 2  }  inner_product_param {    num_output: 500    weight_filler {      type: "xavier"    }    bias_filler {      type: "constant"    }  }}
这样就定义了对来自pool2的blob进行InnerProduct以得到一个有500单元输出的blob ip1。

ReLU处理层

layer {  name: "relu1"  type: "ReLU"  bottom: "ip1"  top: "ip1"}
以相同的名字来命名bottom和top,即对输入进行一次ReLU变换。同理,可以构建InnerProduct layer ip2层。

Loss Layer

layer {  name: "loss"  type: "SoftmaxWithLoss"  bottom: "ip2"  bottom: "label"  top: "loss"}
softmax_loss层实现softmax和多项logistic损失(省时并提高数值稳定性)。它需要两个blob,第一个是预测,第二个是数据层提供的标签。计算损失函数值,在反向传播开始时报告它,并针对ip2启动梯度。

额外注意点:编写层规则

layer {  // ...layer definition...  include: { phase: TRAIN }}

图层的定义可以包含是否以及何时包含在网络定义中的规则中。示例描述的是一个基于当前网络状态来控制网络中的层包含的规则。规则TRAIN说明该层只包含在训练阶段,默认情况下(无规则时)层包含在整个网络中。因此,lenet_train_test.prototxt有两个具有不同batch_size的Data Layers:一个用于训练,另一个用于测试。

layer {  name: "accuracy"  type: "Accuracy"  bottom: "ip2"  bottom: "label"  top: "accuracy"  include {    phase: TEST  }}
此外,还有一个Accurry Layer,仅包含在测试阶段,用于每100次迭代报告模型精度。当然,这里所说的100次是在$CAFFE_ROOT/examples/mnist/lenet_solver.prototxt中描述的。

定义MNIST的Solver

具体描述见$CAFFE_ROOT/examples/mnist/lenet_solver.prototxt

# The train/test net protocol buffer definitionnet: "examples/mnist/lenet_train_test.prototxt"# test_iter specifies how many forward passes the test should carry out.# In the case of MNIST, we have test batch size 100 and 100 test iterations,# covering the full 10,000 testing images.test_iter: 100# Carry out testing every 500 training iterations.test_interval: 500# The base learning rate, momentum and the weight decay of the network.base_lr: 0.01momentum: 0.9weight_decay: 0.0005# The learning rate policylr_policy: "inv"gamma: 0.0001power: 0.75# Display every 100 iterationsdisplay: 100# The maximum number of iterationsmax_iter: 10000# snapshot intermediate resultssnapshot: 5000snapshot_prefix: "examples/mnist/lenet"# solver mode: CPU or GPUsolver_mode: GPU
选择GPU训练,solver_model:GPU

训练和测试模型

运行$CAFFE_ROOT/examples/mnist/train_lenet.sh脚本,训练的主要工具就是caffe中的train操作,并以solver prototxt文件作为它的参数。

#!/usr/bin/env shset -e./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt $@



由图可知,每层的连接和输出规模,并且可在对应的源文件中追踪,如[...   net.cpp:84]。此外,我们还能知道哪些层需要反向传播计算,有无输出loss。在初始化完成后,开始训练过程。

根据solver的设置,每100 iterations打印输出训练损失,以及每500 iterations测试一次网络,那么可以看到:

I1208 10:02:38.242851  4482 solver.cpp:218] Iteration 100 (653.884 iter/s, 0.152932s/100 iters), loss = 0.21386I1208 10:02:38.242880  4482 solver.cpp:237]     Train net output #0: loss = 0.21386 (* 1 = 0.21386 loss)I1208 10:02:38.242887  4482 sgd_solver.cpp:105] Iteration 100, lr = 0.00992565......I1208 10:02:38.758451  4482 solver.cpp:330] Iteration 500, Testing net (#0)I1208 10:02:38.809602  4491 data_layer.cpp:73] Restarting data prefetching from start.I1208 10:02:38.810797  4482 solver.cpp:397]     Test net output #0: accuracy = 0.9726I1208 10:02:38.810818  4482 solver.cpp:397]     Test net output #1: loss = 0.0893905 (* 1 = 0.0893905 loss)......I1208 10:02:51.497777  4482 solver.cpp:447] Snapshotting to binary proto file examples/mnist/lenet_iter_10000.caffemodelI1208 10:02:51.501615  4482 sgd_solver.cpp:273] Snapshotting solver state to binary proto file examples/mnist/lenet_iter_10000.solverstateI1208 10:02:51.503881  4482 solver.cpp:310] Iteration 10000, loss = 0.00287347I1208 10:02:51.503899  4482 solver.cpp:330] Iteration 10000, Testing net (#0)I1208 10:02:51.553721  4491 data_layer.cpp:73] Restarting data prefetching from start.I1208 10:02:51.555130  4482 solver.cpp:397]     Test net output #0: accuracy = 0.9907I1208 10:02:51.555150  4482 solver.cpp:397]     Test net output #1: loss = 0.0314041 (* 1 = 0.0314041 loss)I1208 10:02:51.555155  4482 solver.cpp:315] Optimization Done.I1208 10:02:51.555158  4482 caffe.cpp:259] Optimization Done.
最终的模型,以2进制protobuf文件的形式存储在lenet_iter_10000.caffemodel中,运行测试文件test_lenet.sh.

#!/usr/bin/env sh./build/tools/caffe test --model=examples/mnist/lenet_train_test.prototxt \--weights=examples/mnist/lenet_iter_10000.caffemodel -gpu=0
如果遇到权限问题,加上权限:
$ chmod +x ./examples/mnist/test_lenet.sh



























阅读全文
0 0
原创粉丝点击