機械学習・自然言語処理の勉強メモ

学んだことのメモやまとめ

PyTorch:LSTMの基礎

はじめに



今回はNLPでよく使われるLSTMネットワークについて整理する。
自分で各ゲートのパラメータを記述したTheanoに比べると簡単。
下記のTutorialのコードを説明しながらLSTMの書き方について理解していく。
Sequence Models and Long-Short Term Memory Networks — PyTorch Tutorials 0.3.0.post4 documentation
今回はコードを日本語で説明しただけの備忘録的なもの。

Embedding



まずは、文章のEmbedding。
これは以下のようにnn.Embeddingで簡単に実現できる。

import torch
import torch.autograd as autograd
import torch.nn as nn

torch.manual_seed(1)
sent_idx = [1, 3, 2, 5, 3]
vocab_size = 10
emb_dim = 5
embeds = nn.Embedding(vocab_size, emb_dim)
lookup_tensor = torch.LongTensor(sent_idx)
word_embed = embeds(autograd.Variable(lookup_tensor))
print(word_embed)
Variable containing:
-0.1661 -1.5228  0.3817 -1.0276 -0.5631
 0.2673 -0.4212 -0.5107 -1.5727 -0.1232
-0.8923 -0.0583 -0.1955 -0.9656  0.4224
-0.4791  1.3790  2.5286  0.4107 -0.9880
 0.2673 -0.4212 -0.5107 -1.5727 -0.1232
[torch.FloatTensor of size 5x5]

文章単位で処理する場合、ベクトル→行列となる。
文章のEmbeddingは、以下のイメージ。
f:id:kento1109:20180302152212p:plain:h200

Tutorialでは、ネットワーク構築部で以下のようにしてEmbeddingしている。

self.word_embeddings = nn.Embedding(vocab_size, embedding_dim)

文章をバッチ化して処理する場合、行列→テンソルとなるが、内容は同じ。
今回は文章単位で処理するとして進めていく。

LSTM



Embeddingの行ベクトルが系列ごとにLSTM層に渡る。
イメージはこんな感じ。
f:id:kento1109:20180302154302p:plain:h200

nn.LSTMのユニットは、入力・出力・忘却ゲートとメモリセルからなるので、実際は下記のような「隠れ層 ×(Embedding×4)」の重み行列で計算が展開される。
f:id:kento1109:20180302154706p:plain:h300

self.lstm = nn.LSTM(embedding_dim, hidden_dim)

線形変換



LSTM層の出力は「系列×隠れ層」の行列。
これを「系列×出力ラベル数」の行列に変換する。
※書くほどでも無いがこんな変換を行う。
f:id:kento1109:20180302162208p:plain:h300

self.hidden2tag = nn.Linear(hidden_dim, tagset_size)

ここからは他と同じなので割愛する。