Chainer, Cupy入門

54,315 views

Published on

Chainer meetup #3ではなした、ChainerとCuPyの入門資料です

Published in: Technology
0 Comments
23 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
54,315
On SlideShare
0
From Embeds
0
Number of Embeds
43,279
Actions
Shares
0
Downloads
97
Comments
0
Likes
23
Embeds 0
No embeds

No notes for slide

Chainer, Cupy入門

  1. 1. Chainer, Cupy⼊⾨ 2016/07/02 Chainer Meetup #03 (株)Preferred Networks 海野 裕也 v1.10向け
  2. 2. 今⽇のおはなし l  Deep Learningのおさらい l  Chainer の使い⽅の紹介 l  CuPyの使い⽅の紹介 2
  3. 3. ニューラルネットの基礎
  4. 4. ニューラルネット l  値が伝播していく有向グラフ l  エッジで重みをかけて、ノードに⼊るところで⾜し 込み、ノードの中で⾮線形変換する l  全体としては巨⼤で複雑な関数を表す 4
  5. 5. ニューラルネット=合成関数 l  ベクトルに対して線形・⾮線形な関数をたくさん適 ⽤する合成関数と捉えるとよい l  各ノードはベクトルを保持する変数 5
  6. 6. ⼀般のニューラルネットは DAG = 計算グラフ ⼀般にはグラフが分岐したり合流したりする l  分岐:同じ変数を複数の場所でつかう l  合流:⼆つ以上の変数を受け取る関数を適⽤する 6
  7. 7. 計算グラフの例 z = x ** 2 + 2 * x * y + y 7 x y _ ** 2 2 * _ _ * _ _ + _ z _ + _
  8. 8. 誤差逆伝播は、計算グラフを逆向きにたどる 計算グラフと順伝播時の各変数の値があれば計算可能 8
  9. 9. 機械学習(教師あり学習)のおさらい ⽬的 l  ⼊⼒Xに対して出⼒Yを予測する関数fを求めたい l  例:Xがメール、Yはスパムか否か ⽅法 l  正解のわかっているデータx1, y1 … xn, ynに対し て、f(xi)とyiがなるべく⼀致するfを求める l  |f(x1) – y1| + … + |f(xn) – yn| を最⼩にしたい 9 ⽬的関数
  10. 10. 機械学習のおさらい 多くの機械学習⼿法は、 1.  ⽬的関数の設計 2.  勾配の計算 3.  最⼩化のための反復計算 からなる 10 先ほどの計算は ここに使う
  11. 11. ニューラルネットの学習⽅法 1.  ⽬的関数の設計 l  計算グラフを⾃分で設計する 2.  勾配の計算 l  誤差逆伝播で機械的に計算できる 3.  最⼩化のための反復計算 l  勾配を使って反復更新する 11 1さえ設計すれば残りは ほぼ⾃動化されている
  12. 12. Chainer の使い⽅
  13. 13. Chainer はニューラルネットのフレームワーク l  機能 l  ニューラルネットを記述する l  ニューラルネットの順伝播・逆伝播を実⾏する l  勾配法を実⾏してパラメータを最適化する l  Chainer の特徴 l  順伝播は単純に Python のスクリプトとして書ける l  そのスクリプトの実⾏結果は計算⼿順を記憶してい て、逆伝播を⼿で書く必要はない 13
  14. 14. Chainer のインストール l  環境は Linux(特に Ubuntu)がおすすめ l  インストール⽅法 l  新しめの Python 環境を⽤意(CPython 2.7+, 3.4+, 3.5+) l  pip も⽤意 l  コマンドを実⾏: pip install chainer l  chainer パッケージが import できれば完了です l  Python スタックの環境構築は、Anaconda がお すすめ l  Python のバージョン管理は pyenv がおすすめ l  pyenv からコマンド⼀つで Anaconda もインストールできます 14
  15. 15. 順伝播 l  今まで「変数」と呼んでいたものは、Chainer では Variable オブジェクト l  Variable を Function に⼊れると、順伝搬後の Variable が返ってくる l  Variable が計算グラフを保持している l  Function は、四則演算以外に chainer.functions に⽤意されている 15
  16. 16. 順伝搬とコード例 16 x y _**2 2*_ _*_ _+_ z _+_ x = Varaible(...) y = Variable(...) z = x ** 2 + 2 * x * y + y
  17. 17. Variable オブジェクト l  計算グラフの(データ)ノード l  NumPy または CuPy(後述)の配列を保持する l  初期化時に配列を渡す l  data 属性に保存される l  多くの Function は配列の最初の軸をミニバッチとして 使うので注意 l  下の x は、20 次元ベクトルが 10 個⼊ったミニバッチとみなす l  現状、Chainer は多くの場所で float32 配列を要求する ので注意 17 x = Variable(np.zeros((10, 20), dtype=np.float32)) x.data
  18. 18. Function オブジェクト l  計算グラフの「演算」ノード l  chainer.functions (以降 F) にいろいろ定義され ている l  F.relu, F.max_pooling_2d, F.lstm, ... l  Functionの呼び出し結果が、再びVariableになる l  v1.5からパラメータはLinkとして分離された 18 x = Variable(...) y = F.relu(x) # yもVariable
  19. 19. Link オブジェクト l  パラメータ付きの関数 l  最適化の対象となる l  save/loadができる(v1.5からsave/loadをサポート) l  chainer.links(以降L)に⾊々⽤意されている l  L.Linear, L.Convolution2D, L.EmbedID, ... l  Linkの呼び出し結果が、再びVariableになる l  v1.5からFunctionとパラメータは分離され、パラメータ 付きの関数はLinkオブジェクトになった 19 v1.5~
  20. 20. ChainでLinkをまとめる l  ⼀般的にパラメータ付きの関数(Link)は複数あるので、 Chainでまとめて管理できる l  Chainを継承すると再利⽤しやすくなる model = Chain(embed=L.EmbedID(10000, 100), layer1=L.Linear(100, 100), layer2=L.Linear(100, 10000)) x = Variable(...) h = F.relu(model.layer1(model.embed(x))) y = model.layer2(h) 20 v1.5~
  21. 21. ロス関数、勾配計算 l  ロス関数もFunctionの⼀種 l  ロス関数の出⼒に、Variable.backward() を呼ぶと 勾配が計算できる loss = F.softmax_cross_entropy(y, t) loss.backward() 21
  22. 22. Optimizer の設定 l  勾配が計算できたら、あとは勾配法をまわす l  勾配法のアルゴリズムは Optimizer クラスの⼦クラス l  chainer.optimizers に定義されている l  実装されている最適化⼿法:SGD, MomentumSGD, AdaGrad, RMSprop, RMSpropGraves, AdaDelta, Adam l  最適化対象をsetup メソッドに渡す l  正則化はhook関数として登録する optimizer = optimizers.SGD() optimizer.setup(model) optimizer.add_hook(optimizer.WeightDecay()) 22
  23. 23. Optimizer による最適化 l  まず勾配をゼロ初期化:zerograds() l  順伝播・逆伝播を実⾏ l  最適化ルーチンを実⾏:update() l  以上を何回も繰り返す model.zerograds() loss = ... loss.backward() optimizer.update() 23
  24. 24. Chainer を使う場合の全体の流れ 1.  Linkを使ってChainを定義する 2.  Optimizer に、Chain を設定する 3.  forward 関数を定義する 4.  データセットを読み込み、訓練⽤と評価⽤にわける 5.  訓練ループを回す a.  勾配をゼロ初期化 b.  順伝搬して、得られたロス値の backward メソッドを呼ぶ c.  Optimizerを、update 6.  適当な頻度で評価ループを回す a.  テストデータで順伝搬関数を呼んで結果を記録 24 次のバージョンで訓練ループは抽象化されます
  25. 25. CUDAによる⾏列ライブラリCuPy 25
  26. 26. CuPyとは何か? NumPy互換インターフェースの CUDA実装の⾏列ライブラリ 26 Pythonの⾏列ライブラリ NVIDIA GPUの開発環境とライブラリ
  27. 27. 既存のライブラリと 同じインターフェースで GPUの⾼速性を⼿に⼊れられる 27
  28. 28. CuPyとNumPyの⽐較 import numpy x = numpy.array([1,2,3], numpy.float32) y = x * x s = numpy.sum(y) print(s) import cupy x = cupy.array([1,2,3], cupy.float32) y = x * x s = cupy.sum(y) print(s) 28
  29. 29. CuPyはどのくらい早いの? l  状況しだいですが、最⼤数⼗倍程度速くなります def test(xp): a = xp.arange(1000000).reshape(1000, -1) return a.T * 2 test(numpy) t1 = datetime.datetime.now() for i in range(1000): test(numpy) t2 = datetime.datetime.now() print(t2 -t1) test(cupy) t1 = datetime.datetime.now() for i in range(1000): test(cupy) t2 = datetime.datetime.now() print(t2 -t1) 29 時間 [ms] 倍率 NumPy 2929 1.0 CuPy 585 5.0 CuPy + Memory Pool 123 23.8 Intel Core i7-4790 @3.60GHz, 32GB, GeForce GTX 970
  30. 30. なぜCuPyが求められるのか? l  GPUを使った応⽤研究では、必 要な知識が以前より増えた l  GPU⾃体が複雑 l  GPUを効率的に扱うアルゴリズム も複雑 l  使わないと効率で勝てない l  GPUを効率的に⼿軽に使える仕 組みが必要になっている 30 GPU CUDA ⾏列ライブラリ 深層学習エンジン 応⽤研究
  31. 31. 裏の仕組み l  CUDA⽤ソースを⾃動⽣成してコンパイラが⾛る l  ⽣成されたバイナリをGPUに⾃動的に転送・実⾏する l  ビルド結果はキャッシュされるので2回⽬移⾏⾼速 31 スタブ スタブ 実処理 nvcc コンパイラ .cubin GPU 実行 キャッシュ する
  32. 32. ⾃分でコードを書きたい時 例:z[i] = x[i] + 2 * y[i] を書きたい 32 引数の型: “float32 x, float32 y” 戻り値の型: “float32 z” 処理: “z = x + 2 * y;” ループやインデックスの処理は ⾃動で埋めてくれる これだけ書け ば良い
  33. 33. チューニングの⽅法 l  CUDAのツールがそのまま使える l  NVIDIA Visual Profiler (nvvp)やnvprofコマンド l  CPU⽤のプロファイラではGPUのボトルネックがわ からないので注意 l  詳細はCUDAのサイトへ 33
  34. 34. 深層学習以外にも利⽤できる l  既存のNumPyコードがほぼそのまま動く l  既存の解析⼿法がそのままCUDA上で動く l  NumPyのベクトルデータとの変換は1⾏ 34
  35. 35. まとめ l  ニューラルネットを(おもに実装⾯から)簡単におさら いしました l  Chainerは直感的なインターフェスで深層学習できるラ イブラリ l  CuPyはNumPyインターフェースでCUDAを使えるライ ブラリ 35

×