以大神训练好的模型为基础,利用自己的数据进行了finetune之后,下一步就可以真正使用模型来进行分类操作了。具体步骤如下:
1. 编辑分类网络的配置文件deploy.prototxt
deploy文件是真正使用模型时候用的,其结构与train_val.prototxt基本上是一样的,只是输入和输出模块有区别。因此,可以直接把train_val.prototxt拷贝一份,改名为deploy.prototxt,并对其进行编辑:
(1)输入模块
把其中的data层删除(一般有两个,一个用于train,一个用于test),新增一个Input层,一般参数如下:
layer{ name: "data" type: "Input" top: "data" input_param{ shape: { dim: 1 dim: 3 dim: 227 dim: 227} } }
需要注意的是,top参数要和后面的cov1的bottom一样,才能把网络连接上;其次,shape是输入的图片的shape,可以在调用caffe的代码中进行修改。
(2)输出模块
删除Accuracy层和SoftmaxWithLoss层,新建一个Softmax层,一般参数如下:
layer { name: "prob" type: "Softmax" bottom: "fc8" top: "prob" }
其中,bottom参数为上面的网络中最后一层的top(一般为全连接层)
2.图片信息预处理
在输入到网络之前,需要对图片进行预处理,如减去均值等。具体步骤如下:
(1)转换均值文件格式
因为训练时生成的mean文件是通过caffe自带的工具生成的,是C++使用的格式,使用python接口使用caffe需要先将其转化为npy格式。脚本代码如下:
path = '/Users/Coder/caffe/examples/my_file/' blob = caffe.proto.caffe_pb2.BlobProto() data = open(path + 'mean.binaryproto' , 'rb' ).read() blob.ParseFromString(data) arr = np.array( caffe.io.blobproto_to_array(blob) ) out = arr[0] np.save(path + 'mean.npy' , out )
(2)图片格式化
python中读入的图片与caffe中需要的并不一致,因此需要进行格式化
mu = np.load(my_path + 'mean.npy') mu = mu.mean(1).mean(1) transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) #shape要与net中data的shape一致 transformer.set_transpose('data', (2, 0, 1)) #caffe.io.load_image读取jpg图片时,第三维是channel,需要把channel换到第一维 transformer.set_mean('data', mu) #减去均值 transformer.set_raw_scale('data', 255) #python中将图片存储为[0, 1],而caffe中将图片存储为[0, 255],所以需要一个转换 transformer.set_channel_swap('data', (2, 1, 0)) #python的图片是RGB格式,而caffe中的是BGR格式,需要进行转置
3. 加载模型,进行分类
加载模型的网络和训练好的参数,把图片输入,进行分类
加载模型:
my_path = '/Users/Coder/caffe/examples/my_file/' caffe.set_mode_cpu() #如果只使用CPU,需要这一行,如果使用GPU,则设为GPU model_def = my_path + 'deploy.prototxt' #模型配置文件 model_weights = my_path + 'minemodel/solver_iter_200.caffemodel' #训练好的参数 net = caffe.Net(model_def, model_weights, caffe.TEST)
输入图片,执行分类:
img = caffe.io.load_image('/Users/Coder/caffe/data/re/test/409.jpg') #加载图片,进行预处理 transformed_img = transformer.preprocess('data', img) net.blobs['data'].reshape(1, 3, 227, 227) # 修改net的data的格式,使之与输入匹配(可以修改第一个参数,进行批处理) net.blobs['data'].data[...] = transformed_img #输入 output = net.forward() #分类 output_prob = output['prob'][0] #读取分类结果 print 'predicted class is: ', output_prob.argmax()