今日は少し時間があったのでTitanicの例題をやりました。
pythonでのやり方のページを見て、Anacondaのセッティングをしてみたりしました。
pythonのコードがある程度動くことを確認した上で、どうしてもランダムフォレストをやるのが面倒で、別のコードをRで書くことにしました。
もともと僕は要領の悪い、全探索みたいなコードを書くのが好きなので、前回の記事でやった、『"Fare"を10ごとに区切ってランク分けして、そのランクを元に推定する』方法の改良版をRで書いてみました。
やり方は、『ランクを4つに区切る、その区切の整数3つについて、一番良い組み合わせを全探索で探す』というものです。
『一番良い組み合わせ』の基準は、色々あると思うんですが、自分の中で一番自然に思えるような計算式にしました。
コードは以下のような感じです。ゴリゴリ書いて、まったくまとまっていない。
学生の時と全く変わっていません。後日見たら読解に時間かかるだろうな・・・
traindata <- read.table("train.csv", header=T, sep=",") testdata <- read.table("test.csv", header=T, sep=",") traindata$Fare <- ifelse(is.na(traindata$Fare), 33.3, traindata$Fare) testdata$Fare <- ifelse(is.na(testdata$Fare), 33.3, testdata$Fare) t<-proc.time() maletraindata <- traindata[traindata$Sex == "male", ] femaletraindata <- traindata[traindata$Sex == "female", ] maletestdata <- testdata[testdata$Sex == "male", ] femaletestdata <- testdata[testdata$Sex == "female", ] bestsmaller <- 0 bestmiddle <- 0 bestlarger <- 0 bestscore <- 0 bestmalematrix <- matrix(nrow=3, ncol=4) bestfemalematrix <- matrix(nrow=3, ncol=4) devs <- c(-1,100,100,100,100000) for(dev1 in 1:40){ for(dev2 in dev1+1:40){ for(dev3 in dev2+1:40){ devs[2] <- dev1 devs[3] <- dev2 devs[4] <- dev3 malematrix <- matrix(0,nrow=3, ncol=4) # class = row, farerand = col femalematrix <- matrix(0,nrow=3, ncol=4) for(classind in 1:3){ for(devind in 1:4){ nowdata <- maletraindata[maletraindata$Pclass == classind & maletraindata$Fare > devs[devind] & maletraindata$Fare <= devs[devind+1], ] nowsurviveddata <- nowdata["Survived"] if(nrow(nowsurviveddata) == 0){ malematrix[classind, devind] <- 0 }else{ malematrix[classind, devind] <- (sum(nowsurviveddata) / nrow(nowsurviveddata)) } } } for(classind in 1:3){ for(devind in 1:4){ nowdata <- femaletraindata[femaletraindata$Pclass == classind & femaletraindata$Fare > devs[devind] & femaletraindata$Fare <= devs[devind+1], ] nowsurviveddata <- nowdata["Survived"] if(nrow(nowsurviveddata) == 0){ femalematrix[classind, devind] <- 0 }else{ femalematrix[classind, devind] <- (sum(nowsurviveddata) / nrow(nowsurviveddata)) } } } # ここまでで、traindataからの集計は終わり。testdataへ適用した時のスコア(勝手に自分で決めた基準)を計算する nowscore <- 0 for(classind in 1:3){ for(devind in 1:4){ nowcount <- nrow(maletestdata[maletestdata$Pclass == classind & maletraindata$Fare > devs[devind] & maletraindata$Fare <= devs[devind+1], ]) nowscore <- nowscore + nowcount * abs(0.5 - malematrix[classind, devind]) } } for(classind in 1:3){ for(devind in 1:4){ nowcount <- nrow(femaletestdata[femaletestdata$Pclass == classind & femaletraindata$Fare > devs[devind] & femaletraindata$Fare <= devs[devind+1], ]) nowscore <- nowscore + nowcount * abs(0.5 - femalematrix[classind, devind]) } } if(nowscore > bestscore){ bestsmaller <- dev1 bestmiddle <- dev2 bestlarger <- dev3 bestscore <- nowscore bestmalematrix <- malematrix bestfemalematrix <- femalematrix } print(sprintf("finish -> dev1,2,3 %2d , %2d , %2d", dev1, dev2, dev3)) } } } devs[2] <- bestsmaller devs[3] <- bestmiddle devs[4] <- bestlarger out <- file("./bestDevAns.csv", "w") # 書き込みモードで開く writeLines("PassengerId,Survived", out) # ヘッダーを記入 for(i in 1:nrow(testdata)){ writeLines(paste(testdata[i, "PassengerId"]), out, sep = ",") nowdata <- testdata[i,] nowfare <- nowdata$Fare nowfarerank <- 0 for(rankind in 1:4){ if(devs[rankind] < nowfare & nowfare <= devs[rankind + 1]){ nowfarerank <- rankind } } if(nowdata$Sex == "male"){ if(bestmalematrix[nowdata$Pclass, nowfarerank] < 0.5){ writeLines(paste(0), out, sep = "\n") }else{ writeLines(paste(1), out, sep = "\n") } }else{ if(bestfemalematrix[nowdata$Pclass, nowfarerank] < 0.5){ writeLines(paste(0), out, sep = "\n") }else{ writeLines(paste(1), out, sep = "\n") } } } close(out) # ファイルを閉じる print(sprintf("smaller: %3d , middle: %3d , larger: %3d are bests!", bestsmaller, bestmiddle, bestlarger)) print(proc.time()-t)
これによって、今回の基準で一番良い区切は
x<24, 24 <= x < 56, 56 <= x < 58, 58 <= x
という区切でした。(4つに区切る前提のコードです)
これで提出した回答は・・・
ちゃんとスコアが上がっていました!
スコア:0.78469 (0.00478アップ!)
2014位/3760(全体) ( 約300位アップ!)
上がってホッとしました。
まぁ今回はデータ数が少ないので、このやり方ができましたが、データ量がもっと大きい問題では確実にできないやり方ですね。
その場合は、区切候補の中を少しずつ変えていくやり方ですかね。シュミレーテッドアニーリング。大学のときに少しだけ勉強したので、いつか実装したいです。
そろそろランダムフォレストもやらねば!面倒だー。以上です!