前回の失敗の経験から、もうすこしマシなことをしようと思ってます。
データをさんざん見た結果、どうやらTicket(チケット番号)を使って家族(団体)をカテゴライズできそうです。その中で、子供(16才以下)が死んでる団体は全滅しているといっても、おそらく間違いではないでしょう。(統計的に確認するまでもなく=どうやって確認するのかわからない)
というわけで、testそろそろテストデータを作りはじめます。
条件
1 テストデータで子供が死んでる団体は全滅
というわけで、子供が亡くなっている団体のチケットを集めて、for文まわして代入します。
もっといい方法があるはずだ!
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
2 テストデータで子供が生き残っている団体の女性と子供は生存
ikinokori_ticket = df_train[(df_train["job"]=="Child") & (df_train["Survived"]== 1)]["Ticket"].unique().tolist()
#display(ikinokori_ticket)
for iikinokori_ticket in ikinokori_ticket:
# display(df_train[df_train["Ticket"] == iikinokori_ticket])
df_test.loc[(df_test["Ticket"] == iikinokori_ticket) & (df_test["Sex"]==1), "Survived"] = 1
df_test.loc[(df_test["Ticket"] == iikinokori_ticket) & (df_test["job"]=="Child"), "Survived"] = 1
3 Rev(牧師)は全滅 Col(大佐)も全滅 Dona(貴婦人?)は生存
df_test.loc[df_test["job"] == "Rev", "Survived"] = 0
df_test.loc[df_test["job"] == "Col", "Survived"] = 0
df_test.loc[df_test["job"] == "Dona", "Survived"] = 1
っていう、機械学習でも何でもない推理ゲームをがんばってきました。
testデータの418行中、47行が埋まりました。
trainとtestの共通性があるということに注目する、くっそ卑怯な、機械学習でも何でもない推理をしただけです。
欠損している年齢を推定
この先、生死を分ける要素に年齢は不可欠だと思うので、年齢を推定します。
そのために、trainとtestをつなげて、Ticketでグルーピングもどきをやってデータを眺めたところ、名前とか総合的に判断して、年齢が推定できる部分がいくつかありました。
ただし、それは人間が見てるからであって、アルゴリズムじゃありません。
名前の意味を理解して、「あー これ 夫婦っぽいから同じ年齢」みたいなことをしなければなりませんでした。
もうこれは、機械学習じゃないです(たぶん
df_ALL = pd.concat([df_train,df_test])
NaNlist =df_ALL[df_ALL["Age"].isna()]["Ticket"].unique().tolist()
for inan in NaNlist:
display(df_ALL[df_ALL["Ticket"]==inan])
なので、素直に全年齢の中央値(28.0才)を代入することにしました。
median_age=df_ALL["Age"].median()
print(median_age)
#28.0
df_train.loc[df_train["Age"].isna(),"Age"] = median_age
df_test.loc[df_test["Age"].isna(),"Age"] = median_age
機械学習的な処理 xgboost
機械学習的な処理をするためには、まず学習データが必要だそうです。
特に子供の生死が親の生死に直結する(気がします)
ですので、子供のデータだけを使って、機械学習した何かを作ります。
子供の生死予測モデル
ちなみに、僕はxgboostが何してるものかさっぱり理解しておりません。
手元にGPUも無いので、重い作業はできません。
しかもValidationデータを作ってないという。
df_child_train = df_train[(df_train["job"]== "Child")][["Survived","Pclass","Sex","SibSp","Fare"]]
import xgboost as xgb
reg = xgb.XGBRegressor()
x = df_child_train[["Pclass","Sex","SibSp","Fare","Parch"]]
y = df_child_train["Survived"]
reg.fit(x,y)
y_predict = reg.predict(x)
x_test = df_test[(df_test["job"]== "Child")][["Pclass","Sex","SibSp","Fare","Parch"]]
y_test = reg.predict(x_test)
aaa = []
for i in y_test:
if i > 0.8:
res = 1
else :
res = 0
aaa.append(res)
#print(aaa)
df_test.loc[df_test["job"]=="Child","Survived"] = aaa
display(df_test)
子供が死んでる家族は全滅の法則を再度適用します。
(逆に言うと、子供の生死がずれてたら、ここからどんどん正答率がわるくなります)
zennmetu_ticket2 = df_test[(df_test["job"]=="Child") & (df_test["Survived"]== 0)]["Ticket"].unique().tolist()
for izennmetu2 in zennmetu_ticket2:
display(df_test[df_test["Ticket"]==izennmetu2])
df_test.loc[df_test["Ticket"] == izennmetu, "Survived"] = 0
子供以外の生死予測モデル
子供が死ぬということは大人が死んでるので、大人の死の原因が必要です。
というわけで、子供以外のデータを全部つかって予測します。
プログラム省略
Submissionファイルを作る
省略
結果
8020 0.75598 (2018/10/13)
これは悪いんだか良いんだか。
たぶん、特に何も考えずにxgboostしたやつよりかは悪い気がする。
がんばって、0.8には上げたいなぁと。
まとめ
一晩かかって、Qiitaを書きながら kaggleの超基本チュートリアルをだいたい自力でやってみました。
Kernelも読まずによくやったなぁと思わなくもないです。(自画自賛)
子供の生死部分のデータを捏造して増やすとか、年齢推定を手作業ででもやりきるとか、いろいろやったほうが良さそうなことはたくさん思いつきますが・・・
データが思った以上に関連性がなくて、正直頭かかえてました。
個人的には、子供が死んでたら団体全員死亡説とか、名前から職業的なものを割り出す手法は悪くなかったのではと思っているのですが、結果に結びついてなさそうなので、(´・ω・`)ショボーン
誰かのカーネルの写経もやってみないとなぁと思っています。
あとpandasの扱いがくっそ適当なので、ぜひ誰かコメントください。