0
0

More than 5 years have passed since last update.

何番煎じ? kaggle の Titanic: Machine Learning from Disaster をやってみる。 その3

Last updated at Posted at 2018-10-14

前回の反省

Kernelを眺めていると

すばらしいまとめがありました。
https://www.kaggle.com/pliptor/how-am-i-doing-with-my-score
によると僕が前回までに出した0.75598 というスコアは

全員死亡としてsubmit:0.62679
Sex, Embark, Pclass だけ考慮したら:0.76555

というわけで、僕のスコアは余計な処理をした割には凡人スコアでした。
Embark を使わなかったけど・・・

だいたい0.8が専門家との分かれ目という感じです。(0.8から何が書いてあるのかわからない)

前回断念した、名前の関連性(ファミリーか、親子か?)みたいなこともやってる方がいて、いい結果が出たそうです。

というわけで、

みんなのいいところをパクろう!

Kernelでたくさんのいいね!をもらっている以下のkernelを写経します。
https://www.kaggle.com/startupsci/titanic-data-science-solutions

このkernelは、Age FamilySize などのデータを徹底的に、カテゴリ化して、次元削減?をやっています。
さらに、このkernelは、最後に様々なモデルを使って予想しています。(XGBoost にぶっこんだだけの僕が異常)
Logistic Regression
KNN or k-Nearest Neighbors
Support Vector Machines
Naive Bayes classifier
Decision Tree
Random Forrest
Perceptron
Artificial neural network
RVM or Relevance Vector Machine

このkernelの筆者は訓練データへの予測精度から、Random Forestを採用して結果を予測しています。
機械学習の世界においては、訓練データを過学習してしまうと、汎用性を失ってしまうので、かならずテストデータとの比較(Validation)が必要となります。

Validation

前回の僕の解析で導き出した、少なくとも、牧師全滅説と、子供が死んだ団体全滅説が合っているモデルを使おうと思います。
写経して、最後のpredict部分をかなり触ります。

df_train = pd.read_csv('./train.csv').replace("male",0).replace("female",1)
df_test = pd.read_csv('./test.csv').replace("male",0).replace("female",1)


sep_forward = df_train["Name"].str.split(",",expand=True)
sep_backward = sep_forward[1].str.split(".",expand=True)
job = sep_backward[0].str.replace(" ","")
df_train["job"] = job
sep_forward = df_test["Name"].str.split(",",expand=True)
sep_backward = sep_forward[1].str.split(".",expand=True)
job2 = sep_backward[0].str.replace(" ","")
df_test["job"] = job2



# 16 years old peoples should be child
df_train.loc[df_train["Age"] < 16, ["job"] ] = "Child"
#display(df_train[df_train["Age"]< 18])

df_test.loc[df_test["Age"] < 16, ["job"] ] = "Child"
#display(df_test[df_test["Age"]< 18])

zennmetu_ticket = df_train[(df_train["job"]=="Child") & (df_train["Survived"]== 0)]["Ticket"].unique().tolist()
for izennmetu in zennmetu_ticket:
    df_test.loc[df_test["Ticket"] == izennmetu, "Survived"] = 0

df_test.loc[df_test["job"]=="Rev", "Survived"] = 0
val_index = df_test[df_test["Survived"]== 0 ].index

display(df_test[df_test["Survived"]== 0 ])

Clipboard01_kaggle_01.png
出力結果はこんな感じ。

各出力を目で見て確認します。

display("1",Y_pred_rf[[val_index]])
display("2",Y_pred_DT[[val_index]])
display("3",Y_pred_KNN[[val_index]])
display("4",Y_pred_LS[[val_index]])
display("5",Y_pred_PRE[[val_index]])
display("6",Y_pred_SGD[[val_index]])
display("7",Y_pred_SVC[[val_index]])
display("8",Y_pred_gauss[[val_index]])

最も僕が確信を持っている、「子供が死んでる団体は全滅説」と、「牧師全滅説」を予測していたのは、Perceptron でした。この結果をsubmitしたところ、結果が悪くなりました。orz

素直にRandom Forestを使ったところ、0.77511でした。うーん。

傾向的に、Random Forestの結果が0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 だったので、
80番の実は小家族の子供を生きていると判断(おそらくテストデータで別の子供が死亡)
141の女性
の死亡を予測するのが難しいのかなぁと思います。

推理から求まった結果を上書き

Random Forestの結果に、子供が死んでる家族全滅説と、牧師全滅説を上書きしてsubmitしたところ、0.78468までスコアが伸びました。
どこかのkernelにも書かれてましたが、trainに対してtestの方が明らかに死亡率が高いようです。
というわけで、Random Forestが生きていると判断した部分に対して死亡を提案したので、方向性としては間違ってなかったのでしょう。

Y_pred_rf[[val_index]] = 0

submission = pd.DataFrame({
        "PassengerId": test_df["PassengerId"],
        "Survived": Y_pred_rf
    })
submission.to_csv('submission20181016_rf_2.csv', index=False)

最後に

次は、僕が論理的に導き出したtest中に含まれる生存データもtraiに混ぜてみようかと思います。
あと、「子供が死んでる家族全滅説」となりうるようなパラメータの探索と、家族関係・団体の関係のようなものをするかなぁ?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0