以下の発表で紹介したデータについて解析したフローを示します。
Tokyo.Rでの発表スライドはこちら 。
今回は前々回、前回の解析に、ご恵贈頂いたデータ分析プロセス4章に記載されている
予測モデルの構築の手法を盛り込んだ内容です。
はじめにdevtools::install_github(“dichika/jaguchi”)で
jaguchiパッケージをインストールしておきます。
library(jaguchi)
library(dplyr)
library(caret)
library(mice)
library(pROC)
データを読み込みます。
siero <-jaguchi("siero")
## Loading required package: RCurl
## Loading required package: bitops
##
## Attaching package: 'RCurl'
##
## 以下のオブジェクトは 'package:mice' からマスクされています:
##
## complete
siero2 <- t(siero)
今回の解析でNAになっているのは、
サンプル中の濃度が低すぎて測定器で拾うことができなかった値です。
はじめに欠損値の数から確認していくことにします。
md.pattern(siero2)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
## 261 1 1 1 1 1 1 1 1 1 1 1 1 0
## 4 1 1 1 1 1 1 1 1 1 1 0 1 1
## 2 1 1 1 1 1 0 1 1 1 1 1 1 1
## 2 1 1 1 0 1 1 1 1 1 1 1 1 1
## 1 1 1 1 1 1 1 0 1 1 1 1 1 1
## 1 1 1 1 1 1 1 1 1 0 1 1 1 1
## 3 1 1 1 1 1 1 1 0 1 1 1 1 1
## 1 1 1 0 1 1 1 1 1 1 1 1 1 1
## 2 1 1 1 1 1 1 1 1 1 0 1 1 1
## 1 1 0 1 1 1 1 1 1 1 1 1 1 1
## 2 1 1 1 1 1 1 1 1 1 1 1 0 1
## 1 1 1 1 1 1 1 0 1 1 1 0 1 2
## 1 1 1 1 1 1 0 0 1 1 1 1 1 2
## 2 1 1 1 1 1 0 1 1 0 1 1 1 2
## 1 1 1 1 0 1 1 1 0 1 1 1 1 2
## 1 1 1 1 0 1 1 1 1 1 1 1 0 2
## 1 1 1 1 1 1 1 1 1 1 0 1 0 2
## 1 1 1 1 1 0 1 0 0 1 1 1 1 3
## 1 1 1 0 1 1 1 1 1 0 1 0 1 3
## 1 1 0 1 1 1 1 1 1 1 0 1 0 3
## 1 1 0 1 1 0 1 1 1 0 1 0 1 4
## 1 1 1 0 1 1 1 1 0 0 1 0 0 5
## 1 1 1 1 1 0 1 0 1 0 0 1 0 5
## 1 1 0 1 1 0 0 1 0 1 0 1 0 6
## 1 0 1 0 0 0 0 0 1 1 0 1 0 8
## 1 0 1 0 0 0 1 0 1 0 0 0 0 9
## 2 0 0 0 0 0 0 0 0 0 0 0 0 12
## 4 6 7 8 8 9 9 9 10 10 11 12 103
すべての項目で欠損がないのは261件。 IDと食事の項目があるので実際は259物質です。
次にデータを学習用、検証用に分割します。
set.seed(123)
samples=sort(sample(nrow(siero), nrow(siero)*0.5))
trainpre = siero[samples, -c(1:2)]
testpre = siero[-samples, -c(1:2)]
trainout = siero$Food[samples]
testout = siero$Food[-samples]
trainout2 = as.factor(trainout)
testout2 = as.factor(testout)
trainpre %>% dim
## [1] 6 296
testpre %>% dim
## [1] 6 296
続いて欠損値処理をします。
前回同様、NAにはガンマ分布から得た乱数を入れることにします。
ガンマ分布にしたのは物質の測定値なので、0はあっても負の値はないためです。
trainx <- data.matrix(trainpre, rownames.force = NA)
testx <- data.matrix(trainpre, rownames.force = NA)
n = 1000
rate = 5
set.seed(123)
trainx[is.na(trainx)]<- rgamma(n, rate, scale = 1/rate)
testx[is.na(testx)]<- rgamma(n, rate, scale = 1/rate)
Enetで学習用モデルを作ります。
#elastic net
set.seed(123)
con<-trainControl(method ="LOOCV",
preProc = c("center", "scale"),
summaryFunction = twoClassSummary,
classProbs = TRUE)
train_grid = expand.grid(alpha = 1:10 * 0.1, lambda = 10^{1:5 * -1})
enet_fit = train(trainx,trainout2,
method = "glmnet",
tuneGrid = train_grid,
trControl=con,
metric ="ROC")
## Loading required package: glmnet
## Loading required package: Matrix
## Loading required package: foreach
## Loaded glmnet 2.0-2
##
##
## Attaching package: 'glmnet'
##
## 以下のオブジェクトは 'package:pROC' からマスクされています:
##
## auc
enet_fit$bestTune
## alpha lambda
## 5 0.1 0.1
plot(varImp(enet_fit), top = 10)
続いてこの学習用モデルを検証データに当てはめてみます。
pred <- predict(enet_fit, testx)
(conf.mat <- table(pred,testout2))
## testout2
## pred After Before
## After 3 0
## Before 0 3
どうやら上手く当てはまっているようですね。
確認のためにROC曲線も書いておきましょう。
prob <- predict(enet_fit, testx, type = "prob")
rocCurve <- roc(response = testout2, predictor = prob$After)
plot(rocCurve, legacy.axes = TRUE)
##
## Call:
## roc.default(response = testout2, predictor = prob$After)
##
## Data: prob$After in 3 controls (testout2 After) > 3 cases (testout2 Before).
## Area under the curve: 1
見事に直角ですね。 (2015/10/22 追記: 著者の福島さんからご連絡いただき、上記のコードを修正いたしました。)
ここまで、前処理からモデル構築をデータ分析プロセスに沿って解析してきました。
書籍にある基本的な流れについては触れられたかな、と思っていますが、
ここでは到底やりきれなかったたくさんの技が データ分析プロセス本編には載っています。
スタッキングなどの技術も次に書く論文では取り入れていければ…などと思いつつ、
一連の解析は一区切りにしようと思います。
Rで機械学習を使う方であれば、抑えておきたい本だと思います。