【名前】
【概要】
- ベイジアンフィルタを用いた二値分類器のC++実装
- 素性にはNグラムを利用
- 文字コードはUTF-8にのみ対応
【バージョン】
【ビルド方法】
$ make
$ sudo make install
【ビルド確認環境】
- gcc-4.2.4 ※ 依存: std::tr1::unordered_set, std::tr1::unordered_map
- linuc(POSIX) ※ 依存: mmap
【コマンド】
== bin/hamt:
- 学習コマンド
- 学習結果をテキスト形式で出力する
- フォーマット:
-- 一行目(データ数) : <hamファイル数> <spamファイル数> ==TOTAL==
-- 残りの行(素性定義): <素性のhamファイルでの出現数> <素性のspamファイルでの出現数> <素性文字列>
$ bin/hamt [--octet] [--mbox]
--octet := 指定されている場合は、バイトNグラムを用いる
指定されていない場合は、文字コードをUTF-8と仮定し、文字Nグラムを用いる
--mbox := 学習データをmbox形式として扱う
学習データのファイル名は、それぞれ ${learn-dir}/ham.mbx 及び ${learn-dir}/spam.mbx
learn-dir := 学習用ディレクトリ
このディレクトリは'ham'と'spam'という名前のディレクトリを有する必要がある
- ham : hamデータ(正解データ)ファイルが配置されているディレクトリ
- spam: spamデータ(不正解データ)ファイルが配置されているディレクトリ
ngram-min := 素性として用いるNグラムの最小値 ※ N >= 1
ngram-max := 素性として用いるNグラムの最大値 ※ N <= 32
== bin/hamc:
- bin/hamtの出力結果を標準入力から読み込み、bin/ham用にコンパイルするコマンド
$ bin/hamc [--lower-frequency-limit=2]
--lower-frequency-limit := 使用する素性のフィルタ値
出現頻度が低い素性はノイズとして除去する
デフォルトは2
--omit-redundant-feature := 冗長な素性を除去してコンパイルを行う
- 冗長: 素性A、Bの出現頻度が全く同じで、A(の素性文字列)がBを包含している場合、Bは冗長
- インデックスファイルが多少小さくなるが、分類性能も多少悪くなる傾向がある
試験的に導入中
model-index := 生成されるコンパイル済みファイル
== bin/ham:
- 分類コマンド
- 標準入力から対象テキストを読み込み、それをhamかspamかに分類する
- 標準出力に"#{分類スコア} #{HAM or SPAM}"を出力する
- コマンドの返り値は、テキストがhamなら0、spamなら1、エラーならそれ以外の値
$ bin/ham [--min-spam-score=0.5]
--min-spam-score := spamとして分類されるスコアの下限
この値を下げると、取りこぼしは多くなるが、hamに分類されるテキストの正解率は高くなる
デフォルトは0.5
model-index := bin/hamcが生成したファイル
== bin/hamp:
- 分類結果検証用コマンド
- 実際にはRubyスクリプト
$ bin/hamp [--mbox] [--min-spam-score=0.5]
--mbox := mbox形式のテストデータを用いる
テストデータのファイル名は、それぞれ ${test-data-dir}/ham.mbx 及び ${test-data-dir}/spam.mbx
--min-spam-score := spamとして分類されるスコアの下限
デフォルトは0.5
model-index := bin/hamcが生成したファイル
test-data-dir := テスト用のデータディレクトリ
ディレクトリ構造は、hamtのlearn-dirと同じ
【コマンド実行例】
学習用データ
$ ls learn_data
ham spam # ham以下に正しいデータを、spam以下にはスパムデータを配置しておく
学習
$ bin/hamt learn_data 1 4 | bin/hamc model.idx
分類
$ bin/ham model.idx < "分類対象ファイル"
テスト
$ bin/hamp model.idx test_data
$ ls test_data
ham spam
【API】
TODO: ちゃんとした説明
namespace HAM {
// ファイル: feature_extractor.hh
class FeatureExtract {
public:
// モデルファイルをロード
FeatureExtract(const char* model_index_path);
// ロードに成功したかどうか
operator bool();
// text内の素性を走査
// Callbackは、以下の引数を有する関数(関数オブジェクト)
// - feature_name : 素性名. const char*
// - feature_name_length: 素性名の長さ. unsigned
// - feature_id : 各素性に一意なID. unsigned
// - spam_probability : 素性のスパムらしさ(0.0~1.0). double
template <class Callback>
void each_feature(const char* text, Callback& fn) const;
};
// ファイル: scorer.hh
class Scorer {
public:
Scorer(const FeatureExtractor& fe);
// 分類対象となるテキストを追加する
void add_text(const char* text);
// メソッド呼び出しまでに追加したテキスト群を対象として
// それがスパムテキストである確率(0.0~1.0)を計算する
double calc_score() const;
};
}
【参考】