ずいぶんと前から bogofilter の評価をしているのですが、日本語のメールの判定率がいまいちです。
iconv を使った日本語対応ができるようになっているものの、肝心の単語の抽出ができていないのがいけないのかなぁ…と思い、
bogofilter + kakasi パッチ も最近のバージョンのものは公開されていないようなので、
N-gram による単語分割を組み込んでみました。
N-gram は Unicode のブロックによって N を切り替える複数長 N-gram となっています。
また、プロパティによって記号等を削除(あるいは空白文字に置き換え)を行っているので、判定のノイズの元となるゴミもたまりにくくなっていると思います。
nkf も組み込み可能ですので、パイプで nkf や kakasi を組み合わせないでも bogofilter 単体での日本語メールの扱いができるようになります。
N-gram による単語分割を行うためのパッチは bogofilter-1.0.1-ngram-0.18.patch.gz (2006/1/5 版) をダウンロードしてください。
パッチのファイル名から分かるとおり bogofilter V1.0.1 用なので、V1.0.1 のソースコードを ダウンロードページ よりダウンロードしてください。
これらをダウンロードしたら、
のようにしてパッチを当てます。
パッチが無事あたれば、configure を行うのですが、N-gram による分割を有効にするには --enable-ngram を指定する必要があります。
また、日本語の文字化け対策(メールで指定してあるエンコードと実際のエンコードが違うなど)のため、nkf を利用した自動変換(強制変換?)も利用できます。
こちらは --enable-libnkf を指定してください。
ということで、日本語環境で利用するには、以下のような感じになります。
これでインストールが完了しました。
bogofilter 自体で文字コードの変換と単語分割を行いますので、nkf や kakasi を経由させることなく bogofilter が利用できます。
bogoutil で ngram 関連のオプションが認識されず、設定ファイルと異なるオプション設定で再評価を行ってしまうために登録内容を破壊することが確認できました。 古いパッチをご利用の方は、2006/1/5 版の ngram-0.18 を適用後再コンパイルが必要です。
2006/1/1 に bogofilter V1.0.1 がリリースされましたので、今後は V1.0.1 を扱っていく予定です。V1.0.0 用のパッチは、 bogofilter-1.0.0-ngram-0.18.patch.gz をダウンロードしてください。
N-gram による分割は、まずは Unicode プロパティによって文字の取捨選択を行います。
基本的には、Punctuation, Separator は空白文字に、Letter, Number 以外は無視するようにしています。
次に、Unicode ブロックの種類によって N を変えています。
Hiragana | 3文字 |
Katakana | 4文字 |
CJK Unified Ideographs | 2文字 |
Hangul Syllables | 3文字 |
これ以外のブロックでは、N-Gram による分割をしないので従来どおりの空白による分割になります。
これらの設定は unidata.h で定義していますので変更することもできますし、日本語以外でも N-gram を適用することができます。
ちょっとがんばれば、このデータセットを切り替えるようなこともできますので、同じ CJK 文字でも MIME によって N を変えることもできると思います。
ところが、N-gram による分割をしてみたものの、いまいち判定率が上がらないので辞書の登録内容を眺めていたのですが、
単純な分割では順列組み合わせによる登録単語数ばかり増えてノイズとなっているのかなぁ…と感じました。
そこで N-gram の分割関数をベースにして簡単に実装できるものとして
を実装しています。さらに、分割した単語に対しての選択ルールとして
を実装しています(ただし、これらは N-gram の分割文字数が設定されているブロックにのみ有効ですので、注意してください)。
これらの2つを組み合わせて使うわけですが、途中で切り替えても辞書は変わらないので実運用前に十分テストして、どの組み合わせで使うかを決めてください。
オプションでも設定ファイルでも指定することができますので、サンプルとなるメールに対してオプションを変えてテストをして、
効果の高いものを設定ファイルで指定するようにしたらよいと思います。
個人的には、「ブロックモード」&「長い文字以外を無視する」がいいかなぁ…と思うのですが、登録される単語が減るので初出のスパムに対しての適応性が低下する感じです。
しかしノイズが少なくなるため「unsure」な状態が少なくなり、一度学習させると同類のメールは識別されるようになります。
このあたりはちょっと微妙だと思うので実際に試して実感してください。
ブロックモード以外で --ngram-skip=long を利用すると、分割文字数が設定されているブロックは出力されないので注意してください。
このパッチで追加した単語分割の機能を単独で使えるようにしてみました。
ソースは、ngram_tokenizer-0.18.tar.gz からダウンロードできます。
nkf の組み込みもできますし、オプションも同じものが指定できますので、nkf + kakashi の置換えにも使えるかもしれませんし、
別のプログラムへの組み込みも比較的容易にできると思います。
興味のある方はどうぞ。
Presented by Kazuhiko Iwama.