28
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

ChainerでLSTMを使う (NStepLSTM, NStepBiLSTM)

ChainerでLSTMを使いたい方向けに簡単に使い方を書きます。

入力形式

import numpy as np
from chainer import Variable
import chainer.functions as F
import chainer.links as L

# 入力データの準備
x_list = [[0, 1, 2, 3], [4, 5, 6], [7, 8]] # 可変長データ (4, 3, 2)の長さのデータとする
x_list = [np.array(x, dtype=np.int32) for x in x_list] # numpyに変換する

上記のデータはバッチサイズ3, 長さがそれぞれ4,3,2のデータです。

Word Embeddings

n_vocab = 500
emb_dim = 100
word_embed=L.EmbedID(n_vocab, emb_dim, ignore_label=-1)

NStepLSTM, NStepBiLSTM

use_dropout = 0.25
in_size = 100
hidden_size = 200
n_layers = 1

bi_lstm=L.NStepBiLSTM(n_layers=n_layers, in_size=in_size,
                      out_size=hidden_size, dropout=use_dropout)

単方向の場合はNStepLSTM, 双方向LSTMの場合はNStepBiLSTMを使いましょう。
NStepBiLSTMの場合はhidden_sizeの2倍のベクトルがconcatされたベクトルが返ってきます。

LSTMに入力データを渡す

NStepLSTM, NStepBiLSTMへの入力はVariableのリストです。
この例だと[(4, 100), (3, 100), (2, 100)]というshapeをそれぞれ持つVariableのリストを渡しています。

# Noneを渡すとゼロベクトルを用意してくれます. Encoder-DecoderのDecoderの時は初期ベクトルhxを渡すことが多いです.
hx = None 
cx = None 

xs_f = []
for i, x in enumerate(x_list):
    x = word_embed(Variable(x)) # Word IndexからWord Embeddingに変換
    x = F.dropout(x, ratio=use_dropout) 
    xs_f.append(x)

# xs_fのサイズは
# [(4, 100), (3, 100), (2, 100)]というVariableのリストになっている

hy, cy, ys = bi_lstm(hx=hx, cx=cx, xs=xs_f)

ysがNStepBiLSTMの最終層のベクトルの各ステップのベクトルが返ってきます。

出力

ys

for h in ys:
    print h.data.shape

#     # print ys
#     [<variable at 0x10996f990>, <variable at 0x10996fa50>, <variable at 0x10996fb90>]
#     (4, 400)
#     (3, 400)
#     (2, 400)

ysはリストのVariableが返ってきます。
中身は各timestepのhidden vectorが入っています。
Bi-LSTMの場合の場合は双方向のLSTMのconcatが入っています。
POS TaggingやNERなどのタスクの場合各タイムステップのベクトルに対して適切なタグを予測するように学習させていきます。

※ n_layers = 2と多層にした場合も ysは

#     # print ys
#     [<variable at 0x10996f990>, <variable at 0x10996fa50>, <variable at 0x10996fb90>]
#     (4, 400)
#     (3, 400)
#     (2, 400)

です。つまり最後の層の全てのtimestepのhidden vectorが返ってきます。

hy

print(hy.shape)
# (2, 3, 200)

hyはVarialbeが返ってきます。
BiLSTMの場合は (2 * n_layers, batchsize, hidden_size)が返ってきて,
単方向LSTMの場合は (1 * n_layers, batchsize, hidden_size)が返ってきます。

これは最後のtimestepのhidden vectorが返ってきます.
BiLSTMの場合はforward-LSTMの最後のtimestep (t=T)のベクトルとbackward-LSTMの最後のtimestep (t=0)のベクトルがconcatされて返ってきます。

最後のtimestepのみ必要な場合はhy,
全てのtimestepが必要な場合はysを使うと良いと思います。

※多層の場合, 例えば n_layers=3で単方向LSTMの時 hyは (3, batchsize, hidden_size) のshapeになっているので注意が必要です。

質問や間違い訂正などは @aonotas までお願いします。

NStepLSTM, NStepBiLSTMの部分を
NStepRNN, NStepGRUに置き換えるとRNN, GRUが使えるようになっています。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
28
Help us understand the problem. What are the problem?