楽しい GETA はお好きですか?(GETA-Ruby ブリッジ公開)

趣旨

GETARuby を使って操作する GETA-Ruby ブリッジを作ってみた。Ruby の拡張ライブラリの勉強も兼ねてのことだ。久しぶりの C プログラミングだったが、Ruby の拡張ライブラリの書きやすさは異常。まつもとさんのプログラミングしやすさへのこだわりが C の世界にも貫かれているのはすごい。今回の GETA-Ruby ブリッジは GETA 2 用。かなりコツはつかんだので、GETA 3 用のブリッジを書くのはそれほど難しくないかも。

前提条件

  1. OS は Linux でだけ試した。FreeBSD でも動くとは思う。他の OS はよくわからない。
  2. Ruby 1.8+
  3. サンプルコードを実行するときには GETAROOT 環境変数GETA のインストールディレクトリを指すようにしておくこと。

サンプルコード

$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..")))

require 'geta/wam'
require 'geta/wam_builder'

include Geta

## Part A:  WAM インデックスの生成
builder = WamBuilder.new("mytest")
builder.add("X", "A", 2)
builder.add("X", "B", 1)
builder.add("Y", "B", 2)
builder.add("Y", "C", 3)
builder.build_index

wam = Wam.new("test3")

## Part A:  wsh() 連想計算
query_list = [{ :name => "A", :TF_d => 1 }, 
              { :name => "B", :TF_d => 2 }]
# wsh(軸, クエリリスト, 類似度定義定数, 最大結果個数)
puts wam.wsh(WAM_COL, query_list, WT_SMART, 10).inspect
#=> [{:DF=>2, :DF_d=>2, :weight=>0.297064010862814, :name=>"X", :TF_d=>3, :id=>1, :TF=>3}, 
#    {:DF=>2, :DF_d=>1, :weight=>0.0, :name=>"Y", :TF_d=>2, :id=>2, :TF=>5}]

## Part C: assoc() 拡張連想検索
query_elem_set = ["A", "B"]
puts wam.assoc(query_elem_set, WAM_COL).inspect
#=> ["B", "A", "C"]
Part A: WAM インデックスの生成

WamBuilder というクラスを使う。昨日のエントリと同じ、

A B C
X 2 1
Y 2 3

という行列を生成し、WAM のインデックスを構築している。まず add() メソッドで行列の各セルの情報を内部的にハッシュに溜め込んでおく。build_index() でテンポラリファイルとして、頻度ファイル(freqfile) をつくり、$GETAROOT/sbin/mkw コマンドを実行して、WAM インデックスを構築する。

Part A: wsh() 連想計算

昨日のエントリと同じ、連想計算のクエリである。だが、こちらのほうがずっと見やすいと思う。実際、C のインターフェイスからあまり使われないと思われる引数は省略して Ruby 版の wsh() メソッドを作った。上のコメントを見てもわからなかったら、ソースコードを当たってほしい。

Part B: assoc() 拡張連想計算

たとえば GETA チュートリアル Perlインタフェース活用術 5. 文書連想検索みたいな計算を簡単にできるようしてみた。あくまでも試みのインターフェイスだけどね。たとえば、

query_elem_set = ["A", "B"]
 wam.assoc(query_elem_set, WAM_COL).inspect

が何をやっているか説明しよう。単語集合["A", "B"] から wsh() を使って、類似度の高い文書群 ["X", "Y"] が得られる。そして、今度はこの文書集合 ["X", "Y"] をクエリ入力として wsh() をもういちど呼び出し、これに類似度の高い単語群 ["B", "A", "C"] (類似度準)を得ている、というわけだ。つまりある軸の要素集合に関連する同じ軸の要素集合を求めることができるという意味で、連想検索らしい検索だといえるだろう。 (ふつう連想というのは、ある人を見て、別の人を思い出す、というように、同類の他のものを思い出すのが基本であるので) 同様に文章集合 => 文章集合などという検索も assoc を使って可能。この assoc() メソッドは Ruby でたった 10 行程度のメソッドだから読めば処理内容は比較的簡単に理解できるはず。

どうですか? Ruby だと簡単な感じがしませんか?ひひひ(と Ruby 教の勧誘開始)

インストール

簡単とはいえば簡単だが、拡張ライブラリのコンパイルが必要なので、一発でインストールというわけには行かない。まあそのうち gem か Rails プラグインにでもしようかとも思うのだが・・・。

以下の手順でインストールする。

  1. インストールするディレクトリを決める。Ruby のロードパス($LOAD_PATH) が通っているディレクトリならばどこでもよい。/usr/local/lib/ruby/site_ruby/1.8/ あたりも候補である。とりあえずインストール先ディレクトリを $INSTDIR とする。
  2. % cd $INSTDIR
  3. % su # 必要ならば root になる。
  4. % wget http://softculture.com/download/geta_ruby.tar.gz # ソースコードをダウンロード
  5. % tar zxvf geta_ruby.tar.gz # 解凍
  6. % cd geta
  7. % ruby exconf.rb # Makefile 生成
  8. % make # RubyGETA をつなぐ共有ライブラリ(.so) を構築

アンインストールしたくなったら $INSTDIR を丸ごと削除。たとえば % rm -rf $INSTDIR とすればいい。