Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Chainerの使い方と 自然言語処理への応用

27,196 views

Published on

WebDB forum 2015の招待講演のスライドです。@beam2dさんのスライドがオリジナルです http://www.slideshare.net/beam2d/chainer-52369222

Published in: Technology
  • Be the first to comment

Chainerの使い方と 自然言語処理への応用

  1. 1. Chainerの使い⽅方と ⾃自然⾔言語処理理への応⽤用 2015/11/25  WebDB  forum@芝浦⼯工業⼤大学 (株)Preferred  Infrastructure 海野  裕也 v1.5向け
  2. 2. ⾃自⼰己紹介 海野  裕也 l  -2008 東⼤大情報理理⼯工修⼠士 l  ⾃自然⾔言語処理理 l  2008-2011 ⽇日本アイ・ビー・エム(株)東京基礎研 l  テキストマイニング、⾃自然⾔言語処理理の研究開発 l  2011- (株)プリファードインフラストラクチャー l  ⾃自然⾔言語処理理、情報検索索、機械学習、テキストマイニングなど の研究開発 l  研究開発系案件、コンサルティング l  JubatusやChainerの開発 NLP若若⼿手の会共同委員⻑⾧長(2014-) 「オンライン機械学習」(2015, 講談社) 2
  3. 3. Chainer http://chainer.org/ 3 v1.5が本⽇日リリース
  4. 4. 今⽇日のおはなし l  Chainer の使い⽅方を紹介します l  Deep Learning のおさらいも簡単にしますが、学術 的な詳細は既存の⽂文献を参考にしてください l  CUDA サポートについても解説しますが、CUDA  の 詳細は NVIDIA のドキュメントを参照してください l  ⾃自然⾔言語処理理への応⽤用⽅方法を紹介します l  Recurrent Net などのよく知られた結果を  Chainer で実装する⽅方法を紹介します 4
  5. 5. ニューラルネットの基礎
  6. 6. ニューラルネット l  値が伝播していく有向グラフ l  エッジで重みをかけて、ノードに⼊入るところで⾜足し 込み、ノードの中で⾮非線形変換する l  全体としては巨⼤大で複雑な関数を表す 6
  7. 7. ニューラルネット=合成関数 l  ベクトルに対して線形・⾮非線形な関数をたくさん適 ⽤用する合成関数と捉えるとよい l  各ノードはベクトルを保持する変数 7
  8. 8. ⼀一般のニューラルネットは  DAG = 計算グラフ ⼀一般にはグラフが分岐したり合流流したりする l  分岐:同じ変数を複数の場所でつかう l  合流流:⼆二つ以上の変数を受け取る関数を適⽤用する 8
  9. 9. 計算グラフの例例 z = x ** 2 + 2 * x * y + y 9 x y _ ** 2 2 * _ _ * _ _ + _ z _ + _
  10. 10. 機械学習のおさらい 多くの機械学習⼿手法は、 1.  ⽬目的関数の設計 2.  勾配の計算 3.  最⼩小化のための反復復計算 からなる 10 先ほどの計算は ここに使う
  11. 11. 機械学習の例例:分類学習の⽬目的関数 11 argminw ∑(x, y) l(x, y; w) l  xは⼊入⼒力力ベクトル、yは予測ラベル l  l(x, y)は予測が正しければ⼩小さく、間違えれば⼤大 きくなる値(損失関数) l  上記関数を最⼩小化するパラメータwを求めたい
  12. 12. 機械学習の例例:分類学習のアルゴリズム l  ⽬目的関数をパラメータwで微分した値(勾配) を計算する⽅方法を⽤用意する l  wを勾配の⽅方向に少しだけ動かす、を繰り返す l  実際は更更新⽅方向の取り⽅方に⼯工夫が他数ある 12 initialize w until converge: w := w - η d/dw L(x, y; w) 最急降降下法
  13. 13. 誤差逆伝播(後退型⾃自動微分) 合成関数の微分を計算するには連鎖律律 (chain rule) をつかう 13 z = h(y), y = g(x), x = f(w) z w = z y y x x w = Dh(y)Dg(x)Df (w) 各関数の微分がわかれば機械的に計算できる
  14. 14. 誤差逆伝播は、計算グラフを逆向きにたどる 計算グラフと順伝播時の各変数の値があれば計算可能 14
  15. 15. ニューラルネットの学習⽅方法 1.  ⽬目的関数の設計 l  計算グラフを⾃自分で設計する 2.  勾配の計算 l  誤差逆伝播で機械的に計算できる 3.  最⼩小化のための反復復計算 l  勾配を使って反復復更更新する 15 1さえ設計すれば残りは ほぼ⾃自動化されている
  16. 16. Recurrent Net l  ループがあるニューラルネット l  時刻の概念念があり、t=T の状態は t=T-1 の状態と t=T の⼊入 ⼒力力を使って求める 16 T T-1 T
  17. 17. Recurrent Net は時間展開して考える l  時間展開すれば、DAG の計算グラフになる l  DAG の計算グラフは誤差逆伝播できる(Backprop Through Time) 17 t=1 t=2 t=3 t=4
  18. 18. Truncated BPTT l  ⻑⾧長い系列列を学習するとき、計算グラフが⻑⾧長⼤大になり計算コ ストがかかる l  古い情報を忘れて(グラフを切切り落落として)計算コストを 削減するのが Truncated BPTT(勾配は不不正確になる) 18 t=1 t=2 t=3 t=4 Truncated
  19. 19. Chainer の使い⽅方
  20. 20. Chainer はニューラルネットのフレームワーク l  機能 l  ニューラルネットを記述する l  ニューラルネットの順伝播・逆伝播を実⾏行行する l  勾配法を実⾏行行してパラメータを最適化する l  Chainer の特徴 l  順伝播は単純に Python のスクリプトとして書ける l  そのスクリプトの実⾏行行結果は計算⼿手順を記憶してい て、逆伝播を⼿手で書く必要はない 20
  21. 21. 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 もインストールできます 21
  22. 22. 順伝播 l  今まで「変数」と呼んでいたものは、Chainer では  Variable オブジェクト l  Variable を  Function に⼊入れると、順伝搬後の Variable が返ってくる l  Variable が計算グラフを保持している l  Function は、四則演算以外に chainer.functions に⽤用意されている 22
  23. 23. 順伝搬とコード例例 23 x y _**2 2*_ _*_ _+_ z _+_ x = Varaible(...) y = Variable(...) z = x ** 2 + 2 * x * y + y
  24. 24. Variable オブジェクト l  計算グラフの(データ)ノード l  NumPy または  CuPy(後述)の配列列を保持する l  初期化時に配列列を渡す l  data 属性に保存される l  多くの Function は配列列の最初の軸をミニバッチとして 使うので注意 l  下の x は、20 次元ベクトルが 10 個⼊入ったミニバッチとみなす l  現状、Chainer は多くの場所で  float32 配列列を要求する ので注意 24 x = Variable(np.zeros((10, 20), dtype=np.float32)) x.data
  25. 25. Function オブジェクト l  計算グラフの「演算」ノード l  chainer.functions (以降降 F)  にいろいろ定義され ている l  F.relu, F.max_pooling_2d, F.lstm, ... l  Functionの呼び出し結果が、再びVariableになる l  v1.5からパラメータはLinkとして分離離された(後述) 25 x = Variable(...) y = F.relu(x) # yもVariable
  26. 26. 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オブジェクトになった 26 v1.5~
  27. 27. 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) 27 v1.5~
  28. 28. ロス関数、勾配計算 l  ロス関数もFunctionの⼀一種 l  ロス関数の出⼒力力に、Variable.backward()  を呼ぶと 勾配が計算できる loss = F.softmax_cross_entropy(y, t) loss.backward() 28
  29. 29. 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()) 29
  30. 30. Optimizer による最適化 l  まず勾配をゼロ初期化:zerograds() l  順伝播・逆伝播を実⾏行行 l  最適化ルーチンを実⾏行行:update() l  以上を何回も繰り返す model.zerograds() loss = ... loss.backward() optimizer.update() 30
  31. 31. Chainer を使う場合の全体の流流れ 1.  Linkを使ってChainを定義する 2.  Optimizer  に、Chain を設定する 3.  forward 関数を定義する 4.  データセットを読み込み、訓練⽤用と評価⽤用にわける 5.  訓練ループを回す a.  勾配をゼロ初期化 b.  順伝搬して、得られたロス値の backward メソッドを呼ぶ c.  Optimizerを、update 6.  適当な頻度度で評価ループを回す a.  テストデータで順伝搬関数を呼んで結果を記録 31
  32. 32. 新しい Function を⾃自分で定義する l  Function は Python で新しく作ることができる l  forward(_cpu/_gpu) と backward(_cpu/_gpu) を実装 する必要がある l  配列列のタプルを受け取って、配列列のタプルを返す l  Linkは内部でFunctionを呼んで作る 32
  33. 33. ⾃自作Functionの例例 class SquaredDiff(Function): def forward_cpu(self, inputs): x, y = inputs z = x – y return z * z, def backward_cpu(self, inputs, grad_outputs): x, y = inputs gz = grad_outputs gx = 2 * (x – y) * gz return gx, -gx 33 tupleを返す 勾配をtupleで返す
  34. 34. 新しい Function を⾃自分で定義する l  Function を書いたらテストしましょう l  とくに勾配チェック (gradient check) は必須 l  有限差分法で forward のみから計算した勾配が、backward で 計算した勾配と⼀一致するかを確かめる l  chainer.gradient_check.numerical_grad を使うと簡単 に書ける l  公式リポジトリの tests/chainer_tests/ function_tests にたくさん例例が書いてあります 34
  35. 35. CUDA サポート l  CuPy: 新しい CUDA 配列列実装 l  NumPy と同じようなインターフェイスで使える l  関数・メソッドのサブセットを実装 l  配列列のスライス、転置、reshape 等も⾃自由にできます l  カスタムカーネルも記述できる(elementwise, reduction) 35
  36. 36. CuPy を使う準備 l  まず CUDA が使える GPU を⽤用意する l  CUDA 6.5 以上をインストール l  Ubuntu なら公式に deb パッケージがお薦め l  パスを通す l  PATH と LD_LIBRARY_PATH を通す必要があります l  公式インストーラからはデフォルトで /usr/local/cuda にインストー ルされるので、以下のように設定 l  PATH=/usr/local/cuda/bin:$PATH l  LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH l  Chainer をインストールしたら  cupy モジュールを import してみて動くか確認 36
  37. 37. CuPy の使い⽅方 l  基本的に  numpy の代わりに  cupy を使う以外は   NumPy と⼀一緒 l  CPU/GPU の両⽅方で動く関数の書き⽅方 l  chainer.cuda.get_array_module() を使うと、引数に   cupy.ndarray があるかないかで  numpy / cupy のどちらかを返してく れます l  例例えば下は  NumPy と  CuPy の両⽅方で動く  logsumexp の実装例例(よ り省省メモリな実装を考えてみてください) def logsumexp(x, axis=None): xp = cuda.get_array_module(x) x_max = x.max(axis=axis) return x_max + xp.log(xp.exp(x – x_max).sum(axis=axis)) 37
  38. 38. Chainerをつかった⾃自然⾔言語処理理の例例
  39. 39. ⾃自然⾔言語処理理のサンプルは他数同梱されている l  word2vec l  Skip-gram/Continuous BoW l  Negative Sampling/Hierarchical Softmax l  Recurrent Neural Network l  Long-short term memory l  Gated recurrent unit l  Recursive Neural Network l  Neural Tensor Network 39
  40. 40. Recurrent Neural Network l  次の単語を次々に予測するモデル l  隠れ変数を更更新しながら予測に使う 40 x1 x2 x3 x4 h1 h2 h3 h4 y1 y2 y3 y4 h0 yi は xi+1 の予測
  41. 41. LSTM-RNN⾔言語モデル class RNNLM(chainer.Chain): def __init__(self, n_vocab, n_units, train=True): super(RNNLM, self).__init__( embed=L.EmbedID(n_vocab, n_units), l1=L.LSTM(n_units, n_units), l2=L.LSTM(n_units, n_units), l3=L.Linear(n_units, n_vocab)) self.train = train 41 埋め込みベクトル 2段のLSTM 出⼒力力
  42. 42. LSTM-RNN⾔言語モデル def reset_state(self): self.l1.reset_state() self.l2.reset_state() def __call__(self, x): h0 = self.embed(x) h1 = self.l1(F.dropout(h0, train=self.train)) h2 = self.l2(F.dropout(h1, train=self.train)) y = self.l3(F.dropout(h2, train=self.train)) return y 42 LSTMは前の時刻の隠れ状態を 保持している
  43. 43. LSTM-RNN⾔言語モデルを学習する for i in range(jump * n_epoch): x = chainer.Variable(...) t = chainer.Variable(...) loss_i = model(x, t) accum_loss += loss_i ... model.zerograds() accum_loss.backward() accum_loss.unchain_backward() # truncate accum_loss = 0 optimizer.update() 43 truncated BPTT
  44. 44. word2vec l  周囲の単語から中⼼心の単語を予測するモデル(CBoW) l  中⼼心の単語から周囲の単語を予測するモデル(Skip- gram) 44
  45. 45. word2vec class ContinuousBoW(chainer.Chain): def __init__(self, n_vocab, n_units, loss_func): super(ContinuousBoW, self).__init__( embed=F.EmbedID(n_vocab, args.unit), loss_func=loss_func) def __call__(self, x, context): h = None for c in context: e = self.embed(c) h = h + e if h is not None else e return self.loss_func(h, x) 45 コンテキストの平均を取って出 ⼒力力に投げるだけ 埋め込みベクトル
  46. 46. Recursive Neural Network l  事前に与えられた構造(普通は構⽂文⽊木)に沿って、再帰 的にベクトルを結合する l  Recurrent Netは直鎖に対するRecursive Netともとれる 46 x1 x2 p1 x3 p2 p1 = f(x1, x2) p2 = f(p1, x3)
  47. 47. Recursive Neural Network class RecursiveNet(chainer.Chain): def __init__(self, n_vocab, n_units): super(RecursiveNet, self).__init__( embed=L.EmbedID(n_vocab, n_units), l=L.Linear(n_units * 2, n_units), w=L.Linear(n_units, n_label)) def leaf(self, x): return self.embed(x) def node(self, left, right): return F.tanh(self.l(F.concat((left, right)))) 47 leafで埋め込み nodeで合成
  48. 48. Recursive Netで構⽂文⽊木をたどる def traverse(model, node): if isinstance(node['node'], int): # leaf node word = xp.array([node['node']], np.int32) loss = 0 x = chainer.Variable(word) v = model.leaf(x) else: # internal node left_node, right_node = node['node'] left_loss, left = traverse(model, left_node) right_loss, right = traverse(model, right_node) v = model.node(left, right) loss = left_loss + right_loss 48
  49. 49. 公式の Examples 公式リポジトリの examples ディレクトリにいくつか例例が あります l  mnist: MNIST を多層パーセプトロンで学習するもっと も基本のサンプル l  imagenet: ImageNet からの⼤大規模ConvNet学習 l  modelzoo: Caffe 公式モデルを読み込んでつかう l  ptb: Penn-Tree Bank から LSTM ⾔言語モデルを学習する l  無限⻑⾧長の⼊入⼒力力に対する Truncated BPTT の例例にもなっています l  word2vec: word2vec の実装と PTB からの学習 l  sentiment: Recursive Net を使った極性判定 49
  50. 50. まとめ l  ニューラルネットを(おもに実装⾯面から)簡単におさら いしました l  Chainer の使い⽅方をざっくりお伝えしました l  このチュートリアルをもとに、Chainer を使って⾃自然⾔言 語処理理でなにか作って公開、または論論⽂文発表していただ けると⼤大変うれしいです l  Chainer ⾃自体へのフィードバックもお待ちしております 50

×