Upload
jun-ya-norimatsu
View
80.356
Download
8
Embed Size (px)
Citation preview
Capitalico での chainer 1.1→1.5バージョンアップ事例
J U N - YA N O R I M A T S UEngineer
http://alpaca.ai [email protected]/12/19 Chainer Meetup #01
自己紹介 
乗松潤矢 (Twitter: arrow_elpis, Github: jnory)
Alpaca (Engineer)
フリーランス
博士課程在学中(専門:自然言語処理 , 統計翻訳)
今日の肩書
Entry Point
FX チャートにはパターンがある 
すべて同一カテゴリの事象 
パターン認識で検出したい
プログラミングなしでパターンを発見 
Chainer によるモデル学習 
入力:為替時系列データ
出力:学習時に指定したパターンっぽさ
今日の発表 
弊社環境を Chainer 1.5 にバージョンアップしました
バージョンアップでハマったところは?
バージョンアップで良くなったところは ?
バージョンアップで悪くなったところは ?
Chainer バージョンアップはどの程度のタスク?
今日の発表 
弊社環境を Chainer 1.5 にバージョンアップしました
バージョンアップでハマったところは?
バージョンアップで良くなったところは ?
バージョンアップで悪くなったところは ?
Chainer バージョンアップはどの程度のタスク?
本題の前に… Capitalico での Chainer バージョンアップのトラウマ 
2015 年 9 月 2 日 Chainer 1.3 リリース弊社環境もバージョンアップを試みるが…v1.1 と比較してモデル学習が約 1.5 倍遅い
バージョンアップ失敗
Chainer 1.3 の変更点 CuPy の導入
どうもこれが遅いらしい
バージョンアップで良くなったところ 
ボトルネックだった CuPy が高速化
速くなりました!!!
Chainer 1.1 :約 22 分
Chainer 1.5 :約 16 分
( ありがとうございます!!! )
弊社サービス上でのモデル学習時間
Training Loss 収束の様子 
Chainer 1.1 Chainer 1.5
ほぼ同じ学習ができた
反復回数 反復回数
Chainer の速度で気になっていること 
Dropout が全体の 12% の時間
Linear より重い… ?
モデル学習時の Profile を取った実行時間に大きな偏りはない
今日の発表 
弊社環境を Chainer 1.5 にバージョンアップしました
バージョンアップでハマったところは?
バージョンアップで良くなったところは ?
バージョンアップで悪くなったところは ?
Chainer バージョンアップはどの程度のタスク?
バージョンアップで悪くなったところ 
一度 GPU メモリを確保すると開放されない
学習終了後もプロセスは起動したまま
サーバープログラム内で学習・テスト
メモリ解放したい 
幾つかのプロセスが GPU を使用
GPU メモリが開放されないと同時起動プロセス数に影響
用途ごとにプロセスを分離モデル学習
テスト実行
大量のユーザーに対応できない
Capitalico は BtoC なサービス目標: 1 万人程度が同時アクセス
数千人が同時にモデル学習を走らせても動くようにしたい
[ 解決策 ] ちょっとだけ Chainer を改造 
MemoryPool にこんなコードを追加
(とにかく全部捨てる…という意味)
PR しました
今日の発表 
弊社環境を Chainer 1.5 にバージョンアップしました
バージョンアップでハマったところは?
バージョンアップで良くなったところは ?
バージョンアップで悪くなったところは ?
Chainer バージョンアップはどの程度のタスク?
バージョンアップでハマったところ 
1. インストール
2. FunctionSet → Chain
4. モデルの保存形式を HDF5 に変更
5. 過去に学習したモデルを変換
3. その他の非互換を修正
これ
バージョンアップの流れ
バージョンアップでハマったところ 
HDF5 からの読込:一部のパラメータが読み込まれない
chain.linear = Linear(…, nobias=True)
from chainer.serializers.hdf5 import HDF5Deserializergroup = h5file["chainer"]serializer = HDF5Deserializer(group)serializer.load(chain)
モデルファイルに bias が書かれていても読まれない
今日の発表 
弊社環境を Chainer 1.5 にバージョンアップしました
バージョンアップでハマったところは?
バージョンアップで良くなったところは ?
バージョンアップで悪くなったところは ?
Chainer バージョンアップはどの程度のタスク?
Chainer バージョンアップはどの程度のタスク? 
コード修正: 5.5 人日
動作検証に要した期間: 3 人日
修正開始 11/26 本番環境適用 12/11
デプロイ等々: 2 人日
コード修正量
工数
追加: 500 行 ( くらい )削除: 100 行
コミット回数: 30 回
Chainer に期待すること 
コミュニティが大きくなってほしいと思います
Numpy 非互換部分が少しずつでも減っていくと嬉しいです
CuPy は単体でも十分インパクト大だと思います
モデルフォーマットは今後固定していただけるとありがたい!
ロゴがあると人に紹介するときにより大きいインパクト
まとめ 
Capitalico の Chainer をバージョンアップ
学習機能が高速化
メモリ使用効率は悪化
PR しました m(_ _)m
バージョンアップ作業はそこそこ重いタスク
ハマりどころもそこそこある
おまけ 
Chainer 1.5 での修正必要箇所一覧
Reference: https://groups.google.com/forum/#!topic/chainer/eXyL11thcNY
インストール 
pip install cython==0.23.4pip install h5py==2.5.0pip install chainer==1.5.0.2
何のつまづきもなくすんなり
FunctionSet → Chain 
何のつまづきもなくすんなり
self.model = FunctionSet(**args)
self.model = Chain(**args)
API 互換性有
その他非互換部分 
レイヤー内の変数が (Numpy/gpuarray から )Variable になった
ohlc.W.shape[1]
ohlc.W.data.shape[1]
旧 Function が Function と Link に分離
import chainer.functions as FF.Linear(x_size, self.n_units)
import chainer.links as LL.Linear(x_size, self.n_units)
過去に学習したモデルを変換 
Chainer 1.1 形式のモデル (pickle) を読み込み 1.5 の形式 (HDF5) で出力
import sysfrom chainer.links.connection import linearsys.modules['chainer.functions.linear'] = linear
パッケージの配置が変わっているのでトリックを入れる
with open(path) as fp: chain = cPickle.loads(fp.read())
一応読めるようになる
newchain.linear.W.data[...] = model.W[...]newchain.linear.W.grad[...] = model.gW[...]newchain.linear.b.data[...] = model.b[...]newchain.linear.b.grad[...] = model.gb[...]
newchain = Chain(linear=linear.Linear(x, y))
変数の値を淡々とコピー
nobias=True のとき不要
モデルの保存形式を HDF5 に変更 
保存:何のつまづきもなくすんなり
from chainer.serializers.hdf5 import HDF5Serializergroup = h5file.create_group("/chainer”)serializer = HDF5Serializer(group)serializer.save(model)
読込:一部のパラメータが読み込まれなくてハマる
model = Linear(…, nobias=True)from chainer.serializers.hdf5 import HDF5Deserializergroup = h5file["chainer"]serializer = HDF5Deserializer(group)serializer.load(model) ファイルに bias が書かれていても読まれない
一応の解決策 ( おそらく非推奨 ) 
chain.linear = Linear(…, nobias=True)
nobias=True なレイヤーを無理やり nobias=False に書き換える
del chain.linear.bout_size = chain.linear.W.data.shape[0]chain.linear.add_param('b', out_size)from chainer.serializers.hdf5 import HDF5Deserializergroup = h5file["chainer"]serializer = HDF5Deserializer(group)serializer.load(chain)
b をリセット
以下の定義は修正不可とする
モデル読み込み
( ここを変えられるなら nobias を取るのが正攻法 )