下町柚子黄昏記 by @yuzutas0

したまち発・ゆずたそ作・試行錯誤の瓦礫の記録

Pythonで『恋するプログラム Rubyで作る人工無脳』を再現しました

概要

恋するプログラム―Rubyでつくる人工無脳 (Mynavi Advanced Library) という書籍を参考にして、Pythonで簡易的な人工無脳を作ってみました。 Githubリポジトリyuzutas0/nobypy になります。

f:id:yuzutas0:20180701214023p:plain

もくじ

実装風景・デモ画面

JupyterNotebookにてスクリプトを実行すると、キャラクターの画像、会話ログ、入力フォームを表示します。 この画面上でチャットボットとの会話を楽しむ形になります。

会話を積み重ねていくことで徐々に言葉を学習していきます。

f:id:yuzutas0:20180701212448p:plain

感情モデルやサブカル語録も習得します。 褒めると喜び、アニメの名言には続きを返すといった具合です。 話がたまに噛み合ったり噛み合わなかったりします。

f:id:yuzutas0:20180701212619p:plain

マルコフ連鎖ジョジョの名言集を学習させたところ、完全に会話が破綻するようになりました。

f:id:yuzutas0:20180701212943p:plain

ロジックや辞書ファイルや会話ログを見比べて原因分析&チューニングしたところ、ジョジョの名言はそもそも自然な日常会話ではなかったので、いくら学習させても会話としては成り立たないことが判明しました。 めでたしめでたし。

書籍内容

一時期は絶版となってしまい中古本が高騰していましたが、最近また再販されたようです。 私の手元にあるのは復刊ドットコム経由で購入したものです。

初心者向けにプログラミングの概念やRubyの文法を説明するところから始まり、ゆくゆくは人工無脳の本格的なコーディングまで案内します。 丁寧なイラストとサンプルコードで解説されているため、具体的な実装レベルで理解することができます。 例としてマルコフ連鎖についての解説を一部引用します。

f:id:yuzutas0:20180702090335p:plain
f:id:yuzutas0:20180702090439p:plain
f:id:yuzutas0:20180702090505p:plain

書籍の目次は以下の通りです。 引用元はマイナビ出版の商品紹介ページで、一部内容を割愛しています。

1-1 人工無脳ってなに?

1-2 ActiveScriptRubyのインストール


2-4 繰り返し

2-5 変数と条件

2-6 配列

2-8 ハッシュ

2-9 オリジナルメソッド

2-10 オリジナルオブジェクト


3-3 最初の人工無脳 proto


4-1 VisualuRuby計画(仮称)でGUI

4-2 コントロールイベントハンドラ

4-4 Responderをランダムに切り換える


5-1 辞書はファイルに

5-2 パターンに反応する

5-3 人工無脳のための正規表現

5-4 PatternResponderの作成


6-3 感情モデルの実装 ――Emotionクラス――

6-6 感情モデルの実装 ――表情の変化――


7-1 まるごと覚える

7-2 形態素解析

7-3 キーワードで覚える

7-4 テンプレートとして覚える


8-1 マルコフモデル

8-2 マルコフ辞書の実装


9-1 Googleと仲良くなろう

9-2 ググるプログラム

システム全体像

処理の全体像は以下のようになっています。

f:id:yuzutas0:20180702090042p:plain

  1. ユーザーからの発言を受けつける
  2. その発言を受けて機嫌が良くなったり悪くなったりする
  3. 辞書をもとに返事のテキストを生成する
  4. 会話ログをもとに辞書を更新する(学習する)
  5. 画面を再描画する=返事をする
  6. 以下同じ処理を繰り返す

開発手順

スモールステップで1つ1つ実装していきました。

  1. ユーザーが何を言っても「こんにちは」と返すシンプルなbotを最初に実装。
  2. 次にユーザーが「XXX」と言ったら人工無脳が「XXXって何?」と聞き返すように実装。
  3. ユーザーに何を言われてもランダム辞書からランダムな発言を返すように実装。
  4. パターンで返すように実装。ユーザーの発言に特定のキーワードが含まれていたら、パターン辞書から特定の返答を行う。例えば「おはよう」という言葉が含まれていたら「今日は良い天気ですね」と返す。
  5. ポジティブとネガティブの感情を持たせる。ユーザーが好意を示す発言を与えると、人工無脳の感情パラメータはプラスになり、画面上で笑顔を見せる。反対に、ユーザーがバカにするような言葉を与えると、人工無脳の感情パラメータはマイナスになり、表情に曇りを見せる。ネガポジは特定のキーワードが文中に含まれるかどうかで判定する。該当キーワードが含まれないと徐々に平穏な状態(数値としてはゼロ)に収束する。
  6. ランダム返信の語彙を学習させる。ユーザーの発言をそのままランダム辞書に追加する。
  7. 単語で返信パターンを学習させる。形態素解析で会話ログを分解してパターン辞書に追加する。ユーザーの発言に「牛乳」という単語が含まれていると「牛乳が飲みたい」という発言を返すようになる。
  8. テンプレートで返信パターンを学習させる。形態素解析で会話ログを分解して、テンプレ辞書を作る。「牛乳が飲みたい」という会話ログをもとにして「XXが飲みたい」というテンプレートを作成する。そうすると次からはユーザーの「緑茶」という言葉を受けて、人工無脳は「緑茶が飲みたい」という文章を生成するようになる。
  9. マルコフ連鎖で文章を生成させる。【文章の開始】に来る言葉は「私」(10%)で、「私」の次に来る言葉は「は」(70%)で、その次は「あなた」(50%)、「が」(70%)、「好き」(10%)、そして「好き」の後に【文章の終了】(50%)といった具合で「私はあなたが好き」と発言する。ある言葉の後に別のある言葉が繋がっていくことで文章となる。文章を生成するために、過去の会話ログを形態素解析で分解して、言葉同士が繋がる確率を辞書に反映させる。
  10. インターネットで検索して回答させる。形態素解析でユーザーの発言を分解して、出てきた名詞(キーワード)でGoogle検索した結果を返す。それまでの会話だけでなくインターネット上のテキストから学習できるようにする。

書籍を写経していくと、これらの内容をざっと自分の手で動かすことができます。

Pythonでの再現で工夫したこと

f:id:yuzutas0:20180701222036p:plain

f:id:yuzutas0:20180701214058p:plain

  • 書籍ではデスクトップで起動するGUIツールを使っていますが、今回はJupyterNotebookで画像表示をしました。その際、保守性を保てるようにクラスやファイルは分離しました。個々の処理は .py ファイルとして切り出して、JupyterNotebookからは描画クラスをインポートしています。
  • 形態素解析の辞書は、書籍で案内されている 茶筌 (Chasen) ではなく janome を用いました。Pythonでのインストール手順が1番簡単だったからです。
  • あとはRubyワンライナーPythonのループ処理で愚直に書き直したり、辞書ファイルをpickleで代替したりと、それなりに地味な修正を積み重ねています。Pythonスキルが0.5歩くらい向上しました。

さらなる工夫の余地

書籍自体は最高なのですが、10年以上前に出版された写経本なので、いまこの書籍にチャレンジするなら工夫の余地は多々ありそうです。

  • 内部設計
    • サンプルコードと文章説明だけなので、能動的に読み解く必要があり、なかなか骨が折れました。
    • クラス・メソッド設計をビジュアル化した補足スライドがあると進めやすいだろうなと思いました。
    • あるいはメソッドごとにテストコードを書くようにすれば、少なくともI/Oの見通しは改善するでしょう。
  • 辞書ファイル
    • 取り扱うファイルがShift-JISなので、JupyterNotebookやIDEで確認しにくいです。何か新しい機能を追加するたびに文字コードエラーが出ました。
    • タブや記号で項目を分けているので、Write/Read(パースなど)の処理を自前実装しなければいけないのが面倒でした。
    • SQLite3などの簡易DBを採択したほうが良さそうです。
  • 俺々スクリプト
    • ディレクトリ構成さえも特になく、直接トップディレクトリにスクリプトを置いているだけです。
    • これを例えば Vue.js (SPA) + Flask (WebAPI) + SQLite (RDB) 構成で実装・勉強できると、現代のWEB開発に準拠しているので教材としての価値が高まるかもしれません。
    • あわよくば開発環境や本番環境を構築してデプロイやサーバ運用についても学んだり、テストコードのカバレッジ測定などのCI構築ができると尚良さそうです。
  • ライブラリやツールの活用
    • 今回はロジックのほとんどを手動で実装しました。もともとそういう趣旨の書籍なのでこれはこれで妥当です。
    • しかし、近年のデータ処理ライブラリの充実を考えると、特にPythonならもっと簡単に高性能なものを作ることもできるかもしれません。
    • クラウド機械学習ソリューション(MLaaS)を活用してマッシュアップ的に作るのもアリですね。

色々と書き出しましたが、そもそもDBの利用などは筆者も分かった上で「今後の課題」として読者に委ねており、書籍の最後でカスタマイズ案が提示されています。 実際に、書籍の内容をWEBアプリケーション化したブログ記事も見つかりました。

恋するプログラムをSinatraでWebアプリにする - あかんわ

3・4人で集まって2泊3日の合宿をやれば、この書籍をベースにして「Pythonで作る人工無脳 2018」のソースコードと補足スライド、簡単なチュートリアル資料を作ることはできそうです。 要件定義→システム設計→コーディング→テスト→リリース→運用までの一連の開発プロセスも体験できるような内容だとさらに役立ちそう。 やってみたいなぁ。

まとめ

こんな感じで、Pythonで簡易的な人工無脳を作ってみました。 「プログラミング」や「自然言語処理」、そして「WEBサービス開発」を学ぼうとしている初心者のネタに向いているのではないでしょうか。 時代が変わって本の内容そのままでは使えない点が多々あるので、別のチュートリアル素材で簡単なシステム開発が出来るようになった人が、脱初心者を目指してチャレンジするのがちょうど良い位置付けになると思います。