【Kaggle挑戦記】Titanic 攻略 #13:自己ベスト更新 0.78468!「引き算」と「新しい視点」の勝利
前回(攻略 #12)では、精緻に作り込んだ「敬称」データがまさかの裏目に出て、スコアが 0.77751 まで下落するという苦い経験をしました。しかし、その敗北から学んだ「情報の重複を削る」という教訓、そして新たな物理的要因 Embarked(乗船港) の導入が、ついに 0.78468 という自己ベスト更新を呼び込みました!
1. 逆転の戦略:複雑さを捨て、文脈を足す
今回の成功のポイントは、単なる「足し算」ではなく、勇気を持った「引き算」にあります。スコアを下げていた Title(敬称)を一度捨て、モデルをスリム化した上で、全く新しい切り口である Embarked を追加しました。
- 多重共線性の解消: 性別・年齢・敬称という似通った情報の衝突を解消し、モデルの迷いを取り除きました。
- 乗船港が示す「背景」: シェルブール(C)=富裕層、サウサンプトン(S)=一般層といった、港ごとの生存傾向が、Pclassだけでは説明しきれなかった微細な生存確率を補完しました。
2. 【実装】0.78468 を叩き出した最終コード
シンプルながらも強力な、現時点での「最適解」と言えるコード全文です。Embarkedの欠損値を最頻値で埋め、ダミー変数化して投入しています。
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
# 1. データの読み込み
train_data = pd.read_csv('train.csv')
test_data = pd.read_csv('test.csv')
# 2. Embarked(乗船港)の欠損値補完
# 最も多い乗船港である 'S' で補完
train_data['Embarked'] = train_data['Embarked'].fillna('S')
test_data['Embarked'] = test_data['Embarked'].fillna('S')
# 3. 安定した前処理の再現(属性別Age補完 & 家族サイズ)
group_cols = ['Pclass', 'Sex']
train_data['Age'] = train_data['Age'].fillna(train_data.groupby(group_cols)['Age'].transform('median'))
test_data['Age'] = test_data['Age'].fillna(test_data.groupby(group_cols)['Age'].transform('median'))
for df in [train_data, test_data]:
df['FamilySize'] = df['SibSp'] + df['Parch'] + 1
# テストデータの運賃欠損を中央値で補完
test_data['Fare'] = test_data['Fare'].fillna(test_data['Fare'].median())
# 4. 学習に使用する特徴量の定義
# 迷走した Title はあえて外し、Embarked を新規採用
features = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "FamilySize", "Embarked"]
# 5. カテゴリ変数をダミー変数に変換
X = pd.get_dummies(train_data[features])
y = train_data["Survived"]
X_test = pd.get_dummies(test_data[features])
# 学習とテストの列を一致させる
X, X_test = X.align(X_test, join='left', axis=1, fill_value=0)
# 6. モデル学習(500本の決定木、最大深さ5)
model = RandomForestClassifier(n_estimators=500, max_depth=5, random_state=1)
model.fit(X, y)
# 7. 予測の実行と提出用CSV作成
predictions = model.predict(X_test)
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})
output.to_csv('submission_final_best.csv', index=False)
print("Score 0.78468 達成の予測ファイルを保存しました。")
3. 実験結果:0.77751 → 0.78468 へ跳ねる!
特徴量を1つ入れ替え、整理しただけで、スコアは劇的に改善しました。
- 前回(Title追加): Score 0.77751
- 今回(Title削除+Embarked追加): Score 0.78468 (New Record!)
4. 考察:エンジニアリングの本質は「整理整頓」にあり
エンジニア的な視点:
今回の結果が教えてくれたのは、「良いデータ」を足すことと同じくらい、「不要な相関を削る」ことが重要であるという事実です。一時は 0.77 台まで落ち込み絶望しましたが、そこで立ち止まらずに「なぜ落ちたのか?」を考え、別の軸(Embarked)に切り替えたことが勝機となりました。0.785の壁も見えてきました。次はこの安定した土台の上に、さらなるエッセンスを加えていきます。
自己ベスト更新の余韻に浸りつつも、Kaggleの道はまだ続きます。今回の勝利で「情報の質と整理」の重要性が証明されました。次は、今回あえて削った `Title` を「ノイズにならない形」で再統合するか、あるいは `Cabin`(客室)の深淵に踏み込むか……。戦略を練り直します!
PR