Caffeのデータレイヤで夢が広がる話
第27回コンピュータビジョン勉強会@関東
2015/01/31 @rezoolab (齋藤 真樹)
自己紹介
• 東北大学岡谷研D2 齋藤 真樹 (DC2)
– Twitter ID: @rezoolab
– コンピュータビジョンに関する理論研究
• 主な業績: CVPR 2本 (+1?)
– コンピュータビジョン最先端ガイド6 執筆
– 真面目に就職先探していますのでお気軽に
お声がけください
Convolutional Neural Networks (CNNs)
from flickr.com/photos/125992663/14601014695/
今回はみんな大好きCaffeについての話です
Caffe
• 畳み込みニューラルネット(CNN)をGPUで高速に学習・評価できる
– AlexNet, GoogleNet, VGG (おすすめ) の学習済モデルが利用可能
– C++で実装.Python/Matlab bindingも提供されている
• データセットとレイヤ構成を指定するだけで,誰でも簡単にCNNを
学習,評価できる(と思われている)
Caffe難易度表 (独断と偏見)
比較的取りかかりやすい
• Pre-trained modelを利用した特徴量抽出
• 106オーダーの画像を使って一から多クラス分類
• Transfer Learningによる多クラス分類
ちょっと難しい
• 回帰問題,セグメンテーション問題への応用
• C++弄って独自のレイヤを実装,評価
結構難しい
• Deep Boltzmann Machineの実装
• Recurrent Neural Networkの実装
• 最高精度達成してトップ会議通す(超赤海)
Caffeのアーキテクチャ (学習時)
• CaffeのネットワークはBlobとLayerの2種類から成り立つ
– Blob: CNNの実データを格納するデータ構造
– Layer: 畳み込みやプーリング,内積などの操作単位
“data” “conv1” “pool1” “fc1” “loss”
Layer
Blob
“label”
[( , 3), ( , 5), …]
3
Key-Value
Store
“data” “conv1” “pool1” “fc1” “loss”
Caffe::DataLayer
• レイヤの種類とパラメータを.prototxtファイルに記述
• 入力画像に対して出力が1つの離散ラベルだとCaffeはほんとうに楽
“data” 指定されたKVS(LevelDB, LMDB)から画像を
バッチ数分ロードし,Blobに伝える
“data”
“data”
“true”
• Key: 画像ファイル名など(重複がなければなんでもいい)
• Value: 画像データとラベルのペアをシリアライズ化した文字列
“data”
“data”
“label”
“data” “data”
画像データのみ 画像と離散値1つ 画像と複数の離散・連続値
データレイヤ問題を解決するための2つの方法
データレイヤを増やす
解決案1: データレイヤを2つ用意して対応
• データセットを画像データと教師データの2つに分割して対応
• そのようなツールは存在しないのでpythonで組む必要あり
– (caffeの説明はあっさりすぎてコード読む他ない)
“data”
“data”
“true”
画像 “data” “data”
“true”“true”教師
KVS1
KVS2
解決案1: データレイヤを2つ用意して対応
• 画像データ用KVSの作り方
– Valueの実態はProtocol Bufferで定義された構造体Datum
– ndarrayをdatumに変換するcaffe.io.array_to_datum()がある
shapeは (channels, height, width)
整合性のためにBGRオーダーがベター
import cv2
from caffe.io import array_to_datum
# load an image (BGR order) and serialize it
img = cv2.resize(cv2.imread(path), shape).transpose([2,0,1])
img_datum = array_to_datum(img)
img_str = img_datum.SerializeToString()
# put img_str into KVS
db.Put(key=path, value=img_str)
解決案1: データレイヤを2つ用意して対応
• 教師データ用KVSの作り方
– そのような便利関数は存在しない(世間は厳しい)
– 浮動小数点の配列を格納するためのフィールド
“Datum::float_data”の中に入れる
from caffe.io import caffe_pb2
# suppose that arr is a one-dimensional np.ndarray
d = caffe_pb2.Datum()
d.float_data.extend(list(arr))
d.channels, d.height, d.width = arr.size, 1, 1
datum_str = d.SerializeToString()
# put datum_str into KVS
kvs2.Put(key=path, value=datum_str)
自前でデータレイヤを作る
データレイヤ問題を解決するための2つの方法
解決案2: 自前でデータレイヤを作る
• 既存のデータレイヤが対応していないのなら,自前で作ってみよう
• 面倒だけど色々と融通が効く
1. データレイヤ単体で複数のBlobを出力
2. caffe付属のdata augmentationをさらに拡張
“data1” “true1”“data2” “true2”“data”
Caffe (client)
解決案2: 自前でデータレイヤを作る
• http経由でBlobを取得するHTTPDataLayerを作りました
– データ加工等の面倒な箇所はすべてサーバに委託
“localhost/blob”
Server
KVS1
“data”
http request
response
KVS2
“data1”
“data2”
[“data1”, “data2”]
[blob1, blob2]
解決案2: 自前でデータレイヤを作る
DEMO
まとめ
• Caffeで識別以外の学習を行う方法は2つある
1. データレイヤを2つ作成してがんばる
2. データレイヤを新しく作成する
• 応用としてデータレイヤ用のhttpクライアントとサーバを書いた
• 研究室で試運転中.機能を整えたらGithubで公開
おわり
※アイコンはCC BY 3.0のDripiconsを使用しました: http://www.flaticon.com/packs/dripicons/
※イラストはCC BY-NC-ND 4.0の寿司ゆきを使用しました: http://awayuki.net/sushiyuki/

Caffeのデータレイヤで夢が広がる話