モモノキ&ナノネと一緒にRで機械学習を試してみよう
Rで機械学習、決定木・ランダムフォレスト・SVMの決定境界を可視化してみよう
ナノネ、統計解析用フリーソフト『R』の使い方を練習するよ。今回は機械学習で分類された決定境界をグラフにプロットしてみよう。
どうやって分類したか可視化できるのは、いいね。
前回までに、IrisデータでSVM、決定木、ランダムフォレストを使った分類をやってきたよね。今回はそれぞれの決定境界を可視化してみよう。
モモノキ、決定境界はどうやってプロットするの?
おおまかには、決定境界プロット用にメッシュデータを用意して全データをモデルで予測する。作ったメッシュデータを等高線グラフで重ね書きプロットすればいい感じに描画できるよ。
あと、説明変数はあらかじめ2つに絞っておいてね。今回はPetal.LengthとPetal.Widthを使うことにするよ。
さっそく下のグラフに各モデルの決定境界を追加してみよう。
exclude.cols <- names(iris) %in% c('Sepal.Length', 'Sepal.Width')
df.iris = iris[!exclude.cols]
# Irisデータを単純にプロット
par(mar = c(6, 7, 5, 2))
par(mgp = c(4, 1.2, 0.4))
par(lwd = 2)
plot(df.iris$Petal.Length, df.iris$Petal.Width,
main = "Iris",
xlab = "Petal length (cm)",
ylab = "Petal width (cm)",
col = c(2, 3, 4)[df.iris$Species],
pch=c(0, 1, 2)[df.iris$Species],
cex = 1.5,
cex.main = 2,
cex.lab = 2,
cex.axis = 1.5,
xlim = c(0, 7.5),
xaxp = c(0, 7, 7),
ylim = c(0, 3),
yaxp = c(0, 3, 3)
)
par(family = "serif")
par(font = 3)
legend("topleft",
legend = levels(df.iris$Species),
pch = c(0, 1, 2),
col = c(2, 3, 4),
cex = 1.5,
pt.cex = 1.5,
bty = 'n',
inset = c(0.05, 0.03))
まずは決定木の決定境界から。
# 決定木
# install.packages("rpart") # 必要に応じてインスール
library(rpart)
# Irisデータ準備(Sepal.LengthとSepal.Widthを除外)
exclude.cols <- names(iris) %in% c('Sepal.Length', 'Sepal.Width')
df.iris = iris[!exclude.cols]
# Irisデータをそのままプロット(x軸Petal.Length、y軸Petal.Width)
par(mar = c(6, 7, 5, 2))
par(mgp = c(4, 1.2, 0.4))
par(lwd = 2)
plot(df.iris$Petal.Length, df.iris$Petal.Width,
main = "Iris (Decision tree)",
xlab = "Petal length (cm)",
ylab = "Petal width (cm)",
col = c(2, 3, 4)[df.iris$Species],
pch=c(0, 1, 2)[df.iris$Species],
cex = 1.5,
cex.main = 2,
cex.lab = 2,
cex.axis = 1.5,
xlim = c(0, 7.5),
xaxp = c(0, 7, 7),
ylim = c(0, 3),
yaxp = c(0, 3, 3)
)
par(family = "serif")
par(font = 3)
legend("topleft",
legend = levels(df.iris$Species),
pch = c(0, 1, 2),
col = c(2, 3, 4),
cex = 1.5,
pt.cex = 1.5,
bty = 'n',
inset = c(0.05, 0.03))
# モデル作成
set.seed(100)
model.rp = rpart(Species ~ ., data = df.iris)
# 決定境界プロット用のメッシュ作成
px <- seq(0, 7, 0.01)
py <- seq(0, 3, 0.01)
pgrid <- expand.grid(px, py)
names(pgrid) <- c("Petal.Length", "Petal.Width")
# モデルでメッシュデータの分類を全て予測
pred.pgrid.rp <- predict(model.rp, pgrid, type="class")
# メッシュデータで等高線をプロット(決定境界)
contour(px, py, array(as.numeric(pred.pgrid.rp)-1, dim=c(length(px), length(py))),
xlim=c(0, 7), ylim=c(0, 3),
col="orange", lwd=2, drawlabels=F, add=T)
決定木の境界は軸に平行な直線だ。
次はランダムフォレストの決定境界。
# ランダムフォレスト
# install.packages("randomForest") # 必要に応じてインストール
library(randomForest)
# Irisデータ準備(Sepal.LengthとSepal.Widthを除外)
exclude.cols <- names(iris) %in% c('Sepal.Length', 'Sepal.Width')
df.iris = iris[!exclude.cols]
# Irisデータをそのままプロット(x軸Petal.Length、y軸Petal.Width)
par(mar = c(6, 7, 5, 2))
par(mgp = c(4, 1.2, 0.4))
par(lwd = 2)
plot(df.iris$Petal.Length, df.iris$Petal.Width,
main = "Iris (Random forest)",
xlab = "Petal length (cm)",
ylab = "Petal width (cm)",
col = c(2, 3, 4)[df.iris$Species],
pch=c(0, 1, 2)[df.iris$Species],
cex = 1.5,
cex.main = 2,
cex.lab = 2,
cex.axis = 1.5,
xlim = c(0, 7.5),
xaxp = c(0, 7, 7),
ylim = c(0, 3),
yaxp = c(0, 3, 3)
)
par(family = "serif")
par(font = 3)
legend("topleft",
legend = levels(df.iris$Species),
pch = c(0, 1, 2),
col = c(2, 3, 4),
cex = 1.5,
pt.cex = 1.5,
bty = 'n',
inset = c(0.05, 0.03))
# モデル作成
set.seed(100)
model.rf = randomForest(Species ~ ., data = df.iris)
# 決定境界プロット用のメッシュ作成
px <- seq(0, 7, 0.01)
py <- seq(0, 3, 0.01)
pgrid <- expand.grid(px, py)
names(pgrid) <- c("Petal.Length", "Petal.Width")
# モデルでメッシュデータの分類を全て予測
pred.pgrid.rf <- predict(model.rf, pgrid)
# メッシュデータで等高線をプロット(決定境界)
contour(px, py, array(as.numeric(pred.pgrid.rf)-1, dim=c(length(px), length(py))),
xlim=c(0, 7), ylim=c(0, 3),
col="orange", lwd=2, drawlabels=F, add=T)
ランダムフォレストの境界は複雑にギザギザ折れ曲がってる。
最後はSVM(サポートベクトルマシン)の決定境界。
# SVM(サポートベクトルマシン)
# install.packages( "kernlab" ) # 必要に応じてインストール
library(kernlab)
# Irisデータ準備(Sepal.LengthとSepal.Widthを除外)
exclude.cols <- names(iris) %in% c('Sepal.Length', 'Sepal.Width')
df.iris = iris[!exclude.cols]
# Irisデータをそのままプロット(x軸Petal.Length、y軸Petal.Width)
par(mar = c(6, 7, 5, 2))
par(mgp = c(4, 1.2, 0.4))
par(lwd = 2)
plot(df.iris$Petal.Length, df.iris$Petal.Width,
main = "Iris (Random forest)",
xlab = "Petal length (cm)",
ylab = "Petal width (cm)",
col = c(2, 3, 4)[df.iris$Species],
pch=c(0, 1, 2)[df.iris$Species],
cex = 1.5,
cex.main = 2,
cex.lab = 2,
cex.axis = 1.5,
xlim = c(0, 7.5),
xaxp = c(0, 7, 7),
ylim = c(0, 3),
yaxp = c(0, 3, 3)
)
par(family = "serif")
par(font = 3)
legend("topleft",
legend = levels(df.iris$Species),
pch = c(0, 1, 2),
col = c(2, 3, 4),
cex = 1.5,
pt.cex = 1.5,
bty = 'n',
inset = c(0.05, 0.03))
# モデル作成
set.seed(100)
model.svm = ksvm(Species ~ ., data = df.iris)
# 決定境界プロット用のメッシュ作成
px <- seq(0, 7, 0.01)
py <- seq(0, 3, 0.01)
pgrid <- expand.grid(px, py)
names(pgrid) <- c("Petal.Length", "Petal.Width")
# モデルでメッシュデータの分類を全て予測
pred.pgrid.svm <- predict(model.svm, pgrid)
# メッシュデータで等高線をプロット(決定境界)
contour(px, py, array(as.numeric(pred.pgrid.svm)-1, dim=c(length(px), length(py))),
xlim=c(0, 7), ylim=c(0, 3),
col="orange", lwd=2, drawlabels=F, add=T)
SVMの境界はジャガイモみたいな丸い形になってる。
利用するモデル、パラメータやデータによっても決定境界が変化するから、いろいろ試してみるといいよ。
またね!
0 件のコメント :
コメントを投稿