chainer에서 caffemodel을 사용해보기

소개



향후 여러가지 모델을 Fine-tuning 하는 것을 생각해, chainer에서도 그 기술을 익히고 싶다.
이번에는 caffe model을 읽고 추론만 한다.

참고로 한 사이트는 이쪽
ぃ tp // 이 m / d 씨 오 / ms / 2c9 cfc53b5019475


환경



OS:Ubuntu14.04
GPU:GTX1070
CUDA:8.0 RC
cuDNN:5.1
python2.7.6


caffemodel 다운로드



이번 사용하는 모델은 GoogLeNet. 여기에서
htp // dl. 카후. 베르케 yゔぃ시온. 오 rg/bvlc_오오 ぇ네 t. 카후모도 l
다운로드.

이미지를 numpy 배열로 성형



이미지를 입력에 적합한 numpy 배열로 성형합니다. PIL을 사용하기 때문에 사전에 Pillow 설치가 필요하다.

우선 화상의 종횡 중 작은 쪽이 224가 되도록 축소한다. 다음으로 큰 쪽을 잘라 (224*224) 로 한다. 이것을 float32 의 numpy 배열로 한다.

val_GoogLeNet.py
# -*- coding: utf-8 -*-
from chainer.functions import caffe
from PIL import Image
import numpy as np

image = Image.open('sample01.jpg').convert('RGB')
w_in, h_in = 224, 224 # GoogLeNet in_size
w_img, h_img = image.size # get the size of image

# reduce the size of image
if w_img > h_img:
    shape = (w_in * w_img / h_img, h_in)
else:
    shape = (w_in, h_in * h_img / w_img)
mod_img = image.resize(shape)

# cut both ends

x_space = (shape[0] - w_img) / 2
y_space = (shape[1] - h_img) / 2
in_img = mod_img.crop((x_space, y_space, x_space + w_img, y_space + h_img))
pixels = np.asarray(in_img).astype(np.float32)

그런 다음 numpy 배열을 입력에 적합한 모양으로 정렬합니다. 이미지에서 numpy를 작성한 시점에서는 (y, x, RGB)입니다. 이것을 (index, BGR, y, x)로 한다.

val_GoogLeNet.py
#change RGB to BGR
pixels = pixels[:,:,::-1]

#change axis
pixels = pixels.transpose(2, 0, 1)

다음에 평균 화상을 그린 후, 4차원으로 한다

val_GoogLeNet.py
#subtract mean image
mean_img = np.ndarray((3, 224, 224), dtype=np.float32)
mean_img[0] = 103.939
mean_img[1] = 116.779
mean_img[2] = 123.68
pixels -= self.mean_img

#change to 4 dim
pixels = pixels.reshape(1, 3, 224, 224)

모델의 모양 확인



caffemodel을 로드하기 전에 필요한 정보를 확인합니다.

아래 사이트의 코드에서 모델의 모양을 확인하십시오.
htps : // 기주 b. 이 m/BVLC/캬후/bぉb/마s r/모두 ls/bvlc_오오 gぇ네 t/t등 _ゔぁl. p 여과 txt

train_val.prototxt
name: "GoogleNet"
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
}

.......
.......
.......

layer {
  name: "loss3/top-5"
  type: "Accuracy"
  bottom: "loss3/classifier"
  bottom: "label"
  top: "loss3/top-5"
  include {
    phase: TEST
  }
  accuracy_param {
    top_k: 5
  }
}

입력 레이어의 top이 "data"이고 출력 레이어의 bottom이 "loss3/classifier"인지 확인하십시오.

caffemodel 불러오기



chainer의 기능을 사용하여 caffemodel을로드합니다. 여기에 numpy 배열을 입력합니다.

val_GoogLeNet.py
import chainer
import chainer.functions as F

#read caffemodel
func = caffe.CaffeFunction('bvlc_googlenet.caffemodel')

#define input and output
x = chainer.Variable(pixels, volatile=True)
y, = func(inputs={'data': x}, outputs=['loss3/classifier'],
        disable=['loss1/ave_pool', 'loss2/ave_pool'], train = False)
prediction = F.softmax(y)

`prediction[0]'이 출력 결과이지만, 수치마다의 확률로서 표시되고 있다. 이 수치와 라벨을 대응시키는 라벨 대응표를 다운로드한다.
wget http://dl.caffe.berkeleyvision.org/caffe_ilsvrc12.tar.gz
tar xfvz caffe_ilsvrc12.tar.gz
awk '{$1="";print}' synset_words.txt > labels.txt

이 표의 첫 번째 열을 버리고 두 번째 열의 레이블 만 사용하고 label.txt에 저장합니다.
awk '{$1="";print}' synset_words.txt > labels.txt

결과 출력



먼저 라벨을 로드합니다. 그 위에 점수와 라벨을 묶어 점수가 높은 순서로 한다.

val_GoogLeNet.py
#load labels
categories = np.loadtxt('labels.txt', str, delimiter="\n")
result = zip(prediction.data.reshape((prediction.data.size,)), categories)
result = sorted(result, reverse=True)

#print result of 1st to 5th
for i, (score, label) in enumerate(result[:5]):
    print '{:>3d} {:>6.2f}% {}'.format(i + 1, score * 100, label)

실행 예



아래 사진은 오미야역에서 개최된 후쿠시마현의 PR 이벤트에서 전시된 공룡입니다.

이것의 실행 예는 다음과 같습니다.
python val_GoogLeNet.py
  1  45.46%  common iguana, iguana, Iguana iguana
  2  15.96%  triceratops
  3   8.78%  Chesapeake Bay retriever
  4   3.37%  tiger, Panthera tigris
  5   3.08%  frilled lizard, Chlamydosaurus kingi

이구아나가 45%, 트리케라톱스가 16%. 공룡이지만 이구아나를 닮은 형상이므로 멀지 않은 곳인가.

좋은 웹페이지 즐겨찾기