29このサイトについて本サイトは舞台に立てるロボットを目指して、私が取り組んでいるプロセスを、主として記憶のために書き連ねているものです。日本語wikipediaをprologの二分木で処理するパフォーマンス現在、日本語wikipediaの50%を二分木化したが、そのデータを使って、およそのパフォーマンスがわかってきた。この段階でのファイルサイズは、3.68Gバイト。全てのwikipedia本文を二分木化すると7Gバイトになるということだ。これをswi-prologで読み込ませると(ルールファイルも読み込ませたが、こちらはサイズはとても小さい)、読み込みに約30分かかる。これは、前にも予想した通りだ。すると、swi-prologの実行プログラムのメモリ占有量が15Gバイトくらいになる。Proは64ギガ積んでいるので、それから見ると余裕がまだあるのだが、大きいことは間違いない。それで、例えば、「ロボット」という語を「は」という助詞付きで検索させると、次のような感じの結果を303行出力する。ロボットは使われてきた/この303行を出力するのは約1分で、1秒あたり5行出力していることになり、検索は、超高速だ。読み込んだ日本語wikipediaの二分木をswi-prologのqsave_programで保存する。保存は、数分しか狩らなかったと思う。ここだけは計っていない。短時間で保存できたのだ。保存した結果のバイナリファイルは、2.5Gバイトだった。これは、実行形式になっているので、そのまま(swi-prologを開始することなく)実行できる。コマンドを打って、prologのプロンプトが出るまで、40秒しかかからなかった!!超早い。巨大なデータも、一旦、バイナリ形式(swi-prologの内部表現形式)に変換して保存すると、超高速で実行可能な状況になるのだ。確認する春休みに入って時間も十分あったので、色々回り道をしてしまった。講義で、雑談に入ったら元に戻らないということがよくあるが、それと同じようなことが起きそうだった。それで、改めて、何をやろうとしていたのかを確認しようと思った。12月の記事「短文の要約のアイデア」である。この記事の要点を再掲すると次のようになる。「私が目標とするところからして、今、芸ロボットの到達点は50%くらいだと思っている。短文要約が大きな問題なく、人と同じくらいのレベルでできるようになれば、この到達点は70%くらいまでいくだろう。・・・・ではどうすれば良いのか。一つ頭に浮かんでいるのが、要約対象が含む語の主要なものが含まれている、より短い文章の用例を探すことだ。同じ語については、あるかもしれないが、探すのが大変すぎる。・・・・そこで、言葉をグループ化する。言葉は、ある種の階層性を持っているのである。・・・・このグループ化、階層性を表現するために、類語辞典を使うことができる。類語辞典のコード番号を用いて、日本語ウィキペディアの全文章を用例化する。短文要約については、役に立ちそうな研究が極端に少なく、複数文章のよう役とは違って自然言語処理の高度な実践が必要になる。次に、1月の記事「prologと自然言語解析」である。要点は次のようなものである。「wikipediaのデータも、すべて、「論理的な言い換え」、「極端に複雑なトートロジー」である。これを表現するのにふさわしい言語は、論理型の言語だと思った。prologに至った。本文データのほとんどを、prologの宣言とルールに変換できないかというのが、今、考えていることの中心点である。」この二つは似ているが、道は異なっている。第一のものは、単文要約という具体的な目的に沿って、手順も、用例を捉え、それを類語によって一般的にフォーム化するというところまで、具体的になっている。第二の道は、知識をどう表現するかを課題にしている。コンセプトを語るのが目的になっている。今、wikipediaデータがprologの宣言文となっている段階なので、それはある意味、どちらに向かうこともできるベースを作っているとも言える。どちらにしても、prologに変換されたwikipediaのデータは膨大で、おそらく、全て完成して、swiprologに組み込めたとしても、組み込み自体に1時間かかるというものになるだろう。クエリにもある程度時間がかかることが考えられ、その状況でどう実用化させるのかは不透明だ。人工知能の分野では、ディープラーニングなどの階層的ニューラルネットワークが脚光を浴びている。確かに、驚くべき成果を挙げているのだから、それは当然のことである。それが人間の脳のニューラルネットワークをシミュレートしているかといえばそうではないだろう。ディープラーニングが、その基礎的パーツとして神経回路網的構造を持っていることは確かだが、人間の脳もそのようにシステマティックに階層化されたネットワーク層を積み重ねているとは到底思えない。人間の脳は、もっと非構造的システムのはずだ。脳には、領域ごとに違った機能を果たしていることはわかっている。その領域そのものが莫大な冗長性を持ったものであり、漠然とした機能の瞬間的作用から、人間の意識を想像している感じなのである。いうものは世に出されていた。名前は知っていたのだ。当時の、バックプロぱゲーションなどを実装した並列処理システム、ニューラルネットワークの勢いの中で、真剣に考えてみたいテーマではなかったから、具体的にどのように実装するなどというところまでは全く行かなかった。今この時に、改めてその内容を捕まえてみると、とても興味深い。人間の脳は、きっとこんな感じなのだと思わせる、単純で、それでいてニューラルネットワークらしい漠然として機能を有している気がしてきた。その理論の中身を捉えてみた。それは以下にまとめておいた。そのものではない情報から記憶を再現できるのは、パターンが、そのパターンの次元倍のネットワークの中に、パターン情報を分散させるからなのである。原理的なアイデアはこれに尽きると思う。今日のコンピュータ機能の進化した状況の中で、この単純さと優れた機能は改めて見直されるべきだと思う。先の記事の段階で無視した、prolog化した文書の中にあるリストを処理可能にした。)).追加したことは、(1)の二行目に、目的とする従属語がリストの場合でもtrueになるようにしたこと。swi-prologの組み込みルールのmemberを使っている。(2)の表示ルールで、項目がリストの場合も表示するように二行目を加えた。実行例は次のようになる。.1.は、出力時のリスト処理で、リストをそのまま出力している例だ。2.は、リストの中の文字を検索し、出力している。リストの中にはもともと[通じて,通じる]という、表現型と原型が含まれていたのだが、その表現型の方を検索し、出力している。この場合は、表現型が指定されているので、リストの出力はない。3.は、末端の語を出力させただけである。4.は、二つのリストを出力した例。5.は、「または」の二つ目の山の中にある語を出力させてみた例である。全て、問題なく、狙った通りに出力している。定義をprologの宣言文にするプロセスを書く予定だったが、少し後回しにして、前の記事の宣言文フォーマットを改訂する。前のような構成では、「は」、「と」とか言葉をつなぐ助詞のような項目が関係子の名前として使ったが、こうすると、助詞そのものを扱うときに面倒になる。そこで、普通の二分木のように、ノードの名前を統一する。ここでは、関係子をnodeと言うように記載しよう。日本語の文章を、完全な二分木で表現するような試みは、他にあるのだろうが、私はみていない。二分木を構成するノードは全て次のようになっている。node(結合子,左項,右項)結合子は、助詞など、名詞や動詞をノリのようにつなげるものである。ノリがノードになっているのがこのシステムの最大の特徴であると言っても良い。左項や右項は、「語」か「ノード」である。改良したプログラムの全体を以下に示しておく。)).後半部分が、宣言に再構成された文章である。プログラムそのものの説明は後回しにして、まず、動かしてみよう。いうテキストファイルにしたとする。geinin3.swiで、swi-prologに読み込み、コンパイルする。以下のように、実行を試みる。.最初のものは、「道」にかかる言葉をフレーズとして表示している。[通じて,通じる]にぶつかっているので、そこで表示が止まって、falseになっている。このリストの場合の処理は、次の記事(3)で対応しているので参照されたい。最後のものは、最後のフレーズから取り出してみたものだ。リストに一旦引っかかると、エラーを出してしまう面もあるようだ。それもまた、チェックしていこうと思う。プログラムの解説をしておこう。(1)の部分は、基本的なルールである。その最初のものは、終端条件である。指定された用語と、ノードの右側の項目が一致した場合は終了である。それと同時に、A,Bに当たる情報を保持するようにしている。2番目の指揮は、左側のノードへの検索であり、3番目のものは、右側のノードへの検索である。再帰的に定義されている。A,Bの語情報を維持している。(2)は、質問の開始節である。sentence(T)は、のちに作成した二分木データをTに取り組むための関係子(?)である。sentenceは、ルートノードと考えれば良い。X,A,Bから、検索によって得られた知識を表示させている。(3)は、再帰的に、ノードの内容を表示させて、元の文章を再現している。最初の説は、アトムの場合は、そのまま表示させるというものである。Nがノードであることがわかっているので、ユニフィケーションによって、X,Y,Zの値を得ているのである。(4)は、二分木で表された文章である。二分木の作り方は他にも色々ある。これは、私が直感的に作ったものであるが、本来目指しているのは、実際のデータをcabocha等で構文解析し、JAVAのプログラムで作成しようと考えているものである。人工知能wikipedia「芸人」の定義とprolog(1)これまで説明した、prologを自然言語処理に用いる手法を少し応用することを考える。一例として、wikipediaの「芸人」という項目冒頭にある次のような文章への応用を念頭におく。「芸人とは、なんらかの技芸や芸能の道に通じている人、または身に備わった技芸や芸能をもって職業とする人のことを指す日本特有の概念である」これを、これまでの記事を踏まえた形で、直感的な形でprologの宣言文にする。括弧がネストしているので、タブでその関係を表現する。predic_y)という形になっている。芸人のwikipedia表現したんは、prologで次のように表される。))かっこの対応関係が複雑で、何度も修正した。最終的にprologのコンパイルに成功した。apropos(Word).エラーがないではないか!!と敢えて書きたくなるくらい何度も失敗した(笑)。netbeansでやった)。文章をほとんどそのまま、prolog化できるというのは、とても重要なことである。してみると次のように、インデントが取れた形で組み込まれている。概念))).素晴らしい(ほぼ自画自賛)。クエリ(問い合わせ)もしてみる。概念)).ちゃんと答えてくる。...の部分が省略されていることが気になる。述語をそのまま出していることについては、これからなんとでもなるだろう。述語を日本語に変換するシステムは難しくない気がするから。先の宣言文に戻って、説明すべきことを付け加えておこう。これは、私が直感的に(日本語を使っている私の感覚での意味)変換した。(システマティックな変換については、次の記事にもちこそうと思っている。)(1)三つのリストが加わっている。[通じて,通じる]、[備わっ,備わる]、[もっ,もつ]の動詞については、使われている表現系の他に、原型を次に示しておいた。これについては、活用形をすべてリスト化するつもりでいる。直接的な形容詞や副詞なども、関連語とともになんらかの形で、リスト化する予定である。(2)本来の文書にはない「ところの」という、英語の関係代名詞的なこのを付け加えて、整理している。その辺りが、日本語の曖昧さの無視できないところで、実際のwikipediaのテキストからprolog述語にするときに、こういう処理も必要になるのではないかと考えている。prologは、リスト処理の強みも持っているので、名詞や動詞もなんらかの形でリスト化する、不可分の言葉をリストで処理するなどの、システマティックな使いからを考えていきたい。構文解析をもとに、prolog化することについては、次の記事にする。記憶に残ったprologのプログラムなるほどと思ったprologのプログラムをメモがわりに記載しておく。引用元は以下で、文字コードをEUCにする必要がある。'本').実行してみる。変数Lで、リストを受け取る。最初の言葉に置き換えをして、残りに自分を再帰的に呼び出している。語順とprolog要は、前の記事の続きである。次のような、prologファイルを作ろう。(X,A),で(Y,A),を(Z,A).%%%%%%%%%%%%%%%%%%%%要するに、構文解析で、すべてが最終フレーズにかかっている、先の例の場合、語順をどう変えても、意味は通じるということを示しているのである。読む))).は、すべて「true」となる。この三つの言葉は、ほとんど同じ意味なのだが、逆に、微妙に違ってもいる。それは、表現できていない。助詞「で」のprolog処理:構文解析さらに、「ニワトリは、庭で卵を生む」となったらどうだろう。素直に考えれば、prologに次の宣言文を加えれば良いということになる。質問は、ニワトリはどこで卵を産みますか、という趣旨である。それに「庭」と答えているわけだ。もっともらしいが、ちょっと引っかかる。「を」が「で」の中に入っているのが気になる。逆でもいいのではないかということだ。(ニワトリ,を(卵,で(庭,生む))).これは、構文解析の問題である。そこで、この文章をCabochaにかけてみる。0.000000生ん動詞,自立,*,*,五段・マ行,連用タ接続,生む,ウン,ウンだ助動詞,*,*,*,特殊・タ,基本形,だ,ダ,ダEOSすなわち、ニワトリ、庭、卵、のすべての名詞句が、「生んだ」という動詞句にかかっているのである。*がついた行の2番目の3Dという記号が、3番目の句、「生んだ」への係りを表している。なると、宣言文がは(ニワトリ,生む).で(庭,生む).を(卵,生む).に分解されていると考えてもいいのだろう。(ニワトリ,で(庭,を(卵,生む))).の問い合わせには、「真」を返して欲しい。このこと自体は、prologの規則を使って記述することができる。(ニワトリ,生む),で(庭,生む),を(卵,生む).ということになる。.クエリをかけると、trueとなる。次に、助詞「を」を処理しよう。前と同じ「ニワトリは卵を生む」というデータの中には「を」が入っている。先には、は(ニワトリ,産む(卵)).と知識化したのだが、この後半が良くなかった。そこで、そこを改良して、助詞「を」をオペレータ化をすることにする。(ニワトリ,を(卵,生む)).とても、文章データを基にしたprolog知識としていい線をいっている。ほとんど、文章そのものを形にした感じがある。この知識に対して問い合わせした結果は次のようになる。卵.前半は、「卵というのは、ニワトリが生むものである」というわけである。後半は「ニワトリが生むとしたら、それは卵である」ということになる。面白いのは次の問い合わせである。生む).ニワトリとは何かに対して、卵を生むものであるという、意味を返してきているのである。ここには、プログラム自体と、データを同じように扱うという特色が現れているのだと思う。次のようなことを考える。元々の「ニワトリは卵を生む」という情報の中には、「卵」は「生む」という動詞に結びつくのだという大切な「知識」が含まれている。これも、prolog化できそうな気がする。そこで、を(卵,Z)のユニフィケーションを求めると、次のようにエラーになる。goal)当然なのは当然なのだが、なんとしたものか。生む).を宣言してしまえば、問題はないのだが。なんか方法はあるはずだが、今の私のprologの知識では、なんともならない。宣言文の中にある、相対的に独立した部分知識を取り出す手続きがあればいい。