自然言語処理の深遠

Deep Dive Into Natural Language Processing

gensimを使ってKerasのEmbedding層を取得する

2017/06/21にリリースされた gensim 2.2.0 から Keras との統合機能が導入されました。 具体的には、Word2vec の Keras 用ラッパが導入されました。 これにより、gensim で分散表現を学習した後に、その重みを初期値として設定した Keras の Embedding層を取得できるようになりました。

本記事では、実際に gensim の Keras 統合機能を試してどのようなものなのか確認してみたいと思います。

実装

今回は、Word2vec の Keras 用ラッパーを使って、モデルを実装していきたいと思います。 具体的には 20NewsGroupsデータセットを用いて文書分類タスクに使用する例を示します。 以下の手順で実装していきます。

  • 必要なライブラリのインストール
  • Word2vec の学習と Embedding層の取得
  • モデルの構築

インストール

まずはじめに必要なライブラリをインストールします。 必要なライブラリは以下の通りです。

  • gensim 2.3.0
  • scikit-learn 0.19.0
  • Keras 2.0.8
  • TensorFlow 1.3.0

scikit-learn は 20NewsGroupsデータセットをダウンロードするために使用します。 以上のライブラリは、pip を使って以下のようにインストールします。

$ pip install gensim scikit-learn keras tensorflow

Embedding層の取得

ではまずは、gensim を使って Embedding層を取得してみましょう。 Embedding層の取得手順は以下の通りです。

  • gensim で Word2vec モデルを学習
  • get_embedding_layer メソッドを用いて Embedding層を取得

まずは必要なモジュールをインポートします。

from gensim.models import word2vec
from sklearn.datasets import fetch_20newsgroups

次に、20NewsGroups データセットの取得と、整形を行います。 今回は 20NewsGroups のヘッダ情報は用いないので、取り除いてしまいます。

twenty_train = fetch_20newsgroups(subset='train')
labels = twenty_train.target
texts = []
for doc in twenty_train.data:
    i = doc.find('\n\n')  # skip header
    texts.append(doc[i:])

データが用意できたら、Word2vec のモデルを学習します。

w2v = word2vec.Word2Vec(min_count=1)
w2v.build_vocab([doc.split(' ') for doc in texts])
w2v.train(texts, total_examples=w2v.corpus_count, epochs=w2v.iter)

学習が終わったら、get_embedding_layerメソッドを用いて、Keras の Embedding層を取得します。

embedding_layer = w2v.wv.get_embedding_layer(train_embeddings=True)

get_embedding_layer には train_embeddings という名前の引数があります。 train_embeddings を True にすることで、モデルの学習中に Embedding層を学習します。 False だと学習は行いません。

ここまでで、Embedding層を用意することができました。 ここからは通常通りに Keras のモデルを構築していきます。

モデルの構築

それではモデルを構築しましょう。 以下のようなモデルを構築していきます。

Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 1000)              0         
_________________________________________________________________
embedding_1 (Embedding)      (None, 1000, 100)         39639900  
_________________________________________________________________
lstm_1 (LSTM)                (None, 128)               117248    
_________________________________________________________________
dense_1 (Dense)              (None, 20)                2580      
=================================================================

まずは必要なモジュールのインポートとハイパーパラメータの設定をします。

from keras.models import Model
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils.np_utils import to_categorical
from keras.layers import Dense, Input, LSTM

MAX_SEQUENCE_LENGTH = 1000

次に学習用データセットを準備します。 Keras の Tokenizer を用いて、単語列を単語ID列に変換し、パディングしてしまいます。

tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
x_train = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
y_train = to_categorical(labels)

あとはモデルを構築して、学習するだけです。Embedding層として、先程 gensim で取得したものを用いていることに注意してください。

sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
x = LSTM(128, dropout=0.2, recurrent_dropout=0.2)(embedded_sequences)
preds = Dense(y_train.shape[1], activation='softmax')(x)
model = Model(sequence_input, preds)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
model.fit(x_train, y_train, epochs=10)

以上で使い方の説明は終わりです。

おわりに

今回は、Word2vec の Keras 用ラッパーを使って、モデルを実装してみました。 使ってみた感想としては、実際に使うにはまだまだ洗練されていないのかなという感じがします。 特に、ドキュメントが充実していないことや、事前学習モデルを読み込んで使えるのかといったところに課題があるように感じました。

今後の発展に期待です。

参考資料