About connecting the dots.

data science related trivial things

CaffeのImageNetで特徴量抽出器を動かすまで

前回でCaffeがインストールできたので,とりあえず今回はImageNetの特徴量抽出器を使うまで.Yahoo! JAPAN Tech blogの記事を参考にやってみたら,ハマりどころがたくさんあったので,そのあたりを共有しましょうの会です.ハマりどころを抜けるのに参考にしたのはこことかここになります.特に後者.


準備

とりあえずモデルとかいろいろ落としておきます.このあたり,あるもんだと思ってると普通にNot Foundとかいわれてハマるのが悲しいです.get_caffe_reference_imagenet_model.sh自体をまずは落としておかないといけないとか...

cd ~/caffe/examples/imagenet/
wget https://raw.githubusercontent.com/sguada/caffe-public/master/models/get_caffe_reference_imagenet_model.sh
chmod u+x get_caffe_reference_imagenet_model.sh
./get_caffe_reference_imagenet_model.sh
cd ~/caffe/data/ilsvrc12/
./get_ilsvrc_aux.sh
cd ~/caffe/
wget http://www.vision.caltech.edu/Image_Datasets/Caltech101/101_ObjectCategories.tar.gz
tar xzvf 101_ObjectCategories.tar.gz

パスも通しておかないといけない.

echo "export PYTHONPATH=/Users/smrmkt/Workspace/caffe/python:$PYTHONPATH" >> ~/.zshrc
echo "export DYLD_FALLBACK_LIBRARY_PATH=/usr/local/cuda/lib:$HOME/.pyenv/versions/anaconda-2.0.1/lib:/usr/local/lib:/usr/lib" >> ~/.zshrc
source ~/.zshrc

ImageNetのモデル定義ファイルも,落としてこないといけない.

cd examples/imagenet
wget https://raw.githubusercontent.com/aybassiouny/wincaffe-cmake/master/examples/imagenet/imagenet_deploy.prototxt
cp imagenet_deploy.prototxt imagenet_feature.prototxt

その上で,活性化関数を通す前のfc6層の値を取り出すため,imagenet_feature.prototxtの定義ファイルを変更します.

vim imagenet_feature.prototxt
# edit line 174 & 186
174   top: "fc6wi" # fc6->fc6wi
175   blobs_lr: 1
176   blobs_lr: 2
177   weight_decay: 1
178   weight_decay: 0
179   inner_product_param {
180     num_output: 4096
181   }
182 }
183 layers {
184   name: "relu6"
185   type: RELU
186   bottom: "fc6wi" # fc6->fc6wi
# :q

以上で準備は終わりです.

ImageNetで特徴量抽出

元記事Pythonファイルとほぼ同様のファイルを作成します.違いは12-13行目が,net.~~からcaffe.~~になった点です.この修正をしないと動きません.5-7行目のパスは適宜自分の環境に置き換えてください.ここではcaffeのルートディレクトリからの実行を想定しています.

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os, os.path, numpy, caffe

MEAN_FILE = 'python/caffe/imagenet/ilsvrc_2012_mean.npy'
MODEL_FILE = 'examples/imagenet/imagenet_feature.prototxt'
PRETRAINED = 'examples/imagenet/caffe_reference_imagenet_model'
LAYER = 'fc6wi'
INDEX = 4

net = caffe.Classifier(MODEL_FILE, PRETRAINED)
caffe.set_phase_test()
caffe.set_mode_cpu()
net.set_mean('data', numpy.load(MEAN_FILE))
net.set_raw_scale('data', 255)
net.set_channel_swap('data', (2,1,0))

image = caffe.io.load_image(sys.argv[1])
net.predict([ image ])
feat = net.blobs[LAYER].data[INDEX].flatten().tolist()
print(' '.join(map(str, feat)))

あとは,引数に画像ファイルを指定して,これを実行するだけ.

python feature.py 101_ObjectCategories/airplanes/image_0001.jpg > tmp.txt

実行すると,4096次元の変数に変換することができます.

cat tmp.txt | tr ' ' '\n' | wc -l
4096