GETA 第2版 類似度定義ファイルの実装

昨日 GETA 第3版のインストールについて説明しておいて、今日はなんで第2版か?と思うかもしれないね。第3版は、情報が少ないのでなかなか扱いが大変なのだ。第3版の方が性能はいいのは間違いないので、とりあえずは第2版で慣れておいて、第3版へ挑戦しようという算段なのだ。

さて GETA 2 では libae.a にある wsh() という関数を使って連想検索を行う。チュートリアル2 libae を使って電子メール検索システムを作るを参照のこと。

wsh() は、簡単に言えば、行(列)の頻度ベクトルから列(行)の頻度ベクトルへの写像だ。「行(列)」とか書くのが面倒なので、ここでは「軸」という概念を定義することにする。(これは別に正式な用語でもなんでもなく、私が説明のために便宜的にでっち上げた言葉なのであしからず)

  • 軸とは「行」または「列」である。
  • 基準軸は、とりあえず注目している軸のことである。
  • 反対軸は、基軸から見て直行する軸のことである。たとえば基軸が行なら、反対軸は列となり、基軸が列なら反対軸は行となる。

軸という概念を使ってもう一度 wsh を説明すると、

  • wsh() は基準軸の頻度ベクトルから反対軸の頻度ベクトルへの写像である。

で、この写像の実装は2つの要素に依存している。

  1. WAM (データを行列で表現したもの)
  2. 類似度関数

1 は自明だ。2 については、次のような問題意識から来ている。文章軸と単語軸から成り立つ WAM において、2つの文章に間で、ありふれた単語(たとえば「です」)が多数共有されていたとしても、それをもって「似ている」と考えるのはちょっと変じゃないの、と。類似度関数は、こういう場合、ありふれた単語の重みを下げ、よりユニークな単語(たとえば「経済」)の重みをあげる、ということをしたりする(らしい)。(というのは私も完全に理解しているわけじゃないからだ)

まあ、いいや。正確性については、誰かに突っ込みを入れてもらうとして、これが実装されている仕組みを調べてみた。

まず、チュートリアル「類似度定義ファイルの基礎」を読んでほしい。

いきなり、

name: WT_TF
0:
1:
2:
        wq(t|q) = TF(t|q);
3: 
        wd(t|d) = TF(t|d);
4:
        norm(d) = TF(.|d);
5:

とかいうのが出てきて、ギョッとした。なんじゃい、これは? C 言語のようにも見えないが・・・。調べてみると、これは、類似定義のためのドメイン特化言語(DSL) であることがわかった。

原理は次の通りである。すべては、$GETASRC/lib/ae/wt というディレクトリで展開するストーリーである。GETA 2 コンパイル時に次のようなことが起こる。

  1. f2c.c がコンパイルされて f2c というコマンドができる。
  2. ./f2c *.f が実行される。*.f は類似度定義ファイルである。たとえば wt_tf.f には WT_TF という類似度定義がある。(上のリストがそうだ)
  3. f2c は *.f のないように基づいて、ステップごとに s0.c, s1.c, ..., s5.c というファイルを作る。この過程で " wq(t|q) = TF(t|q);" のような DSL 表現が "wq = ((double)qp->TF_d)" のような実行可能な C 言語のコードに変換される。
  4. s0.c, s1.c, ..., s5.c は $GETASRC/lib/ae/wsh.c にインクルードされて、コンパイルされる。wsh() は巨大な関数で、これらのコードはすべて wsh() のコンテキストで実行される。

独自の類似度定義を作りたい方は、類似度を定義してみるを参照のこと。