caffe上手:mnist学习

最近在做毕设,题目是基于深度学习的行人检测。然后决定要用最popular的caffe深度学习框架,在实验室的Ubuntu服务器上训练。

因为以前从来没用过Linux和ubuntu这种的命令行操作系统,所以学习过程中还是遇到了不少困难,这里记录一下,供自己和大家参考。

首先学习了caffe官网上的example,最简单的使用LeNet识别的Mnist手写数字训练集:http://caffe.berkeleyvision.org/gathered/examples/mnist.html

看了一下网上安装caffe的过程,感觉很麻烦,幸好师兄之前在服务器上安装过caffe,所以直接把他的caffe文件夹拷贝到自己的根目录下就可以直接用了(省去了一两天的工作量,鸣谢sj师兄!)。

然后按照上面网址上的指导一步步往下走。

~$ cd caffe-master
~/caffe-master$ ./data/mnist/get_mnist.sh

然后就出了问题,-bash: ./data/mnist/get_mnist.sh 权限不够。因为这个脚本还没有执行权限,所以先给它加上执行权限:

~/caffe-master$ chmod +x ./data/mnist/get_mnist.sh

再执行~/caffe-master$ ./data/mnist/get_mnist.sh,就出现了开始执行的命令行:

Downloading...
--2016-03-13 15:07:17--  http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
正在解析主机 yann.lecun.com (yann.lecun.com)... 128.122.47.89
正在连接 yann.lecun.com (yann.lecun.com)|128.122.47.89|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 9912422 (9.5M) [application/x-gzip]
正在保存至: “train-images-idx3-ubyte.gz”


100%[=========================================================================================================================================>] 9,912,422   10.9KB/s   用时 9m 54s


2016-03-13 15:17:14 (16.3 KB/s) - 已保存 “train-images-idx3-ubyte.gz” [9912422/9912422])


--2016-03-13 15:17:14--  http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
正在解析主机 yann.lecun.com (yann.lecun.com)... 128.122.47.89
正在连接 yann.lecun.com (yann.lecun.com)|128.122.47.89|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 28881 (28K) [application/x-gzip]
正在保存至: “train-labels-idx1-ubyte.gz”


100%[=========================================================================================================================================>] 28,881      37.3KB/s   用时 0.8s 


2016-03-13 15:17:25 (37.3 KB/s) - 已保存 “train-labels-idx1-ubyte.gz” [28881/28881])


--2016-03-13 15:17:25--  http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
正在解析主机 yann.lecun.com (yann.lecun.com)... 128.122.47.89
正在连接 yann.lecun.com (yann.lecun.com)|128.122.47.89|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 1648877 (1.6M) [application/x-gzip]
正在保存至: “t10k-images-idx3-ubyte.gz”


100%[=========================================================================================================================================>] 1,648,877   35.7KB/s   用时 97s  


2016-03-13 15:19:13 (16.6 KB/s) - 已保存 “t10k-images-idx3-ubyte.gz” [1648877/1648877])


--2016-03-13 15:19:13--  http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
正在解析主机 yann.lecun.com (yann.lecun.com)... 128.122.47.89
正在连接 yann.lecun.com (yann.lecun.com)|128.122.47.89|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 4542 (4.4K) [application/x-gzip]
正在保存至: “t10k-labels-idx1-ubyte.gz”


100%[=========================================================================================================================================>] 4,542       --.-K/s   用时 0s    


2016-03-13 15:19:13 (12.9 MB/s) - 已保存 “t10k-labels-idx1-ubyte.gz” [4542/4542])


Unzipping...
gzip: train-images-idx3-ubyte already exists; do you wish to overwrite (y or n)? y
gzip: train-labels-idx1-ubyte already exists; do you wish to overwrite (y or n)? y
gzip: t10k-images-idx3-ubyte already exists; do you wish to overwrite (y or n)? y
gzip: t10k-labels-idx1-ubyte already exists; do you wish to overwrite (y or n)? y
Done.

然后再执行下面一行:

./examples/mnist/create_mnist.sh
出现如下提示:

Creating lmdb...
./examples/mnist/create_mnist.sh: 16: ./examples/mnist/create_mnist.sh: build/examples/mnist/convert_mnist_data.bin: Permission denied
./examples/mnist/create_mnist.sh: 18: ./examples/mnist/create_mnist.sh: build/examples/mnist/convert_mnist_data.bin: Permission denied
Done.

注意到build/examples/mnist/convert_mnist_data.bin: Permission denied,看来convert_mnist_data.bin这个文件也没有权限,因此给它加执行权限之后再重新运行即可:

~/caffe-master$ chmod +x build/examples/mnist/convert_mnist_data.bin
~/caffe-master$ ./examples/mnist/create_mnist.sh
Creating lmdb...
Done.

这样就把MNIST从网站上下载下来并对数据格式进行了转换,完成了准备工作。

在正式开始训练和测试我们的模型之前,先对LeNet有一个大致了解,如下图所示,它由一个卷积层、后面跟一个下采样层、再跟另外一个卷积层和另一个下采样层,再之后是两个全连接层组成。这里caffe中用的示例和original LeNet的区别是使用ReLU(Rectified Linear Unit)取代了sigmoid激活函数。

caffe上手:mnist学习_第1张图片


LeNet各层的属性在$CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt中进行了定义。
使用~/caffe-master$ vi ./examples/mnist/lenet_train_test.prototxt命令即可查看网络各层的定义。
name: "LeNet"   //网络名称是LeNet
layer {
  name: "mnist"   //数据层名称是mnist
  type: "Data"     //类型是数据
  top: "data"        //输出数据到两个Blob,data和label
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625    //确保输出数据在[0,1)之间,所以乘以1/256
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"    //从这里获得数据
    batch_size: 64        //每批大小是64
    backend: LMDB     
  }
}
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_test_lmdb"
    batch_size: 100    //每批大小是100
    backend: LMDB
  }
}

然后是第一个卷积层和下采样层:

layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"    //以下层传输过来的data Blob作为输入
  top: "conv1"    //这层数据输出到Blob conv1
  param {
    lr_mult: 1      //lr为learning rate,学习率
  } 
  param {
    lr_mult: 2      //bias的学习率是weight的两倍
  }
  convolution_param {
    num_output: 20     //输出有20个channel
    kernel_size: 5      //卷积核大小为5
    stride: 1             //卷积步长为1
    weight_filler {
      type: "xavier"      //使用xavier algorithm,根据输入和输出神经元的数目,自动确定初始化权重的范围
    }
    bias_filler {
      type: "constant"      //将偏置初始化为常数,且为0
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"      //层的类型是Pooling
  bottom: "conv1"     //输入是conv1 Blob
  top: "pool1"            //输出是pool1 Blob
  pooling_param {
    pool: MAX             //下采样方式是最大值采样
    kernel_size: 2       //在2*2的区域内选择最大值
    stride: 2                 //步长为2,防止区域有重叠
  }
}

第二个卷积层和下采样层也都是类似的,就不再赘述了,下面是两个全连接层:

layer {
  name: "ip1"
  type: "InnerProduct"      //Fully Connection Layer在caffe中也叫Inner Product
  bottom: "pool2"              //输入是pool2 Blob
  top: "ip1"                         //输出是ip1 Blob
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500        //输出的神经元个数为500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1" 
  type: "ReLU"
  bottom: "ip1"                //把输入和输出的Blob设为同一个名字,可以是对单个元素操作的relu节省存储空间
  top: "ip1"
}

然后是另一个全连接层,不过只有10个输出,对应10个数字。接下来就是Loss层(和Accuracy层,只在test阶段使用):

layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"               //将全连接层的prediction和data层输出的label作为输入
  bottom: "label"
  top: "loss"
}

这一层没有进一步的输出,只计算损失函数值,当BP开始时将loss 报告出来。这个网络的定义就到此结束了。

此外,还有一点需要注意的是,当如下的格式出现时,

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

说明这一层只在TRAIN阶段出现在网络中,当处在TEST阶段时,这一层不出现在网络中。没有这个标志的层始终出现在网络当中。所以在以上的定义中,DATA层以不同的BATCH出现了两次,分别是TRAIN和TEST阶段。另外在测试阶段还有一个Accuracy层,每100次迭代就计算一下准确率。

再输入命令行:~/caffe-master$ vi ./examples/mnist/lenet_solver.prototxt,可以看到MNIST solver的配置情况:

 The train/test net protocol buffer definition
net: "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.01
momentum: 0.9
weight_decay: 0.0005
# The learning rate policy
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# Display every 100 iterations
display: 100
# The maximum number of iterations
max_iter: 10000
# snapshot intermediate results
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU
solver_mode: GPU

这里可以看到网络训练的配置,每批次训练100张图片,共100批次10000张图片,基础的学习率是0.1,使用GPU计算。因为这里的训练量较小,所以GPU的速度优势还看不太出来,如果在大一些的网络和训练集中,GPU的速度优势会更加明显。说了这么多,还没有执行正式的学习程序,命令行中输入:

~/caffe-master$ chmod +x  ./examples/mnist/train_lenet.sh
~/caffe-master$  ./examples/mnist/train_lenet.sh
./examples/mnist/train_lenet.sh: 3: ./examples/mnist/train_lenet.sh: ./build/tools/caffe: Permission denied(caffe没有执行权限,所以下一行先加权限)
~/caffe-master$ chmod +x ./build/tools/caffe
~/caffe-master$  ./examples/mnist/train_lenet.sh

就正式开始了训练和测试,正常情况下像MNIST这个级别的数据量应该几分钟就可以训练完。截取最后几行:

I0313 19:42:17.450871  4595 solver.cpp:243] Iteration 9900, loss = 0.00442233
I0313 19:42:17.450918  4595 solver.cpp:259]     Train net output #0: loss = 0.00442246 (* 1 = 0.00442246 loss)
I0313 19:42:17.450938  4595 solver.cpp:590] Iteration 9900, lr = 0.00596843
I0313 19:42:18.987057  4595 solver.cpp:468] Snapshotting to binary proto file examples/mnist/lenet_iter_10000.caffemodel
I0313 19:42:19.001791  4595 solver.cpp:753] Snapshotting solver state to binary proto file examples/mnist/lenet_iter_10000.solverstate
I0313 19:42:19.011090  4595 solver.cpp:327] Iteration 10000, loss = 0.00261991
I0313 19:42:19.011143  4595 solver.cpp:347] Iteration 10000, Testing net (#0)
I0313 19:42:19.923885  4595 solver.cpp:415]     Test net output #0: accuracy = 0.9913
I0313 19:42:19.923949  4595 solver.cpp:415]     Test net output #1: loss = 0.0260926 (* 1 = 0.0260926 loss)
I0313 19:42:19.923969  4595 solver.cpp:332] Optimization Done.
I0313 19:42:19.923982  4595 caffe.cpp:215] Optimization Done.

这样程序就正式执行完毕了,我在实验室的服务器上大约运行了174秒的样子。运行结果保存在了lenet_iter_10000.solverstate文件中。

你可能感兴趣的:(【Caffe,及,应用实例】)