牌語備忘録 -pygo

あくまでもメモです。なるべくオフィシャルの情報を参照してください。

牌語備忘録 -pygo

Ruby でやってみる『機械学習 はじめよう第3回 ベイジアンフィルタを実装してみよう』メモ

若干リファクタ naivebayes.rb: 2014-06-30

(ruby2.1)

元ネタは Python

やること

ナイーブベイズアルゴリズムを利用してテキストを読み込み、学習し、自動でカテゴリ分類する。

文章を形態素に分割する

morphological.rb

Yahoo!デベロッパーズネットワークの日本語形態素解析を利用する。
(nokogiri はインストール済で)

require 'open-uri'
require "nokogiri"

APPID = 'Yahoo!デベロッパーズネットワークのアプリケーションIDを入力して下さい'
REQUEST_URL = "http://jlp.yahooapis.jp/MAService/V1/parse"

module Morphological
  extend self
  def split(sentence, appid=APPID, results="ma", filter="1|2|3|4|5|9|10")
    params = "?appid=#{APPID}&results=#{results}&filter=#{URI.encode(filter)}&sentence=#{URI.encode(sentence)}"
    doc = Nokogiri::HTML(open(REQUEST_URL + params))
    surfaces = doc.xpath('//word/surface').map{|i| i.text} rescue nil
    surfaces
  end
end

Rubyベイジアンフィルタの実装

P(cat|doc) = P(doc|cat)P(cat) / P(doc)

naivebayes.rb
include Math
require "set"

require_relative "morphological"


def getwords(doc)
  Morphological::split(doc)
end

class NaiveBayes
  def initialize
    @vocabularies = Set.new
    @wordcount = {}
    @catcount = {}
  end

  def wordcountup(word, cat)
    @wordcount[cat] ||= {}
    @wordcount[cat][word] ||= 0
    @wordcount[cat][word] += 1
    @vocabularies.add(word)
  end

  def catcountup(cat)
    @catcount[cat] ||= 0
    @catcount[cat] += 1
  end

  def train(doc, cat)
    word = getwords(doc)
    word.each do |w|
      wordcountup(w, cat)
    end
    catcountup(cat)
  end

  def classifier(doc)
    best = nil
    maxint = 1 << (1.size * 8 - 2) - 1
    max = -maxint
    word = getwords(doc)

    for cat in @catcount.keys
      prob = score(word, cat)
      if prob > max
        max = prob
        best = cat
      end
    end
    best
  end

  def score(word, cat)
    score = Math.log(priorprob(cat))
    word.each do |w|
      score += Math.log(wordprob(w, cat))
    end
    score
  end

  def priorprob(cat)
    prob = @catcount[cat] / @catcount.values.inject(:+).to_f
    prob
  end

  def incategory(word, cat)
    #あるカテゴリの中に単語が登場した回数を返す
    if @wordcount[cat].has_key?(word)
      return @wordcount[cat][word].to_f
    end
    return 0.0
    # @wordcount[cat].key(word).nil? ? 0.0 : @wordcount[cat][word].to_f
  end

  def wordprob(word, cat)
    # P(word|cat)が生起する確率を求める
    prob = (incategory(word, cat) + 1.0) / (@wordcount[cat].values.inject(:+) + @vocabularies.length * 1.0)
    prob
  end

end

nb = NaiveBayes.new

# 学習させる

doc = <<EOS
Python(パイソン)は、オランダ人のグイド・ヴァンロッサムが作ったオープンソースのプログラミング言語。
オブジェクト指向スクリプト言語の一種であり、Perlとともに欧米で広く普及している。イギリスのテレビ局 BBC が製作したコメディ番組『空飛ぶモンティパイソン』にちなんで名付けられた。
Pythonは英語で爬虫類のニシキヘビの意味で、Python言語のマスコットやアイコンとして使われることがある。Pythonは汎用の高水準言語である。プログラマの生産性とコードの信頼性を重視して設計されており、核となるシンタックスおよびセマンティクスは必要最小限に抑えられている反面、利便性の高い大規模な標準ライブラリを備えている。
Unicodeによる文字列操作をサポートしており、日本語処理も標準で可能である。 多くのプラットフォームをサポートしており(動作するプラットフォーム)、また、豊富なドキュメント、豊富なライブラリがあることから、産業界でも利用が増えつつある。
EOS
nb.train(doc, 'Python')

doc = <<EOS
Ruby(ルビー)は、まつもとゆきひろ(通称Matz)により開発されたオブジェクト指向スクリプト言語であり、従来Perlなどのスクリプト言語が用いられてきた領域でのオブジェクト指向プログラミングを実現する。Rubyは当初1993年2月24日に生まれ、1995年12月にfj上で発表された。名称のRubyは、プログラミング言語Perlが6月の誕生石であるPearl(真珠)と同じ発音をすることから、まつもとの同僚の誕生石(7月)のルビーを取って名付けられた。
EOS
nb.train(doc, 'Ruby')

doc = <<EOS
豊富な機械学習(きかいがくしゅう、Machine learning)とは、人工知能における研究課題の一つで、人間が自然に行っている学習能力と同様の機能をコンピュータで実現させるための技術・手法のことである。 ある程度の数のサンプルデータ集合を対象に解析を行い、そのデータから有用な規則、ルール、知識表現、判断基準などを抽出する。 データ集合を解析するため、統計学との関連も非常に深い。
機械学習は検索エンジン、医療診断、スパムメールの検出、金融市場の予測、DNA配列の分類、音声認識や文字認識などのパターン認識、ゲーム戦略、ロボット、など幅広い分野で用いられている。応用分野の特性に応じて学習手法も適切に選択する必要があり、様々な手法が提案されている。それらの手法は、Machine Learning や IEEE Transactions on Pattern Analysis and Machine Intelligence などの学術雑誌などで発表されることが多い。
EOS
nb.train(doc, '機械学習')

# カテゴライズする

texts = [
  'グイド・ヴァンロッサム氏によって開発されました. ',
  '豊富なドキュメントや豊富なライブラリがあります.',
  '純粋なオブジェクト指向言語です.',
  'Rubyはまつもとゆきひろ氏(通称Matz)により開発されました.',
  '「機械学習 はじめよう」が始まりました',
  '検索エンジンや画像認識に利用されています.',
]

texts.each { |text| puts "#{text} => 推定カテゴリ: #{nb.classifier(text)}"}

実行結果

$ ruby naivebayes.rb
グイド・ヴァンロッサム氏によって開発されました.  => 推定カテゴリ: Python
豊富なドキュメントや豊富なライブラリがあります. => 推定カテゴリ: Python
純粋なオブジェクト指向言語です. => 推定カテゴリ: Ruby
Rubyはまつもとゆきひろ氏(通称Matz)により開発されました. => 推定カテゴリ: Ruby
「機械学習 はじめよう」が始まりました => 推定カテゴリ: 機械学習
検索エンジンや画像認識に利用されています. => 推定カテゴリ: 機械学習

うまくカテゴライズされました!