Clojureでナイーブベイズ分類器(多変数ベルヌーイモデル)
Clojureの練習としてナイーブベイズ分類器を実装してみることに.
まずは,言語処理のための機械学習入門 (自然言語処理シリーズ)のP.105の例題4.1を解いてみました.
参考にしたサイト
- ナイーブベイズ分類器の実装とか 〜畑さん/こだまさん問題〜 - naoya_t@hatenablog
- Clojure Programming/Examples/Norvig Spelling Corrector - Wikibooks, open books for an open world
非常に参考になりました.というか殆ど写しました.ありがとうございます.
実装
(def text_classified_p '(["good" "bad" "good" "good"] ["exciting" "exciting"] ["good" "good" "exciting" "boring"])) (def text_classified_n '(["bad" "boring" "boring" "boring"] ["bad" "good" "bad"] ["bad" "bad" "boring" "exciting"])) (defn train [features] (reduce (fn [model f] (assoc model f (get model f 1))) {} features)) (defn count-wordset [training-data] (apply merge-with + (map train training-data))) (defn mBm-MLestimate [documents datasets] (* (/ (count datasets) (count (concat text_classified_p text_classified_n))) (apply * (map #(/ % (count datasets)) (vals (select-keys (count-wordset datasets) documents)))) (apply * (map #(- 1 (/ % (count datasets)) ) (vals (apply dissoc (count-wordset datasets) documents)))))) (defn classify [d] (sorted-map :positive (mBm-MLestimate d text_classified_p) :negative (mBm-MLestimate d text_classified_n)))
結果
実際にclassifyを実行してみると
> (classify ["good" "good" "bad" "boring"]) {:negative 2/27, :positive 1/81}
このように確率の高い順に結果が出力されるので「"good" "good" "bad" "boring"」と発言したのはn氏,という感じで分類できます.
注意
この実装では例題4.2が解けません!!!今度直します...
- 作者: 高村大也,奥村学
- 出版社/メーカー: コロナ社
- 発売日: 2010/07
- メディア: 単行本
- 購入: 11人 クリック: 174回
- この商品を含むブログ (31件) を見る
(追記:2012/01/26)
例題4.2に対応できるようにアドホックに改良.あと,classifyでソート出来ていなかったので,その部分も少し変更.
(defn mBm-MLestimate [documents datasets] (* (/ (count datasets) (count (concat text_classified_p text_classified_n))) (apply * (map #(/ % (count datasets)) (vals (select-keys (count-wordset datasets) documents)))) (apply * (map #(- 1 (/ % (count datasets)) ) (vals (apply dissoc (count-wordset datasets) documents)))) (if (some nil? (map #(find (count-wordset datasets) % ) documents )) 0 1 ))) (defn classify [d] (sorted-map-by > (mBm-MLestimate d text_classified_p) :positive (mBm-MLestimate d text_classified_n) :negative))