テキストデータをCNNを用いて既定カテゴリに自動分類する実装のまとめ

目的

テキストデータをあるカテゴリに自動分類したい。 既存の手法を集めてみた。といっても論文からではなく、ブログ記事を参考に手法と結果をまとめてみた。

1. 全結合層が2つのシンプルなCNN

KerasのCNNを使って文書分類する  より。

keras/imdb_cnn.py at master · keras-team/keras · GitHub に沿って実装されている。

モデルの設計は

  • 埋め込み層
  • 畳み込み層
  • プーリング層
  • Flatten層
  • 全結合層
  • 全結合層

になっている。

  • MeCabで分かち書きしたテキストを
  • KerasのTokenizerを用いて
from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer()
tokenizer.fit_on_texts(tokenized_text_list)
seq = tokenizer.texts_to_sequences(tokenized_text_list)

単語のインデックス番号が並んだ配列に変換している。

さらに、CNNの入力は固定長でなくてはいけないので、

X = sequence.pad_sequences(seq, maxlen=400)

によってゼロパディングしている。固定長は400としている。

埋め込み層

max_features = 5000
embedding_dims = 50
maxlen = 400
model.add(Embedding(max_features,embedding_dims, input_length=maxlen,dropout=0.2))

畳み込み層

model.add(Convolution1D(
                            nb_filter=nb_filter,
                            filter_length=filter_length,
                            border_mode='valid',
                            activation='relu',
                            subsample_length=1))

border_mode=valid を指定しているので、パディングを行っていない。(すでに入力がpad_sequencesでパディングされている前提だから)

プーリング層

model.add(MaxPooling1D(
  pool_length=model.output_shape[1]
))
  • pool_length: プーリングする領域のサイズ。

Convolution1Dなので対応してMaxPooling1D

Flatten層

全結合層に渡す前に入力を1次元にする。

二重の全結合層

    hidden_dims = 250
    model.add(Dense(hidden_dims))
    model.add(Dropout(0.2))
    model.add(Activation('relu'))

250の隠れ層、20%ドロップアウトを用いている。

 model.add(Dense(1))
 model.add(Activation('sigmoid'))
 model.compile(
                  loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])
  • Adam

Adaptive Moment Estimationの略で、それぞれのパラメータに対して学習率を計算し適応させていく手法. 

  • シグモイド関数

学習

39エポックめで86%程度。

2. シンプルなCNN

けんごさんのブログ より。

  • 入力層
  • 埋め込み層
  • 畳み込み層
  • プーリング層
  • 全結合層
  • 出力層

入力

MeCabで分かち書きし、辞書を作成して、単語IDの配列で一つの文章を置き換える。

ニューラルネットワークへの入力は固定長である必要があるため、 学習用データの中で最も長い配列の長さに合わせてパディングする。

パディングはテキストの最後に任意の文中に存在しない単語を入れることにする。

[  1  2  3  4  5  6  7  8  0  0 0 0 0 ]
[  1  2  9 10 11 12 13 14 15 16 8 0 0 ]
[ 17 18 19  4 20 21 22 23 10  5 6 7 8 ] 
# 0がパディングのために用いられた単語のID。

上記のような配列が入力データとなっている。

埋め込み層 (Embedding Layer)

TensorFlow の embedding_lookup を使った実装を行なっている。

畳み込み層

  • 高さ3、幅が埋め込み表現の次元数×3
  • 高さ4、埋め込み表現の次元数×4
  • 高さ5、埋め込み表現の次元数×5

というサイズの、

それぞれ128 個のフィルタを使って、合計して 384 個のフィルタを学習させている。

プーリング層

スライドなし、1つのフィルタ全体に適用。 最大値プーリング。

全結合層

50%ドロップアウト。損失関数は公差エントロピー。

学習

各エポック内で学習データをミニバッチの数だけランダムに取り出して、それを最適化器に渡して学習を進める。 ミニバッチ数64。 13万件のデータで80%程度の精度。

3. キャラクターレベルCNN

文字レベルの畳込みニューラルネットワークによる文書分類 - 自然言語処理の深遠

全9層のネットワーク。

  • 1層の畳み込み層
  • プーリング層
  • 5層の畳み込み層
  • プーリング層
  • Flatten層
  • 3層の全結合層

畳み込み層

    Conv1D(nb_filter, kernel_sizes[0], activation='relu')

プーリング層

MaxPool1D(pool_size=3)

畳み込み層2~6(i)

Conv1D(nb_filter, kernel_sizes[i], activation='relu')

を繰り返す

プーリング層

MaxPool1D(pool_size=3)

Flatten層

Flatten()

3重の全結合層

Dense(dense_units[0], activation='relu')
Dropout(keep_prob)
Dense(dense_units[1], activation='relu')
Dropout(keep_prob)
Dense(nb_class, activation='softmax')

学習

Yelpのデータセットで、3エポックめで95%が出ている。