深層学習フレームワークChainerの特徴

0
-1

Published on

2016/03/17 産総研人工知能セミナーでお話した、ChainerとCuPyの紹介です。設計思想やメリットデメリットなどがまとまっています

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

No Downloads
Views
Total views
0
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
11
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide

深層学習フレームワークChainerの特徴

  1. 1. 深層学習フレームワーク Chainerの特徴 (株)Preferred Infrastructure 海野  裕也 2016/03/17
 第5回 産総研人工知能セミナー「深層学習フレームワーク」
  2. 2. ⾃自⼰己紹介 海野  裕也 l  -2008 東⼤大情報理理⼯工修⼠士 l  ⾃自然⾔言語処理理 l  2008-2011 ⽇日本アイ・ビー・エム(株)東京基礎研 l  テキストマイニング、⾃自然⾔言語処理理の研究開発 l  2011- (株)プリファードインフラストラクチャー l  ⾃自然⾔言語処理理、情報検索索、機械学習、テキストマイニングなど の研究開発 l  研究開発系案件、コンサルティング l  JubatusやChainerの開発 l  最近は対話処理理 NLP若若⼿手の会共同委員⻑⾧長(2014-) 「オンライン機械学習」(2015, 講談社)2
  3. 3. Chainer http://chainer.org/ 3
  4. 4. CuPy Chainerの構成 4 CPU NVIDIA GPU CUDA cuDNN BLAS NumPy Chainer
  5. 5. 直感的な深層学習フレームワーク Chainer 5
  6. 6. ニューラルネット l  値が伝播していく有向グラフ l  エッジで重みをかけて、ノードに⼊入るところで⾜足し 込み、ノードの中で⾮非線形変換する l  全体としては巨⼤大で複雑な関数を表す 6
  7. 7. ニューラルネット=合成関数 l  ベクトルに対して線形・⾮非線形な関数をたくさん適 ⽤用する合成関数と捉えるとよい l  各ノードはベクトルを保持する変数 7 y = h(g(f(x)))
  8. 8. 計算グラフの例例 z = x ** 2 + 2 * x * y + y 8 x y _ ** 2 2 * _ _ * _ _ + _ z _ + _
  9. 9. 誤差逆伝播によって勾配を計算できるのが重要 l  誤差逆伝播は連鎖律律をつかって勾配を計算する l  計算グラフと順伝播時の変数の値があれば計算可能 l  ニューラルネットのフレームワークはこれを⾃自動で ⾏行行ってくれる 9 y’ = h’(g(f(x))) g’(f(x)) f’(x)
  10. 10. 機械学習のおさらい 多くの機械学習⼿手法は、 1.  ⽬目的関数の設計 2.  勾配の計算 3.  最⼩小化のための反復復計算 からなる 10 先ほどの計算は ここに使う
  11. 11. 機械学習の例例:分類学習のアルゴリズム l  ⽬目的関数をパラメータwで微分した値(勾配) を計算する⽅方法を⽤用意する l  wを勾配の⽅方向に少しだけ動かす、を繰り返す l  実際は更更新⽅方向の取り⽅方に⼯工夫が他数ある 11 initialize w until converge: w := w - η d/dw L(x, y; w) 最急降降下法
  12. 12. ニューラルネットの学習⽅方法 1.  ⽬目的関数の設計 l  計算グラフを⾃自分で設計する 2.  勾配の計算 l  誤差逆伝播で機械的に計算できる 3.  最⼩小化のための反復復計算 l  勾配を使って反復復更更新する 12 1さえ設計すれば残りは ほぼ⾃自動化されている
  13. 13. 深層学習フレームワークの構成要素 l  いずれも似たような構成要素からなる l  テンソルデータ構造 l  レイヤー(関数) l  ネットワーク(計算グラフ) l  最適化ルーチン l  フレームワークによってこれらの設計指針や抽 象化の粒粒度度、インターフェイスが異異なる 13
  14. 14. 深層学習フレームワークの⽐比較ポイント l  計算グラフをどう作るか? l  GPUで計算できるか? l  複数GPUで計算できるか? l  複数ノードで計算できるか? l  何の⾔言語で出来ているか? 14 Chainerはここに特徴がある
  15. 15. 計算グラフの作成戦略略 define-and-runとdefine-by-run l  define-and-run l  まず計算グラフを構築し、構築した計算グラフに データを流流すという、2ステップから成る l  ほとんどのフレームワークがこちら l  Caffeやtheanoなど l  define-by-run l  通常の⾏行行列列演算をする感覚で順伝播処理理をすると同 時に、逆伝播ようの計算グラフが構築される l  Chainer 15
  16. 16. ⼀一般的なDeepLearningフレームワーク(define- and-run) 1.  まず計算グラフを「構築」する処理理を書く 2.  変数の部分にデータを「流流す」処理理を書く 16 x y _ ** 2 2 * _ _ * _ _ + _ z _ + _ (x1, y1) (x2, y2) … x y _ ** 22 * _ _ * _ _ + _ z _ + _
  17. 17. 計算グラフがデータに依存する例例が扱いにくい l  データごとにネットワークの構造が変わってし まう⼿手法も多数存在 l  特に、ここ数年年でRecurrent Network系の研究 が増えてきている 17 Recurrent Net Recursive Net
  18. 18. define-and-runで構造を扱う⽅方法 l  データにごとに挙動の変わるノードをつくる l  例例えばループを表現するTheanoのscan関数 l  計算グラフ中に新たなプログラミング⾔言語を作って いるイメージ l  複数の計算グラフを予め作り、近いものを使う l  ⻑⾧長さ10, 20, 30…のRNNを作っておいて、データご とにいずれかを選択する 18 仕様が複雑になる 指数的な組み合わせに対処できない
  19. 19. Chainerの特徴:define-by-run l  前向き計算をしながら毎回グラフを構築する l  グラフが毎データで違っても良良い l  RNNはfor⽂文でループをそのまま書けば良良い l  特殊なノードは必要ない 19 x y _ ** 22 * _ _ * _ _ + _ z _ + _ x y _ ** 22 * _ _ * _ _ + _ z _ + _ (x1, y1) (x2, y2)
  20. 20. 擬似コードで⽐比較する define-and-run # 構築 x = Variable(‘x’) y = Variable(‘y’) z = x + 2 * y # 評価 for xi, yi in data: eval(z, x=xi, y=yi)) define-by-run # 構築と評価が同時 for xi, yi in data: x = Variable(xi) y = Variable(yi) z = x + 2 * y 20 データを⾒見見ながら 違う処理理をしてもよい
  21. 21. 計算グラフで⽐比較する 21 s = 0 for x in [1, 2, 3]: s += x s x + x + x + ss x + s define-and-runで ループを作る define-by-runでは すべて展開される
  22. 22. インタプリタとコンパイラのアナロジー l  define-and-runはコンパイラ l  計算⼿手順をグラフの形にそのまま変換する l  ループなどの制御構⽂文相当のノードがそのまま残る l  define-by-runはインタプリタ l  ⽣生成されるのは計算の履履歴 l  そのためループは全て展開される l  再帰も含めて、任意の計算⼿手順を実⾏行行できる 22
  23. 23. なぜ、⾃自由度度の⾼高いフレームワークが必要か? 深層学習とは階層の深いニューラルネットのことだけでは なくなってきている l  深いボルツマンマシン l  深い畳込みニューラルネットワーク l  再帰ニューラルネットワーク l  双⽅方向再帰ネットワーク l  注意メカニズム(Attention) 特に⾃自然⾔言語処理理など、対象のデータの構造を活かした ネットワークを作るときに役⽴立立つ 23
  24. 24. 計算グラフ構造がデータごとに異異なる例例 [⼩小林林+16] l  ⽂文中の同⼀一の固有表現の出現ごとに、Bi-RNNでエン コードして、max-pooling l  固有表現の出現パターンはデータごとに全く異異なる 24
  25. 25. define-by-runは何が良良いか? l  任意の構造を構築できる l  Recurrentはforループを、Recursiveは再帰呼び出し でそのまま書ける l  バグの箇所がわかりやすい l  前向き計算のバグはPython中の特定の⾏行行に対応する l  演算中に簡単に処理理を差し込める l  例例えばデバッグプリントやassertを⼊入れられる 25
  26. 26. define-by-runのデメリット l  計算グラフの構築コストが⼤大きい l  毎計算ごとにグラフを構築する l  ループは展開される l  最適化をかけづらい l  2つの演算をまとめたような演算に変換できない 26 演算単位が⼤大きいベクトルなので、オーバー ヘッドは⽐比較的軽微 計算の実⾏行行を遅延させて、JITで最適化を⾏行行う ことはできそう
  27. 27. Chainerを使う場合 l  Pythonのインストール l  pipのインストール l  CUDAのインストール l  pip install chainer 27
  28. 28. NNフレームワークの現在・今後の課題 l  メモリ使⽤用量量の削減 l  ニューラルネットの学習はメモリを⼤大量量に消費する l  ⼀一⽅方でGPUのメモリは⼩小さい l  マルチGPU・マルチノード l  ⾃自動で最適化しないと使ってもらえない l  最後のTensorflowの発表に期待! l  ミニバッチ化をやめたい l  計算効率率率を上げるために、同じデータを纏めて計算している l  そのため、構造の違うデータを⼀一度度に処理理しづらい 28
  29. 29. Chainerのまとめ l  NNフレームワークは誤差逆伝播を⾃自動でやって くれる l  計算グラフ構築の2つの⽅方法論論 l  define-and-runが主流流で、最適化をしやすい l  Chainerはdefine-by-runで、⼿手法の⾃自由度度が⾼高い l  まだ課題はある l  メモリ使⽤用量量、マルチノード、ミニバッチの排除 29
  30. 30. CUDAによる⾏行行列列ライブラリCuPy 30
  31. 31. CuPyとは何か? NumPy互換インターフェースの CUDA実装の⾏行行列列ライブラリ 31 Pythonの⾏行行列列ライブラリ NVIDIA GPUの開発環境とライブラリ
  32. 32. 既存のライブラリと 同じインターフェースで GPUの⾼高速性を⼿手に⼊入れられる 32
  33. 33. 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) 33
  34. 34. 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) 34 時間 [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
  35. 35. なぜCuPyが求められるのか? l  GPUを使った応⽤用研究では、必 要な知識識が以前より増えた l  GPU⾃自体が複雑 l  GPUを効率率率的に扱うアルゴリズム も複雑 l  使わないと効率率率で勝てない l  GPUを効率率率的に⼿手軽に使える仕 組みが必要になっている 35 GPU CUDA ⾏行行列列ライブラリ 深層学習エンジン 応⽤用研究
  36. 36. 裏裏の仕組み l  CUDA⽤用ソースを⾃自動⽣生成してコンパイラが⾛走る l  ⽣生成されたバイナリをGPUに⾃自動的に転送・実⾏行行する l  ビルド結果はキャッシュされるので2回⽬目移⾏行行⾼高速 36 スタブ スタブ 実処理理 nvcc コンパイラ .cubin GPU 実行 キャッシュ する
  37. 37. CUDA関連ライブラリの利利⽤用 l  NVIDIAはCUDA⽤用のライブラリを提供している l  CUPYはこれらのライブラリを内部で利利⽤用する l  cuBLAS、cuDNN l  例例えば内積計算すれば、勝⼿手に効率率率のよいcuBLASが 使われる l  バージョン間の差も吸収 l  cuDNN v2, v3, v4すべてサポート l  全部APIが微妙に変わっている(!) 37
  38. 38. ⾃自分でコードを書きたい時 例例:z[i] = x[i] + 2 * y[i] を書きたい 38 引数の型: “float32 x, float32 y” 戻り値の型: “float32 z” 処理理: “z = x + 2 * y;” ループやインデックスの処理理は ⾃自動で埋めてくれる これだけ書け ば良良い
  39. 39. Elementwiseカーネルの実体 l  Pythonの⽂文字列列テンプレートを使って⽣生成 39 ${preamble} extern "C" __global__ void ${name}(${params}) { ${loop_prep}; CUPY_FOR(i, _ind.size()){ //全要素のループ _ind.set(i); //インデックスを計算 ${operation}; //計算部分 } ${after_loop}; }
  40. 40. できる処理理 l  Elementwise l  各次元に対して同じ処理理をおこなう l  zi = f(xi, yi, …) for all i l  Reduction l  全次元をマージする l  z = f(f(… f(x1, x2), x3, …) それぞれMapReduceのMapとReduceに対応して いると思えば良良い 40
  41. 41. 型を汎⽤用にしたい 例例:z[i] = x[i] + 2 * y[i] をint/float対応にしたい 41 引数の型: “T x, T y” 戻り値の型: “T z” 処理理: “z = x + 2 * y;” 渡された配列列の型に応じて 異異なるソースを⽣生成する
  42. 42. 型解決の仕組み l  基本的にNumPyの型規則に準拠 l  例例えばint32 + float32はfloat64になるなど、 NumPyの仕様が決まっている l  NumPyのバグ(?)も再現 l  渡された型ごとにコードを⾃自動⽣生成する仕組み があるので、int32とfloat32に対して同じコー ドを書けばよい l  例例外を書く⽅方法も⽤用意されている 42
  43. 43. チューニングの⽅方法 l  CUDAのツールがそのまま使える l  NVIDIA Visual Profiler (nvvp)やnvprofコマンド l  CPU⽤用のプロファイラではGPUのボトルネックがわ からないので注意 l  詳細はCUDAのサイトへ 43
  44. 44. 深層学習以外にも利利⽤用できる l  既存のNumPyコードがほぼそのまま動く l  既存の解析⼿手法がそのままCUDA上で動く l  NumPyのベクトルデータとの変換は1⾏行行 44
  45. 45. CuPyの問題点 l  細かい単位の関数呼び出しが多くなる l  GPUの帯域律律速になってしまう l  関数合成の仕組みが必要 l  ⾮非同期呼び出しとメモリプールの相性が悪い l  現在は⼀一つのストリームのみ使っている l  その他 l  NumPyの関数のカバー率率率が低い l  Chainerに必要なものから実装中 45
  46. 46. 全体のまとめ l  Chainerは⾃自由度度が⾼高い l  NNフレームワークは誤差逆伝播をやってくれる l  Chainerのdefine-by-runは⾃自由にネットワークを構築 できる l  メモリ、マルチノード、ミニバッチが今後の課題 l  CuPyはNumPy互換の⾏行行列列ライブラリ l  NumPyとほぼAPI互換 l  ビルド作業などは裏裏で勝⼿手にやってくれる l  CUDAのコードを⾃自分で書くこともできる 46

×