月別アーカイブ: 2016年1月

検索エンジン自作入門/ wiserのPython移植(5)

今回は、書籍のページ順と前後しますが、ふたつのポスティングリストのマージを行うmerge_postings です。書籍のページは80ページです。

引数は、マージするポスティングリストふたつです。

merge_postingsは、document_id の小さい方のポスティングを選んで結果のリストにマージしていくというC言語版の処理を、ジェネレータ関数のnext_pl_entry を呼び出しながら行っていく作りにしてあります。

ジェネレータをきちんと使ったことがなかったのですが、今回勉強になりました。繰り返しをスッキリ書けてよいですね。

次回は、今日作った関数を呼び出す merge_inverted_index と update_postings です。メモリ上のテンポラリ転置インデックス同士や、ストレージ上の本体の転置インデックスとをマージします。

人工知能の「面白さ」へのかかわり

昨今、言葉がビッグデータより遥かにキャッチーなせいか、なんでも人工知能といい過ぎではないでしょうか。こちらのこのカテゴリでは、少し違った立ち位置から人工知能について考えてみたいと思います。

問題意識をハッキリさせるために、けっこう前のことですが去年の夏、茅ヶ崎市美術館で行われた「正しいらくがき展」を見てきた感想など。

http://www.chigasaki-museum.jp/natsufuku/2015/

この、SEMI-SENSELESS-DRAWING-MODULES は、周囲の気温・湿度・騒音などの情報をインプットし、それをもとにシアン・マゼンタ・黄色の3色でを書くマシンです。札幌で展示したものを、茅ヶ崎に持ってきたそうです。

この企画、人間の創造を模倣・学習・偶発性と分類して、それを機械に実装できるかという試みの「模倣」バージョンだそうです。札幌でマシンが描いた絵を、茅ヶ崎の子供たちが「模写」しまして、それをマシンがさらに模写するという企画でした。札幌でのマシンの絵・それを子供が模写した絵・子供の絵をマシンが模写した絵の3つが展示されておりました。

この展示を見て、私の中の日ごろの鬱憤が爆発する思いでした。撮影可だったため写真を撮ってきました。※全体ではなく一部のアップです。

子どもの模写と思われる

子どもによる模写

マシンの絵

マシンの絵

撮影したときに記録していなかったので、どの写真がどの段階のものか判然としなくなってるんですが、確実なのは上の写真は子供による模写であることです。なぜなら、模写元のマシンの絵にはない星形が勝手に付け加えられているからですね。下の絵はマシンのものであるのも確実で、札幌のオリジナルの絵も子供の絵の模写も基本変わらずこのようなものです。子供の付け加えた星形が消えています。

子どもは、このマシンの絵を模写することが楽しかったのだろうか?と考えると、まず面白くないだろうなと思うわけです。そこにない星形を付け加えたところに、「つまらないなあ」という抵抗を感じます(笑) 子供の絵をマシンが模写すると、その星形が消えるのも謎。これが再現性のあることだとすると、大変大きなことなのですが・・・さて。

抽象画のようで綺麗といってる人がいるようですが、グーグルかどこかのAIが描いた絵のように、いってみれば抽象画しかマシンは描けないと考えられます。印象派のような絵を出力できるようになるのか?なったとして、その出力の過程は印象派の作家の絵を描くときの脳・及び身体プロセスとは明らかに異なるでしょう。そういう出力した絵に意味はあるのかないのか。

人工知能のみならず情報技術の過度な導入により、「おもしろくない」世の中になっているというのが、私の問題意識です。意識高い人の話す内容が詰まらないのと、何だか似てませんか(笑)

とにかくさ、子供はこの模写拷問じゃなかった?そうでもないの、最近の子は。

個の企画、模倣・学習・偶発性とバージョンがあり、一番興味深い偶発性はまだICCでやってますね。行ってくるとします。こちらは、模倣バージョンのマシンが気温や騒音などを入力としてましたが、偶発性バージョンは、作家の姿のプロジェクションを投影した空間を鑑賞者含めて入力するらしいので、もっと面白いかもしれません。

同じ作家による SENSELESS-DRAWING-BOT というものがあります。

 

これは、原理的にほぼ同じながら私は逆にかなり面白いと感じるのですが、どうですか。理由を考えると、SEMI-SENSELESS-DRAWING-MACHINE と違って、

  • 重力が作用している
  • 機械が物理的に大きい

これらの要因が大きい気がしますね。最近は身体性がクローズアップされてきてますので、人工知能の世界も変わって行くのかもしれません。

検索エンジン自作入門/ wiserのPython移植(4)

前回実装した text_to_postings_list 内で呼んでいる、token_to_postings_list を実装します。書籍のページは75ページです。この関数は、一つのトークンを受け取ってテンポラリ転置インデックスに登録します。

引数は、

  • document_id : 文書ID
  • token : トークン
  • position : トークン出現位置
  • ii_buffer : テンポラリ転置インデックス

となっています。

オリジナルはマクロでトークンに紐づいたポスティングリストを探しますが、Python版では関数 find_token_from_index により検索します(7行目、コード略)。

その後は、紐づいたポスティングリストの有無によりパラメータをインクリメントしたり、新しくインデックスやポスティングリストのエントリを生成したりします。エントリの生成はC版で専用に関数を作ってますが、Python版ではインスタンスの生成で行うことになります。

ところで、Pythonのユニットテスト界隈はどうなっとるんじゃと調べてみたのですが、unittestから始めてみるのが無難みたいですね。こうやってコードを掲載していってますが、ngram_next 以外はテスト結果を載せてませんね。今日の token_to_postings_list もお手製のテストは通過してますが、そろそろ unittest を使ってみようかと思ってます。

次回は、text_to_postings_list から呼び出される merge_inverted_index です。メモリ上の二つの転置インデックスをマージします。

検索エンジン自作入門/ wiserのPython移植(3)

前回作成した add_document で呼び出している未実装の関数を実装していきます。

add_document の4行目と5行目で呼び出している、db_add_document と db_get_document_id は、データベースを扱う処理です。転置インデックスの本体はDBに格納します。wiser では SQLite を使用していますが、移植にあたって MySQL を利用することにします。Python からの MySQL の利用は、MySQL Connector/Python を利用することにしました(簡単なので)。

https://dev.mysql.com/downloads/connector/python/

これらの関数のコードについては、検索エンジンの本筋ではないので省略します。

次に、12行目で呼んでいる転置インデックスの構築処理 text_to_postings_list に入って行きます。

渡された文字列(文書の本文)をトークンに分解し、それを token_to_postings_list (未実装)に渡してポスティングリストを作成します。既存のテンポラリ転置インデックスがあれば、できたポスティングリストとマージします。なければ新規にテンポラリ転置インデックスを生成します。

Python のドキュメントスタイルなどはまだよくわからないので、ここで引数の説明をしておくと、document_id はデータベースに登録された文書のID、text は処理対象の文書の本文、n は何-gram で切り出すか、ii_buffer はテンポラリ転置インデックスになります。

文書をN-gramに分解する関数 ngram_next を中で呼んでいます。ここは、C版では for 文の条件部で逐一呼び出す形になってますが、Python版では一回の呼び出しで文書内のすべてのトークンを返す作りに変えてあります。

is_ignored_char は検索対象外文字列を弾くためのものです。コードは省略します。

ngram_next はこれで実行できるようになりましたので、bi-gram で動かしてみます。

結果は以下の通りです。bi-gram に分解できました。

未実装の token_to_postings_list と merge_inverted_index を、次回実装していきます。

検索エンジン自作入門/ wiserのPython移植(2)

転置インデックスの構築のエントリポイントの関数 add_document です。書籍のページは69ページになります。

文書をN-gramトークンに分解し、転置インデックスを構築していきます。まずメモリ上のテンポラリ転置インデックスが更新され、それがある程度大きくなればストレージ上の本体の転置インデックスとマージされます。

テンポラリ転置インデックスは、C言語版ではwiser全体の環境情報を保持する構造体にあります。Python版ではクラスを作成します。

wiserは、Wikipediaの情報のXMLを解析して転置インデックスを構築します。

C言語版では、add_document は XML のロード処理のコールバック関数として実装してあります。Python版では、呼び出し側がまだ決まってませんので、とりあえず引数としてテンポラリ転置インデックスのインスタンスを渡すようにしておきました(tmp_ii)。

いくつかの関数は未実装なのでこのままでは動きませんが、この後実装していきます。

検索エンジン自作入門/ wiserのPython移植(1)

2014年に発売された技術評論社の「検索エンジン自作入門」という本があります。しばらく放置していたのですが、この本のC言語で書かれたコードをPythonに移植してみます。

C言語は学生時代に普通に勉強して以来あまり読むこともなかったのですが、ポインタ以外は何とかなるものですね。ポインタも文字列の扱いがほとんどですし。

書籍のサンプルコードのダウンロードはこちらからできます。

まずは、胆となる転置インデックスとポスティングリストのデータ構造です。

構造体をクラスに変更しただけになります。

次回から、転置インデックスの構築の処理を移植していきます。