Link

Stemmerについて

連想計算ではとくに、ngramのように単純に文字列をインデックスの単位とするよりも、意味のある単語単位でインデックスを作成したほうが、個々の単語間の意味関係が反映できるため、一般に検索精度がよいものとなります。GETAssocでは、itbファイルからインデックスの単位の抽出処理をstemmerとして外部プログラムに任せることができます。

日本語の場合

日本語において、単語間に切れ目が存在しないため、文字列を単語ごとに区切る処理が必要となります。この処理を形態素解析と呼び、日本語の形態素解析器を用いれば文字列を単語ごとに区切ることができます。また日本語の形態素解析器の多くは、動詞や形容詞のような活用する語について、その基本形を同時に出力できます。GETAssocでは、次の2つの形態素解析器を簡単な設定で利用できる仕組みを用意しています。

Mecab

Stmdのコンパイル時には次のように指定してください.

./configure --with-icu-config=/usr/bin/icu-config \
            --with-defaultstemmer=MECAB \
            --enable-mecab=yes \
            --with-mecab-config=/usr/local/bin/mecab-config

ChaSen

Stmdのコンパイル時には次のように指定してください.

./configure --with-icu-config=/usr/bin/icu-config \
            --with-defaultstemmer=CHASEN \
            --enable-chasen=yes \
            --with-chasen-config=/usr/local/bin/chasen-config

単語辞書について

形態素解析器はプログラム単独では動作せず、どのような文字列を単語と見なし、その品詞はなにか? 活用のある語ではどのような活用をし、基本形は何か?といった単語辞書が必要になります。MecabとChasenでは次の単語辞書が存在します。

  • IPAdic
  • Naistdic IPAdic の ICOT 条項をクリアするとともに、表記ゆれや複合語の情報が付与された辞書です。
  • Unidic Unidicでは、上記2辞書と基本形の位置が異なるためMeCabで使用するときは、stmdのコンパイル時に次のオプションを指定します。
    • unidic-1.3.11 のとき –with-mecab-kihon-index=9
    • unidic-1.3.12 のとき –with-mecab-kihon-index=12
    • –enable-unidic=yesはv1.1から廃止されました。

英語について

Ngram形式について

bigram、trigramが用意されています。

stemmerに、ngram,2を指定することでbigramを、ngram,3を指定することでtrigramを生成できます。

ただし、文字種に関わらず2ないし3文字の列を切り出しますから、英数記号とかな、漢字などとでは切り出される情報量が異なることに留意してください。

任意の外部プログラムの指定(まだ不完全)

stemmerにEXTSを指定することで、任意のプログラムをstemmerとして使用することができます。ただしGETAssocでは、データの受け渡しには次のルールを設けています。

  • 標準入力からデータを読み込み、標準出力でデータを返す
  • インデックスの単位となる要素は、改行区切りで分割する
  • itbファイル形式の?と同じ形式です
  • ‘037’(0x1f)を受け取ったら、そのまま返す
  • 出力はバッファリングせずに必ずフラッシュする

記号類を取り除き、文字種で分割するサンプルプログラムを、ごく簡単にperlで書くと次のようになります。

toknize.pl

#!/usr/bin/perl
use strict;
use warnings;
binmode STDIN, ":utf8";
binmode STDOUT, ":utf8";
$|=1;
while(my $line = <STDIN>){
    chomp $line;
    if ( $line eq "\x1f" ) {
        print $line, "\n";
    } else {
        while($line =~ m/(\p{InHiragana}+|\p{InKatakana}+|\p{Han}+|\p{Latin}+|\p{Number}+)/g) {
            print $1, "\n";
        }
    }
}

外部プログラムに対する引数はstemmerの指定時に’,’区切りで渡すことができます。

ex. ‘-a’を渡したいとき

stemmer=EXTS,$PROGRAM,-a

複数の外部プログラムを使用したいとき

実験や評価のときに複数の外部プログラムを使い分けて、検索結果を比較したいときがあります。そのようなときはEXTSで渡す外部プログラムの指定にシェルスクリプトを用意し、その引数でプログラム名を指定する手法があります。

#stemmer.sh

#!/bin/sh
case $1 in
    test1)
        exec /usr/local/bin/test1;
    test2)
        exec /usr/local/bin/test2;
    ...
esac}
stemmer=EXTS,stemmer.sh,test1

任意のライブラリ関数の利用(まだ不完全)

EXTSは手軽に新しいstemmerを追加できますが、037(0x1f)文字の扱いやバッファリングを抑制しなければならないことなど、扱いにくい面もあります。 Cから呼び出すことができるライブラリが利用できる場合、stmdに組み込むことで、これらの問題を回避することができます。

組み込みには、Cの専門的な知識が必要になりますので、ここではヒントだけ説明します。 まず、ライブラリが提供する機能としてMeCab?のように解析結果をノードとして返すことができるものと、ChaSenのように文字列としてのみ返すものとに分類できます。

前者に分類されるものを利用するときは、mecabutil.[ch]を参考にラッパを作成し、ystem.[ch]、stmd.cのMECAB、USE_MECABがからんでいる部分をコピーして増殖させ、それを修正します。最後に、configure.inも同様に変更してaclocal, libtoolize, autoconfをかければ完了です。後者の場合は、USE_CHASENを参考に同様の作業をすればよいのですが、文字列をパースする必要があるため、ちょっと面倒なことになるでしょう。