【kaggle】宇宙船タイタニック!?サブミット編

機械学習

前回のこちら『【kaggle】宇宙船タイタニック!?データ整理編』であらかたデータを整えたので
今回は学習からカグル提出した結果まで、やっていこうと思います。

学習用データに編集していきます

前回でここまでやりました。

df_all.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 12970 entries, 0 to 12969
Data columns (total 21 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   PassengerId   12970 non-null  object 
 1   HomePlanet    12970 non-null  object 
 2   CryoSleep     12970 non-null  bool   
 3   Cabin         12671 non-null  object 
 4   Destination   12970 non-null  object 
 5   Age           12970 non-null  float64
 6   VIP           12970 non-null  bool   
 7   RoomService   12970 non-null  float64
 8   FoodCourt     12970 non-null  float64
 9   ShoppingMall  12970 non-null  float64
 10  Spa           12970 non-null  float64
 11  VRDeck        12970 non-null  float64
 12  Name          12676 non-null  object 
 13  Transported   8693 non-null   float64
 14  train/test    12970 non-null  object 
 15  ID01          12970 non-null  int64  
 16  ID02          12970 non-null  int64  
 17  Cabin1        12970 non-null  object 
 18  Cabin2        12970 non-null  int64  
 19  Cabin3        12970 non-null  object 
 20  pay           12970 non-null  float64
dtypes: bool(2), float64(8), int64(3), object(8)
memory usage: 1.9+ MB

名前は今回使わないので落とします。

df_all=df_all.drop(["Name"],axis=1)

文字のデータをラベルエンコーディングします。

from sklearn.preprocessing import LabelEncoder
lbl=LabelEncoder()
df_all["HomePlanet"]=lbl.fit_transform(df_all["HomePlanet"])
df_all["Destination"]=lbl.fit_transform(df_all["Destination"])
df_all["Cabin1"]=lbl.fit_transform(df_all["Cabin1"])
df_all["Cabin3"]=lbl.fit_transform(df_all["Cabin3"])

確認すると、

df_all.head()
PassengerIdHomePlanetCryoSleepCabinDestinationAgeVIPRoomServiceFoodCourtShoppingMallSpaVRDeckTransportedtrain/testID01ID02Cabin1Cabin2Cabin3pay
00001_011FALSEB/0/P239FALSE000000train111100
10002_010FALSEF/0/S224FALSE109925549441train21511736
20003_011FALSEA/0/S258TRUE43357606715490train3101110383
30003_021FALSEA/0/S233FALSE0128337133291930train320115176
40004_010FALSEF/1/S216FALSE3037015156521train415111091

数字になってくれました。さらに、使わないのを落とします。

df_all=df_all.drop(["PassengerId","Cabin","ID01"],axis=1)

学習用データを形成します。

x=df_all.loc[(df_all["train/test"]=="train")].drop(["Transported","train/test"],axis=1)
t=df_all.loc[(df_all["train/test"]=="train")].iloc[:,10:11]
x.head()
HomePlanetCryoSleepDestinationAgeVIPRoomServiceFoodCourtShoppingMallSpaVRDeckID02Cabin1Cabin2Cabin3pay
01FALSE239FALSE0000011100
10FALSE224FALSE109925549441511736
21FALSE258TRUE4335760671549101110383
31FALSE233FALSE01283371332919320115176
40FALSE216FALSE30370151565215111091

すっきりしました。

t.head()
Transported
00
11
20
30
41

テスト用データも。

x_test=df_all.loc[(df_all["train/test"]=="test")].drop(["Transported","train/test"],axis=1)

もろもろ整いました。

OPTUNA×lightGBM×交差検証で学習

さて、やっていきます。

from sklearn.model_selection import train_test_split
from sklearn import metrics
import lightgbm as lgb
from sklearn.model_selection import StratifiedKFold
kf=StratifiedKFold(n_splits=10, shuffle=True, random_state=0)

ひとまず10回で。

def objective(trial):
      params={"metric":"auc",
              "objective":"binary", 
              "max_depth":trial.suggest_int("max_depth",5,1000),
              "num_leaves":trial.suggest_int("num_leaves",10,3000),
              "min_child_samples":trial.suggest_int("min_child_samples",50,500),
              "learning_rate":trial.suggest_uniform("learning_rate",0.01,1.5),
              "feature_fraction":trial.suggest_uniform("feature_fraction",0,1),
              "bagging_fraction":trial.suggest_uniform("bagging_fraction",0,1)}
      
      val_scores=[]

      for i, (train__, val__) in enumerate(kf.split(x,t)):
          x_train, x_val=x.iloc[train__], x.iloc[val__]
          t_train, t_val=t.iloc[train__], t.iloc[val__]
          lgb_train=lgb.Dataset(x_train, t_train)
          lgb_eval=lgb.Dataset(x_val, t_val)

          lgbm=lgb.train(params,
                         lgb_train,
                         valid_sets=lgb_eval,
                         num_boost_round=1000,
                         early_stopping_rounds=50,
                         verbose_eval=False)
          
          t_train_pred=np.round(lgbm.predict(x_train))
          t_val_pred=np.round(lgbm.predict(x_val))
          scoretrain=metrics.accuracy_score(t_train["Transported"],t_train_pred)
          scoreval=metrics.accuracy_score(t_val["Transported"],t_val_pred)
          val_scores.append(scoreval)

      cv_score=np.mean(val_scores)

      return cv_score

OPTUNAが選んだ1組のハイパーパラメータで、10回交差検証やって、検証データの正解率の平均を出し、これを最大化(最小化)するハイパーパラメータ見つけてね。と書いています。

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

ここで最大化を指定し、50回探索します。

Best is trial 31 with value: 0.8131795034588574

ということで、31回目の探索で検証データの平均最大81.3%という結果でした。
ベストなハイパーパラメータが分かったので、これでモデルを作ります。

x_train,x_val,t_train,t_val=train_test_split(x,t,test_size=0.25,stratify=t)
lgb_train=lgb.Dataset(x_train, t_train)
lgb_eval=lgb.Dataset(x_val, t_val)

あらためて、データを定義して、

bestparams={"metric":"auc",
            "objective":"binary", 
            "max_depth":study.best_params["max_depth"],
            "num_leaves":study.best_params["num_leaves"],
            "min_child_samples":study.best_params["min_child_samples"],
            "learning_rate":study.best_params["learning_rate"],
            "feature_fraction":study.best_params["feature_fraction"],
            "bagging_fraction":study.best_params["bagging_fraction"]}


best_lgbm=lgb.train(bestparams,
                    lgb_train,
                    valid_sets=lgb_eval,
                    num_boost_round=1000,
                    early_stopping_rounds=50,
                    verbose_eval=50)

ベストパラムでモデル化。このモデルでテストデータに対する予測をします。

pred=np.round(best_lgbm.predict(x_test))

ちなみにベストパラムはこんな。

study.best_params
{'bagging_fraction': 0.4905227000093506,
 'feature_fraction': 0.9874276185548546,
 'learning_rate': 0.1606778267851563,
 'max_depth': 920,
 'min_child_samples': 200,
 'num_leaves': 236}

訓練データと検証データの正解率も見ておく。

print(metrics.accuracy_score(t_train["Transported"],np.round(best_lgbm.predict(x_train))))
print(metrics.accuracy_score(t_val["Transported"],np.round(best_lgbm.predict(x_val))))
0.8476760239300506
0.8150873965041399

まあまあってとこですかね?

提出用データ形成と結果

作っていきます。

df_predict=pd.DataFrame(pred.astype(int),columns=["Transported"])
df_predict["Transported"]=df_predict["Transported"].astype(bool)

整数にして、さらにbool値で出さなきゃなので変換。

df_submission=pd.concat([df_test["PassengerId"],df_predict],axis=1)

テストデータのIDくっつけて完成!さてはて、結果は!?

うーん、いまいち。上位は81%越えています。IDのとこの前の数字とか、キャビンの真ん中の数字とか、名前とか、このあたりもっとやるともうちょい上がりそうな気がしてます。