改善案を考える・人工無脳について振り返る

彼> この会話で何が起きて欲しいですか?
僕> このプログラムの改善案について話し、それについて質問されることで考えを整理し、新しいアイデアを見つけたい
彼> あなたはその改善案をどう知るのですか?
僕> ユーザの発話の中からどの部分をキーフレーズとして抽出するかについて、最初のバージョンでは直前の発話だけから抽出してランダムに選んでいて、それでは話がどんどんずれていくので次のバージョンでは過去の発話も含めてランダムで選ぶようにして、それだと直前の発話から選ばれる確率がどんどん下がってしまうのでエビングハウス忘却曲線的なのを入れて、IDFで重み付けして、スコアの高いものほど選ばれやすいようにしたのだけども、それでもイマイチなので抜本的に変更しようと思っている。
彼> その直前は、何のようですか?
僕> 直前の発話はまさに今聞いた内容で、やはりそれをきちんと聞いている風の反応をしないとユーザが手応えのなさを感じてしまう
彼> その風は、どんな種類の風ですか?
僕> 相手の発言を受け止めていることを、相手が実感できる
彼> 発話は、どんな種類の発話ですか?
僕> 質問に対するユーザの回答で、
彼> 発話は、どのあたりにありますか?
僕> 質問に対するユーザの反応で、それが長いほど傾聴がうまく言っている証拠、と書こうとしたのだが失敗した。発話は入力としてプログラムに入ってくる
彼> その発話について、他に何かありますか?
僕> 発話が長くなるように適切なキーフレーズを選んで質問することが重要。
彼> 傾聴について、他に何かありますか?
僕> 傾聴こそがこのプログラムがユーザに与える価値なので、まずは傾聴を定量的に計測する尺度を明確にして、その尺度の上で最適化を掛けるのがよいのではないかと考えている。
彼> 発話は、何のようですか?
僕> 発話はユーザという果実から搾り出されたジュースみたいなものだ。絞っているのが質問。
彼> 入力は、どんな種類の入力ですか?
僕> 現状ではキーボードを叩いてチャットのような形で入力している。音声入力が好きな人もいるけど、それは優先度の低いパスだと思う。
彼> そのキーボードは、何のようですか?
僕> 考えを綴る道具って考えるとペンのようだな。
彼> あなたはパスをどう知るのですか?
僕> まあ、音声入力ではなくキーボード入力に選択と集中するのは特に根拠の無い選択ではある。
彼> ユーザは、どこにありますか?
僕> コンピュータの前にいる。当面は僕がユーザだと思って良い。
彼> 音声入力は、どんな種類の音声入力ですか?
僕> NG そちらの話を掘り下げたいとは思っていない
彼> 傾聴は、何のようですか?
僕> ユーザの発話の中から適切なキーフレーズを見つけて、それについて問いかけることで更にたくさんの発話を促す、芋掘りみたいにつながり合っているアイデアを蔓が切れないように気をつけながら引っ張って、土から引きずり出すようなプロセス。
彼> そのキーフレーズは、どこにありますか?
僕> キーフレーズはユーザの発話の中にあって、どこがキーフレーズであるかを判定するのが目下の重要課題
彼> そのキーフレーズは、どんな種類のキーフレーズですか?
僕> 今は、形態素解析で単語を抽出した後名詞を結合してキーフレーズを作っているが、その結果IDFの辞書に登場しないものに関してはスコアが上限に張り付いてしまう。別のスコア付けの方法が必要で、そのスコアは「ユーザがどれだけ長い返答を返すか」に相関する
彼> そのキーフレーズについて、他に何かありますか?
僕> 構成単語やNグラムの特徴量からロジスティック回帰かパッシブアグレッシブみたいな方法でスコア付けする。あ、あと直前の発話の中のキーフレーズは特別扱いで高い優先度にすべき。あとこれを書いていて気づいたけど、今、名詞が連続しているとそれは全部くっつけたもの1個だけをキーフレーズにしてしまっているけど「直前発話中のキーフレーズ」だと「直前発話中」だけをキーフレーズにするんじゃなくて、部分列全部をスコア計算したい。
彼> そのキーフレーズは、何のようですか?
僕> フックのようで、そのフックで引っ掛けて引っ張りだす。
彼> キーフレーズは、どのあたりにありますか?
僕> 直接的にはユーザの入力の中にあるのだけども、過去の発話全部が共通のキーフレーズを介してネットワーク上につながっていて、キーフレーズは個々の発話をつなぐ紐であり、1つの発話の中だけに出てくるキーフレーズはそれほど重要ではない。何度も出てきて幾つもの発話で描写された側面をつなぎあわせているようなタイプのキーフレーズが重要。だから、キーフレーズは発話の中にあるって考えは適切ではないな。それは発話の間にあって、発話の上をゆるやかに覆っているイメージが適切か。
彼> あなたはそのキーフレーズをどう知るのですか?
僕> プログラムがどういう質問を返してきたかによって、プログラムが何をキーフレーズとして認識しているかがわかる。その認識が正しくない時にそれをプログラムに教える手段があればよいのか。
彼> 考えは、どこにありますか?
僕> キーフレーズは発話の中にあるって考えは、発話からキーフレーズを抽出する処理を書いたことに起因する思い込みの中にある
彼> ユーザについて、他に何かありますか?
僕> ユーザは適切な質問をされると楽しくなってさくさく返答が掛ける。だからそれを計測すると質問が適切であったかどうかが計測できるはずか。やはりターン制の対話プログラムではなくリアルタイムなチャットの形にして、入力時間なんかを特徴量として取ることが重要か。
彼> あなたはそのターン制をどう知るのですか?
僕> ターン制を選択したのは単に実装上一番楽であることが理由。必須ではないと当初から考えてた。リアルタイム化も難しくないよ、基本的には人間の発話を待てばいいだけなので。
彼> その実装上は、何のようですか?
僕> よくある間違いだな。何が顧客にとっての価値につながるかではなく、何が自分にとって楽であるかで実装を選択してしまうという間違い。
彼> スコア付けは、どこにありますか?
僕> 今の実装では、入力を受け取って形態素解析した後、その形態素列を受け取ってスコアその他の「環境」を更新する関数がある。キーフレーズのスコア付けがその関数の最初の仕事だったけど、今では拡張されて状態遷移で対話のフローを管理することも引き受けている。
彼> あなたはその状態遷移をどう知るのですか?
僕> 今はMetaphors in Mindを参考にしながらハードコーディングしている。
彼> ターン制について、他に何かありますか?
僕> 簡単な事で、今は入力欄でユーザがEnterを押したことを、即座にターンエンドの宣告として解釈しているわけだけど、現実のリアルタイムのチャットではそうではない。続きを書き始めている時、話が完了してない時はターンエンドではない。続きを書き始めているのはCUIアプリではなくHTML+JSとかのインターフェイスに変えれば簡単に取れる。
彼> ハードコーディングは、どんな種類のハードコーディングですか?
僕> 今の状態を保持する変数があって、ある状態でどういう条件を満たしたらどういう状態に遷移するかってのがコードで実装されている
彼> その条件について、他に何かありますか?
僕> 特にパラメータのあるタイプの条件では、本当にその条件が適切かどうかっていう検証がないのは問題。そこは十分なデータがあれば自動調整することもありえるかと。
彼> その条件は、どんな種類の条件ですか?
僕> 具体的には例えばキーフレーズの抽出数が一定量を超えたら、とか。
彼> その一定量は、どんな種類の一定量ですか?
僕> 今はフィーリングで決め打ちになっている。実際に、一度大きくしすぎて期待した遷移がなかなか起きないこともあった。今もそう。あー、あとはキーワード抽出だった時代に比べてキーフレーズ抽出に変えたから抽出される数が減っているのにそれに合わせてないのも原因か。今後キーフレーズの部分列もキーフレーズにするように変えたら、今度は抽出数がぐっと増えることになるな。
彼> その抽出数は、どこにありますか?
僕> 単純に、今までに出てきたキーフレーズとそのスコアを溜めている変数があって、それのサイズで見ている。
彼> 部分列は、どんな種類の部分列ですか?
僕> 複数の単語で構成されているキーフレーズに
彼> 関数について、他に何かありますか?
僕> キーボードの調子が悪い…Enterキーが2度押しになってしまうとか酷い……。複数の単語で構成されているキーフレーズに関して、その列の一部を取り出してできるフレーズもすべてキーフレーズとしよう、という意味ね。関数は環境更新の話だったか。他には…いろいろな機能を引き受けすぎの感はあるな。でもここはホットスポットなので今はグチャッとしてても仕方ないと思う。状態の更新は今はハードコードでも、最終的には行列に変わると思っている。決定論的な遷移は確率的な遷移の特殊形にすぎないわけで、内部状態が外部からの入力により確率的に遷移して、その状態によって外部へのアウトプットが確率的に決まる、というモデルを考えていて、現状前半が決定論的、後半が確率的になっている状態だけど、前半も確率的になるのが適当だし、それは遷移行列で表現されるだろう。
彼> その2度押しについて、他に何かありますか?
僕> NG その話題を掘り下げるのはやめよう。
彼> その2度押しは、何のようですか?
僕> NG やはり「それやめよう」コマンドは必要だな。直前の質問を作成するのに使われたキーフレーズのスコアを減らすコマンドとして。
彼> その確率的は、どんな種類の確率的ですか?
僕> 今のプログラムの出力を決める確率モデルは単純で、状態が決まるとその状態で出力可能な複数の質問テンプレートが決まり、質問テンプレートに埋め込むキーフレーズは別途抽出されており、その直積の集合から「既出の質問」と「NG登録された質問」を取り除いたものからのサンプリングになる。
彼> 確率的は、どこにありますか?
僕> 今は出力を返す関数の中にハードコードされている。
彼> 確率的について、他に何かありますか?
僕> これも今はハードコードされているけど、出力確率の行列になってもよいと思う。資料中の会話例から頑張って教師データを作ったら隠れマルコフモデルのパラメータ推定問題に帰着するなぁ。めんどくさいし、あんまり顧客価値の改善につながらないと思うのでやらないけど。頑張って教師データを作って学習させるよりは、普段使っているうちに徐々に賢くなる方がいい。
彼> そのハードコードは、どこにありますか?
僕> 出力を返す関数の中。
彼> 教師データは、何のようですか?
僕> 負担。性格的な問題かもしれないけど、僕にはマメさがないので、教師データを事前に頑張って整備したら性能が上がります、っていう系統の手法はあんまり好きになれない。
彼> 決定論的について、他に何かありますか?
僕> 昔の人工無脳はおおよそ決定論的だった。キーワードがマッチした時に出力される言葉が決まっていた。だけどその後、ひとつのキーワードに対して複数の出力を対応付けることができるものが出てきて、その場合、キーワードのマッチした出力の集合からランダムにサンプリングして出力されるような実装になっていた。今から考えると、あれが決定論的な対話から確率的な対話への分かれ道だったかもしれない。
彼> その人工無脳は、どんな種類の人工無脳ですか?
僕> キーワードとそれに対する出力のペアを持っていて、ユーザが入力した時に、その入力の中にキーワードが見つかればそれに対応した出力を出す。このシステムとの比較で説明すれば、キーフレーズ抽出の部分が、あらかじめ登録されているキーワードの文字列パターンマッチで置き換えられている
彼> 遷移は、どこにありますか?
僕> 今説明した範囲では昔の人工無脳に状態遷移はない。僕が中学生の時に作った人工無脳はその点がちょっと改良されていて、文字列パターンマッチの対象がプログラムの発話自体にも拡張されていて、かつ不可視なラベルを埋め込む構文を用意したため、キーワードと出力のペアっていう従来型のデータ形式の枠組みを引き継ぎつつ、内部状態の遷移を記述できた。それまでの人工無脳が刺激に対して単発で反応するだけで記憶を持たなかったのに対して、僕のフレームワークを使えば複数回の出力で構成されるようなやりとりを記述することができた。
彼> その出力は、どのあたりにありますか?
僕> データファイルの中に、キーワードと一対一対応する形で記述されていた。
彼> ハードコードについて、他に何かありますか?
僕> そういう意味では、その人工無脳はなんらの確率モデルをハードコードしていない。全部データ側に押し出されていて、システム側は状態遷移を記述出来るだけの表現能力を持った記述言語を提供することに徹していたといえるだろうなぁ。
彼> その人工無脳は、何のようですか?
僕> 子供だね。知識を与えれば与えるほど成長してより賢くなる。しかしとにかくデータ量を増やせば賢くなるはずだというアプローチは、データ追加の労力あたりの賢くなった実感が徐々に飽和しだしてしまった。アトムを作った天馬博士と同じで、自分の子供だと思っていたアトムが成長しないことに気づいて愛が失われてしまった。
彼> そのデータ量は、どんな種類のデータ量ですか?
僕> 人間が直接手作業で入力することで作られたデータの量。だからさっきの話だと学習データに相当するもので、負担なわけだ。しかし当時は汎化性能って考え方がなかったから、入力した以上に処理できる量をスケールさせる方法がわからなかったんだな。
彼> 人工無脳について、他に何かありますか?
僕> 人間と対話することを主目的とするプログラム、っていう観点から言うと、Siriだとかしゃべってコンサルだとかの形で対話経験のあるユーザはかなり増えたんじゃないのかな。Herって映画もあったし。ただ、20年前のその人工無脳ブームは「Appleが作って与えた人工の人格との会話が楽しくてブームが起きた」のではなく「個々人が自分の好きな仮想の人格を実装して、自分だけの人工無脳を作ることが出来る」というところが顧客価値になっていたと思う。お仕着せの仮想人格と話すことではなく、自分でつくり育てることの方に価値を見出すユーザがいるっていうのが重要なポイントだと思うなぁ。
彼> その人工無脳は、どのあたりにありますか?
僕> インターネット上にチャットルームがあって、まあPerlで書かれたCGIなので簡単に設置や改造ができて、そいつに人工無脳が搭載されている、という時代があったわけだよ。そうか、最近の若い人にとってチャットってのはSkypeやLINEなのか。そうだとすると人工無脳を設置するのはそう手軽ではないか。

所見:当初の目的からずれていってるなー。当初の目的に照らし合わせて有益かもしれない内容を整理すると:

  • 音声入力を避けてキーボード入力に専念していることに、特に根拠は無い
  • 「キーフレーズはユーザの発話の中にある」と考えていたが、これは根拠の無い思い込みにとらわれていた。「キーフレーズは発話の間にある」と捉え直すことで、キーフレーズの役割は複数の発話を結びつけることであり、発話をまたいだ出現回数こそが本質的に重要な尺度なのに今はそれを使ってないってことに気づいた
  • また、適切でないキーフレーズが選ばれている場合、ユーザはそれに気づくことができるので、その気づきをプログラムに教える手段を用意すべき
  • 当初考えていた「ユーザの発話の長さが長くなるように機械学習で適切なキーフレーズを選ぶためのモデルを作る」をやる上では、ユーザの入力時間とかも取れたほうが良いのではないかということで、まずはリアルタイムチャット形式へのUIの変更のほうが優先度高。

という感じか。