いつもの作業の備忘録

作業を忘れがちな自分のためのブログ

【Caffe】特徴量抽出を行いSVMで物体識別する

下記サイトの中盤で紹介されている特徴量抽出部分を実行する
Caffeで手軽に画像分類 - Yahoo! JAPAN Tech Blog

1.ネットワークの定義ファイルを作成

以下のコマンドでimagenet_deploy.prototxtをダウンロードし、名前をimagenet_feature.prototxtと変更。また、元のネットワークでfc6と名付けられている値を取り出すように設定

$ wget https://raw.githubusercontent.com/aybassiouny/wincaffe-cmake/master/examples/imagenet/imagenet_deploy.prototxt
$ mv imagenet_deploy.prototxt imagenet_feature.prototxt
$ vim imagenet_feature.prototxt

imagenet_feature.prototxt

#変更前
layers {
  name: "fc6"
  type: INNER_PRODUCT
  bottom: "pool5"
  top: "fc6"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  inner_product_param {
    num_output: 4096
  }
}
layers {
  name: "relu6"
  type: RELU
  bottom: "fc6"
  top: "fc6"
}
↓
#変更後
layers {
  name: "fc6"
  type: INNER_PRODUCT
  bottom: "pool5"
  top: "fc6wi"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  inner_product_param {
    num_output: 4096
  }
} 
layers {
  name: "relu6" 
  type: RELU
  bottom: "fc6wi"
  top: "fc6"
} 

2.モデルのダウンロード

モデルファイルをダウンロードするスクリプトをダウンロードし、それを実行することでモデルファイルを取得

$ 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

3.特徴量出力用のプログラム作成

1枚の画像の特徴量を抽出するプログラムを作成

feature.py

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

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

net = caffe.Classifier(MODEL_FILE, PRETRAINED)
net.transformer.set_mean('data', numpy.load(MEAN_FILE))
net.transformer.set_raw_scale('data',255)
net.transformer.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)))

feature.pyを実行すると、スペースで区切られた4096個の数字の羅列が出現。fc6の値(4096個)をベクトルにして出力していることがわかる

$ python feature.py 101_ObjectCategories/airplanes/image_0001.jpg

3.libsvm形式データを作成

4096個のデータをlibsvm形式に変換する必要がある。libsvm形式は以下のような構造

(形式)
クラスID  次元:値  次元:値  次元:値 …

(例)
0 1:-44.596577 2:-30.565985 3:-26.004364 4:-1.526159 ...

feature.pyで抽出した特徴量をlibsvm形式に変換する適当なスクリプトを作成。それらを用いてCaltech101のデータからlibsvm形式の学習データ(train.txt)、評価データ(test.txt)を作成。今回は時間節約のために学習データ20枚、評価データ8枚を用意した
※地味に面倒ですが、pythonやらシェルコマンドやらを使って作成してください

4.SVMの学習と評価

必要なコマンド(libsvm)のインストール

$ sudo apt-get install libsvm-tools

データの正規化とsvmの学習

$ svm-scale -s scale.txt train.txt > train_scaled.txt
$ svm-scale -r scale.txt test.txt > test_scaled.txt
$ svm-train -c 0.03 train_scaled.txt caltech101.model

テスト

$ svm-predict test_scaled.txt caltech101.model result.txt

結果

Accuracy = 72.0297% (582/808) (classification)

特徴量次元数4096に対して学習データ枚数が 20×101=2020枚なので過学習気味になるはずだが、ある程度の性能が確認できた。
result.txtには0~100までの数字が808個並んでいる。これはテストデータ(808枚)に対してどのクラスに識別されたかを示す結果になっている

今回使ったネットワークを可視化する方法は以下のページ
【Caffe】ネットワークを可視化する - いつもの作業の備忘録


参考
http://techblog.yahoo.co.jp/programming/caffe-intro/
http://hogehuga.com/caffe_is_tough/
https://groups.google.com/forum/#!topic/caffe-users/4r5dxoFpWxk