Share
Embed
Transcript
50 slides
-
⾃自⼰己紹介 海野 裕也 l -2008 東⼤大情報理理⼯工修⼠士 l ⾃自然⾔言語処理理 l 2008-2011
⽇日本アイ・ビー・エム(株)東京基礎研 l テキストマイニング、⾃自然⾔言語処理理の研究開発 l 2011- (株)プリファードインフラストラクチャー l ⾃自然⾔言語処理理、情報検索索、機械学習、テキストマイニングなど の研究開発 l 研究開発系案件、コンサルティング l JubatusやChainerの開発 NLP若若⼿手の会共同委員⻑⾧長(2014-) 「オンライン機械学習」(2015, 講談社) 2 -
今⽇日のおはなし l Chainer の使い⽅方を紹介します l Deep Learning のおさらいも簡単にしますが、学術 的な詳細は既存の⽂文献を参考にしてください l
CUDA サポートについても解説しますが、CUDA の 詳細は NVIDIA のドキュメントを参照してください l ⾃自然⾔言語処理理への応⽤用⽅方法を紹介します l Recurrent Net などのよく知られた結果を Chainer で実装する⽅方法を紹介します 4 -
計算グラフの例例 z = x ** 2 + 2 * x
* y + y 9 x y _ ** 2 2 * _ _ * _ _ + _ z _ + _ -
機械学習の例例:分類学習の⽬目的関数 11 argminw ∑(x, y) l(x, y; w) l xは⼊入⼒力力ベクトル、yは予測ラベル
l l(x, y)は予測が正しければ⼩小さく、間違えれば⼤大 きくなる値(損失関数) l 上記関数を最⼩小化するパラメータwを求めたい -
機械学習の例例:分類学習のアルゴリズム l ⽬目的関数をパラメータwで微分した値(勾配) を計算する⽅方法を⽤用意する l wを勾配の⽅方向に少しだけ動かす、を繰り返す l 実際は更更新⽅方向の取り⽅方に⼯工夫が他数ある 12 initialize
w until converge: w := w - η d/dw L(x, y; w) 最急降降下法 -
誤差逆伝播(後退型⾃自動微分) 合成関数の微分を計算するには連鎖律律 (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) 各関数の微分がわかれば機械的に計算できる -
ニューラルネットの学習⽅方法 1. ⽬目的関数の設計 l 計算グラフを⾃自分で設計する 2. 勾配の計算 l 誤差逆伝播で機械的に計算できる 3.
最⼩小化のための反復復計算 l 勾配を使って反復復更更新する 15 1さえ設計すれば残りは ほぼ⾃自動化されている -
Recurrent Net l ループがあるニューラルネット l 時刻の概念念があり、t=T の状態は t=T-1 の状態と t=T
の⼊入 ⼒力力を使って求める 16 T T-1 T -
Recurrent Net は時間展開して考える l 時間展開すれば、DAG の計算グラフになる l DAG の計算グラフは誤差逆伝播できる(Backprop Through
Time) 17 t=1 t=2 t=3 t=4 -
Chainer はニューラルネットのフレームワーク l 機能 l ニューラルネットを記述する l ニューラルネットの順伝播・逆伝播を実⾏行行する l 勾配法を実⾏行行してパラメータを最適化する
l Chainer の特徴 l 順伝播は単純に Python のスクリプトとして書ける l そのスクリプトの実⾏行行結果は計算⼿手順を記憶してい て、逆伝播を⼿手で書く必要はない 20 -
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 -
順伝播 l 今まで「変数」と呼んでいたものは、Chainer では Variable オブジェクト l Variable を Function
に⼊入れると、順伝搬後の Variable が返ってくる l Variable が計算グラフを保持している l Function は、四則演算以外に chainer.functions に⽤用意されている 22 -
順伝搬とコード例例 23 x y _**2 2*_ _*_ _+_ z _+_
x = Varaible(...) y = Variable(...) z = x ** 2 + 2 * x * y + y -
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 -
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 -
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~ -
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~ -
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 -
Optimizer による最適化 l まず勾配をゼロ初期化:zerograds() l 順伝播・逆伝播を実⾏行行 l 最適化ルーチンを実⾏行行:update() l 以上を何回も繰り返す
model.zerograds() loss = ... loss.backward() optimizer.update() 30 -
Chainer を使う場合の全体の流流れ 1. Linkを使ってChainを定義する 2. Optimizer に、Chain を設定する 3. forward
関数を定義する 4. データセットを読み込み、訓練⽤用と評価⽤用にわける 5. 訓練ループを回す a. 勾配をゼロ初期化 b. 順伝搬して、得られたロス値の backward メソッドを呼ぶ c. Optimizerを、update 6. 適当な頻度度で評価ループを回す a. テストデータで順伝搬関数を呼んで結果を記録 31 -
新しい Function を⾃自分で定義する l Function は Python で新しく作ることができる l forward(_cpu/_gpu)
と backward(_cpu/_gpu) を実装 する必要がある l 配列列のタプルを受け取って、配列列のタプルを返す l Linkは内部でFunctionを呼んで作る 32 -
⾃自作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で返す -
新しい Function を⾃自分で定義する l Function を書いたらテストしましょう l とくに勾配チェック (gradient check)
は必須 l 有限差分法で forward のみから計算した勾配が、backward で 計算した勾配と⼀一致するかを確かめる l chainer.gradient_check.numerical_grad を使うと簡単 に書ける l 公式リポジトリの tests/chainer_tests/ function_tests にたくさん例例が書いてあります 34 -
CUDA サポート l CuPy: 新しい CUDA 配列列実装 l NumPy と同じようなインターフェイスで使える
l 関数・メソッドのサブセットを実装 l 配列列のスライス、転置、reshape 等も⾃自由にできます l カスタムカーネルも記述できる(elementwise, reduction) 35 -
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 -
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 -
⾃自然⾔言語処理理のサンプルは他数同梱されている 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 -
Recurrent Neural Network l 次の単語を次々に予測するモデル l 隠れ変数を更更新しながら予測に使う 40 x 1
x 2 x 3 x 4 h 1 h 2 h 3 h 4 y 1 y 2 y 3 y 4 h 0 y i は x i+1 の予測 -
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 出⼒力力 -
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は前の時刻の隠れ状態を 保持している -
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 -
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 コンテキストの平均を取って出 ⼒力力に投げるだけ 埋め込みベクトル -
Recursive Neural Network l 事前に与えられた構造(普通は構⽂文⽊木)に沿って、再帰 的にベクトルを結合する l Recurrent Netは直鎖に対するRecursive Netともとれる
46 x 1 x 2 p 1 x 3 p 2 p1 = f(x1, x2) p2 = f(p1, x3) -
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で合成 -
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 -
公式の 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 -
まとめ l ニューラルネットを(おもに実装⾯面から)簡単におさら いしました l Chainer の使い⽅方をざっくりお伝えしました l このチュートリアルをもとに、Chainer を使って⾃自然⾔言
語処理理でなにか作って公開、または論論⽂文発表していただ けると⼤大変うれしいです l Chainer ⾃自体へのフィードバックもお待ちしております 50