「即席!データサイエンス部署にいきなり配属されたどーにかしないといけない」、「妄走!あふれるデータでAnalyだせ、行き先も分からないまま[即席!データサイエンス部署にいきなり配属されたどーにかしないといけない2]」を読んで早速KAGGLEにチャレンジ中と思いますが、、、え、まだチャレンジしていないですと!
初心者向け、Rのcaretを用いてKAGGLEの初心者用課題titanicに挑戦しましょう。
Rでcaredでirisする
irisデータを用いた分類の例
まずはirisでR/caretの使い方から。
#caretパッケージの呼び出し
library(caret)
#乱数の種を固定
set.seeds(1)
#irisデータ150件のうち100件を学習データ、50件をテストデータにする
ids<-sample(150)
train<-iris[ids[1:100], ]
test<-iris[ids[101:150], ]
#クロスバリデーション法ほ指定。ここではCV
fitControl<-trainControl(method="CV")
#学習データにて学習モデルの構築
train.model<-train(train[, 1:4], train[, 5], method = m, preProcess = c("center", "scale"), trControl = fitControl)
#学習データにて学習モデルから予測を行う
train.pred<-predict(train.model, newdata = train[, 1:4])
#学習データにて実際の値と予測値の一致を確認
table(train[, 5], train.pred)
train.pred
setosa versicolor virginica
setosa 32 0 0
versicolor 0 35 1
virginica 0 0 32
つまり、setosaとvifginicaについては32の実績値に対して100%正解と予測し、versicolorについては36の実績値に対し、1つvirginicaと間違えたということ。
ただ、これは答えを教えたデータで学習しているので、別のデータが来たときに当たる保証がない。そのため、答えはわかっているが、答えをモデルに教え込んでないデータで検証を行う。
#テストデータにて学習モデルから予測を行う
test.pred<-predict(train.model, newdata = test[, 1:4])
#テストデータにて実際の値と予測値の一致を確認
table(test[, 5], test.pred)
test.pred
setosa versicolor virginica
setosa 18 0 0
versicolor 0 14 0
virginica 0 3 15
setosaは18件を、versicolorは14件を100%予測し、virginicaについては3件間違えたというところ。
どの学習器が性能がよいのだろうか
上記に続けて下記を実行してみよう。代表的なSVM、RandomForest、再度xgoostを試します。
for (m in c('svmLinear', 'rf', 'xgbTree')) {
train.model<-train(train[, 1:4],
train[, 5],
method = m,
preProcess = c("center", "scale"),
trControl = fitControl)
print(m)
test.pred<-predict(train.model, newdata = test[, 1:4])
print(table(test[, 5], test.pred))
}
[1] "svmLinear"
test.pred
setosa versicolor virginica
setosa 18 0 0
versicolor 0 14 0
virginica 0 1 17
[1] "rf"
test.pred
setosa versicolor virginica
setosa 18 0 0
versicolor 0 14 0
virginica 0 1 17
[1] "xgbTree"
test.pred
setosa versicolor virginica
setosa 18 0 0
versicolor 0 14 0
virginica 0 1 17
うーむ、これくらいのデータ量だと、変わりないですね。KAGGLEではxgboostが席巻しているようなので以下、xgboostを用います。
いよいよKAGGLEに挑戦
で、KAGGLEだ。データサイエンティストの天下一武道会と思ってもらったらいい。平成の皆さん、天下一武道会とは何か。KAGGLEと思ってもらっていい。いい。
怖気づくことはない、僕も怖い。
まずはユーザー登録をしよう。FB、Google、Yahooの各アカウントかマニュアル登録がある。
続いて課題に取り掛かろう。
https://www.kaggle.com/competitions
とたくさんの課題がある。賞金があるもの。練習台。特徴ある課題。初心者用の練習課題。まずは初心者用練習台のタイタニック号の課題Titanic: Machine Learning from Disasterに相対する。
Titanic: Machine Learning from Disaster
タイタニック号の生存者を予測する問題です。年齢、性別、部屋の位置などの情報から生存したか否かを予測します。
データの取得
Get the Dataをクリックします。課題ごとのルール https://www.kaggle.com/c/titanic/rules に同意するかの画面が出るので、納得して同意を。複数アカウントで参加するな、身内だけでコードを共有するなとか。
取り敢えずはtrain.csv, test.csvだけダウンロードすればいいです。
train.csvに正解データがあり、これで学習して予測モデルを作り、test.csvのデータを予測します。
R/caretで実行してみよう
#caretパッケージの呼び出し
library(caret)
# trainデータの読み込み。
train<-read.csv('train.csv', header=T)
head(train)
# Survivedが答え。train.cに格納します。
train.c<-as.factor(train$Survived)
# PassengerId, Survived, Name, Ticket, Cabinを学習データから削除します。
train<-train[, -c(1, 2, 4, 9, 11)]
head(train)
PassengerIDは乗船番号なので使いません。Survivedは生きていたか亡くなったかの答えのデータです。Nameは乗客の名前でTicketはチケット番号です。上級者になると「この苗字は上流階級だから上級の客室にいたはずで生存率が高いはず」などと解析したりするそうですが、ここではスルーします。Cabinは部屋番号ですが、空欄が多いので今回はこれもスルーします。
# カテゴリカルデータをダミー変数にする。
tmp<-dummyVars(~., data = train)
train.d<-as.data.frame(predict(tmp, train))
head(train.d)
性別などの変数はそのままでは学習に用いられません。
性別
男
女
男
女
というデータを
性別.男, 性別.女
1, 0
0, 1
1, 0
0, 1
という風に分ける事をダミー変数にすると言います。
# Embarked.列の削除
train.d<-train.d[, -8]
head(train.d)
Embarked乗船した港のデータが一部レコードで欠失しており、ダミー変数にした場合ごく少数のみが1で以降の処理に支障をきたすのと、testデータにはEmbarkedが欠失しているものがなかったので今回は昨除しました。
# 年齢の欠失を平均値で補完
mean.age<-mean(train.d$Age, na.rm = T)
mean.age
train.d$Age[is.na(train.d$Age)]<-mean.age
年齢の欠失しているレコードが多数ありました。これを削除してしまうと大幅にデータが減ってしまい、testデータでも年齢が欠失しているレコードが多数ありました。
今回はかなりラフですが、年齢の有るデータの平均値で埋めました。
# 乱数の種を1に設定
set.seed(1)
これは本来不要です。ただ実行の度に乱数が変わるので、ここでの例と皆さんの実行結果がズレてしまいます。このように乱数の種を設定することにより、ここでの例と皆さんの実行結果が一致します。
# trainデータを学習用と検証用に分ける
train.index<-createDataPartition(train.c, p=0.5, list=F)
train.train<-train.d[train.index,]
train.test<-train.d[-train.index,]
train.train.c<-train.c[train.index]
train.test.c<-train.c[-train.index]
作成したモデルがどの程度精度がよいか正解のあるデータで検証します。学習したデータそのもので検証すると他のデータでも正しいかどうか分からないので、trainデータを学習用と検証用に分けます。ここではp=0.5で半分ずつに分けています。
# 学習の実施
## クロスバリデーション方をCVに設定
fitControl<-trainControl(method = 'CV')
## 学習モデルの構築、ここではxgbTreeを指定。
train.model<-train(train.train,
train.train.c,
method = 'xgbTree',
preProcess = c('center', 'scale'),
trControl = fitControl)
パラメータを自動で変更しながら学習モデルを構築します。
# 検証=答え合わせ
## 学習データによる
train.train.pred<-predict(train.model, newdata = train.train)
table(train.train.c, train.train.pred)
## テストデータによる
train.test.pred<-predict(train.model, newdata = train.test)
table(train.test.c, train.test.pred)
trainデータのうち学習に用いたデータと検証用に準備したデータでそれぞれ検証してみます。
学習に用いたデータでの結果。
train.train.pred
train.train.c 0 1
0 258 17
1 34 137
train.test.pred
縦側が答え、横側が予測値。0が答えの275件のうち、正解が258件、不正解が17件でした。1が答えの171件のうち、正解が137件、不正解が34件でした。
同様に検証用に用意したデータでの結果は、
train.test.pred
train.test.c 0 1
0 243 31
1 53 118
0が答えの274件のうち、正解が243件、不正解が31件でした。1が答えの171件のうち、正解が118件、不正解が53件でした。ちょっと正解が落ちましたがまずまずかなと思います。続いていよいよtest.csvデータ、つまり正解が分からないデータについての予測に移ります。
# testデータの読み込み
test<-read.csv('test.csv', header = T)
head(test)
# PassengerIDをtest.idに格納
test.id<-test$PassengerId
# PassengerId, Name, Ticket, Cabinを除く
test<-test[, -c(1, 3, 8, 10)]
head(test)
trainデータと同様にデータを読み込み不要なデータを削除します。PassengerIDは答えの提出に用います。
# カテゴリカルデータをダミー変数にする。
tmp<-dummyVars(~., data = test)
test.d<-as.data.frame(predict(tmp, test))
head(test.d)
# 年齢の欠失を平均値で補完
mean.age<-mean(test.d$Age, na.rm = T)
mean.age
test.d$Age[is.na(test.d$Age)]<-mean.age
trainデータと同様にダミー変数の作成と年齢の欠失を保管します。
# Fareの欠失を平均値で補完
mean.fare<-mean(test.d$Fare, na.rm = T)
mean.fare
test.d$Fare[is.na(test.d$Fare)]<-mean.fare
Fare乗船料金の欠失がtestデータにはあったため、年齢と同様に平均値で保管しました。
# 予測の実施
test.pred<-predict(train.model, newdata = test.d)
# PassengerIDを付加
output<-data.frame(test.id, test.pred)
# 列名を付与
names(output)<-c('PassengerID', 'Survived')
# 結果のファイルへの書き出し。
write.table(output, 'output.csv', sep = ',', quote = F, col.names = T, row.names = F)
最終的に結果をファイルに書き出します。結果の一部は下記。さー当たっているでしょうか。
> output[1:10, ]
PassengerID Survived
1 892 0
2 893 0
3 894 0
4 895 0
5 896 0
6 897 0
7 898 1
8 899 0
9 900 1
10 901 0
KAGGLEに投稿しよう
Titanic: Machine Learning from DisasterのページのMake a submissionをクリックします。
一人で実施したならCompete as myselfを、複数人のチームで実施したならCompete as a teamをクリックします。私は一人で実施したのでCompete as myselfを。
Click or drop your submission hereをクリックして、先ほどの出力のoutput.csvファイルを選択し、Submitをクリックします。
ランキングのページに結果が出ます。
上記の結果はScoreが0.76555で、投稿時点で3,467位でした。課題ごとに最低限のラインのBenchmarkとして灰色の行があります。taitanicの場合は全部を亡くなった方とするとScoreが0.62679となるようです。これよりは上位なので少しはマシな予測をしたということですが、まだまだ低いですね。
Scoreは課題によって計算方法が異なりますがtaitanicの場合はCategorization Accuracyとのことで(カテゴリの一致数/レコード数)でしょうか。testデータの正解は分からないので検証用データの結果から計算すると
(243 + 118) / (243 + 31 + 53 + 118) = 0.81
でした。
1位にはScore=1.0つまり全問正解の方がいらっしゃいますね。頑張って上を目指しましょう。
課題により1日の投稿回数が決まっています。
もっと詳しく解析したくなったら
陽動成功!楽しくなりましたか。
ここでは最低限のことしか行ってません。上位を目指すには、データの前処理、モデル構築のパラメータチューニングなどやることがたくさんあります。
下記のサイトなどを参考にして上位を目指し、他の課題にも挑戦してみてください!
(って、私もチュートリアルをそのまま実行レヴェルしかやったことがないのですがねー。会社では出来ないし、家では家事が忙しいんだ許せ)
- caretのチュートリアル等の和訳 拙訳。訳が酷いところがあり申し訳ないですがとっかかりとなれば!
- titanic号の課題。pythonでの実行例ですが、解説が詳しく参考になると思います。
もっとデータ分析について知りたくなったら データサイエンス、データ分析、機械学習関連の本 へ行こう。