Kaggle_テーブルデータ_ベースライン(目的変数:カテゴリ)
EDA~モデル動かす(LGB)までの、ベースラインテンプレ。
シンプルなテーブルデータなら、これだけである程度の精度出ます。
まずこれで提出してからが勝負って感じです。
Kaggle初心者による、半分自分のためのアウトプットです。
初学者の同志はご参考に。上級者の方々はフィードバックお待ちしています。
EDA
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
import lightgbm as lgb
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import log_loss, accuracy_score
このへんはいつもの
train = pd.read_csv("パス")
test = pd.read_csv("パス")
submission = pd.read_csv("パス")
train.head()
print(train.shape)
print(test.shape)
train.dtypes
train.describe()
train.isnull().sum()
test.isnull().sum()
欠損値の可視化(お気に入り)
sns.heatmap(train.isnull(), cbar=False, cmap='viridis')
plt.title('Missing Values Heatmap (using seaborn)')
plt.xlabel('Features')
plt.ylabel('Rows')
plt.show()
目的変数の分布を見る
plt.figure(figsize=(8, 6))
sns.countplot(y=train['カラム名'], order=train['カラム名'].value_counts().index, palette='viridis')
plt.title('タイトル')
plt.xlabel('Count')
plt.ylabel('カラムの値')
plt.tight_layout()
plt.show()
print("\n--- 目的変数 'Personality' のカテゴリ分布(割合) ---")
print(train['Personality'].value_counts(normalize=True))
数値データをヒストグラムで可視化
# 数値型の列を抽出
numeric_cols = train.select_dtypes(include=['int64', 'float64']).columns
# ヒストグラムの表示
plt.figure(figsize=(15, 10))
for i, col in enumerate(numeric_cols):
plt.subplot(3, 6, i + 1)
sns.histplot(train[col], kde=True)
plt.title(f'Histogram of {col}')
plt.xlabel('')
plt.ylabel('')
plt.tight_layout()
plt.show()
説明変数の中身を詳しく見る&特徴量エンジニアリングの部分は省略
- ヒストグラム
- 箱ひげ図
- 相関分析
あたりはほぼ毎回やるかな。
特徴量エンジニアリングは後でしっかりやってくので、この段階で明らかにやるべきものだけ
LGB
欠損値に重大な偏りがないなら、まずはLGBの取り扱いに任せるのがベタ。
データの準備
# 目的変数の列名
TARGET = '目的変数のカラム名'
# 'id' 列の削除
if 'id' in train.columns:
train_ids = train['id'] # 後で使うかもしれないので保存
train = train.drop('id', axis=1)
print("Trainデータから 'id' 列を削除しました。")
if 'id' in test.columns:
test_ids = test['id'] # Submissionファイル作成のために保存
test = test.drop('id', axis=1)
print("Testデータから 'id' 列を削除しました。")
print("\n'id' 列削除後のtrain.head():")
train.head()
# 目的変数をtrainから分離
y_train = train[TARGET]
X_train = train.drop(TARGET, axis=1)
# trainとtestを結合(前処理の一貫性を保つため)
# 結合前にtrainの目的変数を分離しておく
combined_df = pd.concat([X_train, test], ignore_index=True, sort=False) # sort=Falseはwarning回避
print("\nTrainとTestを結合しました。結合後の形状:", combined_df.shape)
ラベルエンコード部分は省略
データ型に合わせて適宜エンコード
パラメータ(暫定)
params = {
'objective': 'binary', # 目的変数が2値分類の場合
'metric': 'binary_logloss', # 評価指標 (Kaggleのコンペの評価指標に合わせる)
'boosting_type': 'gbdt',
'num_leaves': 31,
'learning_rate': 0.05,
'feature_fraction': 0.9,
'bagging_fraction': 0.8,
'bagging_freq': 5,
'verbose': -1, # ログ出力を抑制
'n_jobs': -1, # CPUの全コアを使用
'seed': 42,
'boosting_seed': 42,
'lambda_l1': 0.1, # L1正則化
'lambda_l2': 0.1, # L2正則化
}
交差検証(5×CV)
# 交差検証の設定
N_SPLITS = 5 # 分割数 (5分割)
skf = StratifiedKFold(n_splits=N_SPLITS, shuffle=True, random_state=42)
oof_preds = np.zeros(len(X_train_processed)) # Out-of-Fold予測を格納
test_preds = np.zeros(len(X_test_processed)) # テストデータの平均予測を格納
models = [] # 学習済みモデルを保存するリスト
for fold, (train_idx, val_idx) in enumerate(skf.split(X_train_processed, y_train_encoded)):
print(f"\n--- Fold {fold+1}/{N_SPLITS} ---")
X_train_fold, X_val_fold = X_train_processed.iloc[train_idx], X_train_processed.iloc[val_idx]
y_train_fold, y_val_fold = y_train_encoded[train_idx], y_train_encoded[val_idx]
# LightGBMデータセットの作成
lgb_train = lgb.Dataset(X_train_fold, y_train_fold)
lgb_eval = lgb.Dataset(X_val_fold, y_val_fold, reference=lgb_train)
# モデル学習
model = lgb.train(
params,
lgb_train,
num_boost_round=1000, # 学習回数(多めに設定し、early_stoppingで調整)
valid_sets=lgb_eval,
callbacks=[lgb.early_stopping(100, verbose=True), lgb.log_evaluation(period=50)], # verbose=Trueで詳細表示, log_evaluationで評価間隔を設定
)
models.append(model)
# Out-of-Fold予測
fold_oof_preds = model.predict(X_val_fold, num_iteration=model.best_iteration)
oof_preds[val_idx] = fold_oof_preds
# テストデータ予測(各Foldの予測を平均するために加算)
fold_test_preds = model.predict(X_test_processed, num_iteration=model.best_iteration)
test_preds += fold_test_preds / N_SPLITS
# 各Foldでの評価指標の出力
fold_logloss = log_loss(y_val_fold, fold_oof_preds)
fold_oof_labels = np.round(fold_oof_preds)
fold_accuracy = accuracy_score(y_val_fold, fold_oof_labels)
print(f"Fold {fold+1} Validation Log Loss: {fold_logloss:.4f}")
print(f"Fold {fold+1} Validation Accuracy: {fold_accuracy:.4f}")
# 全体のOOF予測に対する評価
overall_logloss = log_loss(y_train_encoded, oof_preds)
oof_labels = np.round(oof_preds) # 0.5を閾値としてラベルに変換
overall_accuracy = accuracy_score(y_train_encoded, oof_labels)
print(f"\n--- 交差検証結果 ---")
print(f"Overall OOF Log Loss: {overall_logloss:.4f}")
print(f"Overall OOF Accuracy: {overall_accuracy:.4f}")
submissionファイルの作成
(二値分類ならエンコードを戻す。閾値は上で設定した0.5でおk)
submission = pd.DataFrame({
'id': test_ids,
'目的変数のカラム名': final_test_predictions
})
# CSVファイルとして保存
# index=False は、DataFrameのインデックスをCSVファイルに書き込まないための重要な引数
submission.to_csv('submission.csv', index=False)
print("\n'submission' 変数に予測結果を上書きし、'submission.csv' を作成しました。")
submission.head()
念のためsubmmisionファイルの中身の確認
貴重な1/5を無駄にしないように最終チェック。
また、形式が変になってると突き返されるので(たまにある
# OOF予測の分布を可視化 (Optional)
plt.figure(figsize=(10, 6))
sns.histplot(np.argmax(oof_preds_tuned, axis=1), bins=np.arange(len(y.unique()) + 1) - 0.5, kde=False, color='skyblue', edgecolor='black')
plt.title('Distribution of OOF Predictions')
plt.xlabel('Predicted Class')
plt.ylabel('Count')
plt.xticks(range(len(y.unique())), le.inverse_transform(range(len(y.unique())))) # 元のラベルに戻して表示
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.show()
あとは提出するだけ!
さいごに
これくらいならvibeコーディングでも余裕ですね。
いずれ、Kaggleノートブックにも自然言語で一発でここまで来れる機能が実装されるかもしれません。
それに加え、データに基づいて次のアクションまでAIは提案できると思います。
ただ、Kaggleも実務も、まだまだAIにはできない部分が、勝敗を分けますよね。
それに関しては多くを語る必要はないと思います。
Kaggler勢、ビジネスアナリスト勢、これからも共にがんばりましょう。