機械学習でテキスト分類をできないかと調べたところ、2種類の手法が提案されていました。
前者の手法は既にTensorFlowによる実装があったのと、直接Chainerで記述できなかった(covolution_2dではx軸固定の畳み込みができない)ので、後者を実装してみました。
追記
この記事を書いた当時はフィルタの幅と入力行列の幅を同じにしたとき、0除算例外が出てしまっていたのですが、今は問題なくできるようになっていました。自分が試した頃は確かversion 1.6あたりだったと思います。
ChainerによるCNN実装例がQiitaにもあります。
こちらの実装では、単語埋め込み表現をword2vecで既に学習させたものを利用していますが、links.EmbedIDを用いて単語埋め込み表現を同時に学習することもできます。
分類に用いる特徴量としては、こちらの方が多いので性能はより高いのではないかと思います(未検証)。
使い方
データセットを用意します。https://github.com/knok/rcnn-text-classification/blob/master/data.txt のようなCSVで1行ごとに本文,(ラベル番号)を記述してください。
出来上がったデータを用いて訓練をします。
$ python train.py train data.txt
訓練が終わったら、評価してみてください。
$ python train.py eval '今日はいい天気'
[[ 4.75943899 -5.7807641 ]]
hyp: 0
$ python train.py eval '帰りたい'
[[-5.44445753 6.04835653]]
hyp: 1
コードについて
もともとはseq2seqで対話モデルを作ろうとしていて、データをTwitterから収集していたのですが、その時に訓練データとして適切・不適切なものを機械的にやりたいという目的で実装しました。なので、単語単位ではなく文字単位で処理をしています。それでも、だいたい望むような結果は得られています。
適当に書いたので、今のところミニバッチに対応していません。また、max poolingにchainer.function.maximumを使っているため、chainer 1.9.0以降が必要です。小さな関数なので、それ以前のバージョンのchainerでもhttps://github.com/pfnet/chainer/blob/v1.9.0/chainer/functions/math/maximum.py からコードを拝借すれば動くと思います。
元論文
Recurrent convolutional neural networks for text classification
Siwei Lai, Liheng Xu, Kang Liu, Jun Zhao, Chinese Academy of Sciences, China
AAAI. 2015.
blog