Caffe-windows入门学习,编译、训练、测试详细教程

来源:互联网 发布:金庸群侠传 武功数据 编辑:程序博客网 时间:2024/05/02 14:14

目录结构

  • 一. 准备工作
  • 二. 编译
    • 2.1、开启相关caffe版本的编译开关配置内容
    • 2.2、手动更改或者指定版本对应编译器目录
    • 2.3、下载依赖文件dependencies文件到指定目录
    • 2.4、编译
  • 三. MNIST手写体字符识别(C++)
    • 3.1、MNIST数据集下载
    • 3.2、转换数据格式
    • 3.3、训练和测试数据集
    • 3.4、测试单张图片
  • 四. Matlab Demo
    • 4.1、编译Caffe的Matlab接口
    • 4.2、模型文件下载
    • 4.3、测试
  • 五. 附录
    • 5.1、生成网络结构图
    • 5.2、相关文件说明

原创文章,转载请注明出处 http://blog.csdn.net/wanggao_1990/article/details/76721294。


一、 准备工作

1.1、下载BVLC/Caffe-windows源码,点击跳转下载。

1.2、使用GPU版本,提前安装CUDA 7.5(VS2015使用8.0)、cuDnn v5,Python 2.7或Python3.5 x64

1.3、若要生成Matlab接口,还需要安装Matlab

1.4、本次是搭建caffe GPU版本,已经安装VS2015, Python3.5.3 x64, Matlab 2013b, CUDA 8.0,cuDnn v5.1,并生成Matlab接口。

二、 编译

目录.\caffe-windows\scripts\下的build_win.cmd,双击就能在此目录下创建build文件夹并生成VS的.sln解决方案,并编译生成各种版本库和可执行文件。下图是双击.bat后会出现的内容,也会看到相应的一些配置情况。

这里写图片描述

通常需要改动build_win.cmd文件和相关.cmake文件的部分内容,以修改一些目录和下载内容的配置。目录结构如下。

这里写图片描述

这里写图片描述

2.1、开启相关caffe版本的编译开关配置内容如下

这里写图片描述

默认VS2015编译,自动检测CUDA,编译GPU版本,生成release等…
例如 这里写图片描述,表示需要编译Matlab版本接口。若不在这里指定,需要编译Matlab版本接口则需要在cmd中给.bat传入参数,如.\build_win.cmd -DBUILD_matlab=ON

2.2、手动更改或者指定版本对应编译器目录(VS、Python、Matlab等)

(1)Python 版本是3.5,指定Python对应目录。

这里写图片描述

(2)是否编译GPU版本,debug模式下的配置等….

这里写图片描述

(3)指定编译器,VS2015(或其他VS版本,Ninja)

这里写图片描述

2.3、提前下载依赖文件dependencies文件到指定目录

在运行build_win.cmd后,会自动执行位于.\caffe-windows\cmake\目录下的WindowsDownloadPrebuiltDependencies.cmake文件(可在文件中找到相关的下载网站),建议手动下载libraries_v140_x64_py35_1.1.0.tar.bz2并解压到到用户目录C:\Users\Administrator\.caffe\dependencies下。

这里写图片描述
从https://github.com/willyd/caffe-builder/releases下载对应版本的依赖文件并解压到指定位置。
这里写图片描述

若已经手动下载了,需修改WindowsDownloadPrebuiltDependencies.cmake文件使其不再重复下载,找到如下部分并注释。

这里写图片描述

2.4、编译

运行build_win.cmd文件,没其他配置问题,等待一段时间就能生成sln和各种文件了。编译生成的caffe.sln解决方案。编译生成的解决方案,生成Matlab、C++、Python不同版本的caffe接口库和samples的数据转换可执行文件。

三、 MNIST手写体字符识别(C++)

利用编译好的C++版本Caffe对MNIST手写字符进行训练和识别。

3.1、MNIST数据集下载

从http://yann.lecun.com/exdb/mnist/下载MNIST的数据集(如下四个压缩文件),并解压到目录.\caffe-windows\data\mnist\下。
这里写图片描述

3.2、转换数据格式

(1)编译”convert_mnist_data”工程,生成convert_mnist_data.exe,位置如右下图。

这里写图片描述

这里写图片描述

(2)生成LMBD数据文件

.\caffe-windows\data\mnist\目录下新建convert_datas.bat批处理文件,内容如下。

这里写图片描述

双击后,分别在当前目录下的mnist_train_lmdbmnist_test_lmdb文件夹下生成数据文件,分别用于训练和测试。运行和生成文件如下:

这里写图片描述

这里写图片描述

Tips: 若需要生成levelbd格式,需要在”convert_mnist_data”工程中先指定backend为”leveldb”,再编译生成exe,重复执行上述操作即可。
这里写图片描述

3.3、训练和测试数据集

(1)准备prototxt文件

首先从.\caffe-windows\examples\mnist\目录下拷贝lenet_solver.prototxtlenet_train_test.prototxt两个文件到.\caffe-windows\data\mnist\目录下。

这里写图片描述

修改两个文件的数据源路径和生成模型文件路径,内容如下:

这里写图片描述
这里写图片描述

如果数据格不为LMBD,还需修改data_param下的backend为对应格式的字符(文件说明见附录)。

(2)训练数据集,生成.caffemodel模型

.\caffe-windows\data\mnist\目录新建snapshot_lenet文件夹。新建train.bat文件,内容如下。
这里写图片描述

运行得到如下结果。

这里写图片描述

利用GPU训练迭代10000次,最终的准确率为99.05%。生成的模型文件:

这里写图片描述

(3)测试数据集

.\caffe-windows\data\mnist\新建test.bat文件,内容如下。

这里写图片描述

运行得到结果如下,正确率为98.58%。

这里写图片描述

3.4、测试单张图片

测试识别单张图片,准备一张28*28的数字手写体图片文件。另外,还需要数据训练的均值文件、标签文件、deploy.prototxt文件和识别可执行文件。

(1)生成均值文件mean.binaryproto

编译“compute_image_mean”工程,生成对应的exe文件,位置如右下图

这里写图片描述这里写图片描述

.\caffe-windows\data\mnist\新建compute_mean.bat文件,内容如下。

这里写图片描述

运行后会在当前目录下生成一个mean.binaryproto均值文件。

(2)类别标签文件synset_words.txt

.\caffe-windows\data\mnist\新建synset_words.txt文件,内容如下

这里写图片描述

(3)生成测试工具可执行文件

编译“classification”工程,生成对应的exe文件,位置如右下图

这里写图片描述

这里写图片描述

(4)deploy.prototxt文件

该文件由lenet_train_test.prototxt修改而来,可从目录.\caffe-windows\examples\mnist\下直接拷贝文件lenet.prototxt到当前目录,并改名为deploy.prototxt。

(5)测试单张图片

.\caffe-windows\data\mnist\新建mnist_img_classification.bat文件,内容如下

这里写图片描述

测试图片3.bmp位于当前文件夹下,图片和测试结果如下:

这里写图片描述 这里写图片描述

能够正确识别为数字3**(注意,图片背景为黑,前景为白)**。

Tips:
测试当个模型的时候用到了均值文件,建议在训练文件lenet_train_test.prototxt和测试文件deploy.prototxt中transform_param添加处理命令mean_file: "./mean.binaryproto"

四、 Matlab Demo

利用CaffeNet演示图像分类,首先需要编译Caffe的Matlab接口,再下载一个对应的模型文件,最后就可以运行这个demo。

4.1、编译Caffe的Matlab接口

编译“matlab”工程,生成对应的caffe_.mexw64文件,位置如右下图
这里写图片描述 这里写图片描述
再将该文件复制到上一级目录\caffe-windows\matlab\+caffe\private\下。

4.2、模型文件下载

从http://dl.caffe.berkeleyvision.org/bvlc_reference_caffenet.caffemodel下载模型文件,并放到\caffe-windows\models\bvlc_reference_caffenet\文件夹下。

这里写图片描述

4.3、测试

打开Matlab,设置当前目录为.\caffe-windows\matlab\demo\,执行以下代码:
这里写图片描述
图片和结果如下:
这里写图片描述这里写图片描述这里写图片描述

五、 附录

5.1、生成网络结构图

利用.\caffe-windows\python目录下的draw_net.py脚本绘制网络结构图(需要pip安装依赖的包,见requirements.txt)。新建draw_net.bat批处理文件,内容如下。复制lenet_train_test.prototxt到当前目录。

这里写图片描述

运行后结果如下

这里写图片描述

对my_deploy.prototxt生成结构图如下

这里写图片描述

Tips: 可查看大图。 网络结构是从下向上生长,当前层的前一层为bottom,后一层是top。

5.2、相关文件说明

(1)lenet_solver.prototxt
# The train/test net protocol buffer definition(制定训练和测试模型)net: " 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.  (batch size * test_iter = 10000)test_iter: 1001100个测试集样本参与向前计算)# 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"    (inv: return base_lr * (1 + gamma * iter) ^ (- power))gamma: 0.0001power: 0.75# Display every 100 iterationsdisplay: 100()      (每迭代100次打印结果)# The maximum number of iterationsmax_iter: 10000     (最大迭代次数)# snapshot intermediate resultssnapshot: 50005000次迭代保存一次临时模型,名称为lenet_iter_5000.caffemodel)snapshot_prefix: "examples/mnist/lenet"# solver mode: CPU or GPUsolver_mode: GPU        (GPU开关)
(2)lenet_train_test.prototxt
name: "LeNet"           网络名layer {  name: "mnist"         本层名称  type: "Data"          层类型  top: "data"           下一层接口  top: "label"          下一层接口  include {    phase: TRAIN  }  transform_param {    scale: 0.00390625       #1/256,预处理如减均值,尺寸变换,随机剪,镜像等  }  data_param {    source: "mnist_train_lmdb"  训练数据位置    batch_size: 64              一次训练的样本数    backend: LMDB               读入的训练数据格式,默认lmdb  }}layer {  name: "mnist"  type: "Data"  top: "data"  top: "label"  include {    phase: TEST  }  transform_param {    scale: 0.00390625  }  data_param {    source: "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"}

(3)lenet.prototxt

name: "LeNet"(网络的名字)layer {  name: "data"  type: "Input"             (层类型,输入)  top: "data"               (导入数据这一层没有bottom,因为是第一层)  input_param {       shape: { dim: 64 dim: 1 dim: 28 dim: 28 }     }                      (64张图为一批,28*28大小)}读取这批数据维度:64 1 28 28layer {  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,由20个特征图Feature Map构成)    kernel_size: 5      (卷积核的大小是5*5)    stride: 1           (卷积操作步长)    weight_filler {      type: "xavier"    (随机的初始化权重和偏差)    }    bias_filler {      type: "constant"  (bias使用0初始化)    }  }             (通过卷积之后,数据变成(28-5+1)*(28-5+1),20个特征)}卷积之后这批数据维度:64 20 24 24layer {  name: "pool1"  type: "Pooling"           (下采样类型层)  bottom: "conv1"  top: "pool1"  pooling_param {    pool: MAX           (下采样方式,取最大值)    kernel_size: 2          (下采样核函数size)    stride: 2               (步长)  }}下采样之后这批数据维度:64 20 12 12layer {  name: "conv2"  type: "Convolution"  bottom: "pool1"  top: "conv2"  param {    lr_mult: 1  }  param {    lr_mult: 2  }  convolution_param {    num_output: 5050个卷积核)    kernel_size: 5    stride: 1    weight_filler {      type: "xavier"    }    bias_filler {      type: "constant"    }  }}卷积之后这批数据维度:64 50 8 8layer {  name: "pool2"  type: "Pooling"  bottom: "conv2"  top: "pool2"  pooling_param {    pool: MAX    kernel_size: 2    stride: 2  }}下采样之后这批数据维度:64 50 4 4layer {  name: "ip1"  type: "InnerProduct"      (全连接类型层)  bottom: "pool2"  top: "ip1"  param {    lr_mult: 1  }  param {    lr_mult: 2  }  inner_product_param {     (全连接层参数设置)    num_output: 500         (输出为500)    weight_filler {      type: "xavier"    }    bias_filler {      type: "constant"    }  }             (4*4的数据通过4*4的卷积得到1*1的数据)}通过全连接层之后这批数据维度:64 500 1 1layer {  name: "relu1"  type: "ReLU"      (激活函数类型层)  bottom: "ip1"  top: "ip1"    (这个地方还是ip1,底层与顶层相同减少开支,下一层全连接层的输入也还是ip1)}通过ReLU层之后这批数据维度:64 500 1 1(不做改变)layer {  name: "ip2"  type: "InnerProduct"  bottom: "ip1"  top: "ip2"  param {    lr_mult: 1  }  param {    lr_mult: 2  }  inner_product_param {    num_output: 10          (直接输出结果,0-9,十个数字所以维度是10)    weight_filler {      type: "xavier"    }    bias_filler {      type: "constant"    }  }                         (数据的分类判断在这一层中完成)}通过全连接层之后这批数据维度:64 10 1 1layer {  name: "prob"  type: "Softmax"           (损失函数)  bottom: "ip2"  top: "prob"               (一开始数据输入为date的话,这里写label)}

原创文章,转载请注明出处 http://blog.csdn.net/wanggao_1990/article/details/76721294。


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