LoginSignup
16
10

More than 5 years have passed since last update.

"これ"はなんですか、コンピュータさん? -「心を読むシステム」の実装-

Last updated at Posted at 2018-12-20

IMG_0246.jpg

TL;DR

  • 人間が他人の意図などを推察できる現象を説明するために、心の理論という概念が提案されている。
  • 心の理論を説明するために「心を読むシステム」というモデルが作られている。
  • そこで「心を読むシステム」をコンピュータに実装することで、コンピュータが人間の意図をすこし推察できるようにした。

このアドベントカレンダーについて

これは武蔵野アドベントカレンダーの20日目の内容になります。
でも、私は武蔵野で働いていません。横須賀で働いています。
昔は富士山が玄関から見れましたが、最近でかいステージのせいで見れなくなりました。
(去年のアドベントカレンダー参照: 去年のやつ
はい

はじめに

突然ですが、みなさん、ここでクイズです。

"これ"はなんですか?

わかりますか?
これです、これ。
わかりませんか?

はーい、時間切れ

正解は僕の目の前に置かれている視線計測器でした。

IMG_6048.JPG

僕が最近視線計測器こと、アイトラッカーで何かしらやっていることをTwitterで見ていれば、わかったことでしょう。
わかったことでしょうじゃねぇよ。わかるわけねぇだろ!と思った人は正常です。
おめでとうございます。

さて、この茶番で伝えたかったことは、
これという代名詞は会話や文章の中に必ずしもあるわけではなく、言葉の外にある場合もある
ということです。

では、次の問題に移りましょう。以下のイラストを見てください。

イラスト_trim.png

この人は、何を"これ"とよんでいるのでしょうか。

なんとなくわかりますよね。
答えはバナナです。

この「他人が考えていることを言葉で喋っているわけでもないのになんとなくわかる現象」とは、一体何なんでしょうか。
これって誰にでもわかることなんでしょうか。
むしろ、人じゃなくてもコンピュータでもわかるんでしょうか。

本日のアドベントカレンダーでは、この「他人が考えていることがわかる現象」の説明から、その現象を起こるようにコンピュータに実装するところまでをざっくり説明していきます。

「他人が考えていることがわかる現象」を説明するとは

人間はなぜ「他人が考えていることがわかる」のでしょうか。
この問いに答える概念として「心の理論」(Theory of mind)[1]があります。

心の理論とは自己および他人の目的・意図などを推察し、理解するメカニズムのことです*1[1]。この心の理論により人間は他人の意図を推察していると考えられています。現在では、心の理論とは、哲学だけではなく、ロボット工学、発達心理学を巻き込んだ研究テーマになっているそうです[2]。しかし、この心の理論はいまだに確固たる説明ができていません。無論、それをロボットに完全な形で実装することもできていません。いろいろな分野の研究者が取り組んでも解決ができない、大変難しい研究テーマだといえます。

この心の理論を説明するモデルの1つに、「心を読むシステム」があります。心を読むシステムとはサイモン・バロン=コーエンが提案した心を読むことに含まれるメカニズムのこと[3]です。なぜふわっとした書き方をしているかというと、心の理論は「心を読むシステム」ですべて説明できるわけではないけど、その一部は説明できるからです。心を読むシステムは4つの仕組みに以下の分解されます。

  1. 意図の検出器(Intentionality Detector; ID)
    目的や欲求といった原始的・意図的な心の状態に関する刺激を解釈するための仕組み。
    刺激から意図を持って行動しているもの(=行為者、たとえば会話の相手)を抽出する機能を持つ。

  2. 視線方向の検出器(Eye-Direction Detector; EDD)
    行為者が何を何を見ているかという観点から刺激を解釈するための仕組み。
    目を検出し、目はどの方向を向いているか、そして、行為者は視線の先のものを見ているか推論する機能を持つ。
    この結果、自己の中に、行為者と対象の二項表象を構築する。表象とは記号論で言う記号に近い存在である*2。
    二項表象を記号論のように書くと([行為者-関係-対象])になる。
    たとえば、最初のイラストの場合、[男性-見る-バナナ]となる。

  3. 注意共有の仕組み(Shared Attention Mechanism; SAM)
    三項表象と呼ばれる事柄を形成するための仕組み。三項表象とは二項表象と自己との関係を表した表象である。
    行為者と対象の関係を視線の検出器で推察したあと、
    その二項表象を自分の立ち位置を考えて全体を推察する機能を持つ。
    三項表象を記号論のように書くと、[自己-関係-二項表象]という形になる。
    たとえば、最初のイラストの場合、[私-見る-[男性-見る-バナナ]]となる。

  4. 心の理論の仕組み(Theory of Mind Mechanism; ToMM)
    行動からすべての心の状態を解釈するための仕組み。
    二項表象や三項表象からメタ表象(M表象)と呼ばれる表象を作り出し、
    行為者の心の状態を推論する機能を持つ。
    メタ表象を記号論のように書くと、[行為者-態度-命題]という形になる。
    たとえば、最初のイラストの場合、[男性-考える-「これはなんだろう」]となる。
    (ぶっちゃけここだけ雑な説明になっているのはモデルの作者が細かく詰めきれていない、
    そもそも上記3つの仕組みの発見について主張したいからかもしれません。)

これら4つの仕組みは図1のように結合されて心を読むシステムを構成しています。

IMG_6051.JPG

図1 心を読むシステム([3]より引用)

さて、今回は心の理論すべてを対象とするのではなく、対話する相手が何を意図して発言しているのだろうと推察することを対象とすることにします。具体的には、さっきの例で示した問題「これはなんですか?」といった非言語コミュニケーション(Non-Verbal Communication) の要素が含まれる対話の問題をこの「心を読むシステム」に基づいて解決する方法について説明します。

他人の心の中にしかない「これ」を推測することはコンピュータにできるのでしょうか。

心を読むシステムの実装 -これはなんですか?-

今回は、ユーザはディスプレイの前にいて、
ディスプレイ上に2つのオブジェクト、球と立方体が表示されており、
その奥に対話システムの外見を表すキャラクターがいるという状況を仮定します。
この状況を図2に表します。

IMG_0243.jpg
図2 実装の前提条件

この図2の状況において、対話システムはユーザの発する「これはなんですか?」という音声による質問に対して、「これ」が果たして球なのか立方体なのか、あるいはどこも指していないのかを判断して、説明的な応答を返すことにします。

ということで、いきなりですが、こちらの完成動画をご覧ください。

心を読むシステムのイメージが湧いたでしょうか。
それでは今回の実装の物理的な側面から見てみましょう。
実装の写真を図3に示します。

実装.JPG

図3 実装の写真

今回使用したハードウェアとソフトウェアは以下のとおりです。

  • ハードウェア
    • コンピュータ: ゲーミングデスクトップ (x86)
    • アイトラッカー: Tobii Eye Tracker 4C Gaming Peripheral
    • ディスプレイ: テレビ (BRAVIA)
    • スピーカー: テレビ (BRAVIA)
    • マイク: ECM-PCV80U
  • ソフトウェア
    • OS: Windows 10 ver.1809
    • 開発環境: Unity 2018 3.0f2
    • 音声認識エンジン: Windows標準のあれ
    • 音声合成エンジン: Open JTalk
    • 視線検出エンジン: Tobii Unity SDK
    • キャラクターの3Dモデル: アリシア・ソリッド(VRM形式)

次に論理的な側面から説明しましょう。
図4を見てください。

ブロック図.png

図4 今回のブロック図

対話システムは、なんだか、いろいろなモジュールで構成されているようです。

それでは、図3と図4を見ながら、各段階のパーツの実装を見ていきましょう。

意図の検出器+視線の検出器

今回は、アイトラッカーにより視線が計測できれば、
目の前に行為者が存在し、その視線の方向も計測できるということにしました。
具体的には、アイトラッカーにより計測された視線と
各オブジェクトが存在する平面z=0.5の交点Mとし、
この点Mに球体PointingObjectを配置しています。
以上の処理により、二項表象である[ユーザ-見る-対象]を表現し、記憶しています。
Unityでのコードは以下のとおりです。

MovePointingObject.cs
using System.Collections;
using System.Collections.Generic;

using UnityEngine;
using UnityEngine.UI;
using Tobii.Gaming;

public class MovePointingObject: MonoBehaviour
{
    public GameObject pointingObject;

    // Update is called once per frame
    void Update ()
    {
        pointingObject.SetActive(false);
        GazePoint gazePoint = TobiiAPI.GetGazePoint();
        if (gazePoint.IsValid && gazePoint.IsRecent()) {
            Vector2 tmp=(gazePoint.Screen - new Vector2 (Screen.width, Screen.height)/2f);
            Vector3 gazepoint = new Vector3 (-tmp.x/Screen.width*2.3f,tmp.y/Screen.height*1.5f+1.0f,0.5f);
            pointingObject.transform.position=gazepoint;
        }
                // (中略)
        pointingObject.SetActive(true);
    }
}

注意共有の仕組み

今回は、PointingObjectの方向を常に向いてくださいとVRMの機能にお願いしているだけです。
VRMとはVRMコンソーシアムが規格しているVTuber向け3Dモデルの規格です[4]。
VRMを読み込むUnityのライブラリなどが提供されており、このライブラリを使うと3Dモデルの視線の制御などが簡単に行なえます。
本来VTuber向けですが、こういったAI(?)を搭載したキャラクターにも使うことができます。
以上の処理により、三項表象である[キャラクター-見る-[ユーザ-見る-対象]]を表現し、記憶しています。
Unityでのスクリーンショットは以下のとおりです。
gaze.PNG

心の理論の仕組み

今回はシンプルな前提なので、if-thenのルールベースで作りました。
具体的には、ユーザが球を見ていれば、[キャラクター-見る-[ユーザ-見る-球]]という三項表象が考えられるため、
[ユーザ-考える-「球とはなにか」]というメタ表象を作成し、そのメタ表象をもとにキャラクターが球について説明します。立方体も同様の処理をしています。
Unityでのコードは以下のとおりです。
なお、画面表示や音声認識、音声合成はすべてここで行っています。

STT.cs
using UnityEngine;
using UnityEngine.UI;

using UnityEngine.Windows.Speech;
using System.Collections.Generic;
using System.Linq;

public class STT : MonoBehaviour
{
    public UnityEngine.UI.Text resultDisplay;
    public UnityEngine.UI.Text TTSDisplay;
    public AudioSource sphere;
    public AudioSource cube;
    public AudioSource what;
    public AudioSource hello;
    public AudioSource goodbye;

    public GameObject pointingObject;

    public GameObject[] gameObjects;

    KeywordRecognizer keywordRecognizer;
    Dictionary<string, System.Action> keywords = new Dictionary<string, System.Action>();

    void Start()
    {
        //キーワード認識器用にキーワードとそれに対するアクションを入力
        keywords.Add("これはなんですか", () =>
            {
                resultDisplay.text = "プレーヤー:これはなんですか";
                GameObject thisObject=null;

                                //視線とオブジェクトの衝突判定
                foreach(GameObject gameObject in gameObjects){
                    if(isCollision(gameObject.transform.position,pointingObject.transform.position,0.5f)){
                        thisObject=gameObject;
                    }
                }

                if(thisObject == null){
                    what.Play();
                    TTSDisplay.text="アリシア:どれのことですか?";
                }else if(thisObject.name == "Ball"){
                    sphere.Play();
                    TTSDisplay.text="アリシア:これは球です。";
                }else if(thisObject.name == "Box"){
                    cube.Play();
                    TTSDisplay.text="アリシア:これは立方体です。";
                }
            });
        keywords.Add("こんにちは", () =>
            {
                resultDisplay.text = "プレーヤー:こんにちは";
                hello.Play();
                TTSDisplay.text="アリシア:こんにちは";
            });
        keywords.Add("さようなら", () =>
            {
                resultDisplay.text = "プレーヤー:さようなら。";
                goodbye.Play();
                TTSDisplay.text="アリシア:さようなら。またお会いしましょう。";
            });

        keywordRecognizer = new KeywordRecognizer(keywords.Keys.ToArray());
        keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized;
        keywordRecognizer.Start();
        Debug.Log("Setting done.");
    }

        //衝突判定をするための関数。なんかColliderクラスが調子悪くてな・・・
    private bool isCollision(Vector3 a,Vector3 b,float r){
        float x = a.x - b.x;
        float y = a.y - b.y;
        float z = a.z - b.z;

        // on collision
        if (x * x + y * y + z * z < r*r) {
            return true;
        } else {
            return false;
        }
    }

    private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
    {
        System.Action keywordAction;
        // if the keyword recognized is in our dictionary, call that Action.
        if (keywords.TryGetValue(args.text, out keywordAction))
        {
            keywordAction.Invoke();
        }
    }
}

実装結果

実装したシステムの構造を振り返りながら、もう一度、デモ動画をご覧ください。

心を読むシステムやその実装を理解できたでしょうか。

まとめと今後の発展

簡単な茶番を通じて、人間が当たり前にやっている他人の意図を推察することの難しさを説明し、
「これはなんですか?」という相手の意図を推察できないと解けない問題を個人的にはシンプルな例で説明したつもりです。

さて、最初に書いた、「この人間が当たり前にやっている他人の意図を推察すること」は、本当に誰でもできるのかという話ですが、
実はこの推察が先天的にできない人もいます。
その人たちは発達障害者と呼ばれます。
かつてはアスペルガー症候群患者とか自閉症患者とか呼ばれていましたが、
この推察できない問題の理解が進むにつれ、名称が変わりました。
心の理論をもつ技術の開発は対話システムやコミュニケーションロボットの開発にも応用できますが、
このような障害者の方々を支えることも将来できるようになってくると思います。
私はロボット開発もそうですが、そのような方々を支援する技術も作っていきたいとは考えています。

みなさんもぜひ心の理論について学び、その機能を技術としてAIに組み込んでいってください。
将来、いや、今でも世界でロボットや発達障害者の方々が活躍するには必要な技術だと思っています。

参考文献

[1] Premack, D. G., Woodruff, G., "Does the chimpanzee have a theory of mind?", Behavioral and Brain Sciences, 1978
[2] 子安 増生 (編集), 郷式 徹 (編集),"心の理論 第2世代の研究へ", 2016
[3] サイモン バロン=コーエン, 長野 敬 (翻訳), 今野 義孝 (翻訳), 長畑 正道 (翻訳), "自閉症とマインド・ブラインドネス", 2002
[4] VRMコンソーシアム 設立準備会, 2018, https://vrm-c.github.io/

プログラミングの参考記事

注釈

*1 なぜ、名前に「理論」という言葉が付いているかというと、「場の理論」(Theory of Field)といったような人間が物理現象を理解するプロセスと同じように、「心の理論」といったような人間が心理現象を理解するプロセスを語りたたかったのだと考えられます。場の理論での対比でも理解できないという人は、次の説明はどうでしょうか。我々は、りんごが落ちたといった物理現象を物理法則(たとえば、万有引力の法則)により解釈することができます。これと同じように、りんごが欲しいという心理現象を心理の法則(たとえば、心の理論)により解釈することができると考えることができます。もっと詳しく知りたい方はカントのコペルニクス的転回について勉強するとすんなり理解できると思います。
*2 記号論における記号については、去年のアドベントカレンダー(こちら)をご覧ください。

16
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
10