※ WIP。
はじめに
- caffeいれたばかりで使い方よくわからない
- 機械学習で何か実装してみたい
- 論文読むより実装を通じて理解を深めていきたい
- pythonはやったことない。インデントが大事だということぐらい
- プログラミングはそれなりにやったことがある
ゴール
Caffeのリファレンスモデル(※有名な論文で使われているパラメータチューニングも終わってるモデル)を使って、Caltechの画像を分類すること。具体的に目に見える形として、以下のようなアウトプットを出すことがゴール。
(画像。無事実装が完了したら乗っける)
おおまかな手順
STEP1. 分類する画像データセットをダウンロード
STEP2. データセットの画像から特徴を抽出する
STEP3. 抽出した特徴を線形SVMで分類するためにSVMを学習させる。
STEP4. 学習させたSVMで特徴量からクラス分類
1. 分類する画像データセットをダウンロード
以下のページに飛び、Download。
http://www.vision.caltech.edu/Image_Datasets/Caltech101/#Download
2. データセットの画像から特徴を抽出する
2-1. リファレンスモデルのダウンロード
$ scripts/download_model_binary.py models/bvlc_reference_caffenet
2-2. 画像の特徴を抽出するためのコードの実装
リファレンスモデルを使って画像の特徴データを抽出。
色がRGBという3つの数値で表されるみたいに、今回のモデルでは1つの画像の特徴は 4096個の数値 で表される。
2-2.では入力:jpgデータ、出力:4096の数値データ、な処理を行うスクリプトを作成する。
以下をcaffeのルート・ディレクトリに作成。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os, os.path, numpy as np, caffe
# path to git-cloned caffe dir
CAFFE_DIR = os.getenv('CAFFE_ROOT')
MEAN_FILE = os.path.join(CAFFE_DIR, 'python/caffe/imagenet/ilsvrc_2012_mean.npy')
MODEL_FILE = os.path.join(CAFFE_DIR, 'models/bvlc_reference_caffenet/deploy.prototxt')
PRETRAINED = os.path.join(CAFFE_DIR, 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel')
LAYER = 'fc7'
INDEX = 4
class FeatureExtraction:
def __init__(self):
net = caffe.Classifier(MODEL_FILE, PRETRAINED)
caffe.set_mode_cpu()
net.transformer.set_mean('data', np.load(MEAN_FILE))
net.transformer.set_raw_scale('data', 255)
net.transformer.set_channel_swap('data', (2,1,0))
self.net = net
def extract_features(self):
imageDirPath = sys.argv[1]
previousLabelName = ''
labelIntValue = 0
for root, dirs, files in os.walk(imageDirPath):
for filename in files:
if filename == '.DS_Store':
continue
fullPath = os.path.join(root, filename)
dirname = os.path.dirname(fullPath)
labelName = dirname.split("/")[-1]
if labelName != previousLabelName:
labelIntValue += 1
previousLabelName = labelName
image = caffe.io.load_image(fullPath)
feat = self.extract_features_from_image(image)
self.print_feature_with_libsvm_format(labelIntValue, feat)
def build_test_data(self, imagePaths):
for fullPath in imagePaths:
image = caffe.io.load_image(fullPath)
feat = self.extract_features_from_image(image)
self.print_feature_with_libsvm_format(-1, feat)
def extract_features_from_image(self, image):
self.net.predict([image])
feat = self.net.blobs[LAYER].data[INDEX].flatten().tolist()
return feat
def print_feature_with_libsvm_format(self, labelIntValue, feat):
formatted_feat_array = [str(index+1)+':'+str(f_i) for index, f_i in enumerate(feat)]
print str(labelIntValue) + " " + " ".join(formatted_feat_array)
2-3. STEP1 でダウンロードした全画像の特徴データを一つのファイルに書き出す
上記の実行用のスクリプトを用意しておいて、
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from feature_extraction import FeatureExtraction
FeatureExtraction().extract_features()
以下を実行して、特徴データ(feature.txt)を作成する。
$ python exec.py path/to/images_dir > feature.txt
手元のマシンでは1行目に
(10, 3, 227, 227)
という文字列が入ってしまう。
コレは特徴データではなく、別処理でのゴミprintみたいなものなので消しておく。
補足: 出力した特徴データのフォーマットについて
STEP3.ではlibsvmによるSVMの学習を行う。libsvmで扱うために、特徴データを以下のような形に書き出す必要がある。
...
4 1:0.89 2:0.19 3:0.10 ... 4096:0.77
1 1:0.01 2:0.99 3:0.11 ... 4096:0.97
...
1データが、
(labelの番号) 1:1番目の特徴量の数値 2:2番目の特徴量の数値 ...
という形で表されている。feature.txtでは画像枚数分の行数がある。
3. 抽出した特徴を線形SVMで分類するためにSVMを学習させる。
SVMには有名なlibsvmというパッケージを使う。
libsvmやsvmの説明はこのあたりが親切。
- SVMを使いこなす!チェックポイント8つ
- 10秒で設定可能なlibsvmで機械学習を行う
- [Webで見つけたサポートベクターマシンの参考文献] (http://ameblo.jp/economics-teru/theme-10067699498.html)
3-1. libsvmのインストール
$ brew install libsvm
3-2. 学習
SVMを学習させる。
以下のコマンドを打つ。
$ svm-scale -s scale.txt feature.txt > feature.scaled.txt
$ svm-train -c 0.03 feature.scaled.txt caltech101.model
svm-scaleはlibsvmでスケーリングを行うコマンドで、svm-trainが学習を行うコマンド。
各ファイルの意味は以下のとおり。
- scale.txt: どうscaleしたかが保存してあるファイル。
- feature.txt: 特徴データのファイル(STEP2で作成したもの)
- feature.scaled.txt: スケーリング後の特徴データ
- caltech101.model: 学習させたSVMのパラメータが保存されているファイル
4. 学習させたSVMでカテゴリ分類
※ WIP。多分SVMのところ勘違いしている疑惑。
4-1. 試しに同じデータで実験
$ cp feature.txt feature_test.txt
$ svm-scale -r scale.txt feature_test.txt > feature_test.scaled.txt
$ svm-predict feature_test.scaled.txt caltech101.model result.txt
...精度わるっ! now debugging...
Next Step 候補
- ファインチューニングする
- 一からモデル作る
- Detection
8月中に3つともできれば。。。
参考にしたURLリスト
全体の流れにおいて
-
CaffeでDeep Learning つまずきやすいところを中心に
- Caffeの一般的な実装の流れが簡単に触れられている。全体像を知りたいならこれ。
-
Caffeで手軽に画像分類
- 今回の元ネタ。ただし2015-08-21現在では手軽にできなくなっているので他の参考URLも見ながら進める。
-
CaffeのImageNetで特徴量抽出器を動かすまで
- 元ネタを現在版にアレンジしたもの。
-
”Caffeで手軽に画像分類”の”Caffeを特徴抽出器として使った分類”をやってみた1
- あんまり参考になっていない。
-
『Caffeで手軽に画像分類』が手軽にできない。
- 困ったときのFAQ的な資料。ありがとうございます。
-
Caffe, Pylearn2をまとめて試す
- Caffeでリファレンスモデルを利用するときの手順の参考になる。
-
Caffeによる特徴抽出+AROWによる分類を試した
- 特徴抽出の部分のソースコード、参考にさせていただきました。
-
Caffe Pukiwiki
- libsvm用のフォーマットにするためのコードはここを参考にしました。
libsvm
-
10秒で設定可能なlibsvmで機械学習を行う
- libsvmのチュートリアル的な資料。
-
Homebrew + Virtualenv 環境でlibsvmのインストール
- pythonでlibsvm。使ってみたい。installはしたが使っておらず。後回し。
FAQ
Q1. python/caffe/imagenet/ilsvrc_2012_mean.npyってなんぞ?
A. 平均画像のこと。以下を参照。
Q2. SVMって2値分類器では?
A. 多値分類もできる。libsvmでは入力した教師データのクラスの数をさりげにカウントして、必要であれば多値分類器をつくるように、よしなにやってくれている...なんて甘い話ではなかった。