caffe--python版利用训练好模型进行测试

小鱼最近在caffe上用faster rcnn网络进行目标的检测,但是网络是先按设置好的训练迭代次数进行训练,得到训练模型之后进行一次性的测试(这里小鱼认为是验证更合理),最终网络得到的输出只有train net output的四个输出。下面为某次迭代的输出结果:

I1224 13:55:23.250411 16953 solver.cpp:229] Iteration 20000, loss = 0.179466
I1224 13:55:23.250457 16953 solver.cpp:245]     Train net output #0: loss_bbox = 0.0858043 (* 1 = 0.0858043 loss)
I1224 13:55:23.250463 16953 solver.cpp:245]     Train net output #1: loss_cls = 0.106088 (* 1 = 0.106088 loss)
I1224 13:55:23.250465 16953 solver.cpp:245]     Train net output #2: rpn_cls_loss = 0.000335818 (* 1 = 0.000335818 loss)
I1224 13:55:23.250469 16953 solver.cpp:245]     Train net output #3: rpn_loss_bbox = 0.00807029 (* 1 = 0.00807029 loss)
I1224 13:55:23.250474 16953 sgd_solver.cpp:106] Iteration 20000, lr = 0.001

但是只得到训练阶段的结果没有太大的意义,如果可以让网络边训练边测试,并且输出自己想要的结果那就完美了。
A.实现让网络边训练边测试方法

有两个地方需要改,第一是solver.prototxt文件

train_net: "models/pascal_voc/VGG16/faster_rcnn_end2end/train.prototxt"
test_net: "models/pascal_voc/VGG16/faster_rcnn_end2end/test.prototxt"
test_iter:10
test_interval:100

加入训练和测试的配置文件,并且加入训练多少次测试一次的参数。
其中test_iter为测试时要迭代的次数,iter_iter*batchsize要等于或大于测试集的数量
test_interval表示训练的时候每迭代多少次进行一次训练
关于改两个参数还有不懂可参考:test_iter test_interval等概念
第二个需要修改的地方为train.prototxt文件,加入你想要的输出层,比如这里是加入accuracy精度层

layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "cls_score"
  bottom: "labels"
  top: "accuracy"
  accuracy_param {
    ignore_label: -1
  }
}

你在加入层时注意bottom和top层需要什么就可以。
得到的结果为

I1225 16:00:46.513276 29753 solver.cpp:229] Iteration 150, loss = 0.650436
I1225 16:00:46.513305 29753 solver.cpp:245]     Train net output #0: loss_bbox = 0.32511 (* 1 = 0.32511 loss)
I1225 16:00:46.513310 29753 solver.cpp:245]     Train net output #1: loss_cls = 0.174398 (* 1 = 0.174398 loss)
I1225 16:00:46.513314 29753 solver.cpp:245]     Train net output #2: rpn_cls_loss = 0.0964653 (* 1 = 0.0964653 loss)
I1225 16:00:46.513319 29753 solver.cpp:245]     Train net output #3: rpn_loss_bbox = 0.124464 (* 1 = 0.124464 loss)
I1225 16:00:46.513337 29753 sgd_solver.cpp:106] Iteration 150, lr = 0.001
I1225 16:01:08.406378 29753 solver.cpp:338] Iteration 200, Testing net (#0)
I1225 16:01:08.406400 29753 net.cpp:748] Ignoring source layer input-data
I1225 16:01:08.406404 29753 net.cpp:748] Ignoring source layer data_input-data_0_split
I1225 16:01:08.406404 29753 net.cpp:748] Ignoring source layer im_info_input-data_1_split
I1225 16:01:08.406406 29753 net.cpp:748] Ignoring source layer gt_boxes_input-data_2_split
I1225 16:01:08.406419 29753 net.cpp:748] Ignoring source layer rpn_cls_score_rpn_cls_score_0_split
I1225 16:01:08.406422 29753 net.cpp:748] Ignoring source layer rpn_bbox_pred_rpn_bbox_pred_0_split
I1225 16:01:08.406424 29753 net.cpp:748] Ignoring source layer rpn_cls_score_reshape_rpn_cls_score_reshape_0_split
I1225 16:01:08.406425 29753 net.cpp:748] Ignoring source layer rpn-data
I1225 16:01:08.406427 29753 net.cpp:748] Ignoring source layer rpn_loss_cls
I1225 16:01:08.406428 29753 net.cpp:748] Ignoring source layer rpn_loss_bbox
I1225 16:01:08.406432 29753 net.cpp:748] Ignoring source layer roi-data
I1225 16:01:08.406437 29753 net.cpp:748] Ignoring source layer loss_cls
I1225 16:01:08.406440 29753 net.cpp:748] Ignoring source layer loss_bbox
I1225 16:01:08.664206 29753 solver.cpp:406]     Test net output #0: bbox_pred = 0.00942488
I1225 16:01:08.664227 29753 solver.cpp:406]     Test net output #1: bbox_pred = -0.0537473
I1225 16:01:08.664244 29753 solver.cpp:406]     Test net output #2: bbox_pred = 0.00265342
I1225 16:01:08.664248 29753 solver.cpp:406]     Test net output #3: bbox_pred = -0.021216
I1225 16:01:08.664250 29753 solver.cpp:406]     Test net output #4: bbox_pred = -0.534974
I1225 16:01:08.664253 29753 solver.cpp:406]     Test net output #5: bbox_pred = -0.0314645
I1225 16:01:08.664255 29753 solver.cpp:406]     Test net output #6: bbox_pred = -0.161127
I1225 16:01:08.664258 29753 solver.cpp:406]     Test net output #7: bbox_pred = -0.848146
I1225 16:01:08.664274 29753 solver.cpp:406]     Test net output #8: cls_prob = 0.999959
I1225 16:01:08.664276 29753 solver.cpp:406]     Test net output #9: cls_prob = 4.12374e-05

有一个问题小鱼还没有解决是,为什么测试网络的loss输出都被忽略,可能是因为测试阶段的loss不重要,test阶段一般更加关注accuracy,AP值。
B.自己编写脚本实现利用已训练好的模型进行测试

#!/usr/bin/env python
# -*- coding: utf-8 -*-


"""
make prediction for test images using trained model ,then come out the test accuracy
"""

import caffe
import os
import numpy as np

#导入deploy文件及训练好的模型
root='/home/work/py-faster-rcnn/'
model_def=root+'/deploy.prototxt'
caffe_model=root+'/vgg16_faster_rcnn_iter_50000.caffemodel'

img=root+'data/demo/00101.jpg'

f=file("/data/testresult.txt","w")
#类别名称文件,将数字标签转换回类别名称
labels_filename=root+'data/label.txt'

net=caffe.Net(model_def,
              caffe_model,
              caffe.TEST)
#图片预处理设置
transformer=caffe.io.Transformer({'data':net.blobs['data'].data.shape})  
   #设定图片的shape格式为(1,3,224,224)
transformer.set_transpose('data',(2,0,1))  
   #改变维度的顺序,原始图片(224,224,3)变成(3,224,224)
transformer.set_raw_scale('data',255)   
   #缩放到[0,225之间]
transformer.set_channel_swap('data',(2,1,0))  
   #交换通道,由图片RGB转为BGR
#加载图片
im=caffe.io.load_image(img)
#执行预处理操作,并将图片载入到blob中
net.blobs['data'].data[...]=transformer.preprocess('data',im)
#执行测试
out=net.forward()
#读取类别名称文件
labels=np.loadtxt(labels_filename,str,delimiter='\t')
#取出最后一层属于某个类别的概率值并打印
prob=net.blobs['cls_prob'].data[0].flatten()
print prob
#取出最大值所在的序号
order=prob.argsort()[-1]
#将改序号转换为对应的类别名称打印并写入指定txt文件中
print 'the class is:',labels[order]
f=file("/data/testresult.txt","a+")
f.writelines(img+' '+labels[order]+' '+str(prob)+'\n')

这里是拿一张图片作为演示,如果有多张图,写一个for循环读入图片就好。同时代码中的路径都是视具体路径改的,你是什么路径就写什么路径。
需要注意的点为
问题一:最上面的#!/usr/bin/env python一定要记得写上,不然一直会报如下错

>>>import caffe
   Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
   ImportError: No module named caffe

这里的解决方法除了加上这一行之外,还有就是将caffe放到配置文件中,把环境变量路径放到 ~/.bashrc文件中,可以永久有效果,解决方法如下:
打开新终端,输入

sudo gedit ~/.bashrc

打开bashrc文件之后,在最后添加如下行:

export PYTHONPATH=~/caffe/python:$PYTHONPATH #~为自己caffe的目录

添加之后,保存关闭文件,要想环境变量生效,需要在终端下输入

source ~/.bashrc 

问题二,代码中的testresult.txt表示的是新建的用来保存测试精度的文本;代码中的label.txt为你的类别文件,格式如下:

0 person
1 dog

今天的内容有点多,希望能帮到大家,小鱼还要探究怎么写脚本将测试阶段的准确率和召回率提出来。
如果有哪位大牛看到这篇博文,知道怎么将测试阶段的precision和recall提取出来的话,教教小鱼,当然小鱼如果学会了也会和大家分享。
关于本博文有不懂的同学欢迎相互沟通,加油!

猜你喜欢

转载自blog.csdn.net/zllljf/article/details/78926078