この記事はまだ書きかけです.

はじめに

RでNaïve Bayes(ナイーブ・ベイズ)を使います.

準備

Rのインストールについては,次のページを見てください.

Naïve Bayesは,e1071パッケージに含まれています. そこで,e1071パッケージをインストールします. install.packagesコマンドを実行すると,パッケージをダウンロードするサーバーを聞かれますので,リストからJapanのどれかを選択します.

> install.packages("e1071")
> library("e1071")

ここでは,標準で使用できるirisデータセットを使います.

> data(iris)

このデータセットは,アヤメの種類(Species)を花びらの長さ(Sepal.Length),幅(Lepal.Width),がくの長さ(Petal.Length),幅(Petal.Width)によって分類する問題です. 長さと幅は連続値,種類はsetosa, versicolor, virginicaのいずれかをとる離散値です.

このデータセットには,setosa, versicolor, virginicaという3種類のアヤメについて,それぞれ50個ずつ,合計150個のデータが含まれています. ランダムに10個のデータを選択して,見てみましょう.

> iris[sort(sample(1:150,10)),]
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
4            4.6         3.1          1.5         0.2     setosa
22           5.1         3.7          1.5         0.4     setosa
65           5.6         2.9          3.6         1.3 versicolor
97           5.7         2.9          4.2         1.3 versicolor
100          5.7         2.8          4.1         1.3 versicolor
108          7.3         2.9          6.3         1.8  virginica
116          6.4         3.2          5.3         2.3  virginica
122          5.6         2.8          4.9         2.0  virginica
136          7.7         3.0          6.1         2.3  virginica
146          6.7         3.0          5.2         2.3  virginica

最初は,離散値属性のNaïve Bayesについて説明しますので,このデータを二値化したものを用意します.

まずは,データフレームごとコピーします.

> iris.bi <- data.frame(iris)

各属性の平均を求め,平均より大きければ1,そうでなければ0とします. ベクトルの平均を求めるにはmean関数,ベクトルの二値化にはcut関数,データフレームの値を入れ替えるにはtransform関数を使います.

> mu <- mean(iris.bi$Sepal.Length)
> bi <- cut(iris.bi$Sepal.Length, breaks=c(-Inf, mu, Inf), labels=c(0, 1))
> iris.bi <- transform(iris.bi, Sepal.Length = bi)

これを他の属性にも行います.

> mu <- mean(iris.bi$Sepal.Width)
> bi <- cut(iris.bi$Sepal.Width, breaks=c(-Inf, mu, Inf), labels=c(0, 1))
> iris.bi <- transform(iris.bi, Sepal.Width = bi)
> mu <- mean(iris.bi$Petal.Length)
> bi <- cut(iris.bi$Petal.Length, breaks=c(-Inf, mu, Inf), labels=c(0, 1))
> iris.bi <- transform(iris.bi, Petal.Length = bi)
> mu <- mean(iris.bi$Petal.Width)
> bi <- cut(iris.bi$Petal.Width, breaks=c(-Inf, mu, Inf), labels=c(0, 1))
> iris.bi <- transform(iris.bi, Petal.Width = bi)

ランダムに10個サンプリングして,二値化されたデータを確認しましょう.

> iris.bi[sort(sample(1:150,10)),]
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
23             0           1            0           0     setosa
49             0           1            0           0     setosa
59             1           0            1           1 versicolor
72             1           0            1           1 versicolor
75             1           0            1           1 versicolor
84             1           0            1           1 versicolor
108            1           0            1           1  virginica
116            1           1            1           1  virginica
123            1           0            1           1  virginica
125            1           1            1           1  virginica

これをランダム・サンプリングして80%を訓練データとし,のこりの20%をテスト・データとします.

> idx <- sample(nrow(iris.bi), as.integer(nrow(iris.bi)*0.8))
> iris.bi.train <- iris.bi[idx,]
> iris.bi.test <- iris.bi[-idx,]

Naïve Bayes

Naïve Bayesはスパム・メール・フィルターなどで用いられている機械学習の手法です.

Naïve Bayesでは,それぞれの特徴が独立に出現することを仮定して,Bayesの定理に基づいて分類規則を生成します.

式で書くと,次のようになります. \[ \hat{c}_i = \mathrm{argmax}_{c_1,...,c_k} \Pi_{j=1}^{m}P(v_{i,j}|c_k)P(c_k) \]

ここで,[math]\hat{c}_i[/math] は [math]i[/math] 番目の事例のクラスの予測値,[math]v_{i,j}[/math] は [math]i[/math] 番目の事例の [math]j[/math] 番目の属性の値,[math]P(v_{i,j}|c_k)[/math] はクラス [math]c_k[/math] の中で [math]j[/math] 番目の属性の値が [math]v_{i,j}[/math] となる確率(条件付き確率),[math]P(c_k)[/math] は全事例の中でクラスが [math]c_k[/math] となる確率(クラスの事前確率)を表します.

Naïve Bayesで学習する

Naïve Bayesを使うには,e1071パッケージnaiveBayes関数を用います.

> NB.model <- naiveBayes(Species~., iris.bi.train)

naiveBayes関数の第1引数には,モデルの式を「被説明変数 ~ 説明変数1+説明変数2+,...,説明変数k」という形で与えます. 説明変数を列挙する替わりに,被説明変数以外の全ての変数という意味の .(ドット)を使うこともできます. 第2引数には訓練データを与えます.

学習したモデルの中身を見てみると次のようになっています.

> NB.model

Naive Bayes Classifier for Discrete Predictors

Call:
naiveBayes.default(x = X, y = Y, laplace = laplace)

A-priori probabilities:
Y
    setosa versicolor  virginica 
 0.3416667  0.3500000  0.3083333 

Conditional probabilities:
            Sepal.Length
Y                    0         1
  setosa     1.0000000 0.0000000
  versicolor 0.4285714 0.5714286
  virginica  0.1081081 0.8918919

            Sepal.Width
Y                    0         1
  setosa     0.1707317 0.8292683
  versicolor 0.8095238 0.1904762
  virginica  0.6216216 0.3783784

            Petal.Length
Y                    0         1
  setosa     1.0000000 0.0000000
  versicolor 0.1190476 0.8809524
  virginica  0.0000000 1.0000000

            Petal.Width
Y                    0         1
  setosa     1.0000000 0.0000000
  versicolor 0.1904762 0.8095238
  virginica  0.0000000 1.0000000
 

クラスの事前確率(A-priori prob.),各属性値の条件付き確率(Conditional prob.)が計算されていることがわかります.

テスト・データのクラスを予測する

学習したモデルを用いてクラスを予測するには,predict関数を使います.

> NB.predict <- predict(NB.model, iris.bi.test)

中身を見ると,予測値が出力されていることがわかります.

> NB.predict
 [1] setosa     setosa     setosa     setosa     setosa    
 [6] setosa     setosa     setosa     setosa     versicolor
[11] virginica  virginica  setosa     versicolor setosa    
[16] versicolor versicolor virginica  virginica  virginica 
[21] virginica  versicolor virginica  virginica  virginica 
[26] virginica  virginica  versicolor virginica  virginica 
Levels: setosa versicolor virginica

この予測クラスを真のクラスと照らし合わせてみます.

> result <- table(NB.predict, iris.bi.test$Species)
> result

NB.predict   setosa versicolor virginica
  setosa          9          2         0
  versicolor      0          4         2
  virginica       0          2        11

ここから,setosaと予測した11個のうち真のクラスがsetosaだったのは9個で,2個のversicolorをsetosaと予測してしまっていることがわかります.

対角要素の和が正解数なので,ここから正解率を求めます.

正解率は80%でした.

Naïve Bayesによるテキスト分類

ついでに,スパム・メールの分類をやってみましょう.

文書分類にNaïve Bayesを用いるときは,文書を単語の集合とみなし,それぞれの単語が独立に出現することを仮定することになります.

データには,kernlabパッケージに含まれているspamデータを用います. そこで,kernlabパッケージをインストールします. install.packagesコマンドを実行すると,パッケージをダウンロードするサーバーを聞かれますので,リストからJapanのどれかを選択します.

> sum(diag(result))/nrow(iris.bi.test)
[1] 0.8

このデータは,4601個のメールを1813個のスパムと2788個のスパムでないものに分けたデータです.

> iris.train <- iris[idx,]
> iris.test <- iris[-idx,]
トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS