にほんごのれんしゅう

日本語として伝えるための訓練を兼ねたテクログ

Seq2Seqで小説自動生成の学習を失敗した話

Seq2Seqで小説自動生成の学習を失敗した話

  • 失敗した経験をネット上に上げることにいくつか意見があるでしょうが、機械学習を行って、学習が失敗すると、大きな時間的な損失になるよという見地を示す目的があります。
  • 小説の自動生成では、ディープラーニングを実用に移した例では、韓国資本の会社がRNNモデルを利用して、VOYAGERなる小説(アプリ?)を公開するに至りました。考え方としては、Seq2Seqによる文章作成はこれに該当すると思われます[1]。

Seq2Seqとは

f:id:catindog:20160823133458p:plain

                                                             図.1
 この図は、inputを文字のシーケンシャルな列としたとき、アプトプットをシーケンシャルな文字の列とすることです。
 ユニークなのは、図の”I”という出力を次のインプットとすることで、”am”という最尤度を持つ文字を取り出していることです。さらに次の出力をインプットとすることで文字列を作り出すということを行っています。
 基幹技術としてLong short-term memoryが大きく関与しており、Long short-term memoryの詳細な解説は別の文献を参考にしていただければ幸いです。

機械翻訳装置としてのSeq2Seq

 非常に高い翻訳を行うとして有名な、Seq2Seqですが、GoogleのTensorFlowのサンプルコードに英語-フランス語翻訳のプログラムが収録されています[2]。英語-フランス語の巨大な対応するニュース記事のコーパスで英語とフランス語の対応する文字を学ぶことで、翻訳してしまおうという発想です。

Who is a preident of US? -> Qui est un président des Etats-Unis ?

 翻訳の成績も大変良いらしく、既存のルールベースの翻訳方法とは一線を画す存在です[3]。

チャットボットとして利用するSeq2Seq

 インターネットが繋がらない、VPNが繋がらないなどのヘルプデスクの対応ログをとって、チャットボットを作った例がGoogleで例示されました[4]。会話の質問と答えの対応ログを学んだものです。人間による評価で"人らしい"とする既存手法のいかなるものよりも高いスコアを出しています。

 映画のシナリオを学習させる場合ではSF映画のエイリアンのような応答を返すので、"人間らしい"とは言い切れない部分がありますが。
 様々なヘルプデスクで人工知能が応用されている(されようとしている)のです。短いテキストでの簡単な対話は、Seq2Seqで学習しやすそうではあります。

小説の構造の仮説

 小説の文字列とはいったい何なのでしょうか。真面目に考えるとちょっとエモいことを言いそうになるのですが、今回はエモいことはなしです。
 小説のある分は、前の文と次の文に時系列、もしくは、意味的に強い関連があるのではないか、と仮定しました。

 [N-1の文] -> [Nの文] -> [N+1の文]

 ※Nはある文のシーケンシャルな番号; ->は強い関連を表す

 非常に視野の狭い考え方ではありますが、この仮定で文脈が決定されているとしたら、わかりやすいことこの上ないです。

 もっと遠いところの文の関連があったりして、なかなか法則性はないのが実態ではありました。
 
 この仮説が正しいとすると、ちゃんと学習したモデルがあれば、初期値さえ与えてあげれば、結果を次の入力にすることで、にょろにょろと文章を作成するはずです。Character-levelのRNNにフィーチャーされた考え方です。

実験で使った学習するデータ

 小説家になろうの「人狼への転生、魔王の副官」というコンテンツで学習を行いました。なろうの運営会社様、作者様、引用させていただきます。
 最初に記述しておきますが、これは失敗した例なので、このままやるとたぶん変なところに収束してしまいます。
 小説を改行を区切り句にして、リストに変換します。変換したリストを、二つのペアにさらに変換し、以下のような構造に変換します。

 [N番目] 俺 は 森 の 奥 から 、 丘 の 下 に ある 街 を 見下ろし た 。
 [N+1番目] 傍ら に 控える 犬 人 族 の 伝令 たち が 、 新た な 報告 を 行う

 [N番目]と[N+1番目]は連続したデータです。[N番目]を入力として、[N+1番目]を正解データとして一連の学習データを作りました。
 これを該当作品のデータを全取得して、全体のコンテンツの4/5を学習データに、1/5をDevelopmentデータにしました。後から気づいたのですが、この学習データの振り分けがいけなかったのかなと。

学習に適応した日数

 GPUマシンで丸三日ほど回したという[5]記事をみて、CPUマシンですが、三日間回し続けました。
 使用したプログラムのコードは、以下のgithubのコードを日本語に対応するように改造したものです。

github.com

変なところに収束した

 混乱度(パープレキティ)が、100以下になかなか下がらなかった(この時点でヤバい方向に行っていると気付くべきでした)ので、回し続けた結果、明らかに収束に失敗しただろうデータが出てきてしまいました(´;ω;`)。

 INPUTが文字の入力で、ANSがこのモデルが出力です。

INPUT:>   同席 し て いる 竜 人 族 の クルツェ 技官 が 、 そんな アイリア に 質問 し た 。
ANS:>   俺 は は は を を を 。
INPUT:> 「 以前 から 疑問 だっ た の です が 、 なぜ 魔王 陛下 に 比肩 し うる ほど の 英雄 が 、 『 勇 王 』 で は なく 『 勇者 』 な の です か ? 」
ANS:>   俺 は は 。
INPUT:> 「 ああ 、 俺 が 答えよ う 」
ANS:> 「 骸骨 、 」

 結果、"俺はははは"ばっかりになりました。どんなだけ自意識強いんですか。
 でも、確かに多くの場合において文頭は"俺は"から始まるので、理解できる結果ではあります。これ以上深く、収束ができなかったので、下手に文字を追加するより、短い文章の方が誤差がすくないから、短い単語のような文章になってしまったのでしょう。

改善案

  • Developmentのデータを学習データで用いたものを適切に混ぜ合わせたデータを使い、可能な限り正しく学習させる。
  • あまりに重いので、レイヤーなどを削減してみて、より素早い学習を行う。
  • 前提としていた、前の文が次の文に対して強い相関を持つということはないかもしれない、ということを受けいれる。
  • 国語が苦手だったので、日本語を分析的にみるという視点がなく、ほんとどうしようもない。

参考文献

[1] http://www.metaps.com/press/ja/315-ai-nasa
[2] https://www.tensorflow.org/versions/r0.10/tutorials/seq2seq/index.html
[3] http://qiita.com/yoh_okuno/items/50e7dccfb6ebfa8a7238
[4] http://wired.jp/2015/07/12/chatbot-debates-meaning-life/
[5] http://qiita.com/yoh_okuno/items/50e7dccfb6ebfa8a7238