Successfully reported this slideshow.
Your SlideShare is downloading. ×

Introduction to Chainer and CuPy

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 32 Ad

More Related Content

Slideshows for you (20)

Viewers also liked (20)

Advertisement

Similar to Introduction to Chainer and CuPy (20)

More from Kenta Oono (14)

Advertisement

Recently uploaded (20)

Introduction to Chainer and CuPy

  1. 1. Chainer・CuPy⼊⾨ 株式会社 Preferred Networks ⼤野健太 oono@preferred.jp 2016/03/17 Chainer Meetup #2@ドワンゴ
  2. 2. ⾃⼰紹介 • ⼤野健太(@delta2323_) • 経歴:数理科学研究科・修⼠課程(共形幾何) • → 2012.3 PFI → 2014.10 PFN • 所属:研究班(理論解析・ライフサイエンス・Chainer開発メンバー) • ブログ:http://delta2323.github.io • 最近の活動 • NIPS2014・ICML2015・NIPS2015勉強会主催 • ⽇経ビッグデータ短期連載・雑誌寄稿など 2
  3. 3. アジェンダ • 深層学習基礎 • Chainer • CuPy
  4. 4. 機械学習の訓練 = 損失関数の最⼩化 • L は予測が正しいほど値が⼩さくなるように設計された関数 • 深層学習の場合 • L をニューラルネットを⽤いて作成する • w はニューラルネットが持つパラメータ argminw ∑(x, y) L(x, y; w) w:パラメータ x:⼊⼒ベクトル y:正解ラベル L:損失関数 例:分類問題(⼊⼒ x に振られるラベル y を予測する) 4
  5. 5. 順伝播(Forward Propagation) • 計算グラフの先頭のユニットに データを与え、順⽅向に計算を進 める x w _ ** 2 2 * _ _ * _ SCE L _ + _ z t 5 x = chainer.Variable(np.array(…)) # same as w, t z = x ** 2 + 2 * x * w L = SoftmaxCrossEntropy(z, t)
  6. 6. パラメータの学習アルゴリズム(最急降下法) 学習は以下の2操作の繰り返し • 勾配(⽬的関数 L をパラメータ w に関する微分、∇wL)の計算 • w を勾配⽅向に少し動かす initialize w until convergence: get data (x, y) w ← w - η ∇w L(x, y; w) η:学習率 ← この更新式にはバリエーションがある ニューラルネットは誤差逆伝播により勾配を効率的に計算できる 6
  7. 7. 逆伝播(Backward Propagation) • 計算グラフの末端のユニットからエラー(損失関数の勾配)を計算する x w _ ** 2 2 * _ _ * _ SCE L _ + _ z ∇z L ∇w L ∇x L ∇L L = 1 t ∇t L 7
  8. 8. 連鎖律(Chain Rule) • Forward Propagationを以下のように書く • 損失をLとすると、連鎖律より • 勾配を と書くと → 勾配は活性と逆向きに伝播する 活性の伝播⽅向 エラーの伝播⽅向 x f y x f y 8
  9. 9. 深層学習の訓練の実装⽅法 1. ⽬的関数を設計 = 計算グラフを構築 + 訓練データを順伝播 → ユーザーはこの開発に集中すれば良い 2. 勾配を計算 → 誤差逆伝播を⽤いて⾃動的に計算 3. ⽬的関数最⼩化のために、パラメータを反復更新 → 勾配法を⽤いて⾃動的に計算 9 L(x, y, w) ∇w L w ← w - η ∇w L
  10. 10. アジェンダ • 深層学習基礎 • Chainer • CuPy
  11. 11. Chainer概要 http://chainer.org • 製作者:得居誠也、開発:PFN、PFI • 公開:2015年6⽉9⽇ • 隔週⽔曜⽇リリース • 最新バージョン:1.7.1(2016年3⽉15⽇) • ライセンス:MIT (Expat) ⽬標:複雑なNNの直感的な記述 ü NNの構築をPythonのプログラムとして記述 ü ループや分岐などを伴う複雑なNNの構築 ü 動的なNN構築(Define-by-Run) ü Pythonのスタックトレースを利⽤したデバッグ ü データごとに異なるNNを構築 ü CuPyによるCPU/GPU agnosticなコード記述 11
  12. 12. セットアップ • OS:Ubuntu14.04, CentOS7 • 依存ライブラリ(最⼩要件) • Python 2.7.6+, 3.4.3+, 3.5.1+ • NumPy 1.9, 1.10 • Six 1.9 • CUDAサポート:6.5, 7.0, 7.5 • 追加依存ライブラリ:filelock, g++ 4.8.4+ • cuDNN:v2, v3, v4 • インストール • pip install chainer 12
  13. 13. Chainer技術スタック:Chainer本体 + CuPy • Chainer:ディープラーニングフレームワーク • 計算グラフ構築・最適化アルゴリズムをPython プログラムとして記述 • CuPy:GPU版NumPy* • NumPyの配列操作のサブセットと互換 CPU GPU BLAS CUDA Toolkit cuDNN NumPy CuPy Chainer Python * NumPy:Pythonの数値計算ライブラリ。 多次元配列の操作や数学関数が充実しており、 多くのPythonデータ解析ツールがNumPyを ベースに制作されている 13
  14. 14. 計算グラフ構築のパラダイム:Define-and-Run vs. Define-by-Run f g x f g 計算グラフ構築 データフィード x yf x = chainer.Variable(...) y = f(x) z = g(x) zg データフィード = 計算グラフ構築 Define-and-Run Define-by-Run 誤解を恐れず⾔えば • Define-and-Run = NNのコンパイラ • Define-by-Run = NNのインタープリタ 14
  15. 15. 疑似コードでの⽐較 15 # 構築と評価が同時 for xi, yi in data: x = Variable(xi) y = Variable(yi) z = x + 2 * y Define-by-RunDefine-and-Run # 構築 x = Variable(‘x’) y = Variable(‘y’) z = x + 2 * y # 評価 for xi, yi in data: eval(z, x=xi, y=yi))
  16. 16. 命令的なフレームワークでは柔軟な計算グラフ構築が可能 • ネットワーク構築にPythonの制御構⽂ を利⽤できる • if / for / while etc… • 応⽤ • 訓練・テストで層を取り替える • For⽂を⽤いてRNNを構築 • 訓練データごとに異なる計算グラフ def forward(x, t, train=True): h = F.relu(model.l1(x)) y = model.l2(h) if train: loss = F.softmax_cross_entropy(y, t) return loss else: prob = F.softmax(y) acc = F.accuracy(prob, t) return acc …… y sce lo ss …… y sm pr ob acc ac c 訓練 テスト … … … … 16
  17. 17. Variableオブジェクト • 計算グラフのデータノード • NumPyもしくはCuPyの多次元配列を保持する • 多くのFunctionは配列の最初の軸をミニバッチとして扱う x = Variable(np.zeros((10, 20), dtype=np.float32)) x.data # Variableが格納している配列へアクセス x 17
  18. 18. Functionオブジェクト • パラメータなし関数 • chainer.functions(以降F)に⾊々定義されている • Variable(のタプル)を受け取り、Variable(のタプル)を出⼒する • 損失関数もFunctionの1つ x = Variable(...) y = F.relu(x) # yもVariable relu x y 18
  19. 19. Linkオブジェクト • パラメータ付き関数 • Linkの持つパラメータは • Optimizer(後述)の最適化の対象 • シリアライザでsave/loadができる • 多くのLinkには対応するパラメータなしの Functionが存在する • 例:LinearLinkとLinearFunction • 内部で対応するFunctionを利⽤している LinearFunction x W b y LinearLink W b x y LinearFunction 19
  20. 20. model Chainオブジェクト • Linkをまとめるオブジェクト • Chain⾃⾝がLinkを継承しているので、Linkを階層的に扱える • 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 layer1 W b layer2 W b embed W
  21. 21. Optimizerオブジェクト • Backwardにより計算できた勾配を⽤いて、パラメータ を最適化する • chainer.optimizersに定義されている • 実装されている最適化法 • SGD, MomentumSGD, AdaGrad, RMSprop, RMSpropGraves, AdaDelta, Adam 21 model layer1 W b layer2 W b embed W opt
  22. 22. 例:MNISTによる多層パーセプトロンの訓練 class MnistMLP(chainer.Chain): def __init__(self, n_in, n_units, n_out): super(MnistMLP, self).__init__( l1=L.Linear(n_in, n_units), l2=L.Linear(n_units, n_units), l3=L.Linear(n_units, n_out),) def __call__(self, x): h1 = F.relu(self.l1(x)) h2 = F.relu(self.l2(h1)) return self.l3(h2) model = MnistMLP(784, 100, 10) opt = optimizers.SGD() opt.setup(model) for epoch in xrange(n_epoch): for i in xrange(0, N, batchsize): x = Variable(to_gpu(...)) t = Variable(to_gpu(...)) opt.zero_grads() loss = model(x, t) loss.backward() opt.update() 784 100 100 10 0:2% 1:5% 2:90% ・ ・ 9:1% 22
  23. 23. Linear L1 例:MNIST Forward Propagation詳細 L1 = L.Linear(784, n_units) L2 = L.Linear(n_units, n_units)) L3 = L.Linear(n_units, 10)) x W bias 0 5 9 ReLU def forward(self, x): h1 = F.relu(L1(x)) h2 = F.relu(L2(x)) return L3(h2) Linear L1 h1 W bias ReLU Linear L1 h2 W bias 23
  24. 24. ベンチマーク https://github.com/soumith/ convnet-benchmarks 24
  25. 25. アジェンダ • 深層学習基礎 • Chainer • CuPy
  26. 26. CuPy:GPU版NumPy (CUDA + NumPy) ü NumPy互換の関数を約170個実装済 ü CPU/GPUコードの統⼀的な記述 ü カスタムカーネルの記述 ü CuPy単独での利⽤も可能 ü 深層学習以外の⽤途でも利⽤可能 26
  27. 27. CuPyの使い⽅ • chainer.cuda.get_array_moduleを⽤いてCPU / GPU agnosticなコードが書ける • 例:NumPy, CuPy両⽅の多次元配列(ndarray)を受け付けるSoftmaxの実装 def softmax(x) xp = get_array_module(x) y = x – x.max(axis=1, keepdims=True) y = xp.exp(y) return y / y.sum(axis=1, keepdims=True) xp = numpy/cupyいずれでもOK ⼊⼒に応じてnumpy/cupyを選択 x_cpu = numpy.array([1, 2, 3]) l2_cpu = numpy.linalg.norm(x_cpu) x_gpu = cupy.array([1, 2, 3]) l2_gpu = cupy.linalg.norm(x_gpu) • numpy.*** を cupy.*** に 変更すればだいたい動く 27
  28. 28. CuPyはどのくらい早いの? 状況次第ですが、最⼤数⼗倍程度速くなります 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) 時間[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 28
  29. 29. 独⾃Elementwiseカーネル実装 • 例:2つの配列のユークリッド距離の2乗を計算する関数 squared_diff = cupy.ElementwiseKernel( 'float32 x, float32 y', #⼊⼒ 'float32 z', #出⼒ 'z = (x - y) * (x - y)', #計算 'squared_diff') #名前 diff = squared_diff(cupy.arange(10), 10)) 10がbroadcastされて、 [1, 2, 3, …, 10]と[10, 10, …, 10] の2乗誤差を計算 CuPyは内部でCUDAコードのテンプレートを持 つ。引数でテンプレートを埋めて動的にコード ⽣成、コンパイルを⾏う 29
  30. 30. 独⾃Reductionカーネル実装 • 例:配列のユークリッドノルム(L2ノルム)を計算する関数 l2norm_kernel = cupy.ReductionKernel( 'T x', # ⼊⼒ 'T y', # 出⼒ 'x * x', # 前処理 ‘a + b’, # Reduce操作 'y = sqrt(a)', # 後処理 '0', # 初期値 'l2norm’) # 名前 x = cupy.arange(10, dtype=‘f’) dist = l2norm_kernel( x, axis=1, keepdims=True) 30
  31. 31. まとめ • 深層学習ではNNで損失関数が表現され、誤差 逆伝播を⽤いた勾配降下法でパラメータに関す る損失関数の最⼩化で訓練します • ChainerはDefine-by-Runのパラダイムを採⽤ し、複雑なNNを柔軟に構築できることを⽬指 した深層学習フレームワークです • CuPyはNumPyと同様のAPIやカスタムカーネ ルを⽤いて、GPU上での配列操作を簡単に扱う ことを⽬指した多次元配列ライブラリです • 公式HP:http://chainer.org • レポジトリ: https://github.com/pfnet/chainer • Twitter:@ChainerOfficial • Google Group:Chainer Uesr Group • Contribution Guide: http://docs.chainer.org/en/stable/contribution.html We are hiring! 31
  32. 32. Copyright © 2014- Preferred Networks All Right Reserved.

×