【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