工具下载
微软官方移植的Caffe:https://github.com/Microsoft/caffe
对属性表的操作
需要把实例属性表的后缀改成vs可用的.props
打开同一个文件夹下的Caffe.sln,查看其中的属性表
<CpuOnlyBuild>true</CpuOnlyBuild>
<UseCuDNN>false</UseCuDNN>
分别指的是只利用CPU的环境和利用GPU进行CUDA编程,只能二选一,保持一个为true。
如果想进行CUDA编程首先要确保自己的GPU是英伟达NVIDIA的,然后在https://developer.nvidia.com/cudnn下载cuDNN(CUDA Deep Neural Network library),一个专门为深度神经网络提供GPU加速的库。下载好解压缩之后,
<!-- CuDNN 4 and 5 are supported -->
<CuDnnPath></CuDnnPath>
要填写cuDNN的路径。
解决方案
可以看到,解决方案中有16个项目(不用数,有显示)。我们最关注的是caffe和libcaffe。
对caffe:
右击“解决方案‘Caffe’”,选择“属性”,将“配置属性”-“配置”修改成Release和x64
(这一步是使用Release来进行编译,若用Debug,则之后每次都要打开vs,会不方便)
注意:在上图顶部工具栏中的“解决方案配置”和“解决方案平台”框,若你的vs2013中将这两个框在工具栏中显示,则要在工具栏中将配置改成Release和x64,否则直接右击“解决方案Caffe”来更改配置是无效的。
对libcaffe:
右击解决方案中的libcaffe项目,选择“属性”,在打开的属性页中选择“C/C++”-“常规”,将“将警告视为错误”设为“否。然后右击libcaffe项目,生成。期间会利用NuGet对caffe的一些依赖文件进行自动还原。同时会在caffe-master的同级目录生成文件夹NugetPackages。里面是一些依赖库(包括OpenCV),这也是选择windows版caffe的好处。
这时候就可以生成解决方案了。但是打开解决方法的属性可以看到默认的是只编译libcaffe。我们可以选择编译其他项目。
此时在\caffe-master目录下会生成Build文件夹,即为我们编译成功的文件夹,而\caffe-master\Build\x64\Release目录下则会有我们编译出的caffe.exe执行文件。
MINIST下载、转换和训练
这是一个手写数字数据集,有60,000个训练样本,10,000个测试样本,测试集和训练集是没有交集的。数字尺寸都已经标准化,并且保证数字在图像中心。数字是20x20像素的,图像是28x28像素大小。
下载地址:http://yann.lecun.com/exdb/mnist/
train-images-idx3-ubyte.gz: training set images (9912422 bytes)
train-labels-idx1-ubyte.gz: training set labels (28881 bytes)
t10k-images-idx3-ubyte.gz: test set images (1648877 bytes)
t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes)
图像是以矩阵在一个特殊的格式中存储的,所以是无法直接打开查看的。若发现下载的文件比官方给出的大,则说明浏览器已经自动解压缩了。这个时候只需要重命名就可以移除.gz文件了。
这四个文件不能直接用于caffe的训练和测试。需要利用生成的Release中的convert_mnist_data.exe把四个文件转换为caffe所支持的leveldb或lmdb文件。lmdb是lightning(闪电的) memory-mapped database manager的缩写,能够把原始数据通过更为高效的存储方式存储,从而加快读取和训练速度(lmdb比leveldb更快,可以看看刚刚的NugetPackages文件夹,当中就包含着对应的库)。具体转换方法如下:
a) 四个文件放到 . \examples\mnist\mnist_data文件夹下。
b) 在caffe-windows安装的根目录下,新建一个convert-mnist-data-train.bat文件转换为训练数据,并在文件中添加代码:
Build\x64\Release\convert_mnist_data.exe--backend=lmdbexamples\mnist\mnist_data\train-images.idx3-ubyteexamples\mnist\mnist_data\train-labels.idx1-ubyteexamples\mnist\mnist_data\mnist_train_lmdb
Pause
再新建一个convert-mnist-data-test.bat转换测试数据,代码为:
Build\x64\Release\convert_mnist_data.exe--backend=lmdb examples\mnist\mnist_data\t10k-images.idx3-ubyteexamples\mnist\mnist_data\t10k-labels.idx1-ubyteexamples\mnist\mnist_data\mnist_test_lmdb
Pause
运行
a) 转换好的训练\测试数据集(mnist_train_lmdb\ mnist_train_lmdb或mnist_train_leveldb\mnist_train_leveldb)文件夹放在.\examples\mnist中。
b) 修改lenet_solver.prototxt 中solver_mode: CPU;修改lenet_train_test.prototxt中
source:"examples/mnist/mnist_train_lmdb"
source:"examples/mnist/mnist_test_lmdb"
backend: LMDB
保证训练集和测试集的路径正确。
c) 在caffe-windows根目录下新建一个run.bat,文件中代码:
Build\x64\Release\caffe.exe train--solver=examples/mnist/lenet_solver.prototxt
Pause
d) 保存并双击运行run.bat,会开始打印一些日志文件。当迭代次数达到lenet_solver.prototxt定义的max_iter时,就可以认为训练结束了。训练完成后会在examples/mnist生成 .caffemodel 文件和 .solverstate 文件。分别是训练一半和训练结束的结果。
Ps:lenet_solver.prototxt是examples/mnist下的.prototxt文件。定义了网络的结构。可以用vs打开。
solver.prototxt是solver配置文件,规定了如何优化求解loss function(非凸函数没有解析解)。比如最常用的方法是Stochastic Gradient Descent (type:"SGD")。
这两个文件很重要,因为它们决定了网络是如何设计的,可以自己设计网络,从而生成自己的.caffemodel 文件
Ps: 官方文档Lenet NIST tutorial 给出的方法:在Linux下,直接利用
./data/mnist/get_mnist.sh
./examples/mnist/create_mnist.sh
得到MNIST文件并且转换为Lmdb格式。.sh是Linux下的脚本文件
测试
虽然之前的步骤应该都成功了,但是没有结果感觉还是不踏实。现在终于可以开始测试了。测试手写数字就是机器学习中的hello world,还有点小兴奋呢。
训练集图片均值文件
第一步,仍然要通过一个根目录下的bat文件利用release下面的compute_image_mean.exe。
bat命令:Build\x64\Release\compute_image_mean.exeexamples\mnist\mnist_train_lmdb mean.binaryproto --backend=lmdb
然后就可以得到一个mean.binaryproto文件。含义是图片减去均值后的残差图片。
然后我们需要修改\examples\mnist\lenet_train_test.prototxt。预处理transform_param中要添加mean_file文件。如下图:
开始mnist测试
依然是通过bat,利用的是caffe.exe。
Build\x64\Release\caffe.exe test--model=examples\mnist\lenet_train_test.prototxt-weights=examples\mnist\lenet_iter_10000.caffemodel
Pause
批处理文件一不小心写错了好几回。在这里我们指定了测试模式,随后指定模型和训练出来的参数。
可以看到前面是时间和日期。测试是以batch为单位进行的,从0~49一共50个batch。分别给出了每个batch的accuracy和loss。准确率在99%左右。
问题1:但是重新保存修改之后的\examples\mnist\lenet_train_test.prototxt预处理transform_param,即使用减去均值的残差图像,准确率反而下降了。如上图,准确率只有92%。
连接https://blog.csdn.net/swj110119/article/details/53423957的测试结果和我一样。他认为是均值预处理之后相对于均值滤波,图像变模糊了。这里其实有两个问题,一个是都说利用均值文件是为了提高准确率,但是这里却下降了;一个是预处理是简单地对测试图像进行图像相减呢,还是会重新调整网络权重,生成一个新的网络?
问题2:50个batch是由上面决定的呢?:”从一到二”博客里面说是caffe.cpp中一个叫做FLAGS_iterations的变量指定的。但是看了一下代码也没有什么宏定义直接显示50
自己手写数据测试
刚才是以batch测试的,还是没有直观的感受。
1.画图和准备标签
开启画图,调整到像素大小为28x28.然后手写0~9的数字,保存为bmp格式。这里有一个问题,虽然利用classification.exe不再需要转换成lmdb格式,但是也要求是单通道的。
Ps:如果保存的格式为单色位图bmp格式,它与单通道有什么关系呢?单色位图是黑白二值图像;单通道是只有一个通道,灰度图,图像的色阶是0~255的。
事实证明是没什么关系的。完全是对图像的两个角度的衡量。三通道当然可以生成二值图像。只不过当imread以参数为0读入图像时就无需转换成gray了。
把转换好的单通道bmp图像放在\examples\mnist目录下。同时准备一个标签文件label.txt,里面是0~9的数字。
2. 通过test_personal.bat利用classification.exe去识别某张图片
Build\x64\Release\classification.exeexamples\mnist\lenet.prototxt examples\mnist\lenet_iter_10000.caffemodelmean.binaryproto examples\mnist\label.txt examples\mnist\8.bmp
Pause
下图是对“8”的识别情况
可惜“9”识别错了
Reference:
1. Caffe编译https://blog.csdn.net/xierhacker/article/details/51834563
2. Mnist转换https://blog.csdn.net/foreyang00/article/details/71122866
3. prototxt文件的设置解读https://blog.csdn.net/u014696921/article/details/52166015
4. 从零到一http://www.cnblogs.com/yixuan-xu/p/5858595.html
5. 从一到二http://www.cnblogs.com/yixuan-xu/p/5862657.html