助詞「で」のprolog処理:構文解析

さらに、「ニワトリは、庭で卵を生む」となったらどうだろう。素直に考えれば、prologに次の宣言文を加えれば良いということになる。

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

例えば、これに

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

と問い合わせると、

X = 庭.

と返してくる。質問は、ニワトリはどこで卵を産みますか、という趣旨である。それに「庭」と答えているわけだ。

一見もっともらしいが、ちょっと引っかかる。「を」が「で」の中に入っているのが気になる。逆でもいいのではないかということだ。

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

これは、構文解析の問題である。

そこで、この文章をCabochaにかけてみる。

$ cabocha -f1
ニワトリは庭で卵を生んだ
* 0 3D 0/1 -1.268576
ニワトリ	名詞,一般,*,*,*,*,ニワトリ,ニワトリ,ニワトリ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
* 1 3D 0/1 -1.268576
庭	名詞,一般,*,*,*,*,庭,ニワ,ニワ
で	助詞,格助詞,一般,*,*,*,で,デ,デ
* 2 3D 0/1 -1.268576
卵	名詞,一般,*,*,*,*,卵,タマゴ,タマゴ
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
* 3 -1D 0/1 0.000000
生ん	動詞,自立,*,*,五段・マ行,連用タ接続,生む,ウン,ウン
だ	助動詞,*,*,*,特殊・タ,基本形,だ,ダ,ダ
EOS

すなわち、ニワトリ、庭、卵、のすべての名詞句が、「生んだ」という動詞句にかかっているのである。*がついた行の2番目の3Dという記号が、3番目の句、「生んだ」への係りを表している。

そうなると、宣言文が

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

に分解されていると考えてもいいのだろう。この三つの宣言が真の時は、

?- は(ニワトリ,で(庭,を(卵,生む))).

の問い合わせには、「真」を返して欲しい。このこと自体は、prologの規則を使って記述することができる。

は(ニワトリ,で(庭,を(卵,生む))) :- は(ニワトリ,生む),で(庭,生む),を(卵,生む).

ということになる。

次のようなファイル、test2.swiを作成して、

%%%%%%%%%%%%%%%%%%%%%
% 事実の宣言
は(ニワトリ,生む).
で(庭,生む).
を(卵,生む).
% ルール
は(ニワトリ,で(庭,を(卵,生む))) :- は(ニワトリ,生む),で(庭,生む),を(卵,生む).
%%%%%%%%%%%%%%%%%%%%%

$ swirl -f test2.swi

とprologに読み込ませて、

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

クエリをかけると、trueとなる。

助詞「を」の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の宣言とルールに変換できないかというのが、今、考えていることの中心点である。

あらゆる説明は、言い換えに過ぎない:「知っている」という現象(2)

ある対象に対する知識を持っているとは、ある対象を「説明できる」と言えるだろう。説明はある意味きりがない。

「私はなぜ失敗したのですか?」
「君には能力がなかったからだ」
「私にはどうして能力がないのですか?」
「必要な努力を怠ったからだ」
普通この辺りでやめるか・・・・・・
「必要な努力とはどれくらいの努力なのですか」
「結果、失敗しないような努力だ」
こうなると、一種のトートロジーである。

なんでもそうだと思うが、結局説明されるがわが「なるほど」と納得できるほどに、違った言い換えができることが知識の条件なのである。

「卵ってなんですか」
「にわとりが産むものだ」
ここで納得すれば終わりとなる。
「にわとりってなんですか」
「卵から生まれたものだ」

これもまた説明である。後の二つの文は、無意味なものではない。ただ、全体は、トートロジーと言われても仕方がない。

「知っている」とはどういう現象なのだろう(1)

あることに対する「知識を有する」とか「知っている」ということは、いったいどのような現象なのだろうかと考えた。

人工知能に関するチューリングの基準のようなことを考えよう。

例えば、壁の向こうに人かコンピュータがあって、こちら側にいる人間は、その相手に対して質問することができる。質問することはある概念だ。例えば「卵(たまご)」という概念を壁の向こうのコンピュータが知っているかどうかを尋ねて、それが人が答えているかコンピュータが答えているか区別できなかったら、そのような対応ができるコンピュータは、卵という概念を知っているのだ。答え方のルールも必要かもしれないが、その辺は、曖昧にしておく。

人間「卵って知っていますか?」
相手「ええ、知っています」
人間「何をするものですか?」
相手「孵化すれば、親と同じ生物が生まれるものです」
人間「食べられますか?」
相手「ええ、食べることもできます」
人間「どうやって食べますか?」
相手「焼いて食べます」
・・・・・・・

こうやってずっと正しく答えれば、このコンピュータは卵について知っているのだ。このような卵に対する知識を人工的に作りたいと思ったら、どうするのか。

例えば、Wikipediaに書いてある文章を全部調べて、「卵」がどのような文章の中で使われているかを調べれば良い。

unable to launch "cinnamon-session-cinnamon" X session - 云々

タイトルのエラーを吐いて、突然、ロボット制御用に使っているLinux Mint (32ビット)が立ち上がらくなった。ネットには色々書かれているが、私の場合、次の方法で解決した。

(1)エラーメッセージが出ている状態で、Ctrl-Alt-F1でXウィンドウを使わないCUIモードに変更する。

(2)ログインする

(3) $ sudo apt-get install mint-meta-cinnamon を実行する

なぜ、こんなことになるのか、なぜこの方法で解消するのか、一切不明。

両足ジャンプ with DCM

DCMを使ってジャンプさせてみた。

目に見えて飛び上がるまでになっていない。ただ、動きは前より格段に早くなった。ジャンプしそうな雰囲気を出しているし、実際 0.5mm くらいは浮いたような気がしないでもない(笑)

 

NAOQIに付属しているDCMサンプル

NAOQIにDCMのサンプルがついている。=> ココ
fastgetsetsample
という名前になっている。

このなかには、DCMの使い方のいろいろなノウハウが詰まっている。DCMは、単独の動作を直接アクチュエーターやセンサー、LEDに送ることができるが、ここには、同時に、10msecという短い周期で、DCMからよびだすことができるコールバック関数の書き方が示されている。

このコールバック関数に記載すれば、ロボットのボディの全体状況を細かく制御できる。

たとえば、NAOが倒れた瞬間に、すべての関節状態の硬直性を一瞬にゼロにして、破壊を出来る限り回避する力を持っている。これは、NAOが足が地面から離れることをセンサーで感知したり、体の急速な傾きを感知したりして、その瞬間に、Stiffnessをゼロにする操作をしているからである。10msecあれば、その対応は十分できるのだろう。

ジャンプには、このコールバック関数は使わなくてもいいと思った。なにしろ、瞬発力が問題なので。先にも書いたように、コールバックを使わなくても、DCMコマンドを単体で叩いても、高速な動きは作れるからである。

しかし、ジャンプしたあとの体制の制御や、着地のことを考えると、このコールバック関数を使わなくてはならなくなるときが来るような気もするのだ。

NAOのDCMを直接叩く

NAOをジャンプさせようとして、ぬるい関節の動きに失望したという話を前回に書いた。そして、高次のNAOQIのAPIを使うことをやめて、DCMを直接叩くことにした。

まだ、きちんとコントロールはできていないが、試してみた関節の動きは、「すさまじく高速」だった。これで、ジャンプをさせることはできそうだが、コントロールできるかどうかはわからない。