《21天实战Caffe》第六章习题6.4 自己的手写体数字图片送入lenet测试

来源:互联网 发布:ubuntu rm 编辑:程序博客网 时间:2024/06/18 01:38

在看完卜居老师的《21天实战Caffe》第六章后收获颇丰,对之前在Caffe官网看的Tutorial,超入门的examples mnist的训练与识别终于有了一个比较清晰的认识。

果然还是对英语写的指导不太敏感呢(T_T)...感谢卜居大大写的书~~

如果说“Hello World”是所有编程语言的第一个入门练习的话,那mnist就是深度学习方面的“Hello World”了。它是Mixed National Institute of Standards and Technology的缩写,是一个大型的手写体数字数据库,广泛用于机器学习领域的训练和测试,是NYU的Yann LeCun教授整理,具体信息在这里http://yann.lecun.com/exdb/mnist/,这里有个教程也不错MNIST机器学习入门 

在这一章中,卜居老师详细介绍了caffe是如何转换mnist数据格式并进行训练和测试的,最后留下的习题是让自己写个程序,将自己的手写体数字图片送入自己训练好的LeNet进行测试,评估效果。这个题刚看到还是觉得很难的,并没有什么思路,于是果断打开收藏的卜老师的习题答案,【深度学习:21 天实战 Caffe】课后习题参考答案:思路:用 Windows 画图软件绘制手写体数字,缩放到 28 x 28,另存为图片(jpg 或 png 均可),用 MATLAB 将图片转换为 MNIST 格式数据,替换掉 test 数据集,之后再创建 test_lmdb,修改 lenet_train_val.prototxt 使用该数据集。利用训练好的模型和 lenet_train_val.prototxt 进行 caffe test,检查正确率。

于是按这个思路,搜索了相关的实现,一开始还看到有人用C++实现,我觉得一方面实在工作量比较大,另一方面既然都用C++将数据转换为mnist格式,再运行create_mnist.sh脚本调用Caffe里的convert_mnist_data.cpp将图片转换成普通的数组格式,不是浪费时间吗,可能也只有练习C++的作用了,以后用C++的场合应该就直接修改Caffe源码来进行相关练习和测试吧。那么关于matlab的话主要参考这篇文章,图像转化为手写体mnist格式的数据,然后自己做了点微小的工作。

1.先使用PS故意画了个很挫的6,保存为28*28像素的png文件;


2.使用matlab打开它可以看到是28*28*3的矩阵,因为我使用的RGB标准,所以这里既可以在PS里直接把它改为灰度图,也可以在matlab里取三个分量的平均值或取单个通道的值也可以(因为我画的时候纯白底纯黑画笔画的);

3.将这个原始图像以mnist格式写入一个文件,类似mnist官方下载到的t10k-images.idx3-ubyte和t10k-labels.idx1-ubyte

代码如下:

clc;clear;imgOrigin = imread('6.png');imgBinaryImg = imgOrigin(:,:,1);          %只取原图像一个分量,转换为灰度图像imgMnist = fopen('test_img_ubyte', 'wb');  %w:写,如果没有自动创建magic = 2051;numImages = 1;numRows = 28;numCols = 28;  fwrite(imgMnist, magic, 'int32', 0, 'ieee-be');  %ieee-be:大端存储fwrite(imgMnist, numImages, 'int32', 0, 'ieee-be');%0貌似表是读完这个都下个之前的skip,0就是连着读,不跳fwrite(imgMnist, numRows, 'int32', 0, 'ieee-be');  fwrite(imgMnist, numCols, 'int32', 0, 'ieee-be');  imgBinaryImg = permute(imgBinaryImg, [2 1]); %matlab以列为主进行运算  imgBinaryImg = reshape(imgBinaryImg, 1, numCols* numRows* numImages); %reshape按列转换fwrite(imgMnist, imgBinaryImg, 'unsigned char');  fclose(imgMnist);  %将label转换为二进制flabel = fopen('test_lable_ubyte', 'wb');  magic = 2049;numLabels = 1;labels = 6;fwrite(flabel, magic, 'int32', 0, 'ieee-be');  fwrite(flabel, numLabels, 'int32', 0, 'ieee-be');  fwrite(flabel, labels, 'unsigned char');  fclose(flabel);  
代码里面反正我一开始不懂的地方我都加了注释,小伙伴们有疑问的话欢迎讨论。

今晚有点晚了,只实现了一张图片,后面有时间写个循环多加几张自己画的测试图片进去。

运行后matlab的工作空间如下:


生成的mnist格式测试数据属性如下:



可以看到test_img_ubyte大小刚好为4B+4B+4B+4B+28*28B = 800B;

test_lable_ubyte大小为4B+4B+1B。


然后修改lenet_train_test.prototxt里的

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: 1    backend: LMDB  }}

batch_size为 1,因为只有一张图片嘛

然后调用想create_mnist.sh生成caffe需要的lmdb格式数据,然而这里我一直用的是win10系统,不能直接用linux下的脚本(找不到shell命令),于是再转到ubuntu16.04下继续工作,实际后面就与常规的训练mnist步骤差不多了,Caffe官网也有tutorial.

然后修改create_mnist.sh里面创建lmdb,输入对应要转换的自己的文件名,所以其实一开始直接将原测试文件替换掉也可以,可以省去这一步。

set -eEXAMPLE=examples/mnistDATA=data/mnistBUILD=build/examples/mnistBACKEND="lmdb"echo "Creating ${BACKEND}..."rm -rf $EXAMPLE/mnist_test_zfq_${BACKEND}$BUILD/convert_mnist_data.bin $DATA/test_img_ubyte \  $DATA/test_lable_ubyte $EXAMPLE/mnist_test_zfq_${BACKEND} --backend=${BACKEND}echo "Done.

然后调用Caffe的test语句,测试模型对于我画的6的accuracy,如下:

./build/tools/caffe test -model examples/mnist/lenet_train_test.prototxt \-weights examples/mnist/lenet_iter_10000.caffemodel -iterations 1

输出的最后几行:

I1213 12:13:12.657213  4049 net.cpp:283] Network initialization done.
I1213 12:13:12.662529  4049 caffe.cpp:285] Running for 1 iterations.
I1213 12:13:12.668015  4049 caffe.cpp:308] Batch 0, accuracy = 1
I1213 12:13:12.668031  4049 caffe.cpp:308] Batch 0, loss = 3.26639e-05
I1213 12:13:12.668035  4049 caffe.cpp:313] Loss: 3.26639e-05
I1213 12:13:12.668042  4049 caffe.cpp:325] accuracy = 1
I1213 12:13:12.668048  4049 caffe.cpp:325] loss = 3.26639e-05 (* 1 = 3.26639e-05 loss)

有几行还不能完全看懂,不过貌似是成功了,这么丑它都能识别出来。。

2 1