Caffe编译 Mnist训练测试---基本参数学习

Caffe编译

进入目录/caffe-master/,输入下列命令编译整个caffe工程

make clean
make all 
  • 1
  • 2

补充说明:很多添加编译选项,据说是为利用cpu的4个核并行编译加快编译效率,然而这里编译时报错所以就make all。其实make all 编译些什么可以看同目录下的Makefile文件。 
补充说明:在make all 之前需要修改Makefile.config.example文件具体修改说明如下:

## Refer to http://caffe.berkeleyvision.org/installation.html
# Contributions simplifying and improving our build system are welcome!

# cuDNN acceleration switch (uncomment to build with cuDNN).
# USE_CUDNN := 1
//CuDNN是NVIDIA 出的专门针对Deep Learning框架设计的一套GPU计算加速库,用于实现高性能的并行计算。在有GPU并且安装cudnn的情况下可以打开即将注释去掉。

# CPU-only switch (uncomment to build without GPU support).
#CPU_ONLY := 1
//表示是否用gpu如果只有cpu这里要打开,如果只有一个gpu建议不要打开,测试过只有一个gpu的情况下,速度并未得到提升反而更慢,当然可以打开gpu尝试下啦~

# uncomment to disable IO dependencies and corresponding data layers
USE_OPENCV := 1
# USE_LEVELDB := 0
# USE_LMDB := 0
//因为要用到opencv库所以要打开,下面这两个选项表示是选择caffe的数据管理第三方库,两者都不打开 caffe默认用的是LMDB,这两者均是嵌入式数据库管理系统编程库,详细介绍:http://www.cnblogs.com/yymn/p/4479216.html

# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)
#   You should not set this flag if you will be reading LMDBs with any
#   possibility of simultaneous read and write
# ALLOW_LMDB_NOLOCK := 1
//打开这个注释是当需要读取LMDB文件时,默认不打开,所以不取消注释

# Uncomment if you're using OpenCV 3
OPENCV_VERSION := 2.4.10
//用pkg-config --modversion opencv命令查看opencv版本
# To customize your choice of compiler, uncomment and set the following.
# N.B. the default for Linux is g++ and the default for OSX is clang++
# CUSTOM_CXX := g++
//linux系统一般用得都是g++编译器

# CUDA directory contains bin/ and lib/ directories that we need.
CUDA_DIR := /usr/local/cuda
//cuda的安装目录
# On Ubuntu 14.04, if cuda tools are installed via
# "sudo apt-get install nvidia-cuda-toolkit" then use this instead:
# CUDA_DIR := /usr

# CUDA architecture setting: going with all of them.
# For CUDA < 6.0, comment the *_50 lines for compatibility.
CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \
        -gencode arch=compute_20,code=sm_21 \
        -gencode arch=compute_30,code=sm_30 \
        -gencode arch=compute_35,code=sm_35 \
        -gencode arch=compute_50,code=sm_50 \
        -gencode arch=compute_50,code=compute_50
//这些是指gpu的计算能力,6.0以下的版本不支持×_50的计算能力,这里有个链接介绍:http://www.tuicool.com/articles/qUN322z

# BLAS choice:
# atlas for ATLAS (default)
# mkl for MKL
# open for OpenBlas
BLAS := open
//BLAS这个值如果用的是atlas计算库则赋值ATLAS,mkl计算库则用MKL赋值,OpenBlas则赋值open

# Custom (MKL/ATLAS/OpenBLAS) include and lib directories.
# Leave commented to accept the defaults for your choice of BLAS
# (which should work)!
BLAS_INCLUDE := /usr/local/OpenBlas/include
BLAS_LIB := /usr/local/OpenBlas/lib
//blas库安装目录

# Homebrew puts openblas in a directory that is not on the standard search path
# BLAS_INCLUDE := $(shell brew --prefix openblas)/include
# BLAS_LIB := $(shell brew --prefix openblas)/lib
//如果不是安装在标准路径则要指明

# This is required only if you will compile the matlab interface.
# MATLAB directory should contain the mex binary in /bin.
# MATLAB_DIR := /usr/local
# MATLAB_DIR := /Applications/MATLAB_R2012b.app
//matlab安装库的目录

# NOTE: this is required only if you will compile the python interface.
# We need to be able to find Python.h and numpy/arrayobject.h.
PYTHON_INCLUDE := /usr/include/python2.7 \
        /usr/lib/python2.7/dist-packages/numpy/core/include
//python安装目录
# Anaconda Python distribution is quite popular. Include path:
# Verify anaconda location, sometimes it's in root.
# ANACONDA_HOME := $(HOME)/anaconda
# PYTHON_INCLUDE := $(ANACONDA_HOME)/include \
        # $(ANACONDA_HOME)/include/python2.7 \
        # $(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include \

# Uncomment to use Python 3 (default is Python 2)
# PYTHON_LIBRARIES := boost_python3 python3.5m
# PYTHON_INCLUDE := /usr/include/python3.5m \
#                 /usr/lib/python3.5/dist-packages/numpy/core/include

# We need to be able to find libpythonX.X.so or .dylib.
PYTHON_LIB := /usr/lib
//python库位置
# PYTHON_LIB := $(ANACONDA_HOME)/lib

# Homebrew installs numpy in a non standard path (keg only)
# PYTHON_INCLUDE += $(dir $(shell python -c 'import numpy.core; print(numpy.core.__file__)'))/include
# PYTHON_LIB += $(shell brew --prefix numpy)/lib

# Uncomment to support layers written in Python (will link against Python libs)
WITH_PYTHON_LAYER := 1

# Whatever else you find you need goes here.
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib

# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies
# INCLUDE_DIRS += $(shell brew --prefix)/include
# LIBRARY_DIRS += $(shell brew --prefix)/lib

# Uncomment to use `pkg-config` to specify OpenCV library paths.
# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)
# USE_PKG_CONFIG := 1

# N.B. both build and distribute dirs are cleared on `make clean`
BUILD_DIR := build
DISTRIBUTE_DIR := distribute

# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171
# DEBUG := 1

# The ID of the GPU that 'make runtest' will use to run unit tests.
TEST_GPUID := 0
//所用的gpu的ID编号

# enable pretty build (comment to see full commands)
Q ?= @
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

这样改动之后还是会报错???哈哈哈,那是因为Makefile引用的不是这个编译配置文件,把Makefile里第二行改成:CONFIG_FILE := Makefile.config.example

Mnist训练

首先进入/caffe-master/目录,在当前目录下执行下列命令:

1、./data/mnist/get_mnist.sh
  • 1

获得mnist数据训训练的4个数据包

2、./examples/mnist/create_mnist.sh
  • 1

利用caffe-master/build/examples/mnist/的convert_mnist_data.bin工具,将mnist date转化为可用的lmdb格式的文件。并将新生成的2个文件mnist-train-lmdb 和 mnist-test-lmdb放于create_mnist.sh同目录下。

3、./examples/mnist/train_lenet.sh
  • 1

训练数据,下面再看下train_lenet.sh中 –solver=examples/mnist/lenet_solver.prototxt ,这个文件定义了具体的训练参数

# 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
//test迭代次数 如果batch_size =100,则100张图一批,训练100次,则可以覆盖10000张图的需求
# Carry out testing every 500 training iterations.
test_interval: 500
//训练迭代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
//每迭代100次显示一次
# The maximum number of iterations
max_iter: 10000
//最大迭代次数
# snapshot intermediate results
snapshot: 5000
//每5000次迭代存储一次数据,路径前缀是<</span>span style="font-family: Arial, Helvetica, sans-serif;">examples/mnist/lenet</</span>span>
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU
solver_mode: GPU
//是否使用GPU还是CPU
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

下面看看文件lenet_solver.prototxt ,这个文件定义了具体的lenet网络参数

name: "LeNet"           网络名
layer {
  name: "mnist"         本层名称
  type: "Data"              层类型
  top: "data"               下一层接口
  top: "label"              下一层接口
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625           #1/256,预处理如减均值,尺寸变换,随机剪,镜像等
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"   训练数据位置
    batch_size: 64                  一次训练的样本数
    backend: LMDB                   读入的训练数据格式,默认leveldb
  }
}


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”
  top: "conv1"                  下一层接口“conv1”
  param {
    lr_mult: 1                  (weights的学习率与全局相同)
  }
  param {
    lr_mult: 2                  (biases的学习率是全局的2倍)
  }
  convolution_param {
    num_output: 20              卷积核20个
    kernel_size: 5              卷积核尺寸5×5
    stride: 1                   步长1
    weight_filler {
      type: "xavier"                (随机的初始化权重和偏差)
    }
    bias_filler {
      type: "constant"              bias用0初始化
    }
  }
}


layer {
  name: "pool1"
  type: "Pooling"               池化层
  bottom: "conv1"               上层“conv1”
  top: "pool1"                  下层接口“pool1”
  pooling_param {
    pool: MAX                   池化函数用MAX
    kernel_size: 2              池化核函数大小2×2
    stride: 2                   步长2
  }
}


layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 50              卷积核50个
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}


layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}


layer {
  name: "ip1"
  type: "InnerProduct"              全连接层
  bottom: "pool2"               上层连接“pool2”
  top: "ip1"                    “下层输出接口ip1”
  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"
  top: "ip1"    (这个地方还是ip1,底层与顶层相同减少开支,下一层全连接层的输入也还是ip1)
}


layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 10              输出结果10个
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}


layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"         上层连接ip2全连接层
  bottom: "label"           上层连接label层
  top: "accuracy"           输出接口为accuracy
  include {
    phase: TEST        
  }
}


layer {
  name: "loss"
  type: "SoftmaxWithLoss"       损失函数
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
4、./build/tools/caffe.bin test -model=examples/mnist/lenet_train_test.prototxt -weights=examples/mnist/lenet_iter_10000.caffemodel -gpu=0   或者不使用GPU
       ./build/tools/caffe.bin test -model=examples/mnist/lenet_train_test.prototxt -weights=examples/mnist/lenet_iter_10000.caffemodel
  • 1
  • 2

所有数据都训练好之后,接下来就是如何将模型应用到实际数据了。test:表示对训练好的模型进行Testing,而不是training。其他参数包括train, time, device_query。 
-model=XXX:指定模型prototxt文件,这是一个文本文件,详细描述了网络结构和数据集信息。

下面解释下caffe程序的命令行格式

caffe的c++主程序(caffe.cpp)放在根目录下的tools文件夹内, 当然还有一些其它的功能文件,如:convert_imageset.cpp, train_net.cpp, test_net.cpp等也放在这个文件夹内。经过编译后,这些文件都被编译成了可执行文件,放在了 ./build/tools/ 文件夹内。因此我们要执行caffe程序,都需要加 ./build/tools/ 前缀。如上述的train_lenet.sh脚本文件:

sudo sh ./build/tools/caffe train --solver=examples/mnist/train_lenet.sh
  • 1

caffe程序的命令行执行格式如下:

caffe <command> <args>
  • 1

其中command命令有如下四种:

  1. train:::训练或finetune模型(model)
  2. test :::测试模型
  3. device_query:::显示gpu信息
  4. time:::显示程序执行时间

其中args参数有如下几种:

-solver:必选参数。一个protocol buffer类型的文件,即模型的配置文件。:

./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt
  • 1

-gpu: 可选参数。该参数用来指定用哪一块gpu运行,根据gpu的id进行选择,如果设置为’-gpu all’则使用所有的gpu运行。如使用第二块gpu运行:

./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt -gpu 2
  • 1

-snapshot:可选参数。该参数用来从快照(snapshot)中恢复训练。可以在solver配置文件设置快照,保存solverstate。如:

./build/tools/caffe train -solver examples/mnist/lenet_solver.prototxt -snapshot examples/mnist/lenet_iter_5000.solverstate
  • 1

-weights:可选参数。用预先训练好的权重来fine-tuning模型,需要一个caffemodel,不能和-snapshot同时使用。如:

./build/tools/caffe train -solver examples/finetuning_on_flickr_style/solver.prototxt -weights models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel
  • 1

-iterations: 可选参数,迭代次数,默认为50。 如果在配置文件文件中没有设定迭代次数,则默认迭代50次。 
-model:可选参数,定义在protocol buffer文件中的模型。也可以在solver配置文件中指定。 
-sighup_effect:可选参数。用来设定当程序发生挂起事件时,执行的操作,可以设置为snapshot, stop或none, 默认为snapshot 
-sigint_effect: 可选参数。用来设定当程序发生键盘中止事件时(ctrl+c), 执行的操作,可以设置为snapshot, stop或none, 默认为stop

test参数用在测试阶段,用于最终结果的输出,要模型配置文件中我们可以设定需要输入accuracy还是loss. 假设我们要在验证集中验证已经训练好的模型,就可以这样写

./build/tools/caffe test -model examples/mnist/lenet_train_test.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel -gpu 0 -iterations 100
  • 1

这个例子比较长,不仅用到了test参数,还用到了-model, -weights, -gpu和-iteration四个参数。意思是利用训练好了的权重(-weight),输入到测试模型中(-model),用编号为0的gpu(-gpu)测试100次(-iteration)。

time参数用来在屏幕上显示程序运行时间。如:

./build/tools/caffe time -model examples/mnist/lenet_train_test.prototxt -iterations 10
  • 1

这个例子用来在屏幕上显示lenet模型迭代10次所使用的时间。包括每次迭代的forward和backward所用的时间,也包括每层forward和backward所用的平均时间。

device_query参数用来诊断gpu信息:

./build/tools/caffe device_query -gpu 0
  • 1

会显示如下关于gpu信息

Querying GPUs 0
Device id:                     0
Major revision number:         2
Minor revision number:         1
Name:                          GeForce GT 630
Total global memory:           2146631680
Total shared memory per block: 49152
Total registers per block:     32768
Warp size:                     32
Maximum memory pitch:          2147483647
Maximum threads per block:     1024
Maximum dimension of block:    1024, 1024, 64
Maximum dimension of grid:     65535, 65535, 65535
Clock rate:                    1500000
Total constant memory:         65536
Texture alignment:             512
Concurrent copy and execution: Yes
Number of multiprocessors:     2
Kernel execution timeout:      Yes
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

因为我只有一块gpu所以用-gpu运行时速度反而更慢

猜你喜欢

转载自blog.csdn.net/haoji007/article/details/80299069