Caffe的prototxt分为两个文件,一个是网络模型定义文件,如train_val.prototxt,在模型训练以及验证时使用。另一个是deploy.prototxt模型配置文件,在模型test时使用。利用lenet-5的网络模型结构进行改写并测试各自结构训练出的模型准确率。
在编写网络模型prototxt文件时,出现了以下几个错误,
解决的时在定义时文件中不要加注释,单词拼写,layer结构中各层的type的大小写情况
以下分别对lenet-5的结构进行了三个方案的改写:
- 减少一个相连的conv层和pooling层。
模型结构图:
模型训练结果:
- 增加一个相连的conv层和pooling层。(因在pool2层,图像输出尺寸为5*5,故在conv3层,卷积核可定义为3*3,那么conv3层的输出尺寸为(5-3)/1+1=3,而3*3进行2*2pooling时, stride因设置为2。)
模型结构图:
模型训练结果:
- 根据论文中的lenet-5的卷积网络结构进行结构定义。
中间的conv2层没有像论文中所述的那样特征组合进行卷积。
模型训练结果:
Caffe自带的lenet模型模型训练图:
模型训练结果图:
deploy.prototxt与train_val.prototxt的区别:
- 开头处,layer的type类型不同:
其中input_param的参数定义:
dim:10 ——表示对待识别样本进行数据增广的数量,该值的大小可自行定义。但一般会进行5次crop,将整幅图像分为多个flip。该值为10则表示会将待识别的样本分为10部分输入到网络进行识别。如果相对整幅图像进行识别而不进行图像数据增广,则可将该值设置为1.
dim:3 ——该值表示处理的图像的通道数,若图像为RGB图像则通道数为3,设置该值为3;若图像为灰度图,通道数为1则设置该值为1.
dim:227 ——图像的长度,可以通过网络配置文件中的数据层中的crop_size来获取。
dim:227——图像的宽度,可以通过网络配置文件中的数据层中的crop_size来获取。
- 中间部分处,在deploy中layer的param、以及一些weights、bias等参数定义被删除,如下图:
- 结尾部分中,deploy文件不需要进行方向传播以及输出准确度和loss等信息,故将layer的Accuracy层删除,将SoftmaxWithLoss层类型改成了Softmax。
其它部分是不变的。
将lenet-5的网络模型修改得到deploy文件,并对自己手写的数据进行测试:
- 准备数据
利用windows自带的画图软件写了0~9的数字,resize(28*28)然后进行灰度黑白转换处理,得到10张仿手写数字。
链接:https://pan.baidu.com/s/1RrRgEcWc-itHC_4Uzdwztg 密码:mn4v
建立image_label.txt和val.txt文件,方法在前面博客介绍了,(注意指令的图片格式)。
标签格式与前面的不同
- 测试代码:(测试代码在读取标签文件时减去了“\t”的参数)
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 30 20:41:03 2017
@author: hans
"""
import sys
sys.path.append('/home/****/caffe/python')
import caffe
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import os
caffe_root = '/home/****/caffe/lenetTest/'
deploy = caffe_root + 'deploy.prototxt' # 需要修改inout_dim: 1, 1, 28, 28
caffe_model = caffe_root + 'lenet_iter_10000.caffemodel'
labels_filename = caffe_root + 'image_label.txt'
labels = np.loadtxt(labels_filename, str)
myfile = open("/home/****/caffe/myself/label.txt", "w+")
mean_file = caffe_root+'mnist_mean.npy'
net = caffe.Net(deploy, caffe_model, caffe.TEST)
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) # data blob 结构(n, k, h, w)
transformer.set_transpose('data', (2, 0, 1)) # 改变图片维度顺序,(h, w, k) -> (k, h, w)
transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))
transformer.set_raw_scale('data', 255) # 将像素范围改成缩放到[0,1]
# transformer.set_channel_swap('data', (2, 1, 0)) # mnist单通道不需要转换
myfile = open("/home/****/caffe/lenetTest/label.txt", "w+")
for root, dir, files in os.walk(caffe_root + 'val/'):
for file in files:
image_file = os.path.join(root, file)
image_path = os.path.join(root, file)
print(image_path)
myfile.write(image_path)
myfile.write(":")
img = Image.open(image_path)
plt.imshow(img)
plt.axis('off')
plt.show()
im = caffe.io.load_image(image_file) # 加载图片
im = caffe.io.resize_image(im, (28, 28, 1)) # 修改图片尺寸维度
caffe_in = transformer.preprocess('data', im) # 将处理好的数据放入caffe_in
out = net.forward(**{'data': caffe_in}) # 将数据放入网络中进行一次前向传播
prob = out['prob'].reshape(10, ) # 可以看出网络中blob都是以字典形式存储数据的。
#print prob
top_five = prob.argsort()[-5:][::-1]
for i in top_five:
class_string = labels[i]
score = prob[i]
lines = "testresult:"+str(class_string)+" "+ "score="+str(score)
myfile.write(lines)
myfile.write(",")
print('%s (score = %.15s)' % (class_string, score))
myfile.write("\n")
比较发现均值文件的有无,发现加了均值文件的测试效果错误比不加时降低一个。