いかにたいしとことをやってないかって話

ベイズフィルタって難しいんじゃね?」と思ってる人へ。
環境を作るのは、JARがなかったりビルドエラーが出たり結構面倒です(難しいっていよりだるい)。しかし、APIをつかうだけならとても簡単です。


参考にした元ネタのサイトはこちら


Javaベイズ実装 ci-bayes を試す
http://diary.voq.jp/archives/8

//ベイズのエンジンを作ります。
FisherClassifier fc=new FisherClassifierImpl();


//文章を与えてトレーニングします。
//Popfileの「このメールはXXXバケツへ」と同じノリです。
fc.train("The quick brown fox jumps over the lazy dog's tail","good");
fc.train("Make money fast!", "bad");


//こちらが判定用のメソッドです。
String classification=fc.getClassification("money", null);
System.out.println(classification);


ぶっちゃけ、コアとなる部分はこれだけ。本当にこれだけです。


後、作りこまなければならない重要な点としては、

  • FisherClassifierImplに与えるWordLister (パーサです)の実装


となります。日本語の場合は、Java版ベイズ実装 ci-bayes を試すを見てください。


今回、私は、はてブをパースするのが目的となりますので、はてブを現すBEANを定義し、それをパースする形にしました。

/**
 * 1ブックマークURLに対応するBEAN
 */
public class BookMarkInfo implements Serializable {

	/**
	 * ブックマーク対象のURL
	 */
	public String link;

	/**
	 * ブックマーク対象のHTMLのタイトル
	 */
	public String title;

	/**
	 * はてぶの詳細ページ
	 * 例:http://b.hatena.ne.jp/entry/http://techtalk.jp/
	 */
	public String ditailLink;
	/**
	 * はてぶの詳細ページ(ユーザ数が多い場合のみ出現)
	 */
	public String moreLink;
	/**
	 * 一人、一人のブックマークを現すデータのセット
	 */
	public SortedSet<BookMarkDitailOneUserInfo> set = new TreeSet<BookMarkDitailOneUserInfo>(
			new BookMarkDitailOneUserInfo.DateComparator());
}
/**
 * 1ユーザがブックマークしたことを示すBean。
 * 「誰が =user」「いつ =date」ブックマークしたかを保持。
 * 将来的には、あるユーザの「これはすごい」タグは参考になる
 * とか解析したいのでBean化してる。
 */
public class BookMarkDitailOneUserInfo implements Serializable {

	public String user;
	public String dateStr;
	public Date date;
}

/**
 * ハテナ用の分析用のパーサー
 * FisherClassifier fc = new FisherClassifierImpl(new HatenaWordLister());
 * 上記みたいな使い方をする。 
 */
public class HatenaWordLister implements WordLister, Serializable {

	/**
         * データをSet<String>にする責務を持つ。
         */
	public Set<String> getUniqueWords(Object document) {

		Set<String> set = new HashSet<String>();

		if (document instanceof BookMarkInfo) {

            //ブックマークから、ユーザ情報のみを抜き取って、
            //設定って感じ。
			BookMarkInfo d = (BookMarkInfo) document;
			for (BookMarkDitailOneUserInfo info : d.set) {

				set.add(info.user);
			}

                        //あと、URLのある層までは役に立つと思ってるので、
                        //それも登録。
            // d.link が 「http://blog.livedoor.jp/dankogai/archives/51088368.html」
            // の時、http://blog.livedoor.jp/dankogaiを登録する感じ。
            // 好きなブログ、サイト抽出に近いロジック。            
			set.add(getURLLayer1(d.link));

		}

		return set;
	}
}


ベイジアンフィルタにかかわるコアの部分はこれだけです。
実装が難しいというよりも、どの情報に着目してWordListerを作るかって話かと思います。


ってことで、興味がある人はぜひ試してください。
Gmailとかを読み込ませて、フィルタリングアプリを作っているだけで、結構の間遊べますよ。


まあ、周辺系をつくるのが相当だるかったりしますけど(Imapのコードとか、クローラ、HTMLパーサのコードとか)。