第一部分:Caffe 简介
caffe是有伯克利视觉和学习中心(BVLC)开发。作者是伯克利博士贾杨清。
caffe是一个深度学习(deep learning)框架。其具有易读、快速和模块化思想。
第二部分:Caffe安装与配置
2.1 配置环境:ubuntu 14.04LTS, 使用Homebrew进行安装。暂不使用GPU,所以使用CPU-ONLY模式。不使用Python,所以没有下关于Python的任何支持库。
2.2 支持库
2.2.1 利用Homebrew 安装所需要的库,其中包括:boost snappy leveldb protobuf gflags glog szip lmdb homebrew/science/opencv
sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
sudo apt-get install --no-install-recommends libboost-all-dev
sudo apt-get install libatlas-base-dev
sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev
2.2.2:apt-get 简介:
apt-get是一条linux命令,适用于deb包管理式的操作系统,主要用于自动从互联网的软件仓库中搜索、安装、升级、卸载软件或操作系统。
2.3 所需要的库简介:
2.3.1 snappy
Snappy 是一个 C++ 的用来压缩和解压缩的开发包。其目标不是最大限度压缩或者兼容其他压缩格式,而是旨在提供高速压缩速度和合理的压缩率。Snappy 比 zlib 更快,但文件相对要大 20% 到 100%。在 64位模式的 Core i7 处理器上,可达每秒 250~500兆的压缩速度。
2.3.2 leveldb
Leveldb是一个google实现的非常高效的kv数据库,目前的版本1.2能够支持billion级别的数据量了。 在这个数量级别下还有着非常高的性能,主要归功于它的良好的设计。特别是LSM算法.
2.3.3 gflags
gflags是google的一个开源的处理命令行参数的库,使用c++开发,具备python接口,可以替代getopt。
gflags使用起来比getopt方便,但是不支持参数的简写。
2.3.4 glog
Google Glog 是一个C++语言的应用级日志记录框架,提供了 C++ 风格的流操作和各种助手宏。
2.3.5 szip
szip是一个快速,优良,跨平台的开源数据压缩程序。
2.3.6 lmdb
lmdb是openLDAP项目开发的嵌入式(作为一个库嵌入到宿主程序)存储引擎。
2.3.7 hdf5
Hierarchical Data Format(HDF),可以存储不同类型的图像和数码数据的文件格式,并且可以在不同类型的机器上传输,同时还有统一处理这种文件格式的函数库。大多数普通计算机都支持这种文件格式。
2.3.8 opencv
OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV用C++语言编写,它的主要接口也是C++语言,但是依然保留了大量的C语言接口。该库也有大量的Python, Java and MATLAB/OCTAVE (版本2.5)的接口。这些语言的API接口函数可以通过在线文档获得。如今也提供对于C#,Ch, Ruby的支持。
2.3.9 protobuf
protocolbuffer是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。
2.3.10 Boost
Boost库是为C++语言标准库提供扩展的一些C++程序库的总称。
第三部分 Caffe编译
3 使用Make编译Caffe
在caffe$的路径下:
#caffe文件夹中默认含有一个示例Makefile,只要去复制修改这个文件就可以了
cp Makefile.config.example Makefile.config
然后打开Makefile.config进行修改,笔者这里没有GPU,所以使用CPU-ONLY模式。所以反注释掉了 CPU_ONLY := 1
make all
make test
make runtest
经过以上之后Caffe就算是编译成功了!
第四部分 利用Caffe在MNIST数据集上进行LeNet训练
4.1 MNIST简介
MNISTs是一个手写数字电子版的数据集,其包含60000张的训练集,10000张的测试集,均为32*32格式。
4.2 LeNet简介
LeNet是一个用来进行手写数字分类的网络,作者是Yann LeCun。具体可以查询:
http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf
在这里使用时把原方法中的sigmoid激活函数改成了ReLU激活函数。
4.3 数据集准备
下载所需要的数据并且转换为所需的数据格式
cd $CAFFE_ROOT
./data/mnist/get_mnist.sh
./examples/mnist/creat_mnist.sh
4.4 MNIST网络的定义
网络定义在了lenet_train_test.prototxt中。Caffe中的模型都是以Google Protobuf方式定义的。
4.4.1 定义名字
name: "LeNet"
4.4.2 定义数据层
layer {
name: "mnist"
type: "Data"
transform_param {
scale: 0.00390625
}
data_param {
source: "mnist_train_lmdb"
backend: LMDB
batch_size: 64
}
top: "data"
top: "label"
}
4.4.2 定义卷积层
layer {
name: "conv1"
type: "Convolution"
param { lr_mult: 1 }
param { lr_mult: 2 }
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
bottom: "data"
top: "conv1"
}
4.4.3 定义池化层
layer {
name: "pool1"
type: "Pooling"
pooling_param {
kernel_size: 2
stride: 2
pool: MAX
}
bottom: "conv1"
top: "pool1"
}
4.4.4 定义全连接层
layer {
name: "ip1"
type: "InnerProduct"
param { lr_mult: 1 }
param { lr_mult: 2 }
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
bottom: "pool2"
top: "ip1"
}
4.4.5 定义ReLU层
layer {
name: "ip2"
type: "InnerProduct"
param { lr_mult: 1 }
param { lr_mult: 2 }
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
bottom: "ip1"
top: "ip2"
}
4.4.6 定义损失层
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
}
4.5 定义Solver
4.5.1 Solver简介
Solver通过协调Caffe中的Net的前向推断计算和反向梯度计算,来对参数进行更新,从而达到减小loss的目的
4.5.2 定义MNIST Solver
定义在$CAFFE_ROOT/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
# 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
4.6 训练与测试模型
运行脚本,这个脚本已经写了所有的训练和测试
cd $CAFFE_ROOT
./examples/mnist/train_lenet.sh
屏幕上闪过类似于如下的信息:
I1203 net.cpp:66] Creating Layer conv1
I1203 net.cpp:76] conv1 <- data
I1203 net.cpp:101] conv1 -> conv1
I1203 net.cpp:116] Top shape: 20 24 24
I1203 net.cpp:127] conv1 needs backward computation.
这是解释了网络中的每一层都是如何工作的。
最终得到了如下信息:
I1203 solver.cpp:84] Testing net
I1203 solver.cpp:111] Test score #0: 0.9897
I1203 solver.cpp:111] Test score #1: 0.0324599
I1203 solver.cpp:126] Snapshotting to lenet_iter_10000
I1203 solver.cpp:133] Snapshotting solver state to lenet_iter_10000.solverstate
I1203 solver.cpp:78] Optimization Done.
网络迭代了10000次,最终accurary是0.9897,loss是0.0324599