lstmで自然な受け答えができるボットをつくった

(2016-12-11 追記) この記事で紹介している学習済モデルは、現行のchainerのバージョンでは使用できなくなっているので、chainer 1.4.1 をインストールしたdocker imageを使う方法を追記しました。新しく学習される方は最新のchainerを使うことをおすすめします。

 

コードを理解する程度のスキルがあればDeep Learningが使える世の中になっているので、試しに自然な受け答えができるボットを作ってみた。

学習

自然な受け答えを行う日本語のデータセットということで、ask.fmをクロールしたデータを用いる。

ask.fmのディレクトリは”ask.fm/アカウント名”のようになっていて、ask.fmのアカウント名のリストがないことにはクロールしようがない。今回は、トップページに訪れた際に表示されるアカウントのリストを定期的に収集することでアカウント名のリストを作った。

Ask_fm

負荷をかけすぎないよう、30分に1回ぐらいトップページにアクセスすること1ヶ月、1,600ぐらいのアカウント名が取得できた。各アカウントのページには最新の質問と答えがいくつか表示されているので、それらを取得する。データ量は8MBぐらいになった。(ちなみに10日ぐらいで600ぐらいのアカウント、学習データは4MBぐらいになるのでそれでも十分)

中身はこんな感じ。

lstm-input

質問と答えの後に1行空白行を入れている。

ChainerでLanguage ModelをLSTMで使うコードがあったので、ありがたく使わせてもらう。

https://github.com/yusuketomoto/chainer-char-rnn

askfmをクロールしたデータをinput.txtとした。パラメータはDeepDazaiを参考にして、隠れ層のノード数を増やした。

前に作ったCUDAとDockerをインストール済のAMIをオレゴンに作り、cudaとchainerをインストールしてあるDocker imageをpullして学習させる。


# gpuの有効化
/usr/local/cuda/samples/1_Utilities/deviceQuery/deviceQuery

# docker imageの起動
DOCKER_NVIDIA_DEVICES=”–device /dev/nvidia0:/dev/nvidia0 –device /dev/nvidiactl:/dev/nvidiactl –device /dev/nvidia-uvm:/dev/nvidia-uvm”
sudo docker run –name chainer -v $PWD:/notebook -p 8888:8888 -d $DOCKER_NVIDIA_DEVICES drunkar/cuda-caffe-anaconda-chainer

# deep-dazaiのbranchを取ってくる
git clone https://github.com/longjie/chainer-char-rnn.git
cd chainer-char-rnn
git checkout -b new-branch origin/new-branch

# cv/askfm、data/askfmディレクトリを作る
# 学習データをinput.txtとしてdata/askfmに置く

# 学習の実行
python train.py --data_dir data/askfm --checkpoint_dir cv/askfm --rnn_size 1024

4MBの学習データなら8時間ぐらい、8MBのデータなら20時間ぐらい学習にかかったと思う。オレゴンのgpuインスタンスで2000円ぐらい。高い。

学習途中にモデルデータがどんどん溜まっていくので、インスタンスの容量が少ない場合は適宜消さないと学習が途中で終わってしまうので注意。時は金なり(切実)。

hubotにしゃべらせる

モデルの学習が終わったら、それを使ってhubotにしゃべってもらう。getリクエストのパラメータに文字列を渡すと、続きを予測して表示してくれるAPIをtornadoで作り、hubotからAPIでアクセスする。hubot側の返答パターンは2通り。

  • askfmは「質問と答え」という特殊な文字列なので、「?」の後には回答が来やすくなる。なのでhubotは質問をメンションで受け取り、クエスチョンマークを末尾につけてAPIをコールするようにした。
  • たまに自然に会話に参加してほしいので、全発言をhearして、メンション以外の全発言に対して10%の確率で返答するようにした。APIは発言の続きを予測するので、2文目以降をhubotの発言とした。

しばらくしゃべってもらって調整したのは以下の2点。

  • クエスチョンマークの後にはクエスチョンマークがかなりの確率でやってきてしまう (「??」みたいな聞き方が多いため)ので、”?¥n”をAPI側でlstripした。
  • あまり意味が通じないとしても、hubotの発言は短ければそれなりに破綻しない発言として人間に解釈されやすい。ので、hubotの発言は1文か2文(ランダム)に制限した。

tornadoで作ったAPIとhubotスクリプトはgithubに上げてます。1,600アカウント分のデータを学習した学習済モデルも含まれているので、dockerがインストールしてあるマシンなら今すぐにでもしゃべらせられます。

https://github.com/Drunkar/japanese_talk_api


# apiデータをclone
git clone https://github.com/Drunkar/japanese_talk_api.git

# tornadoを動かすdocker containerを起動
# entrypointではjupiter notebookが走るけど気にしない
docker run --name japanese_talk_api -d -p 80:8787 -v japanese_talk_api:/app drunkar/cuda-caffe-anaconda-chainer

# (2016-12-11 追記)
# 学習済モデルを使う場合は、以下のコマンドでdockerを起動してください。
docker run --name japanese_talk_api -d -p 80:8787 -v japanese_talk_api:/app drunkar/cuda-caffe-anaconda-chainer1.4.1

# tornadoを起動するための別プロセスを走らせる
docker exec -it japanese_talk_api bash
# sampleモデルをダウンロード
cd /app/tornado/models ./download_sample_model.sh
# tornadoを起動
cd /app python tornado/app.py --port=8787 --debug=True
# プロセスを走らせたままcontainerから抜ける
ctrl+p, ctrl+q 

pickleモデル(chainermodel)のロードに30秒ぐらいかかるので、ちょっと待ってからAPIと試す。

http://localhost/?q=こんにちは

なんか適当にjsonが返ってきたらおk。後は付属のhubot scriptでアクセスしましょう。

名言集

hyohyoがボット。(名前は『カイバ』から。アイコンは忍野扇(女))

  • 出演を断る

hyohyo1__1_

  • ツイ廃

hyohyo2_2

 

  • 独特の世界観

hyohyo3

ask.fmがツイッターを中心としたメディアなので、やたらとツイッターのことを言ってくるし、淫夢厨だったりゲスかったりします。日本からask.fmにアクセスしているとはいえ、日本語以外のアカウントもまあまあ紛れているので英語や韓国語も話せます。

わかったこと

  • 人工無能でもAIは愛しい: 予想の斜め上をいく発言をしたり、うまく発言してくれなかったりすることもあって妙に可愛いです。AIBOがヒットする理由もなんとなく分かりましたし、ヒューマノイドが話相手になるということに確信が持てました。
  • チャットが和む: 普通に会話している時に突如パンツの話とかをしだすので、チャットが和みます。

2 thoughts on “lstmで自然な受け答えができるボットをつくった

Leave a Comment

Your email address will not be published. Required fields are marked *