助詞「を」のprolog処理

次に、助詞「を」を処理しよう。前と同じ「ニワトリは卵を生む」というデータの中には「を」が入っている。先には、

は(ニワトリ,産む(卵)).

と知識化したのだが、この後半が良くなかった。そこで、そこを改良して、助詞「を」をオペレータ化をすることにする。つまり、

は(ニワトリ,を(卵,生む)).

とても、文章データを基にしたprolog知識としていい線をいっている。ほとんど、文章そのものを形にした感じがある。
この知識に対して問い合わせした結果は次のようになる。

?- は(X,を(卵,Y)).
X = ニワトリ,
Y = 生む.

?- は(ニワトリ,を(Z,生む)).
Z = 卵.

前半は、「卵というのは、ニワトリが生むものである」というわけである。後半は「ニワトリが生むとしたら、それは卵である」ということになる。少し面白いのは次の問い合わせである。

?- は(ニワトリ,Z).
Z = を(卵, 生む).

ニワトリとは何かに対して、卵を生むものであるという、意味を返してきているのである。ここには、プログラム自体と、データを同じように扱うという特色が現れているのだと思う。

さらに次のようなことを考える。元々の「ニワトリは卵を生む」という情報の中には、「卵」は「生む」という動詞に結びつくのだという大切な「知識」が含まれている。これも、prolog化できそうな気がする。

そこで、

を(卵,Z)

のユニフィケーションを求めると、次のようにエラーになる。

?- を(卵,Z).
ERROR: Undefined procedure: を/2 (DWIM could not correct goal)

当然なのは当然なのだが、なんとしたものか。もちろん、を(卵, 生む).を宣言してしまえば、問題はないのだが。なんか方法はあるはずだが、今の私のprologの知識では、なんともならない。

宣言文の中にある、相対的に独立した部分知識を取り出す手続きがあればいい。(要検討)

格助詞「は」のprolog処理

先の記事で、助詞「の」の prolog処理の例を示したが、格助詞「は」の処理例は以下のようになる。

は(ニワトリ, 鳥).
生む(A, 卵) :- は(A, 鳥).

一行目は、宣言文である。すなわち「ニワトリは鳥である」。二行目は、規則となるで、「鳥は卵を生む」を表している。もう少し丁寧に文に即して言えば「卵を生むものであるためには、それが鳥であれば良い」とも言える。

この知識を利用すると、次のように質問に答えることができる。

?- 生む(ニワトリ,卵).  %一つ目の問い合わせ
true.

?- 生む(ニワトリ,Y).   % 二つ目の問い合わせ
Y = 卵.

となる。一つ目は、ニワトリは卵を生むというのは正しい、二つ目は、ニワトリが生むとしたら、それは卵だろうということを表している。

ただ、ちょっと気に入らないところがある。元々は、「ニワトリは卵を生む」という文章をprolog化したかったのだが、少し趣旨が違ってきたように思う。

は(ニワトリ,生む(卵)).

書けば上記のようになるはずだ。これだけを prologの宣言文とする。すると次のような、問い合わせに対応できる。

%(1)
?- は(X,生む(Y)). 
X = ニワトリ,
Y = 卵.
%(2)
?- は(ニワトリ,生む(Y)).
Y = 卵.
%(3)
?- は(X,生む(卵)). 
X = ニワトリ.

(1)は、現状の知識では、何かを生む何者とは、という問い合わせに、ニワトリならば卵を生むけれどね、という答えしか出さない。(2)ニワトリが何かを生むとしたら、それは卵であると答える。(3)卵を生むものであるならば、それはニワトリであろう、というわけである。

知識が増えたらどうなるだろう。「アヒルも卵を生む」というわけである。宣言文が二つになる。

% 知識の表現
は(ニワトリ,生む(卵)).
は(アヒル,生む(卵)).

すると、先の答えが少し違ってくる。

?- は(ニワトリ,生む(卵)).
true.

?- は(アヒル,生む(卵)).
true.

?- は(X,生む(卵)).
X = ニワトリ ;
X = アヒル.

卵を生むものには、ニワトリもいるがアヒルもいる、というわけである。前者の場合は、

% 知識の表現
は(ニワトリ, 鳥).
は(アヒル, 鳥).
生む(A, 卵) :- は(A, 鳥).

となる。増えた分は単純だ。問い合わせの例は次のようになる

?- 生む(X,卵).
X = ニワトリ ;
X = アヒル.

となる。こっちの方が、単純に思える。ただ、単純な文章が持つ「知識」が、単純に表現されていないから、しっくりいかないのである。

prologと自然言語解析

ニューラルネットワークを基にしたシステムでは、word2vecくらいしか、役に立たなかった。word2vecはとても優れているが、結局、言葉を低次元ベクトルに変換し、言葉の親近度を計るところまでである。

結局、例えば、wikipediaのデータ、情報を知識化するのにはそう言う、ネットワーク系のシステムでは対応できない気がして悩んだ。

なぜ対応できないのか、とどのつまり、言葉がロジック、論理であって、画像認識のような直感的なものとは異なるからなのだ。人間が直感的にやっていること、例えば、画像認識以外にも、将棋や囲碁の形成の判断のようなものには、人間を上回る力を発揮する。しかし、言葉は違う。直感があったとしても、ベースには論理がある。逆かもしれない。直感をベースにした論理というべきか。

wikipediaのデータも、すべて、「論理的な言い換え」、「極端に複雑なトートロジー」である。これを表現するのにふさわしい言語は、論理型の言語だと思った。そして、prologに至った。

prologは、古い、カビの生えたような言語だ。何しろ、私が神戸大学の大学院経済学研究科の最初のゼミで、発表したのがprologを使って経済データのトレンドを判定する、しかも単純に上昇か下降かだけだが、そんな結果を発表するために使った言語だ。指導教員にダメ出しをされて、すぐにその方向はやめてしまったが。それは正しい判断だった。そんなものに使うべきではない。

例えば「ニワトリは卵を生む」という知識があったとしよう。これを、「ニワトリの卵」という表現が正しいかどうかを調べることができる知識に変換することを考える。

(prologは、swi-prologを使用する。Macの場合、brew install swi-prolog で、簡単にインストールできる。)

2 ?- [user].
|: の(X,Y) :- 産む(X,Y).
|: ^D
% user://1 compiled 0.00 sec, 1 clauses
true.

3 ?- [user].
|: 産む(ニワトリ,卵).
|: ^D
% user://2 compiled 0.00 sec, 1 clauses
true.

3 ?- の(ニワトリ,Y).
Y = 卵.

4 ?- の(ニワトリ,卵).
true.

5 ?- 

となる。?-がprologのプロンプトで、[user].は、論理や宣言をプロンプトから付け加えるための、疑似ストリームである。「ニワトリは卵を生む」を
産む(ニワトリ,卵).
という宣言に変換している。
そして、〇〇の〇〇という表現は可能になれば、trueが帰ってくるというわけである。

ここでは、「の」という助詞と、「産む」という動詞をoperatorにしているが、「は」とか「で」なんかも、そのようにして、文章が含意している知識を定式化したいと思うわけだ。

wikipediaの 本文データのほとんどを、prologの宣言とルールに変換できないかというのが、今、考えていることの中心点である。