Mae向きなブログ

Mae向きな情報発信を続けていきたいと思います。

ベイジアンフィルター

ベイジアンフィルターについて調べていたら、Classifier*1というのを知りました(via http://d.hatena.ne.jp/zariganitosh/20070712/1184230093)

Usageを見てみると、

require 'classifier'
b = Classifier::Bayes.new 'Interesting', 'Uninteresting'
b.train_interesting "here are some good words. I hope you love them"
b.train_uninteresting "here are some bad words, I hate you"
b.classify "I hate bad words and you" # returns 'Uninteresting'

とあります。Classifier::Bayes#train_interestingメソッドというのは、存在しないのですが、Classifier::Bayes#method_missingメソッドがいいように処理してくれるみたいです。面白い仕組みだなぁと思います。

def method_missing(name, *args)
  category = name.to_s.gsub(/(un)?train_([\w]+)/, '\2').prepare_category_name
  if @categories.has_key? category
    args.each { |text| eval("#{$1}train(category, text)") }
  elsif name.to_s =~ /(un)?train_([\w]+)/
    raise StandardError, "No such category: #{category}"
  else
    super  #raise StandardError, "No such method: #{name}"
  end
end

流れはこんな感じだと思います。

  1. 「b.train_interesting "here are some good words. I hope you love them"」を実行
  2. Classifier::Bayes#train_interestingメソッドは定義されていないので,method_missingメソッドを実行
  3. name="train_interesting"からcategory="interesting"を得る。
  4. eval("train("interesting", "here are some good words. I hope you love them"))を実行