Rでデータ解析を始めよう006 Rで機械学習(決定木でIris分類)

Rでデータ解析を始めよう006 Rで機械学習(決定木でIris分類)

モモノキ&ナノネと一緒に統計ソフトRの使い方を学習していきます。

モモノキ&ナノネと一緒にRで機械学習を試してみよう




Rで機械学習、決定木でIrisデータを分類

ナノネ、統計解析用フリーソフト『R』の使い方を練習するよ。今回は機械学習の決定木(decision tree)を試してみよう。

枝分かれして分類するやつね。

データは今回もIrisを使うよ。

3種類のアヤメは少し覚えたかも。Irisは前回のSVM練習でも使ったし。

これが『Setosa』で、

これは『Versicolor』、

こっちが『Virginica』だよね。

データもグラフで再確認。

In [2]:
plot(iris, col=c(2, 3, 4)[iris$Species])

今回は決定木分類に『rpart』を使うよ。rpartはRにデフォルトでインスールされてるみたいだから、library()で読み込んでみて。

In [3]:
# install.packages("rpart") # 必要に応じインスール
library(rpart)

rpart準備OK。

さっそく決定木で分類をやってみよう。rpart()で引数にモデル式とデータを指定すれば、とりあえず分類を実行できるよ。

モデル式は目的変数がSpecies(アヤメの種類)、~でつないで、残り4つを説明変数に設定(ピリオドで目的変数以外を全指定)。dataにはirisを指定すればOKだね。

モデルを作るコードはsvmのときと同じ感じだね。

In [4]:
iris.rpart <- rpart(Species ~ ., data = iris) # 決定木モデル作成
In [5]:
iris.rpart
n= 150 

node), split, n, loss, yval, (yprob)
      * denotes terminal node

1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)  
  2) Petal.Length< 2.45 50   0 setosa (1.00000000 0.00000000 0.00000000) *
  3) Petal.Length>=2.45 100  50 versicolor (0.00000000 0.50000000 0.50000000)  
    6) Petal.Width< 1.75 54   5 versicolor (0.00000000 0.90740741 0.09259259) *
    7) Petal.Width>=1.75 46   1 virginica (0.00000000 0.02173913 0.97826087) *

分類できたみたいだけど...。Rでも分かりやすく図示できる?

図示できるよ。決定木の分類結果を図示する方法は複数あるから、いくつか実際に試してみよう。

In [6]:
# 決定木の図示 その1
plot(iris.rpart)
text(iris.rpart, use.n=TRUE, cex=0.5)

シンプルな図だけど、どう分類されたか分かるね。Petal.Length(がく片長さ)が2.45より小さいとsetosa。2.45以上のときはさらに分岐してPetal.Width(花弁幅)が1.75より小さいとversicolor、1.75以上だとvirginicaに分類されている。

次はもうちょっとグラフィカルに。partykitを使って図示してみよう。

In [7]:
# 決定木の図示 その2
# install.packages("partykit") # 初回利用時はインスール必要
library(partykit) # partykit読み込み

options(repr.plot.width=10, repr.plot.height=7) # グラフサイズ調整(jupyter notebook)

plot(as.party(iris.rpart)) # プロットの引数にas.party(データ)を指定
Loading required package: grid
Loading required package: libcoin
Loading required package: mvtnorm

グラフも付いてちょっと見やすくなったかも。

最後はポップな感じに。rpart.plotを使って図示してみよう。

In [8]:
options(repr.plot.width=7, repr.plot.height=7) # グラフサイズデフォルト
In [9]:
# 決定木の図示 その3-1
# install.packages("rpart.plot") # 初回利用時はインスール必要
library(rpart.plot) # rpart.plot読み込み

rpart.plot(iris.rpart) # プロット

カラフルな図になった。見やすさは好みにもよるけど。

オプションでtypeとextraを変更すると表示方法を少し変更できるみたい。いろいろ試して見てね。

In [10]:
# 決定木の図示 その3-2
rpart.plot(iris.rpart, type=4, extra=1) # オプションのtypeとextraで表示方法変更

分類結果の図示方法はこれくらいにして、次は決定木モデルで予測をやってみよう。

まずは訓練用とテスト用データを準備。前回のSVM練習と一緒で、割合は適当に訓練用70%、テスト用30%としておこう。

In [11]:
# 訓練データとテストデータに分割
set.seed(100)
df.rows = nrow(iris) # 150
train.rate = 0.7 # 訓練データの比率
train.index <- sample(df.rows, df.rows * train.rate)
df.train = iris[train.index,] # 訓練データ
df.test = iris[-train.index,] # テストデータ
cat("train=", nrow(df.train), " test=", nrow(df.test))
train= 105  test= 45

データ準備完了。訓練用が105データ、テスト用は45データ。

次は訓練データを使って決定木のモデルをつくるよ。

In [12]:
model.rpart <- rpart(Species ~ ., data = df.train) # 決定木モデル、データは訓練用を指定

式の書き方は最初と一緒で、データに訓練用を指定すればOKかな。

続いて訓練データで学習したモデルを使って、テストデータの予測をやってみよう。予測はpredict()で、引数にモデルとデータを指定してね。あと分類の場合はオプション引数のtypeに"class"も指定しておいてね。

In [13]:
# テストデータの予測
prediction = predict(model.rpart, df.test, type="class" )

OK、さっき作ったモデルとテストデータを指定、typeは"class"とした。

うまく分類できたかな?tableを使って予測と正解を確認してみよう。

In [23]:
(result <- table(prediction, df.test$Species)) # ()で括って内容表示
            
prediction   setosa versicolor virginica
  setosa         19          0         0
  versicolor      0         12         2
  virginica       0          1        11
In [15]:
# 精度の計算(行列の対角合計 / 行列の合計)
(accuracy_prediction = sum(diag(result)) / sum(result))
0.933333333333333

正解率は93.3%でまずまずの結果。グラフにプロットしてみる。

In [16]:
# モデル予測結果を図示(Petal.Length / Petal.Width)
par(mar = c(6, 7, 5, 2))
par(mgp = c(4, 1.2, 0.4))
par(lwd = 2)

plot(df.test$Petal.Length, df.test$Petal.Width,
     main = "Iris (decision tree)",
     xlab = "Petal length (cm)",
     ylab = "Petal width (cm)",
     #col = prediction,
     pch=c(1,2,3)[prediction],
     cex = 2,
     cex.main = 2,
     cex.lab = 2,
     cex.axis = 1.5,
     xlim = c(0, 7),
     ylim = c(0, 3.5),
     yaxp = c(0, 3, 3)
    )

par(family = "serif")
par(font = 3)

legend("topleft",
       legend = levels(prediction),
       pch = c(1, 2, 3),
       # col = c(1, 2, 3),
       cex = 1.7,
       pt.cex = 2,
       bty = 'n',
       inset = c(0.05, 0.03))

今回はPetal.LengthとPetal.Widthを軸にプロットしてみた。

Rのグラフの作成も少し慣れてきたね。

最後に木の複雑さを調整してみよう。木の枝を刈ったり、伸ばしたりする方法だよ。

木の複雑さの調整は、rpart()オプションのcontrolパラメータを変更すればOK。木を作る制約条件を変更できるよ。

controlパラメータとデフォルト値は下の通り。minsplit、cp、maxdepthあたりの値を変更するといい感じに調整できるよ。

In [17]:
rpart.control()
$minsplit
20
$minbucket
7
$cp
0.01
$maxcompete
4
$maxsurrogate
5
$usesurrogate
2
$surrogatestyle
0
$maxdepth
30
$xval
10

どんな数値を指定すればよいかは、printcp(モデル)やplotcp(モデル)を出力すると参考になるよ。

In [18]:
iris.rpart <- rpart(Species ~ ., data = iris) # 決定木モデル
printcp(iris.rpart)
Classification tree:
rpart(formula = Species ~ ., data = iris)

Variables actually used in tree construction:
[1] Petal.Length Petal.Width 

Root node error: 100/150 = 0.66667

n= 150 

    CP nsplit rel error xerror     xstd
1 0.50      0      1.00   1.15 0.051801
2 0.44      1      0.50   0.61 0.060161
3 0.01      2      0.06   0.09 0.029086
In [19]:
plotcp(iris.rpart)

たとえば、枝を短くする場合。

In [24]:
options(repr.plot.width=12, repr.plot.height=7)

iris.rpart <- rpart(Species ~ .,
                   data=iris,
                   control = rpart.control(cp = 0.44)) # maxdepth = 1としても同じ結果

plot(as.party(iris.rpart))

こんどは枝を長くする場合の例だよ。

In [21]:
options(repr.plot.width=12, repr.plot.height=7)

iris.rpart <- rpart(Species ~ .,
                   data=iris,
                   control = rpart.control(
                     minsplit=0,    # 分岐の最少データ数(小さいと細かく分岐)
                     cp=0,          # モデルの複雑さ(小さいと細かく分岐)
                     maxdepth = 5)) # 木の最大深さ(大きいと細かく分岐)
                                    
plot(as.party(iris.rpart))
In [22]:
printcp(iris.rpart)
Classification tree:
rpart(formula = Species ~ ., data = iris, control = rpart.control(minsplit = 0, 
    cp = 0, maxdepth = 5))

Variables actually used in tree construction:
[1] Petal.Length Petal.Width  Sepal.Length

Root node error: 100/150 = 0.66667

n= 150 

     CP nsplit rel error xerror     xstd
1 0.500      0      1.00   1.15 0.051801
2 0.440      1      0.50   0.65 0.060690
3 0.020      2      0.06   0.10 0.030551
4 0.010      3      0.04   0.10 0.030551
5 0.005      6      0.01   0.07 0.025833
6 0.000      8      0.00   0.08 0.027520

あとでパラメータの値を変えて、いろいろ試してみるよ。

今回の決定木を使った分類練習は以上で。
またね!





スポンサーリンク

0 件のコメント :

コメントを投稿