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

#前回の反省

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部分をかなり触ります。


```python
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](https://qiita-image-store.s3.amazonaws.com/0/180426/4179e19d-49d6-df8d-5653-340fe065015d.png)
出力結果はこんな感じ。

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

```python
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 だったので、
８０番の実は小家族の子供を生きていると判断（おそらくテストデータで別の子供が死亡）
１４１の女性
の死亡を予測するのが難しいのかなぁと思います。

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

```python
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に混ぜてみようかと思います。
あと、「子供が死んでる家族全滅説」となりうるようなパラメータの探索と、家族関係・団体の関係のようなものをするかなぁ？