Island Babies

いろんなことを書きます

ディープラーニングで映画レビュー分類

導入

買ったまましばらくさわれていなかった、PythonとKerasによるディープラーニング をやっていこうと思っています。
今の所そこそこわかりやすい感じがします。元が英語なのでそういう意味でのわかりづらさは多少ありますし、内容としても0から勉強するには少し向かないような気もしますが(特にそこそこ数学的な表現がたまに出てくる)、雰囲気をつかむのにはいいのかもしれないです。
今回の記事では3.4についての内容をまとめます。

タスクについて

今回考えるタスクは、映画レビューをポジティブなものとネガティブなものに分類するというタスクです。IMDbというデータセットが用意されていて、それについて教師あり学習を行って判定ができるようにします。

コード

データのロード

まず、データをロードします。

from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = \
    imdb.load_data(num_words=10000)

num_words = ... で出現頻度が高い順から10000番目までの語のみを残して、残りを捨ててしまいます。どれくらい出現するかによるとは思うのですが、ある程度出現頻度が低い単語は捨ててしまうというのはよく使えそうな手法ではあります。

このtrain_data中の一つ一つの要素(レビューの一つ一つ)は、例えば [1, 14, 22, ... 16, ..] という感じで、単語を表すインデックスからなるリストになっていて、imdbに用意されている単語とインデックスの対応関係を保持しているディクショナリを使うことでそれぞれのレビューを数字での表現から文字列での表現に戻すことができます。

このインデックスの値を用いて(整数だと思って)学習を行っていきます。直感的には、これはかなり素朴な方法であると言えると思います。なぜなら、このインデックス同士の関係には言葉同士の関係性はほとんど考慮されていないと考えられるためです。例えば単語の埋め込み表現なんかを使うと、単語同士の関係性も考慮したような計算が行えるのではないかと思っています(やったことはないけど)

データを整形

整数のリストはそのままニューラルネットには入力できないので、テンソルに変換する必要があります。変換する方針として2通りの方針があるようです。 * リストをパディングして全て同じ長さに揃え、(samples, word_indices) という形状のテンソルに変換する. * one-hot エンコーディングを用いて変換する. 今回はone-hot エンコーディングを用いて変換します。 例えば、[1, 3] という表現に対しては、[0, 1, 0, 1, 0, ..., 0]というベクトルが対応します。

ネットワークを定義

ネットワークを構築します。今回得たい出力はネガティブorポジティブの2値分類なので、[0,1]の範囲になるように出力層でシグモイド関数により変換を行います。入力は、語数が10000のone-hot エンコーディングされたベクトルなので、(10000,) とします。オプティマイザとしてrmspropを用いることとします。損失関数として、出力層でsoftmaxを使うときによく用いられる交差エントロピーを用います。

from keras import models
from keras import layers

model = models.Sequential()
model.add(layers.Dense(16, activation="relu", input_shape=(10000, )))
model.add(layers.Dense(16, activation="relu"))
model.add(layers.Dense(1, activation="sigmoid"))
model.compile(optimizer="rmsprop",
                          loss="binary_crossentropy",
                          metrics=["accuracy"])

あとは、学習データと確認用データに分けたりして学習を行うと良いです。
これだけでも88%くらいの精度が出ます。かなり良い精度が出ていると言えると思います。

感想

バイトでもDNNを使うのですが(主に物体検出のネットワーク)正直かなりコードを書くのが怪しいので、かなりゴリゴリ書いていかないといけないなと思った次第。。。