数万件のレビューを学習させた人工知能を惑わせてみた

なかなか面白かったんで書いてみる。

やった事

某サイトから数万件のレビューのテキストデータをスクレイピングして人工知能に食わせ、「文章が好意的か否定的か」を学習させた。それに対して、自分が考えたテキストを与えて、人工知能の出力結果を惑わせてみた。

結果

例その1:

「価格の割に安っぽい作りでかなり不満です。買わなければよかったと後悔しています。このメーカーの商品は二度と買いません。しかし良く見ると価格の割には安っぽく見えないデザインと思えてきました。やっぱり買ってよかったと満足しています。このメーカーの商品をまた買いたいです。とても感謝しています。二度と買わねーよ馬鹿野郎!!」

上記の入力結果が以下になります。グラフが横長になってしまって見にくいので、やむなく縦にしました(強硬策)。赤いラインより右(0.5以上)ならば好意的と解釈していて、赤いラインより左側ならば否定的と解釈しています。判定は形態素解析した単語を入力するごとに行われます。

review1

おーおー、惑ってますね。ウケる。冒頭から否定的な文言が並んでいますが、なぜか好意的と解釈しています。結局「二度と買いません」のあたりで否定的に傾くものの、後半では一気に好意的に、しかし最後の「二度と買わねーよ馬鹿」のところで一気に下がってます。ちなみに、「野郎!!」が抜け落ちているのは、使用した辞書データ(のようなもの、正確には後述)に単語が無かったからです。

前段の「不満です」「後悔しています」あたりで顕著に下がるかと思いきやそうでないのはちょっと意外ですね。不満や後悔という単語はかなり否定的と思うのですが。まあ、ちゃんと学習できてないのもあるでしょう(GPUが無く時間がかかるので学習途中で打ち切ってる)。精度を上げるためには、学習データの品質も上げる必要がありそうです。

例その2:

予想していたよりもすごく便利でした。我が家では大型犬を二匹飼っていますが(名前はペスとボスです)、大型犬の体重をものともせず突き進んでいく姿には次女も驚愕していました。ちなみに次女ちゃんは、地元では有名な進学校に通っていて、全国模試でも上位に入る成績をおさめています。二度と買うか!!地獄へ落ちろ電気グルーヴ!!

レビューでよくある、突然自分語りが始まるパターンですね。金持ちの家のババアがこんな感じですね。親類の功績をあたかも勝手に自分の功績であるかのように認識し、聞かれても無いのに勝手に話し始めるババアです。こういうババアって何故か犬飼ってるんですよねー。だから私は犬のカッティングシートが張ってある車を見ると「おほほ、そうか、そうか」みたいな気持ちになるんですよねー。おほほ。そして最後は突然の電気グルーヴ。

例としては全然ふさわしくなく、もはや遊んでいる感じですがまあやってみましょう。

review2

「すごく便利でした」までは好意的な方に振れてますね。「我が家では大型犬」の下りで上昇はいったん止まっています。余計な話が始まったので、好意的とも否定的ともどちらにも解釈できなかったのでしょう。その通りです。その後、「名前はペスとボスです」の下りで一気に否定的な方向へ下降しています。なにかお気に召さなかったのでしょうか。やっぱり私が作った人工知能なので犬が嫌いなんでしょう。

その後、「体重をものともせず突き進んでいく」のあたりで再び好意的評価に傾いていきます。「あっ、一応大型犬の下りはは意味があるのね」と再評価したのかもしれません。一体何が突き進んでいくのかは触れずにおいておきましょう。

しかしながら、また次女ちゃんが進学校に通っているというあたりで判定は変化しなくなります。ここも蛇足と判断したのでしょう。その通りです。「全国模試で上位に入る」のあたりでは何故か否定的に傾きました。学歴コンプレックスがあるのでしょうか。

最終的には「地獄へ落ちろ電気グルーヴ!!」のあたりで一気に急上昇しています。これも人間には理解できないですが、人工知能もテクノが好きなんだなという解釈も出来ない事は無いです。嘘です。

解説

コードはDeepLearning4J(DL4J)で書きました。公式サンプルにあるコードほぼそのままです。食わせるデータだけ変えた感じです。

このサンプルはWord2Vecでベクトル化した単語をRNN(LSTM)の入力にして、文章の感情(好意的か否定的かの2クラス分類)を求めるというものです。

ちょっと手こずったところを書きますと、

  • DL4Jのバージョン0.4-rc3.10にはWord2Vecの結果を読み込むWordVectorSerializerにバグがあってArrayIndexOutOfBoundsExceptionがスローされる。これを使ってるdeeplearning4J-uiのビジュアライズツール(コサイン距離で近い単語を表示)もエラーが発生して使えない。数日前にリリースされた0.4.0を使う必要あり

  • 形態素解析ではMeCabを使ったが、Javaのラッパーは使うまでの設定がちょっと面倒くさそうだった。Scalaから使うのであれば、import scala.sys.process._して直接コマンドを叩き、標準入力&出力越しに解析してしまうのが手軽。

  • MultiLayerNetworkをシリアライズしてディスクに書き出し、DL4Jのバージョンを変更してから読みだそうとするとSerialViersionUIDが違うと怒られる。(当然なのだけど、時間をかけて育てたネットワークが使えなくなってしまうので注意)ウェイト&バイアスを手動で読み書きすれば復元できるかもしれない。

  • MeCabの辞書はデフォルトだとEUC-JPのものが入る。UTF-8にするには再コンパイルするか、Ubuntuだとmecab-ipadic-utf8パッケージをインストールすることでUTF-8の辞書が入る。

    って感じでしょうか。

    DL4J、手軽に動くんでなかなか面白いです。