RでNaïve Bayesを使う

2013-12-23 (月) 10:00:14 (3968d) | Topic path: Top / バイオ・データ・マイニング / RでNaïve Bayesを使う

はじめに

ここでは,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の定理に基づいて分類規則を生成します.

Naïve Bayesを式で書くと,次のようになります. \[ \hat{c}_i = \mathrm{argmax}_{c_k} P(c_k)\Pi_{j=1}^{m}P(v_{i,j}|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は,ベイズの定理 \[ P(Y|X_1,X_2,...,X_m) = \frac{P(X_1,X_2,...,X_m|Y)P(Y)}{P(X_1,X_2,...,X_m)} \] を用いて,各属性の値が [math]x_1,x_2,...,x_m[/math] のときに [math]P(y|x_1,x_2,...,x_m)[/math] の値が最大となるような [math]Y[/math] の値を予測クラスとして出力します.

このとき,[math]X_1,X_2,...,X_m[/math] が独立であると仮定すると,分子の [math]P(X_1,X_2,...,X_m|Y)[/math] はそれぞれの条件付き確率の積で表すことができます. \[ P(X_1,X_2,...,X_m|Y) = P(X_1|Y) P(X_2|Y) \dots P(X_m|Y) = \Pi_{j=1}^m P(X_j|Y) \]

これによって,Bayesの定理の式は \[ P(Y|X_1,X_2,...,X_m) = \frac{P(Y)\Pi_{j=1}^m P(X_j|Y)}{P(X_1,X_2,...,X_m)} \] と変形できるので,この右辺を最大化する [math]Y[/math] の値を調べます.

ここで,この右辺の分母 [math]P(X_1,X_2,...,X_m)[/math] はどのクラス [math]Y[/math] に対しても同じ値なので,この右辺を最大化する [math]Y[/math] を調べるには,この右辺の分子を最大化する [math]Y[/math] を調べればいいことになります.

このようにして,Naïve Bayesの式 \[ \hat{Y} = \mathrm{argmax}_Y P(Y)\Pi_{j=1}^m P(X_j|Y) \] が導かれます.

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と予測してしまっていることがわかります.

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

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

正解率は80%でした.

Gaussian Naïve Bayes

ここまではNaïve Bayesを理解しやすいように属性の値は離散値としてきました.

しかし,属性の値が正規分布に従って発生していると仮定することで,Naïve Bayesを連続値の属性に拡張することができます. これをGaussian Naïve Bayesといいます.

離散化したirisデータと同じ番号を用いて,連続値のirisデータの事例を訓練データとテスト・データに分けます.

> iris.train <- iris[idx,]
> iris.test <- iris[-idx,]

NaiveBayes関数を用いて学習します.

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

学習したモデルを見てみます.

> 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                [,1]      [,2]
  setosa     5.009756 0.3541221
  versicolor 5.966667 0.5135561
  virginica  6.664865 0.6684211

            Sepal.Width
Y                [,1]      [,2]
  setosa     3.439024 0.4110219
  versicolor 2.797619 0.3024196
  virginica  3.021622 0.3250087

            Petal.Length
Y                [,1]      [,2]
  setosa     1.475610 0.1699713
  versicolor 4.285714 0.4791107
  virginica  5.621622 0.5826830

            Petal.Width
Y                 [,1]      [,2]
  setosa     0.2487805 0.1120758
  versicolor 1.3380952 0.1987183
  virginica  2.0594595 0.2722942
 

条件付き確率(Conditional prob.)のところには,正規分布のパラメーターである平均と不偏標準偏差が出ています.

テスト・データのラベルを予測し,正解と照らし合わせてから予測精度を求めます.

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

NB.predict   setosa versicolor virginica
  setosa          9          0         0
  versicolor      0          8         1
  virginica       0          0        12
> sum(diag(result))/nrow(iris.test)
[1] 0.9666667

正解率は97%でした.

まとめ

Naïve Bayesは,Bayes統計に基づく分類手法です.

説明変数の値が独立に発生するという現実的でないことを仮定していますが,それでも高い分類精度を得ることができます.

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS