【Kaggle挑戦記】S4E11 #1:メンタルヘルス予測コンペ参戦。LightGBMで「0.94」の初陣
次なるターゲットに選んだのはKaggle Playground Series S4E11。 実在のアンケート結果をベースにした「メンタルヘルス(うつ病)の予測」です。 実務的なデータ構造を相手に、まずは何も考えずLightGBMでベースラインを構築してみました。
1. コンペの概要:生体ログから「心の状態」をデバッグする
今回のミッションは、年齢、性別、仕事のストレス、睡眠時間、食事習慣といった多角的なデータから、 対象者がうつ病(Depression)の状態にあるかどうかを予測する2値分類です。
| 主要な特徴量 | エンジニア的解釈 |
|---|---|
| Academic/Work Pressure | システムの負荷状況(リソース逼迫度) |
| Sleep Duration / Dietary Habits | メンテナンス(自己回復)のログ |
| Financial Stress | 外部環境によるエラー因子 |
2. 実装:特徴量は「すべてぶっ込んだ」最短ルート
「どの項目が重要か?」を人間が考える前に、まずはマシンパワーに任せてみます。 今回はID以外の特徴量をすべてぶっ込み、カテゴリ変数はLightGBMのcategory型指定で一気に処理する、いわば「全件スキャン」的なアプローチをとりました。
通常なら除外するはずの「Name(名前)」のような文字列データも、モデルがどう解釈するかを見るためにあえて残しています。
import pandas as pd
import lightgbm as lgb
from sklearn.preprocessing import LabelEncoder
# データの読み込み
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')
target_col = 'Depression'
# ターゲットの数値化
le = LabelEncoder()
train[target_col] = le.fit_transform(train[target_col])
# 特徴量は全投入(idのみ除外)
X = train.drop(['id', target_col], axis=1)
y = train[target_col]
X_test = test.drop(['id'], axis=1)
# カテゴリ型への一括変換
cat_cols = X.select_dtypes(include=['object']).columns.tolist()
for col in cat_cols:
X[col] = X[col].astype('category')
X_test[col] = X_test[col].astype('category')
# モデル構築(2値分類:Binary)
model = lgb.LGBMClassifier(objective='binary', random_state=42)
model.fit(X, y)
# 予測と提出ファイルの作成
submission = pd.DataFrame({
'id': test['id'],
target_col: model.predict(X_test)
})
submission.to_csv('submission.csv', index=False)
3. 結果と考察:見えてきた「データの罠」
初回のSubmit結果は以下の通りです。
なかなかの高スコアですが、Feature Importance(重要度)を見るとデバッグすべき点が見つかりました。
--- Feature Importance Top 5 --- 1. Name : 1308 2. City : 223 3. Age : 204 4. Financial Stress : 174 5. Profession : 159
「Name(名前)」が重要度のトップに君臨しています。 「全特徴量投入」の結果、モデルは名前に含まれる特定のパターン(あるいは個別のID的な性質)を、うつ病の判定材料として「暗記」してしまったようです。 これは典型的な過学習の予兆であり、システム開発で言えば「テストデータのみに通るハードコーディング」に近い状態かもしれません。
4. まとめと次回の課題
まずは「動くもの」を作り、0.94というベンチマークを得ることに成功しました。
次回は、この「Name」というノイズを除去した際にスコアがどう変化するか、そしてLog Lossを意識した確率予測のチューニングに挑みます。