AIのブラックボックス問題って難しいか？

#はじめに 

ちまたで大流行りの人工知能だが、ブラックボックス問題というのがあるらしい。AIは猫の画像を見て被写体が猫であると判断する事はできるが、それがなぜ猫であるかを説明できないと。

しかし俺自身を鑑みるに、猫の画像を見てそれが猫であると判断するのは直観の働きであり、なぜそれが猫であると感じたのかを説明することはできない。その画像の被写体がなぜ猫であるかを説明するのは言語的な知識に基づいた別の脳の働きに依る。

AIに自身の結論を説明させる場合も同じで、ニューラルネットワークが導いた結論の理由を知識ベースのAIに説明させれば良いのではないか。そんな事をつらつら考えつつ散歩していたところ、Prologに結論の理由を説明させるための簡単な仕組みを思いついたので以下にご紹介。

#メタ述語

ものすっごい簡単なのでいきなりコードを示してしまうと、

	meta(A, B, P, R, H) :-
	    nonvar(A),
	    not(member(A, H)),
	    meta(A, C, P1, R1, [A | H]),
	    meta(C, B, P2, R2, [A | H]),
	    P is P1 * P2,
	    append(R1, R2, R).
	
	meta(A, B, P, R) :-
	    meta(A, B, P, R, []).
	
基本これだけ。metaはAがBであることについての確率Pと理由Rを示す述語である。Hは循環論法によるスタックオーバーフローを防ぐためのリストだ。メタっていう名前にしたのは何となくかっこいいからｗ

このメタ述語で用いる事実は次のように記述するのであって、

	meta(pyonkichi, frog, 0.5, [(pyonkichi, frog, 0.5)], _).
	meta(frog, amphibian, 1.0, [(frog, amphibian, 1.0)], _).
	meta(amphibian, creature, 1.0, [(amphibian, creature, 1.0)], _).
	meta(creature, die, 1.0, [(creature, die, 1.0)], _).
	
これらはピョン吉（知ってる？）が50%の確率でカエルであるという事実と、以下カエルは両生類であり両生類は生き物であり生き物は死ぬという事実を表している。

ここでピョン吉が死ぬ事についての確率Pと理由Rを求めるには、

	?- meta(pyonkichi, die, P, R).
	P = 0.5,
	R = [(pyonkichi, frog, 0.5),  (frog, amphibian, 1.0),  (amphibian, creature, 1.0),  (creature, die, 1.0)] .
	
ふむふむ。

#ヲタクは黒い髪の女が好き 

メタ述語においてAやBは別にシンボルでなくてもいい。例えば『ヲタクは50%の確率で黒い髪の女が好き』という規則は次のように記述できる。

	meta(wotaku, (likes, O), 0.5, R, _) :-
	    meta(O, woman, 1.0, R1),
	    meta(O, (hair_color, black), 1.0, R2),
	    append(R1, R2, R3),
	    append([(wotaku, (likes, [and, woman, (hair_color, black)]), 0.5)], [[and | R3]], R).

ここで黒い髪の女サザエさん登場。

	meta(sazaesan, woman, 1.0, [(sazaesan, woman, 1.0)], _).
	meta(sazaesan, (hair_color, black), 1.0, [(sazaesan, (hair_color, black), 1.0)], _).

そして俺様登場。

	meta(ossan_buhibuhi, wotaku, 0.5, [(ossan_buhibuhi, wotaku, 0.5)], _).

俺様がサザエさんを好きな確率Pと理由Rは

	?- meta(ossan_buhibuhi, (likes, sazaesan), P, R).
	P = 0.25,
	R = [(ossan_buhibuhi, wotaku, 0.5),  (wotaku, (likes, [and, woman,  (hair_color, black)]), 0.5), [and,  (sazaesan, woman, 1.0),  (sazaesan, (hair_color, black), 1.0)]] .

とまあ、このような次第である。

#文脈の保持

しかし上でメタ述語が行った推論過程を人間の思考と照らし合わせた時、不自然な点がある。文脈がないのだ。

ピョン吉はカエルに置換されたのちピョン吉である事の情報が失われてしまうし、俺はヲタクに置換されたのち俺である事の情報が失われてしまう。

人間がピョン吉についてそれが死すべき生物なのかを考える時、結論の最後までピョン吉を忘れる事はない。問題を抽象化する場合でも、常に具象と行き来し妥当性を検証しながら考えるはずだ。

このような文脈の喪失は、明らかにシンボルが別のシンボルに置換される事により起こっている。そこでシンボルを全てタプルに代え、常に文脈を受け渡しながら推論するように改良する。

	meta((pyonkichi, C), (frog, C), 0.5, [(pyonkichi, frog, 0.5)]).
	meta((frog, C), (amphibian, C), 1.0, [(frog, amphibian, 1.0)]).
	meta((amphibian, C), (creature, C), 1.0, [(amphibian, creature, 1.0)]).
	meta((creature, C), (die, C), 1.0, [(creature, die, 1.0)]).
	
	meta((pyonkichi, [(this, pyhonkichi)]), (frog, C), P, R)
	?- meta((pyonkichi, [(this, pyhonkichi)]), (die, C), P, R).
	C = [(this, pyhonkichi)],
	P = 0.5,
	R = [(pyonkichi, frog, 0.5),  (frog, amphibian, 1.0),  (amphibian, creature, 1.0),  (creature, die, 1.0)]
	
ここでは文脈Cが活用される事は一切ないが、[(this, pyonkichi)]という情報が最後まで保持されている事が分かる。

次にヲタクは黒い髪の女が好きという規則について、『男のアイドルオタクまたはアニメオタクは黒い髪の女が好き』と変更してみる。いい加減キモいw

	meta((wotaku, C, J), (likes, C, O), 0.5, R, H) :-
	    nonvar(C),
	    nonvar(J),
	    member(J, [anime, idol]),
	    member((this, T), C),
	    meta((T, []), (man, _), 1.0, R4),
	    meta((O, [(this, O)]), (woman, _), 1.0, R1, H),
	    meta((O, [(this, O)]), (hair_color, _, black), 1.0, R2, H),
	    append(R1, R2, R3),
	    append(R3, R4, R5),
	    append([([and, (wotaku, J), (this, man)], (likes, [and, woman, (hair_color, black)]), 0.5)], [[and | R5]], R).
	
ここでは文脈Cを活用し、男のヲタクであるか確認している。文脈から取り出した情報を元にクエリを行う場合、文脈は空にする必要がある。そうしないと文脈から取り出した情報を元に行うクエリの先で更に文脈から取り出した情報を元にクエリを行う事になり、無限循環に陥る。

上の meta((T, []), (man, _), 1.0, R4) というのを meta((T, [(this, T)]), (man, _), 1.0, R4) とするとスタックオーバーフローするし、meta((T, [(this, T)]), (man, _), 1.0, R4, H) とすると循環論法のチェックに引っかかり偽となる。

なので、文脈から取り出せる情報は文脈を必要としない情報に限られる。これは人間でも同じ…たぶんねｗ

そういうわけでサザエさんと俺に関する事実についても以下のように変更する。

	meta((sazaesan, C), (woman, C), 1.0, [(sazaesan, woman, 1.0)], _).
	meta((sazaesan, C), (hair_color, C, black), 1.0, [(sazaesan, (hair_color, black), 1.0)], _).
	meta((ossan_buhibuhi, C), (wotaku, C, anime), 0.5, [(ossan_buhibuhi, wotaku, 0.5)], _).
	meta((ossan_buhibuhi, C), (man, C), 1.0, [(ossan_buhibuhi, man, 1.0)], _).
	
クエリの結果は良好である。

	?- meta((ossan_buhibuhi, [(this, ossan_buhibuhi)]), (likes, C, sazaesan), P, R).
	C = [(this, ossan_buhibuhi)],
	P = 0.25,
	R = [(ossan_buhibuhi, (wotaku, anime), 0.5),  ([and,  (wotaku, anime),  (this, man)], (likes, [and, woman,  (hair_color, black)]), 0.5), [and,  (sazaesan, woman, 1.0),  (sazaesan, (hair_color, black), 1.0),  (ossan_buhibuhi, man, 1.0)]]
	
規則を書くのが面倒そうだと思うかもしれないが、これはたぶんパターン化して自動生成できると思う。

#おわりに

このメタ述語は命題をどう記述するか、どう解釈するかが全く自由なので、汎用の証明器と言ってもいいんじゃないかと思う。気が向いたら方程式を解いたりするのもやってみたい。

しかし万能の証明器ではないのであって、例えば幾何学の証明で用いる補助線のように新しいアイデアを加えて何かを説明する事はできない。あくまで知識の枠内で成立する事を探索しているだけだ。

始めのブラックボックス問題に立ち返ると、それで充分必要を満たすのではないかと思われる。AIが自分の結論を説明できない時、それをどう評価するかは人間次第だ。

いじょう