用訓練好的模型測試單張圖片存在的問題

用CNN做圖像分類,在得到訓練好的模型之後,往往會用caffe自帶的classification.bin測試單張圖片的分類結果,但是這會存在一些問題,下面我用caffe自帶的Cifar10來分析。

訓練得到Cifar10的網絡模型
網上有很多博文,可以參考 學習筆記:Caffe上配置和運行Cifar10的示例

用單張圖片測試訓練好的模型

  • 利用classification.bin識別單張圖片
cd caffe  #進入caffe目錄
./build/examples/cpp_classification/classification.bin \
examples/cifar10/cifar10_quick.prototxt \  #網絡結構描述文件
examples/cifar10/cifar10_quick_iter_5000.caffemodel.h5 \  #保存的網絡模型
examples/cifar10/mean.binaryproto \  #數據集的均值文件
data/cifar/batches.meta.txt \  #分類標籤文件
.../.../*.jpg  #測試圖像

下載一張圖片測試
這裏寫圖片描述
注意:這裏的圖片要resize到32*32,例如

from PIL import Image
img = Image.open('dog.jpg')
image = img.resize((32, 32), Image.ANTIALIAS)
image.save('dog.jpg')

測試結果:

0.7372 - "dog"
0.1329 - "cat"
0.0622 - "deer"
0.0573 - "horse"
0.0064 - "frog"

右邊是分類標籤,左邊是相對應的概率值

  • 利用python接口測試
import sys
import numpy as np

caffe_root = '/home/***/caffe'
sys.path.insert(0, caffe_root + '/python')
import caffe

img = 'dog.jpg'
image = caffe.io.load_image(img)

net_file = caffe_root + '/examples/cifar10/cifar10_quick.prototxt'
caffe_model = caffe_root + '/examples/cifar10/cifar10_quick_iter_5000.caffemodel.h5'
mean_file = caffe_root + '/examples/cifar10/mean.binaryproto'
net = caffe.Net(net_file, caffe_model, caffe.TEST)

# 把二進制均值文件轉換爲np數組
mean_blob = caffe.proto.caffe_pb2.BlobProto()
mean_blob.ParseFromString(open(mean_file, 'rb').read())
mean_npy = caffe.io.blobproto_to_array(mean_blob)

transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2, 0, 1))
transformer.set_mean('data', mean_npy[0].mean(1).mean(1))  # 圖像去均值
transformer.set_raw_scale('data', 255)
transformer.set_channel_swap('data', (2, 1, 0))
net.blobs['data'].data[...] = transformer.preprocess('data', image)

net.forward()  # 網絡前向傳播

cifarnet_labels_filename = caffe_root + '/data/cifar10/batches.meta.txt'
labels = np.loadtxt(cifarnet_labels_filename, str, delimiter='\t')

prob = net.blobs['prob'].data[0]
top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1]
for i in np.arange(top_k.size):
    print prob[top_k[i]], labels[top_k[i]]

測試結果:

0.739209 dog
0.132969 cat
0.0591916 deer
0.0578966 horse
0.00681575 frog

對比兩種測試方法,結果幾乎是相同的,其中的細微差異是由於python與c++的計算精度不同引起的。

至此,你是否覺得測試已經完成了?不,其實上面測試的結果是有問題的,先來看看網絡結構的數據輸入層

layer {
  name: "cifar"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mean_file: "examples/cifar10/mean.binaryproto"
  }
  data_param {
    source: "examples/cifar10/cifar10_train_lmdb"
    batch_size: 100
    backend: LMDB
  }
}

這裏的均值文件是一個與圖像尺寸相同的矩陣,去均值操作是用圖像減去該矩陣。但是,用上述兩種方法測試時,是對應RGB每個通道計算一個均值,再用圖像每個像素點的RGB值減去相對應的均值,也就是說,在測試單張圖片時,去均值操作與訓練過程是不同的,那麼結果自然不可靠。

利用classification.bin測試方法是caffe自帶默認的測試方法,不易更改。因此,用python改進去均值操作如下

import sys
import numpy as np

caffe_root = '/home/***/caffe'
sys.path.insert(0, caffe_root + '/python')
import caffe

net_file = caffe_root + '/examples/cifar10/cifar10_quick.prototxt'
caffe_model = caffe_root + '/examples/cifar10/cifar10_quick_iter_5000.caffemodel.h5'
mean_file = caffe_root + '/examples/cifar10/mean.binaryproto'

net = caffe.Net(net_file, caffe_model, caffe.TEST)

img = 'dog.jpg'
image = caffe.io.load_image(img)  # caffe導入的圖像數組是歸一化以後的RGB值

# 讀取mean.binaryproto文件,轉換爲np數組
mean_blob = caffe.proto.caffe_pb2.BlobProto()
mean_blob.ParseFromString(open(mean_file, 'rb').read())
mean_npy = caffe.io.blobproto_to_array(mean_blob)

# 圖像去均值操作
for i in xrange(3):
    image[:,:,i] -= mean_npy[0,i,:,:] / 255.0

transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_raw_scale('data', 255)
transformer.set_channel_swap('data', (2,1,0))
net.blobs['data'].data[...] = transformer.preprocess('data', image)

net.forward()

cifarnet_labels_filename = caffe_root + '/data/cifar10/batches.meta.txt'
labels = np.loadtxt(cifarnet_labels_filename, str, delimiter='\t')

prob = net.blobs['prob'].data[0]
top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1]
for i in np.arange(top_k.size):
    print prob[top_k[i]], labels[top_k[i]]

測試結果:

0.826519 dog
0.115232 cat
0.0310607 horse
0.0251935 deer
0.00147604 frog

雖然分類的結果沒有變,但是對應的概率值是不同的,測試得到的概率值在某些應用中是比較重要的。因此,測試時一定要與訓練過程保持一致,這樣得到的結果纔有說服力。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章