前のポストでは学習済モデルでのテスト環境のみを整備した。
今回は具体的にデータを使ってモデル学習を回せるようにする。
caffeは上に書いてあるinstructionにより、BVLC/caffe:master @ 74cc497をcheckoutして使う。
https://github.com/shelhamer/fcn.berkeleyvision.org
-> 別に74cc497をチェックアウトしなくても最新版で行けた。
用いるデータセットはPASCAL VOC 2010
http://host.robots.ox.ac.uk/pascal/VOC/voc2010/
タグデータはpascal-contextのデータの59_context_labels.tar.gzを利用
http://www.cs.stanford.edu/~roozbeh/pascal-context/
validationに使うデータは以下のサイトにあるseg11valid.txtを参照。それ以外はtrainに。
https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/seg11valid.txt
LMDBを作成するには以下のサイトのスクリプトをベースに行う
https://groups.google.com/forum/#!topic/caffe-users/-vWuaM3bnro
学習を回そうとした時に、
F0616 18:37:35.315524 29112 math_functions.cu:123] Check failed: status == CUBLAS_STATUS_SUCCESS (14 vs. 0) CUBLAS_STATUS_INTERNAL_ERROR
が出る場合、出力層のラベル値が何かしら間違っている。
-> non integerだったり、負値があったり、0-60のラベルを0-255レンジの飛び飛びラベル付けをしていたり。
ネット学習中、全くloss値が減らない場合、solve.pyのfc6,fc7において
solver.net.copy_from(base_weights)
が機能せずパラメータに0値が入っている恐れがある。
I0426 23:23:46.976120 6412 net.cpp:752] Ignoring source layer fc6
I0426 23:23:46.976181 6412 net.cpp:752] Ignoring source layer fc7
みたいなのが出てたらダウト。
caffeのexampleにあるnet_surgeryを参考にして手動でコピーする。以下例
caffe_root = '/home/ubuntu/' # this file is expected to be in {caffe_root}/examples
import sys
sys.path.insert(0, caffe_root + 'python')
# Load the original network and extract the fully connected layers' parameters.
net = caffe.Net(rootpath+'vggmodel/vgg16fc.prototxt',
rootpath+'vggmodel/vgg16fc.caffemodel',
caffe.TEST)
params = ['fc6-conv', 'fc7-conv']
# fc_params = {name: (weights, biases)}
fc_params = {pr: (net.params[pr][0].data, net.params[pr][1].data) for pr in params}
for fc in params:
print '{} weights are {} dimensional and biases are {} dimensional'.format(fc, fc_params[fc][0].shape, fc_params[fc][1].shape)
params2 = ['fc6', 'fc7']
fc_params2 = {pr: (solver.net.params[pr][0].data, solver.net.params[pr][1].data) for pr in params2}
for fc in params2:
print '{} weights are {} dimensional and biases are {} dimensional'.format(fc, fc_params2[fc][0].shape, fc_params2[fc][1].shape)
# transparent
for pr, pr2 in zip(params, params2):
fc_params2[pr2][0].flat = fc_params[pr][0].flat # flat unrolls the arrays
fc_params2[pr2][1][...] = fc_params[pr][1]
学習後モデルを使ったテスト時、モデルを読み込むと
I0426 23:23:46.976120 6412 net.cpp:752] Ignoring source layer upscore
I0426 23:23:46.976181 6412 net.cpp:752] Ignoring source layer score
といった表示が余計に出る場合、対応する層に関するパラメータが読めていない。
deploy.prototxtとtrain_val.prototxtを比較するなどして、ネットワーク構造の不整合を修正する。
例えばnum_output、layerの名前とかがあってなかったりする。
デフォルトで入ってるdeploy.txtはfcn8s仕様なので、fcn32s仕様にするには、upscore周りを修正する必要あり。
メモリが足りないようであれば、下の修正を適用してshared memory仕様にする。(が最終的にうまく行かなかったので注意)
https://github.com/BVLC/caffe/pull/2016/commits/839b0502648a5dcf056c3f4a6ace1d0198e6b03e
しかし以下によればg2インスタンスはこれに対応していない模様。また最新版のcudaなどではいくつかside effectがあって良くないとの事。
https://github.com/torrvision/crfasrnn/issues/4
一応CUDA 7.5にすれば動くとの事だが、g2.x2largeはCUDA 7.5がうまく動かないため以下のサイトにあるコードを実行:
https://devtalk.nvidia.com/default/topic/880246/cuda-7-5-unstable-on-ec2-/
export DEBIAN_FRONTEND=noninteractive
apt-get update -q -y
apt-get -q -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install linux-generic
wget http://developer.download.nvidia.com/compute/cuda/7.5/Prod/local_installers/cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb
dpkg -i cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb
apt-get update -q -y
apt-get install cuda -q -y
echo ' /usr/local/cuda/lib64
/usr/local/cuda/lib' | tee -a /etc/ld.so.conf.d/cuda.conf > /dev/null
ただこれをやっても結局メモリエラーが出てしまった。
結局上記shared memoryはやめて画像サイズを軒並み半分にしてなんとか動いた。
あるいは画像を手動でスライドウインドウ方式で切り取って、新たに小さい画像のデータセットを作成した。
fcn16s, fcn8s
fcn32sの学習が終わったら、そのcaffemodelをpretrain modelにしてfcn16sを学習へ移行する事が可能。(16sから8sも同様)(vggmodelをpretrain modelにして学習する事も可)
その際の基本プロトコルは以下のサイトにあるvoc_fcn16sやvoc_fcn8sにあるものを用いると楽だった。
https://github.com/shelhamer/fcn.berkeleyvision.org
今までと違うのは、train.prototxtとval.prototxtが分かれている事と、dataの読み込みがlmdbではなくpythonベースで書かれている事。
ここはtrain.prototxtのdataの読み込み部をlmdbベースのものにTRAIN, TEST phase両方とも持ってきて置き換えてしまえばOK。するとval.prototxtはもういらない。solver.prototxtがtrainとval.prototxt双方読む設定になっているが、それも合わせて修正。
fcn32sで使ったtrain_val.prototxtと比較してnum_outputとかlayer名とかupscoreの繋げ方とかが少し違うので比較しながら修正する。deploy.prototxtに関しても同様。
なぜかdrop layerが使われなくなっているが理由は不明。
あとはsolve.pyを修正してpretrainしたfcn32sのcaffemodelからweightをfcn16sへ新しくコピーしてくるようにし、学習すれば動くはず。
この時upscoreとscore系がignoreされたと言われるけど学習は問題なく動いた。