Help us understand the problem. What is going on with this article?

Kerasで可変長系列をEmbeddingしてLSTMに入力するときはmask_zero=Trueにする

KerasのLSTMに文章を入力して何らかの評価値を出力する場合、よく次のような流れで処理すると思います。

  1. 文章を形態素解析器で単語に分割
  2. 単語系列の系列長を揃える
  3. 単語ベクトルでEmbedding
  4. LSTMに入力
  5. 評価値を出力

「系列長を揃える」というのは、具体的には長すぎる系列を切断したり短すぎる系列をゼロパディングしたりします。

さて、これで問題なく学習できるかと思いきや、学習後にどんな文章を入力しても同じ評価値しか出力しないという状況に陥ってしまいました。

実はこのままだとゼロパディングした部分を0の系列として扱うため、うまく学習できなくなるケースがあるようです。
Embeddingレイヤーmask_zero=Trueにすると、ゼロパディングした部分を無視(?)してくれるようです。

  • mask_zero: 真理値.入力の0をパディングのための特別値として扱うかどうか. これは入力の系列長が可変長となりうる変数を入力にもつRecurrentレイヤーに対して有効です. この引数がTrueのとき,以降のレイヤーは全てこのマスクをサポートする必要があり, そうしなければ,例外が起きます. mask_zeroがTrueのとき,index 0は語彙の中で使えません(input_dim は語彙数+1と等しくなるべきです).

プログラムは次のようになります。

# 文章を形態素解析器で単語に分割
import MeCab
tagger = MeCab.Tagger('-Owakati')
texts = [tagger.parse(x).rstrip() for x in texts]

# 単語をインデックスに変換
from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)

# 単語系列の系列長を揃える
from keras.preprocessing.sequence import pad_sequences
maxlen = 8000
X = pad_sequences(sequences, maxlen=maxlen)
print(X.shape) # (2000, 8000)

# embedding_matrixを作成
embedding_matrix = np.zeros((max(tokenizer.word_index.values())+1, word2vec.vector_size))
for word, i in tokenizer.word_index.items():
    if word in wv:
        embedding_matrix[i] = word2vec.wv[word]

# Embedding&LSTM
main_input = Input(shape=(x.shape[1],), name='main_input')
embedding1 = Embedding(
        input_dim=embedding_matrix.shape[0], 
        output_dim=embedding_matrix.shape[1], 
        weights=[embedding_matrix], 
        trainable=False, 
        mask_zero=True, 
        name='embedding1')(main_input)
lstm1 = LSTM(32, name='lstm1')(embedding1)
main_output = Dense(8, name='main_output')(lstm1)
model = Model(inputs=main_input, outputs=main_output)
model.compile(loss='mse', optimizer='adam')

無題.png

embedding_matrixはインデックスをキーとする単語ベクトルの辞書です。
mask_zeroの説明に「index 0は語彙の中で使えません」とあるので、1から開始するようにします。

このようにすると、文章ごとに異なる評価値を出力するようになりました。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away