10行でナイーブベイズ ~Rって便利だね!~

某企業がデータマイニングエンジニアの望ましい条件として「R言語の使用経験」を挙げていて一部では話題になってたりしますね.
そんなわけで,Rだとこんなに簡単にコードが書けちゃうよって紹介です.

ナイーブベイズとは?

ナイーブベイズは条件付き独立を仮定した単純な識別器なので学習が非常に高速なんですが実用的な精度が出るとういことでスパムフィルタなどに利用されている識別器です.
式で表すと次のような感じです.

\[\hat C = \mathrm{argmax}_C \sum_{i=1}^{|\mathcal{W}|} n(C,w_i)\log P(w_i|C) + \log P(C)\]

wiはi番目の単語(語彙)で,Wが単語の集合,n(C,wi) がカテゴリCに出現したwiの回数です.
Rだったらこれぐらい10行で実装できちゃいます.

ナイーブベイズのコード

10行っていうのは関数の中のコードのみ(コメント行除く)という条件付きですけど,
無理矢理1行に詰め込んでる感じもしないはずなので,すっきりしてますよね.

試しにRMeCabで配布されてるdata.tar.gzに同梱されているwritersってディレクトリ内の文書を識別してみました.

demoNaiveBayes.R

library(RMeCab)

d <- t(docMatrix2("data/writers"))

myNaiveBayes <- function(x, y) {
    lev <- levels(y) #1
    # term frequency in each category
    ctf <- sapply(lev, function(label) colSums(x[y == label,])) #2
    # term probability in each category smoothed using Laplace smoothing
    ctp <- t(t(ctf + 1) / (colSums(ctf) + nrow(ctf))) #3
    # number of each class documents
    nc <- table(y, dnn = NULL) #4
    # class prior
    cp <- nc / sum(nc) #5
    structure(list(lev = lev, cp = cp, ctp = ctp), class = "myNaiveBayes") #6
}

predict.myNaiveBayes <- function(model, x) {
    prob <- apply(x, 1, function(x) colSums(log(model$ctp) * x)) #7
    prob <- prob + log(as.numeric(model$cp)) #8
    level <- apply(prob, 2, which.max) #9
    model$lev[level] #10!!
}


train.index <- c(1:3, 5, 6)
y <- factor(sub("^([a-z]*?)_.*", "\\1", rownames(d), perl = TRUE))
model <- myNaiveBayes(d[train.index,], y[train.index])
predict(model, d[-train.index,])

実行

$ R --slave -f demoNiveBayes.R
file_name =  data/writers/ogai_gan.txt opened
file_name =  data/writers/ogai_kanoyoni.txt opened
file_name =  data/writers/ogai_niwatori.txt opened
file_name =  data/writers/ogai_vita.txt opened
file_name =  data/writers/soseki_eijitsu.txt opened
file_name =  data/writers/soseki_garasu.txt opened
file_name =  data/writers/soseki_omoidasu.txt opened
file_name =  data/writers/soseki_yume.txt opened
number of extracted terms = 5209
to make matrix now

[1] "ogai"   "soseki" "soseki"

ちゃんと識別できてますね!
Rって便利ですね!!
みなさんR使いましょ!!!!