0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

新米データサイエンティストの日常(架空)|Kaggleチュートリアル編

Last updated at Posted at 2025-03-06

はじめに

今回は、「新米データサイエンティストの日常」シリーズの第2弾になります。
新米データサイエンティストが躓きがちなテーマについて、先輩データサイエンティストと会話しているシーンをChatGPTに生成しもらいました。

第1弾はこちら↓


登場人物(架空)

  • 新米データサイエンティスト:新卒1年目のKaggle初心者。OJTでKaggleのコンペに挑戦中。
  • 先輩データサイエンティスト:入社5年目のKaggle GrandMaster。OJT担当。

シーン1:コンペの選定

後輩:「先輩、OJTの一環でKaggleのコンペに参加することになったんですが、どのコンペに挑戦すればいいですか?」

先輩:「Kaggleのコンペには大きく分けて 初心者向け(PlaygroundやGetting Started) と、 本格的な競争型コンペ(FeaturedやResearch) があるんだ。最初はデータ処理やモデリングの基礎を学べる House Prices - Advanced Regression TechniquesTitanic - Machine Learning from Disaster がおすすめだね。」

後輩:「Titanicは有名ですね!でも、ちょっと簡単すぎる気がします。」

先輩:「じゃあ、 House Prices に挑戦しようか。これは回帰問題で、特徴量エンジニアリングが重要になる。データの前処理や扱い方を学ぶのにちょうどいい。」


シーン2:データの確認

後輩:「データはもうダウンロードしました。いきなりモデルを作ればいいですか?」

先輩:「ダメダメ(笑)。まずはデータを "理解" しないと。train.csvdf = pd.read_csv("train.csv") で読み込んで、 df.info()df.describe() でデータの基本情報を確認してみよう。」

後輩:「なるほど…あ、LotFrontageAlley ってカラムに NaN が結構あります!」

先輩:「いい気づきだね!データの 欠損値処理 は重要な前処理のひとつ。適切な処理方法を選ぶのがポイントだよ。」


シーン3:前処理のコツ

後輩:「欠損値の処理って、fillna() で適当に埋めればいいんですか?」

先輩:「場合によるね。例えば、LotFrontage は数値データだけど、ランダムに埋めると意味がなくなる。だから 中央値で補完 するのが一般的だね。」

df["LotFrontage"] = df["LotFrontage"].fillna(df["LotFrontage"].median())

後輩:「なるほど!じゃあ、Alley みたいなカテゴリ変数は?」

先輩:「カテゴリ変数なら "None" や "Unknown" で埋める のがいいね。あるいは、欠損を 'has_alley' みたいな 新しい特徴量として追加 する手もある。」

df["Alley"] = df["Alley"].fillna("None")
df["HasAlley"] = df["Alley"].apply(lambda x: 0 if x == "None" else 1)

後輩:「なるほど、欠損情報自体を特徴量にするのもアリなんですね!」


シーン4:特徴量エンジニアリング

後輩:「他に前処理で気をつけることってありますか?」

先輩:「例えば、 カテゴリ変数のエンコーディング も重要。pd.get_dummies() でOne-Hotエンコーディングするのが基本だけど、 カテゴリの種類が多いとカラムが増えすぎる から、ラベルエンコーディングやターゲットエンコーディングを使うこともあるよ。」

from sklearn.preprocessing import LabelEncoder

encoder = LabelEncoder()
df["Neighborhood"] = encoder.fit_transform(df["Neighborhood"])

後輩:「へぇ~、ターゲットエンコーディングってなんですか?」

先輩:「カテゴリごとの 目的変数(SalePrice)の平均をエンコード する方法だね。ただし、リークを防ぐために K-foldで分割して計算 するのがコツ。」


シーン5:ベースラインモデルの作成

後輩:「前処理が終わったら、すぐに高精度なモデルを作るんですか?」

先輩:「いや、その前にまずは ベースラインモデル を作ろう。LightGBM や XGBoost をそのまま使って、スコアの目安を作るのが大事。」

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

X = df.drop("SalePrice", axis=1)
y = df["SalePrice"]

X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=42)

model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

preds = model.predict(X_valid)
print("RMSE:", mean_squared_error(y_valid, preds, squared=False))

後輩:「おお!これで最初のモデルができました!」

先輩:「これをベースラインにして、特徴量を増やしたり、ハイパーパラメータを調整したりして改善していくんだよ。」


シーン6:Kaggleでの提出

後輩:「できたモデルを提出するにはどうすればいいんですか?」

先輩:「予測結果を .csv に保存して提出するんだ。」

submission = pd.DataFrame({"Id": test_df["Id"], "SalePrice": model.predict(test_df)})
submission.to_csv("submission.csv", index=False)

後輩:「簡単ですね!でも、スコアがあまり良くないかも…。」

先輩:「それがKaggleの面白いところ!ここから 特徴量を工夫したり、アンサンブルしたりして改善 していくんだよ。」


シーン7:ベースラインモデルのスコア確認

後輩:「先輩、ベースラインモデルのRMSEスコアが 0.23 でした。でも、KaggleのLB(リーダーボード)を見たら、上位の人たちは 0.12 とかになってます…。こんなに差があると、どう改善すればいいのか分からなくて。」

先輩:「いい質問だね!スコアを改善する方法は大きく分けて 3つ ある。

  1. 特徴量エンジニアリングを改善する
  2. モデルを工夫する(アルゴリズム選定、ハイパーパラメータ調整、アンサンブル)
  3. データの扱い方を最適化する(外れ値処理、データ拡張など)

まずは 特徴量エンジニアリング からやってみよう。」


シーン8:特徴量エンジニアリング

後輩:「前処理のときに LotFrontage を中央値で補完したんですが、それ以外に改善点ってありますか?」

先輩:「例えば 新しい特徴量を作る のがいいね。LotFrontage'LotArea'(土地の広さ)で割ると、土地の形状に関する情報が得られる かもしれない。」

df["Frontage_Ratio"] = df["LotFrontage"] / df["LotArea"]
df["Frontage_Ratio"].fillna(0, inplace=True)

後輩:「なるほど!単純な数値をそのまま使うんじゃなくて、新しい指標を作るんですね。」

先輩:「そうそう。他にも YearBuiltYearRemodAdd から "築年数" の特徴量を作るのもよく使う手法だよ。」

df["HouseAge"] = 2024 - df["YearBuilt"]
df["RemodAge"] = 2024 - df["YearRemodAdd"]

後輩:「あ!それなら GarageYrBltGarageAge に変えた方がいいですね。」

df["GarageAge"] = 2024 - df["GarageYrBlt"]
df["GarageAge"].fillna(0, inplace=True)

先輩:「いいね!そうやって 意味のある特徴量を増やす と、モデルの予測精度が上がることが多いよ。」


シーン9:モデルの選定

後輩:「次にモデルを強化したいんですが、ランダムフォレスト以外に何がいいですか?」

先輩:「Kaggleでは 勾配ブースティング系のモデル(LightGBM, XGBoost, CatBoost) がよく使われるね。まずは LightGBM を試してみよう。」

from lightgbm import LGBMRegressor

model = LGBMRegressor(n_estimators=1000, learning_rate=0.05, num_leaves=31, random_state=42)
model.fit(X_train, y_train, eval_set=[(X_valid, y_valid)], early_stopping_rounds=100, verbose=50)

preds = model.predict(X_valid)
print("RMSE:", mean_squared_error(y_valid, preds, squared=False))

後輩:「おお、ランダムフォレストよりスコアが 0.18 まで改善しました!」

先輩:「LightGBMは計算も速くて便利だよ。他にも、 XGBoostCatBoost も試すといいね。」


シーン10:ハイパーパラメータチューニング

後輩:「でも、num_leaveslearning_rate って適当に決めました…。これってどうやって調整するんですか?」

先輩:「ハイパーパラメータの最適化には Optuna ってライブラリを使うといいよ。」

import optuna

def objective(trial):
    param = {
        "n_estimators": trial.suggest_int("n_estimators", 100, 2000),
        "learning_rate": trial.suggest_loguniform("learning_rate", 0.01, 0.3),
        "num_leaves": trial.suggest_int("num_leaves", 20, 100),
        "max_depth": trial.suggest_int("max_depth", 3, 12),
    }
    
    model = LGBMRegressor(**param, random_state=42)
    model.fit(X_train, y_train, eval_set=[(X_valid, y_valid)], early_stopping_rounds=100, verbose=0)
    
    preds = model.predict(X_valid)
    return mean_squared_error(y_valid, preds, squared=False)

study = optuna.create_study(direction="minimize")
study.optimize(objective, n_trials=50)

print("Best Params:", study.best_params)

後輩:「なるほど…これを使えば、自動でいいパラメータを見つけられるんですね!」

先輩:「そうそう。手動で調整するより効率がいいし、精度も上がりやすいよ。」


シーン11:アンサンブル

後輩:「LightGBMのスコアは0.16になったけど、まだ上位の人たちには追いつけないですね…。」

先輩:「そういうときは アンサンブル を試してみよう。複数のモデルを組み合わせることで、より強いモデルを作れる。」

from sklearn.ensemble import StackingRegressor
from xgboost import XGBRegressor
from catboost import CatBoostRegressor

lgb = LGBMRegressor(n_estimators=1000, learning_rate=0.05, num_leaves=31, random_state=42)
xgb = XGBRegressor(n_estimators=1000, learning_rate=0.05, random_state=42)
cat = CatBoostRegressor(n_estimators=1000, learning_rate=0.05, verbose=0, random_state=42)

stacking_model = StackingRegressor(
    estimators=[("lgb", lgb), ("xgb", xgb), ("cat", cat)],
    final_estimator=RandomForestRegressor(n_estimators=500, random_state=42)
)

stacking_model.fit(X_train, y_train)
preds = stacking_model.predict(X_valid)
print("RMSE:", mean_squared_error(y_valid, preds, squared=False))

後輩:「おお!スコアが 0.14 まで改善しました!でも、まだトップとの差がありますね。」

先輩:「そうだね。あとは 外れ値の処理やデータの拡張 も試すといいよ。それに、上位陣のNotebookを参考にするのも大事。」


シーン12:最終的なまとめ

後輩:「今日は 特徴量エンジニアリング、モデル選定、ハイパーパラメータ調整、アンサンブル を学びました!Kaggleって、ほんとに奥が深いですね。」

先輩:「そうだね。最初は大変だけど、慣れれば楽しくなるよ。とにかく試行錯誤を繰り返して、少しずつスコアを改善していくのがKaggleの醍醐味だからね!」

後輩:「ありがとうございます!引き続き、改善を続けてみます!」

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?