10万件の飲食店クチコミからRNNで文章を生成

深層学習による自動的な文章生成を目的として、リカレントニューラルネットワーク(以下RNN)の一種であるGated Recurrent Unit(以下GRU)を試してみました。まず、実際の生成結果をお見せします。

>今日はちょっとかわっている数で楽しみます。おまけに流れたところに、もんくの人はなかとかがわしている人が多いですね。テーブルにあんないされた二人。店内のメニューは、サラダ、ハイボール、ドリンク、テーブル、

文章全体としてはほとんど意味を成していませんが、部分的には自然な日本語表現が現れてきています。

自然言語処理はいろいろな未解決タスクがありますが、言語現象の潜在的な特徴を見つけ出すのは深層学習の得意とするところなのではないでしょうか。

##学習モデル
深層学習ライブラリであるPyTorch[1]を利用することで、LSTMやGRUなどの既存のネットワーク構造を利用することができます。これらは単純なRNNで問題となる勾配消失や勾配爆発などの問題を軽減できるという特徴があります。RNNは数々のタスクへ応用することができますが、ここでは文字レベルの文章生成を目的とするので、many-to-manyのモデルを採用します。つまり、ある文字が与えられたときに、その次の文字を予測することで文章を生成するのです。

##教師データ
教師データとして、東京都内の飲食店のクチコミ文章10万件を使います。WEBスクレイピングで取得し、テキストファイルで約86MBの容量でした。文字数は6698万文字あります。データの前処理として、文字数の削減を行いました。UTF-8で表現できる文字数(87,882文字)だと特徴空間が大きく、仮にone-hot-vectorの場合、一文字を表現するのに87,882次元のベクトルが必要となります。ところで、PyTorchのRNNでは、one-hot-vectorではなく連続値による分散表現が用いられるため、87882のボキャブラリー（この実験では文字数）を例えば10個の実数で表現することも理論上は可能です。しかし、元の文字数がいくら多くても分散表現の次元数を低くできるというのは無理があるはずです。この理由で、元の文字数を削減する意義は大いにあると考えました。具体的には、使用可能な漢字を限定することで文字数を削減しました。使用可能な漢字は、小学2年までに学習する240字の漢字[2]としました。それ以外の漢字が使われている単語の場合は平仮名で代用します。これは形態素解析により単語の読みを参照することで可能になります。なお、形態素解析にはMeCab、辞書は最新語に対応したmecab-ipadic-NEologd[4]を利用しました。

前処理により文字数を99.2%を削減しました。内訳は、平仮名81字、カタカナ85字、ASCII文字100字、その他基本的な記号などを含めた計735文字です。

>0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c、。「」　ー０１２３４５６７８９あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをんっぁぃぅぇぉゃゅょがぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヲンヴヵヶ一右雨円王音下火花貝学気九休玉金空月犬見五口校左三山子四糸字耳七車手十出女小上森人水正生青夕石赤千川先早草足村大男竹中虫町天田土二日入年白八百文木本名目立力林六引羽雲園遠何科夏家歌画回会海絵外角楽活間丸岩顔汽記帰弓牛魚京強教近兄形計元言原戸古午後語工公広交光考行高黄合谷国黒今才細作算止市矢姉思紙寺自時室社弱首秋週春書少場色食心新親図数西声星晴切雪船線前組走多太体台地池知茶昼長鳥朝直通弟店点電刀冬当東答頭同道読内南肉馬売買麦半番父風分聞米歩母方北毎妹万明鳴毛門夜野友用曜来里理話悪安暗医委意育員院飲運泳駅央横屋温化荷界開階寒感漢館岸起期客究急級宮球去橋業曲局銀区苦具君係軽血決研県庫湖向幸港号根祭皿仕死使始指歯詩次事持式実写者主守取酒受州拾終習集住重宿所暑助昭消商章勝乗植申身神真深進世整昔全相送想息速族他打対待代第題炭短談着注柱丁帳調追定庭笛鉄転都度投豆島湯登等動童農波配倍箱畑発反坂板皮悲美鼻筆氷表秒病品負部服福物平返勉放味命面問役薬由油有遊予羊洋葉陽様落流旅両緑礼列練路和

##学習と評価
学習にはAWSのP2インスタンスで約30分かかりました。ところで、10万件のクチコミ文章の6698万文字から、200文字をランダムに切り出し、ミニバッチとしてこれを1000セット用意したものを教師データとします。これを3000エポック学習させるため、ネットワークに読ませる文字数は200*1000*3000=600,000,000文字です。日本語話者は平均一分間に約600文字を読めるということなので、約700日間読み続けることに相当します。

さて、学習済みのモデルを利用して、文章を生成することができます。冒頭の例のように、以下のような文章を生成することができます。

>こともありますね。このつきではながいもよかったです。まずは、べつにおきなわの、じゅうぎょういんに由来すれば、先ずしか、「ジャンボ」も「おやこどん」。　たこやきだけ人が、どれもしっかりした味わい。ぐざいは

##考察
自動生成された文章を理解しようとすると、文章全体としてほとんど意味を成していないということがすぐに分かります。一方、文法的に正しい「てにをは」が使えているのは興味深いです。例えば、上の例の文中で「よかったです。」や、「どれもしっかりした味わい。」などは、この部分だけで評価すれば完璧かと思います。また、カギ括弧を正しく使えているのは興味深いと思います。RNNはこれらの自然な言い回しを、文法を抜きにして学習しています。また、一点気づいた点としては、限定的ではあるものの漢字を正しく使えているという点です。漢字には意味があり、この点はアルファベットなど基本的な文字とは異なっています。

##まとめと課題
部分的な箇所においては自然な日本語を生成することができたものの、単語の意味という観点ではほぼランダムと言わざるを得ないです。局所的な文字の使い方と、単語の意味との関係については、今後追求したいところです。

##参考情報
[1] PyTorch
[http://pytorch.org/](http://pytorch.org/)

[2] 文部科学省 学年別漢字配当表
[http://www.mext.go.jp/a_menu/shotou/new-cs/youryou/syo/koku/001.htm](http://www.mext.go.jp/a_menu/shotou/new-cs/youryou/syo/koku/001.htm)

[3] Practical PyTorch
[https://github.com/spro/practical-pytorch/blob/master/char-rnn-classification/char-rnn-classification.ipynb](https://github.com/spro/practical-pytorch/blob/master/char-rnn-classification/char-rnn-classification.ipynb)

[4] mecab-ipadic-NEologd
[https://github.com/neologd/mecab-ipadic-neologd](https://github.com/neologd/mecab-ipadic-neologd)