Windows下使用caffe识别Mnist图片

Windows下使用caffe识别Mnist图片

这是一个windows下的使用caffe的入门教程,使用单纯编译好的exe文件来进行手写体训练并识别的教程。

按照以下的路线来叙述:

配置caffe环境—–>训练mnistmodel—–>使用训练好的model来预测图片


一、配置Windows下的caffe环境

1.下载编译好的caffe

https://github.com/BVLC/caffe/tree/windows

选择符合你的计算机配置的版本,我们这里下载的是Release版本的caffe,所以不需要我们去对它进行编译,大家根据是否具有NVIDIA显卡去选择GPU版本或CPU版本的caffe,另外要编译python接口,根据大家使用的python版本选择一下。

我这里选择的是“Visual Studio 2015,CUDA 8.0, Python 2.7: Caffe Release

下载完成之后解压,可以看到其简单的目录结构。

其中的bin文件夹都是编译好的exe文件和其所依赖的链接库。

2.编译python接口

PS:我这里使用的是Anaconda2python

注意:和Ubuntu编译pythonmake pycaffe的方式不同,下载的这个caffe已经将pycaffe编译好了,你只需要配置好protobuf,不然会报错如下:

caffe python error: No module named google.protobuf.internal

我试过编译protobuf-2.6.1,发现不适用于我们下载的这个caffe,所以最后改用protobuf-3.3.0并成功,我这里给出我使用的protobuf-3.3.0

链接:https://pan.baidu.com/s/1fpIdES3sAP-6uyzr_ByO6w 密码:qhyv

解压之后进入里面的python文件夹,cmd命令行到这个目录下面,执行:

python setup.py build
python setup.py test
python setup.py install

即可完成protobuf的配置。

如果中途没有遇到bug(注意build过程需要Download文件)的话,那就说明protobuf是配置好了,可以尝试 import google.protobuf.internal 看看会不会遇到什么问题以检验一下。

没有问题的话caffeimport应该也没有问题。但是要注意caffepython文件夹下面有一个requirements.txt,我想是Anaconda已经都配置好这些库了,所以这里没有遇到问题,如果使用的是原生的python‘而不具备这些库的话可能需要pip自行安装了。

PS:编译protobufpython接口需要主目录下的src文件夹内有编译好的protoc.exe文件,我提供的protobuf-3.3.0里面是有的,大家在网上下载的其他的版本可能没有这个文件,另外这个是对Windows平台下的编译,此教程不适用于Linux平台。

最后,大家cmd命令行到caffe\python目录下,运行pythonimport caffe看看是否导入成功,如果没有报错则Windows下的pycaffe以及编译好可以使用了。

二、训练mnist的model

PS:我们先运行Mnist来验证caffe,因为我们使用的是编译好的程序,所以不需要配置其他变量,但这里需要的是下载Mnist的四个文件,在官网下载可能比较慢,这里百度云分享给大家。(这里除了四个数据文件还有接下来我用到的一些文件)

链接:https://pan.baidu.com/s/1DuMMufJBfaI8vHKWghv4Hg 密码:iqmi

如果大家百度云下载比较慢,可以参考IT之家一篇博客,有讲解如何下载百度云的文件,我试过可以。

1.下载Mnist的数据文件

大家下载完之后得到这四个文件。我接下来的脚本是按照我的目录结构改的,使用的是相对路径,大家可以根据自己的目录结构对代码做修改。(我在主目录下创建了一个mnist文件夹,并将数据文件都放进去了)

2.定义网络结构以及设置超参数

接下来在mnist里面创建一个文件名为“lenet_train_test.prototxt”的文件来定义网络结构:

name: "LeNet"
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "./mnist_train_lmdb"
    batch_size: 64
    backend: 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
    backend: LMDB
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  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"
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 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"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 10
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}

再创建一个名为“lenet_solver.prototxt”的文件来定义网络的超参数:

net: "./lenet_train_test.prototxt"
test_iter: 100
test_interval: 500
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
lr_policy: "inv"
gamma: 0.0001
power: 0.75
display: 100
max_iter: 10000
snapshot: 5000
snapshot_prefix: "./"
solver_mode: GPU

3.转化LMDB文件

有了整体网络的定义,我们就可以利用我们现有的数据来进行训练了,但是,我们不能使用我们如下的数据,需要将它们转化为caffe可识别的LMDB的文件形式。

而我们之前已经编译好的caffe提供了很多工具来方便我们使用。

我们可以使用convert_mnist_data.exe来将我们四个数据文件转化为LMDB格式的文件。这里可以把转化数据文件的操作写成一个windows批处理的脚本,双击运行就可以了。

mnist文件夹下创建一个名为“convert_mnist_data.bat”的文件,使用记事本编译这个bat文件,复制粘贴:

..\bin\convert_mnist_data.exe  .\train-images.idx3-ubyte .\train-labels.idx1-ubyte .\mnist_train_lmdb  
echo.  
..\bin\convert_mnist_data.exe  .\t10k-images.idx3-ubyte  .\t10k-labels.idx1-ubyte .\mnist_test_lmdb 
pause  

保存之后,双击convert_mnist_data.bat运行,即可看到生成的两个LMDB的文件夹。

4.训练网络并生成model

到这里我们已经具备了训练Mnist的所有条件了,这时候我们可以再写一个train_mnist.bat文件来自行我们的训练,和刚才一样创建一个名为“train_mnist.bat”的文件,复制粘贴:

..\bin\caffe.exe train --solver=./lenet_solver.prototxt
pause  

我使用的是相对路径,如果大家的目录结构和我一样的话应该不会遇到什么问题。

这时候双击train_mnist.bat即调用caffe.exe对我们的数据文件进行训练了。(并且是使用GPU进行训练的)

训练完成之后,可以看到训练精度是达到0.9906的,并且过程中没迭代5000次便生成一次快照,这些在lenet_solver.prototxt都是可定义的。

三、使用训练好的model来预测图片

也就是说,我们有了model,代表我们网络的各个层的权重,当我们要利用我们现有的model去预测一张新的图片的时候,我们需要有原来的网络结构为model中的参数指明位置。

之前的lenet_train_test.prototxt定义了我们的数据集的位置,而在预测的时候不需要这些数据。

所以这次我们重新创建一个lenet.prototxt(在mnist文件夹下面):

name: "LeNet"
layer {
  name: "data"
  type: "Input"
  top: "data"
  input_param { shape: { dim: 64 dim: 1 dim: 28 dim: 28 } }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  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"
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 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"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 10
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "prob"
  type: "Softmax"
  bottom: "ip2"
  top: "prob"
}

我们预测的时候用到了pythoncaffe接口,使用的是python代码调用caffe,我创建了一个“testModel.py”文件,内容如下:

PS:注意修改’D:\APP\caffe\python‘为你自己的目录;import cv2失败的同学需要把cv2.pyd拷贝到Anaconda2\Lib\site-packages目录下面,再重新import试一下,python3的同学网上找找别的方法。

import numpy as np
import cv2
import sys
sys.path.insert(0,'D:\APP\caffe\python')
import caffe

MEAN = 128
SCALE = 0.00390625
imgPath=sys.argv[1]

caffe.set_mode_gpu()
caffe.set_device(0)
net = caffe.Net('lenet.prototxt', '_iter_10000.caffemodel', caffe.TEST)
net.blobs['data'].reshape(1, 1, 28, 28)

image = cv2.imread(imgPath, cv2.IMREAD_GRAYSCALE).astype(np.float) - MEAN
image *= SCALE
net.blobs['data'].data[...] = image
output = net.forward()
pred_label = np.argmax(output['prob'][0])
print('\nPredicted digit for {} is {}'.format(imgPath, pred_label))

我使用了sys.argv[1]这个,所以等一下要预测的图片的路径我们在命令行下面输入即可,如果要批量预测的同学可以修改一下代码。到目前我的mnist目录结构如下:

我创建了testImg文件夹里面放了几张图片:

我现在使用testModel.py预测一下mnist_test_132.png代表的内容:

预测结果十分顺利,大家可以试着改一下代码进行批量的处理并计算一下准确率。

猜你喜欢

转载自blog.csdn.net/wuzebiao2016/article/details/80186731