ディープラーニングで文書分類(1)

はじめに

前回前々回とSVM、ニューラルネットワークを使ったLivedoor Newsコーパス文書分類器を作成してきた。
今回からは、いよいよディープラーニングを使った文書分類器を作成してみたいと思う。ディープラーニングの中でも、畳み込みニューラルネットワーク (Convolutional Neural Networks: CNN) を使って、実装を行っていきたい。CNNと言うと、画像分類を思い浮かべる人が多いかと思われるが、最近はCNNを使った自然言語処理に関する研究も盛んになってきている。
まずは、文書分類に対してどのようにCNNを適用するのかを見ていきたい。
尚、CNN自体の説明は、ここでは行わない。

全体像

今回作成するモデルの全体像は、(いくらか省略はしているが)以下の図のようになる。
Livedoor Corpusの各文書をインプットに、畳み込み層(Convolution Layer)、プーリング層(Pooling Layer)と続き、9つのカテゴリーに分類する出力層へとつながっている。

入力層

これまで行ってきた分類問題では、インプットにBag of Wordsを利用してきた。これは、出現する単語全てを1つの袋に入れて、単語の出現回数を1つずつ数えるようなもので、文書のどの位置に単語が出現してきたのかは考慮されない。
それに対して、今回使うインプットは、以下の図のようになる。

行(縦)は、各文書の単語の並びだが、全文書で行数を合わせるために、最初の500単語で切っている。500単語に満たない文書の場合は、足りない部分を0でパディングしている。
列(横)は、以前作成した100次元のWord2Vecのモデルを利用する。
よって、500 x 100の行列がインプットとなる。

フィルタ

畳み込みを行う為のフィルタには、3単語、4単語、5単語の3種類を使うこととした。これにより、文書内に出てくる前後数単語を考慮した特徴量が抽出されることとなる。
またそれぞれの種類に対して128個のフィルタを使うので、合計384個のフィルタを利用することとなる。

畳み込み層

上述のインプットに対して、フィルタを1単語づつスライドさせながら掛け合わせることで畳み込みを行う。
また活性化関数にはReLU関数(ランプ関数)を使う。
結果、384個の特徴量が抽出できる。

プーリング層

畳み込み層で、それぞれのフィルタから計算された特徴量ベクトルからMax Poolingにより副次標本を取り、全ての副次標本をつなげて、ひとつのベクトルとする。

出力層

最後は、プーリング層の結果をインプットにソフトマックス関数を使って9つのカテゴリーに分類させる。

まとめ

今回は、Livedoor Corpusをカテゴリ分けする問題を、ディープラーニング(CNN)を使って行う方法について纏めてみた。
次回は、今回纏めた手法を、実際にTensorflowを用いて実装・テストを行っていきたい。

BoW+ニューラルネットワークで文書分類

はじめに

前回、SVMを使い、Livedoor Corpusのカテゴリ分類を行った。
今回は、シンプルな2層ニューラルネットワークを使って文書分類器を作成してみる。
実装は、Python3、TensorFlowを利用して行った。

データの準備

前回作成したBoWモデルを学習用データ、テスト用データとして利用するため、特にデータの準備は必要ない。
Livedoor Corpusの各文章は、300次元のベクトルになっており、正解ラベル(カテゴリ)が付与されている状態である。

今回作成するニューラルネットワークイメージ

以下のような隠れ層1層+出力層の2層ニューラルネットワークを使う。

隠れ層の活性化関数にはシグモイド関数を利用して、出力層にはソフトマックス関数を利用する。
入力(文書ベクトル)に対して、正しい正解(カテゴリー)が得られるように、Weight、Biasの値を学習していく。

TensorFlowでの実装

まずは各種変数の準備。

隠れ層の活性化関数にはシグモイド関数を使い、出力層はソフトマックス関数を使う。
それぞれTensorFlowに用意されている関数を利用する。

これで、予測カテゴリー(y)が求められ、実際のカテゴリー(y_)との差分がコスト(予測との乖離)となる。
このコストを最小化するような最適なWeight、Biasを学習させることで分類器ができあがる。
尚、ここでは、コスト関数に「y – y_」の二乗誤差ではなく、交差エントロピーを使う。
また、過学習を防ぐために、L2正則化も行っておく。

さて、後は、上記コスト関数を最適化するよう勾配下降法を使う。
TensorFlowで用意されているGradientDescentOptimizer関数を使えば良い。
尚、学習率は、当関数のパラメータとして渡す。
今回は、0.001とした。

最後に、正答率を計算する式も定義しておく。

これで準備はできたので、後は実際の学習用データを使ってトレーニングを行い、テストデータでの正解率を見てみる。

結果

ここまでの内容を実行してみたところ、トレーニングデータに対しては97%くらいの正解率が出るが、テストデータに対しては87%と、典型的な過学習の状態になっていた。
その後、正則化パラメータのlambdaや隠れ層の数などを調整して、最終的な結果としては以下の通りまずまずの結果となった。