capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

30
Capitalico でで chainer 1.1→1.5 でででででででででで JUN-YA NORIMATSU Engineer http://alpaca.ai [email protected] 015/12/19 Chainer Meetup #01

Upload: jun-ya-norimatsu

Post on 06-Jan-2017

80.356 views

Category:

Engineering


8 download

TRANSCRIPT

Page 1: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

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

Page 2: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

自己紹介 

乗松潤矢 (Twitter: arrow_elpis, Github: jnory)

Alpaca (Engineer)

フリーランス

博士課程在学中(専門:自然言語処理 , 統計翻訳)

今日の肩書

Page 3: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

Entry Point

FX チャートにはパターンがある 

Page 4: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

すべて同一カテゴリの事象 

パターン認識で検出したい

Page 5: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

プログラミングなしでパターンを発見 

Page 6: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

Chainer によるモデル学習 

入力:為替時系列データ

出力:学習時に指定したパターンっぽさ

Page 7: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

今日の発表 

弊社環境を Chainer 1.5 にバージョンアップしました

バージョンアップでハマったところは?

バージョンアップで良くなったところは ?

バージョンアップで悪くなったところは ?

Chainer バージョンアップはどの程度のタスク?

Page 8: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

今日の発表 

弊社環境を Chainer 1.5 にバージョンアップしました

バージョンアップでハマったところは?

バージョンアップで良くなったところは ?

バージョンアップで悪くなったところは ?

Chainer バージョンアップはどの程度のタスク?

Page 9: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

本題の前に… Capitalico での Chainer バージョンアップのトラウマ 

2015 年 9 月 2 日 Chainer 1.3 リリース弊社環境もバージョンアップを試みるが…v1.1 と比較してモデル学習が約 1.5 倍遅い

バージョンアップ失敗

Chainer 1.3 の変更点 CuPy の導入

どうもこれが遅いらしい

Page 10: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

バージョンアップで良くなったところ 

ボトルネックだった CuPy が高速化

速くなりました!!!

Chainer 1.1 :約 22 分

Chainer 1.5 :約 16 分

( ありがとうございます!!! )

弊社サービス上でのモデル学習時間

Page 11: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

Training Loss 収束の様子 

Chainer 1.1 Chainer 1.5

ほぼ同じ学習ができた

反復回数 反復回数

Page 12: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

Chainer の速度で気になっていること 

Dropout が全体の 12% の時間

Linear より重い… ?

モデル学習時の Profile を取った実行時間に大きな偏りはない

Page 13: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

今日の発表 

弊社環境を Chainer 1.5 にバージョンアップしました

バージョンアップでハマったところは?

バージョンアップで良くなったところは ?

バージョンアップで悪くなったところは ?

Chainer バージョンアップはどの程度のタスク?

Page 14: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

バージョンアップで悪くなったところ 

一度 GPU メモリを確保すると開放されない

学習終了後もプロセスは起動したまま

サーバープログラム内で学習・テスト

Page 15: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

メモリ解放したい 

幾つかのプロセスが GPU を使用

GPU メモリが開放されないと同時起動プロセス数に影響

用途ごとにプロセスを分離モデル学習

テスト実行

大量のユーザーに対応できない

Capitalico は BtoC なサービス目標: 1 万人程度が同時アクセス

数千人が同時にモデル学習を走らせても動くようにしたい

Page 16: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

[ 解決策 ] ちょっとだけ Chainer を改造 

MemoryPool にこんなコードを追加

(とにかく全部捨てる…という意味)

PR しました

Page 17: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

今日の発表 

弊社環境を Chainer 1.5 にバージョンアップしました

バージョンアップでハマったところは?

バージョンアップで良くなったところは ?

バージョンアップで悪くなったところは ?

Chainer バージョンアップはどの程度のタスク?

Page 18: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

バージョンアップでハマったところ 

1. インストール

2. FunctionSet → Chain

4. モデルの保存形式を HDF5 に変更

5. 過去に学習したモデルを変換

3. その他の非互換を修正

これ

バージョンアップの流れ

Page 19: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

バージョンアップでハマったところ 

HDF5 からの読込:一部のパラメータが読み込まれない

chain.linear = Linear(…, nobias=True)

from chainer.serializers.hdf5 import HDF5Deserializergroup = h5file["chainer"]serializer = HDF5Deserializer(group)serializer.load(chain)

モデルファイルに bias が書かれていても読まれない

Page 20: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

今日の発表 

弊社環境を Chainer 1.5 にバージョンアップしました

バージョンアップでハマったところは?

バージョンアップで良くなったところは ?

バージョンアップで悪くなったところは ?

Chainer バージョンアップはどの程度のタスク?

Page 21: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

Chainer バージョンアップはどの程度のタスク? 

コード修正: 5.5 人日

動作検証に要した期間: 3 人日

修正開始 11/26 本番環境適用 12/11

デプロイ等々: 2 人日

コード修正量

工数

追加: 500 行 ( くらい )削除: 100 行

コミット回数: 30 回

Page 22: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

Chainer に期待すること 

コミュニティが大きくなってほしいと思います

Numpy 非互換部分が少しずつでも減っていくと嬉しいです

CuPy は単体でも十分インパクト大だと思います

モデルフォーマットは今後固定していただけるとありがたい!

ロゴがあると人に紹介するときにより大きいインパクト

Page 23: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

まとめ 

Capitalico の Chainer をバージョンアップ

学習機能が高速化

メモリ使用効率は悪化

PR しました m(_ _)m

バージョンアップ作業はそこそこ重いタスク

ハマりどころもそこそこある

Page 24: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

おまけ 

Chainer 1.5 での修正必要箇所一覧

Reference: https://groups.google.com/forum/#!topic/chainer/eXyL11thcNY

Page 25: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

インストール 

pip install cython==0.23.4pip install h5py==2.5.0pip install chainer==1.5.0.2

何のつまづきもなくすんなり

Page 26: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

FunctionSet → Chain 

何のつまづきもなくすんなり

self.model = FunctionSet(**args)

self.model = Chain(**args)

API 互換性有

Page 27: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

その他非互換部分 

レイヤー内の変数が (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)

Page 28: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

過去に学習したモデルを変換 

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 のとき不要

Page 29: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

モデルの保存形式を 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 が書かれていても読まれない

Page 30: Capitalicoでのchainer 1.1 → 1.5 バージョンアップ事例

一応の解決策 ( おそらく非推奨 ) 

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 を取るのが正攻法 )