Lispmeetup #39 MGLの紹介: Common Lispによるディープラーニング

5,317 views

Published on

Lispmeetup #39 発表資料

Published in: Engineering
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,317
On SlideShare
0
From Embeds
0
Number of Embeds
3,862
Actions
Shares
0
Downloads
24
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Lispmeetup #39 MGLの紹介: Common Lispによるディープラーニング

  1. 1. MGLの紹介 Satoshi Imai / 今井 悟士 Twitter: @masatoi0 Github: masatoi Common Lispによるディープラーニング
  2. 2. MGLとは ● Common Lisp用の機械学習ライブラリ ● ディープラーニングの割と最近の手法までカバー ● MGL-MATという行列演算ライブラリを使う – cl-cuda、LLA(Lisp Linear Algebra)によって高速化 ● cl-cuda非対応の旧版はQuicklispにある(最新版はGithubから) ● サンプルが長かったので整理した – https://github.com/masatoi/mgl-user
  3. 3. MGLに実装されているモデル ● 教師あり学習 – FFNN (Feed Forward Neural Networks) ● 教師なし事前学習 – DBN (Deep Brief Networks) – DBM (Deep Boltzmann Machine) ● 時系列向けモデル – RNN (Reccurent Neural Networks) – LSTM (Long Short Term Memory)
  4. 4. ニューラルネットワーク 入力層 隠れ層 出力層 ● フィードフォワードニューラルネットワーク(FFNN)
  5. 5. ニューラルネットワークによる予測 入力層 隠れ層 出力層 入力 重み
  6. 6. 活性化関数 入力層 隠れ層 出力層 入力 重み 活性化関数
  7. 7. 出力層の活性化関数は問題に応じて変える 入力層 隠れ層 出力層 ● 回帰問題なら恒等写像 ● 分類問題ならソフトマックス関数 0.2 0.5 0.3 例えば3クラス分類問題なら...
  8. 8. ニューラルネットワークの学習 ● 予測値と実測値の違いを表す損失関数を最小化する → 勾配法 ● 勾配は出力層から入力層に向かって伝搬するように計算(逆伝搬) ● 勾配法の色々なバリエーション – 確率的勾配降下法(SGD) – Momentum SGD – ADAM ● 詳細は本を読もう!
  9. 9. ディープラーニング ● 隠れ層を多層にしたニューラルネットワーク – 勾配消失問題:多層にすると逆伝搬のときに勾配が消失/発散する ● → オートエンコーダ/RBMによる教師なし事前学習 (後述) ● → 活性化関数にReLUやMaxoutを使う (後述) ● 特徴量を作りこまなくても生のデータを与えればいい。手軽。性能良し ● 一方で計算時間はかかる – → データを小分けしてまとめて並列に処理する → ミニバッチ ● ネットワークを複雑にすると過学習する – → Dropout (後述)を使って汎化性能を上げられる
  10. 10. ディープラーニングで使われる活性化関数: ReLU、Maxout ● 正規化線形関数(Rectified Linear Unit; ReLU) – 勾配が消失しにくい – 計算が単純で速い – 多分一番メジャー ● Maxout – 複数の線形ユニットから成る – 活性化関数自体が学習 – ReLUよりも良い場合も多い – 計算時間は増える
  11. 11. 例題:MNIST ● 手書き数字認識のデータセット。よく例題に使われる ● 28×28ピクセルの画像(784次元)に正解ラベルがついている ● 訓練データ60000個、テストデータ10000個 ● http://yann.lecun.com/exdb/mnist
  12. 12. データセットの読み込み ● MNISTのデータを読み込む関数training-data、test-data ● データセットはデータ点の構造体の配列 ● データ点の中身 MGL­USER> (aref *training­data* 0) #S(DATUM    :ID 1    :LABEL 5    :ARRAY #<MAT             784 AB #(0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0                      0.011764705882352941d0 0.07058823529411765d0 ...                      0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0                      0.0d0 0.0d0 0.0d0 0.0d0)>) MGL-MATの構造体
  13. 13. ネットワークの構造を定義する ● build-fnnマクロでネットワークの構造を指定してmake-instanceする – 入力層784次元、1200次元の隠れ層が3層、出力層10次元 – 隠れ層の活性化関数はReLU、出力層の活性化関数はソフトマックス関数 – バッチサイズ100 (defparameter my­fnn   (build­fnn (:class 'fnn :max­n­stripes 100)     ;; Input Layer 784 dim     (inputs (­>input :size 784))     ;; Hidden Layer 1 1200 units, ReLU     (f1­activations (­>activation inputs :name 'f1 :size 1200))     (f1 (­>relu f1­activations))     ;; Hidden Layer 2 1200 units, ReLU     (f2­activations (­>activation f1 :name 'f2 :size 1200))     (f2 (­>relu f2­activations))     ;; Hidden Layer 3 1200 units, ReLU     (f3­activations (­>activation f2 :name 'f3 :size 1200))     (f3 (­>relu f3­activations))     ;; Output Layer: Softmax layer 10 dim     (prediction (­>softmax­xe­loss (­>activation f3 :name 'prediction :size 10)                                    :name 'prediction))))
  14. 14. ネットワークの内容 ● ネットワークはlumpというオブジェクトの集合から構成されている – ->input、 ->relu、 ->softmax-xe-lossなど – ->activationは層間の重みを持っている MGL­USER> (describe my­fnn) #<FNN {10205FDD53}> BPN description:   CLUMPS = #(#<­>INPUT INPUTS :SIZE 784 1/100 :NORM 0.00000>              #<­>ACTIVATION (F1 :ACTIVATION) :STRIPES 1/100 :CLUMPS 4>              #<­>RELU F1 :SIZE 1200 1/100 :NORM 0.00000>              #<­>ACTIVATION (F2 :ACTIVATION) :STRIPES 1/100 :CLUMPS 4>              #<­>RELU F2 :SIZE 1200 1/100 :NORM 0.00000>              #<­>ACTIVATION (F3 :ACTIVATION) :STRIPES 1/100 :CLUMPS 4>              #<­>RELU F3 :SIZE 1200 1/100 :NORM 0.00000>              #<­>ACTIVATION (PREDICTION :ACTIVATION) :STRIPES 1/100                :CLUMPS 4>              #<­>SOFTMAX­XE­LOSS PREDICTION :SIZE                10 1/100 :NORM 0.00000>)   N­STRIPES = 1   MAX­N­STRIPES = 100
  15. 15. ネットワークの内容 ● 各層のオブジェクトはnodesとderivativesというスロットを持っていて、それ ぞれ順伝搬、逆伝搬の値が入る MGL­USER> (describe (aref (clumps my­fnn) 0)) #<­>INPUT INPUTS :SIZE 784 100/100 :NORM 94.94252>   [standard­object] Slots with :INSTANCE allocation:   NAME               = INPUTS   SIZE               = 784   NODES              = #<MAT 100x784 AF #2A((0.0d0 0.0d0 0.0d0 0.0d0 0.0d0..   DERIVATIVES        = #<MAT 100x784 A #2A((­3.2746879326098654d­13 ­2.3442..   DEFAULT­VALUE      = 0   SHARED­WITH­CLUMP  = NIL   X                  = #<­>INPUT INPUTS :SIZE 784 100/100 :NORM 94.94252>   DROPOUT            = NIL   MASK               = NIL
  16. 16. ネットワークの内容 ● 出力層は教師信号を表すtargetスロットを持っている MGL­USER> (describe (aref (clumps my­fnn) 8)) #<­>SOFTMAX­XE­LOSS PREDICTION :SIZE 10 100/100 :NORM 9.98895>   [standard­object] Slots with :INSTANCE allocation:   NAME               = PREDICTION   SIZE               = 10   NODES              = #<MAT 100x10 ABF #2A((2.017507522628972d­9..   DERIVATIVES        = NIL   DEFAULT­VALUE      = 0   SHARED­WITH­CLUMP  = NIL   X                  = #<­>ACTIVATION (PREDICTION :ACTIVATION) :STRIPES 100/10   TARGET             = (3 8 6 1 0 0 9 4 8 7 0 4 2 5 6 0 6 3 9 3 2 0 9 3 1 ..
  17. 17. ネットワークに入出力を設定 ● 入力層のnodesと出力層のtargetにデータセットの値を設定する (defmethod set­input (samples (bpn fnn))   (let* ((inputs (or (find­clump (chunk­lump­name 'inputs nil) bpn :errorp nil)                      (find­clump 'inputs bpn)))          (prediction (find­clump 'prediction bpn)))     (clamp­data samples (nodes inputs))     (setf (target prediction) (label­target­list samples))))
  18. 18. 学習部分 ● 最適化の本体はminimize ● 最適化アルゴリズムを表すoptimizerと学習対象を表すlearnerを渡 す (defun train­fnn (fnn training &key                                  (n­epochs 3000)                                  (learning­rate 0.1) (momentum 0.9))   (let ((optimizer (make­instance 'segmented­gd­optimizer                       :segmenter                       (constantly                        (make­instance 'sgd­optimizer                           :learning­rate learning­rate                           :momentum momentum                           :batch­size (max­n­stripes fnn)))))         (learner (make­instance 'bp­learner :bpn fnn))         (dateset (make­sampler training :n­epochs n­epochs)))     (minimize optimizer learner :dataset dateset)     fnn))
  19. 19. モニタリング関数 ● optimizerに学習の途中経過を表示するモニタリング関数を付ける (defun train­fnn­with­monitor (fnn training test                                &key (n­epochs 3000)                                     (learning­rate 0.1) (momentum 0.9))   (let ((optimizer (monitor­optimization­periodically                     (make­instance 'segmented­gd­optimizer­with­data                        :training training                        :test test                        :segmenter (constantly                                    (make­instance 'sgd­optimizer                                       :learning­rate learning­rate                                       :momentum momentum                                       :batch­size (max­n­stripes fnn))))                     '((:fn log­bpn­test­error :period log­test­period)                       (:fn reset­optimization­monitors                        :period log­training­period                        :last­eval 0))))         (learner (make­instance 'bp­learner :bpn fnn))         (dateset (make­sampler training :n­epochs n­epochs)))     (minimize optimizer learner :dataset dateset)     fnn))
  20. 20. 学習の進行部分 ● fnnの重みをランダムに初期化して訓練を実行 ● with-cuda*マクロを被せることでGPUを使った計算ができる – CPUを使う場合は変数 *cuda-enable* を nil に設定する (defun train­fnn­process­with­monitor (fnn training test                       &key (n­epochs 30) (learning­rate 0.1) (momentum 0.9))   (with­cuda* ()     (repeatably ()       (init­bpn­weights fnn :stddev 0.01)       (train­fnn­with­monitor fnn training test                               :n­epochs n­epochs                               :learning­rate learning­rate                               :momentum momentum)))   fnn)
  21. 21. 実験 ● 784-1200-1200-1200-10のネットワーク ● 隠れ層の活性化関数はReLU (time (train­fnn­process­with­monitor        my­fnn        *training­data*        *test­data*        :n­epochs 30)) Evaluation took:   1638.934 seconds of real time   1638.103618 seconds of total run time (1364.208722 user, 273.894896 system)   [ Run times consist of 0.873 seconds GC time, and 1637.231 seconds non­GC time.   99.95% CPU   5,559,500,797,670 processor cycles   1 page fault   6,657,802,576 bytes consed
  22. 22. Dropout ● 一定確率でユニットを無効化して学習する – 小さなネットワークの集団学習と見なせる → 汎化性能が向上 ● 一方で収束は遅くなる 入力層 隠れ層 出力層
  23. 23. Dropoutを入れたネットワークの定義 ● Dropoutのためのlumpが増えている ● 入力層の20%、隠れ層の50%を無効化する (defparameter fnn­relu­dropout   (build­fnn (:class 'fnn :max­n­stripes 100)     (inputs (­>input :size 784 :dropout 0.2))     (f1­activations (­>activation inputs :name 'f1 :size 1200))     (f1* (­>relu f1­activations))     (f1 (­>dropout f1* :dropout 0.5))     (f2­activations (­>activation f1 :name 'f2 :size 1200))     (f2* (­>relu f2­activations))     (f2 (­>dropout f2* :dropout 0.5))     (f3­activations (­>activation f2 :name 'f3 :size 1200))     (f3* (­>relu f3­activations))     (f3 (­>dropout f3* :dropout 0.5))     (prediction (­>softmax­xe­loss (­>activation f3 :name 'prediction :size 10)                                    :name 'prediction))))
  24. 24. Dropout+Maxout ● 隠れ層の活性化関数をReLUからMaxoutに ● Maxoutのユニット数(group-size)を指定する (defparameter fnn­maxout­dropout   (let ((group­size 5))     (build­fnn (:class 'fnn :max­n­stripes 100)       (inputs (­>input :size 784 :dropout 0.2))       (f1­activations (­>activation inputs :name 'f1 :size 1200))       (f1* (­>max f1­activations :group­size group­size))       (f1 (­>dropout f1*))       (f2­activations (­>activation f1 :name 'f2 :size 1200))       (f2* (­>max f2­activations :group­size group­size))       (f2 (­>dropout f2*))       (f3­activations (­>activation f2 :name 'f3 :size 1200))       (f3* (­>max f3­activations :group­size group­size))       (f3 (­>dropout f3*))       (prediction (­>softmax­xe­loss (­>activation f3 :name 'prediction :size 10)                                      :name 'prediction)))))
  25. 25. テストデータに対する予測性能 ● 大差ない (ReLU: 98.51%、 ReLU+Dropout: 98.65%、Maxout+Dropout:98.51%)
  26. 26. 計算時間 ● 同じ784-1200-1200-1200-10のネットワーク ● CPUとGPUでReLU、ReLU+Dropout、Maxout+Dropoutを比較 ● CPU: Core i5 4670 (4コア)、GPU: GeForce GTX750Ti (640 CUDAコア) ● MGL-MATのデータ型がdouble-floatになっていると遅い – → MGL-MAT:*default-mat-ctype* を :float に設定 ReLU ReLU+Dropout Maxout+Dropout CPU 884s 1030s NIL GPU 243s 248s 130s
  27. 27. Tensorflowとの比較 ● Tensorflow: Googleが出しているフレームワーク (C++/Python) – Tensorflow 0.8.0 ● MNIST、隠れ層2層(256ユニット)、ReLU、Momentum SGD ● CPU(Core i5 4670)による実行時間の比較 – TensorflowはCPU使用率が低く、220%くらいしか出ていない – MGLのCPU使用率はほぼ400% (4コアCPU) real total MGL 36.6s 146.04s Tensorflow 95.52s 175.55s
  28. 28. Tensorflowとの比較 ● MNIST、隠れ層2層(256ユニット)、ReLU、Momentum SGD ● GPU(GeForce GTX750Ti)による実行時間の比較 ● MNIST、隠れ層2層(2560ユニット)、ReLU、Momentum SGD – 隠れ層の次元を10倍にしてみる real MGL 22.609s Tensorflow 28.209s real MGL 206.371s Tensorflow 216.011s
  29. 29. まとめ ● Lispで機械学習できない理由はない – 同じ言語の中で高い記述力と計算速度のトレードオフを調節できる – モデル記述はPython、学習アルゴリズムはC++で書くといった面倒がない ● ReLU、Maxout、Dropout、RNN、LSTMなど、最近よく使われる手法や モデルが揃っている – 畳み込みニューラルネットは実装されていない ● 計算速度も他のライブラリに比べて遜色ない。むしろ速い

×