こんにちは。
テービーテックの村松です。
本日はこちらの続きをご紹介いたします。
ds-blog.tbtech.co.jp
前回は各項目が生存率に確認していそうかグラフ化しながら確認していきました。
今日は使用する項目を選んで前処理から最終のKaggleに提出してスコアを出すところまでやっていきます。
どれを使っていこうか・・・
とりあえず、前回生存率と関係がありそうだと確認が取れている以下の7つを使用していきます。
・Pclass
・Sex
・Age
・SibSp
・Parch
・Fare
・Embarked
そのまま学習するにはいろいろ不都合もありますのでそれぞれの項目に前処理を施していきます。
最初に欠損値の確認をしてみましょうか。
#欠損値の確認(train_data)
train_data.isnull().sum()
#output PassengerId 0 Survived 0 Pclass 0 Name 0 Sex 0 Age 177 SibSp 0 Parch 0 Ticket 0 Fare 0 Cabin 687 Embarked 2 dtype: int64
#欠損値の確認(test_data)
test_data.isnull().sum()
#output PassengerId 0 Pclass 0 Name 0 Sex 0 Age 86 SibSp 0 Parch 0 Ticket 0 Fare 1 Cabin 327 Embarked 0 dtype: int64
使用する項目で欠損があるのは「Age」・「Fare」・「Embarked」ですね。
これを踏まえて前処理を考えていきましょう。
- Pclass
要素は整数型で入ってはいますが、項目としてはカテゴリの意味合いだと思います。
なのでOne-Hot Encodingで行きましょう。
- Sex
こちらもOne-Hot Encodingしましょう。
- Age
こちらは欠損値の数が結構あります。
悩ましいところですが、変に平均値とか中央値で埋めるのも違和感がありますので、今回はあえて欠損のままにしておきます。
- SibSp・Parch
こちら2項目は欠損もありませんし、特に何もしません。
- Fare
欠損数は2つなので中央値あたりで補完します。
- Embarked
欠損は最頻値で埋めて、そのうえでOne-Hot Encodingします。
前処理開始
まずは前処理をまとめてするために「train_data」と「test_data」結合します。
df_original = pd.concat([train_data, test_data], sort=False)
片方だけ処理し忘れ等うかっり防止と、
test_dataを考慮した処理が可能という利点があります。
ただ、実務ではtest_dataがない場合も多いのでtest_dataの情報を利用することに否定的な意見もあるようです。
続いて、今回使用する項目のみを抜き出します。
#不要な列の削除 drop_list = ['PassengerId', 'Name', 'Ticket', 'Cabin', 'Survived'] _df = df_original.drop(drop_list, axis=1) _df
では、欠損値を補完します。
#’Fare’中央値で補完 _df.Fare.fillna(_df.Fare.median(), inplace=True) #’Embarked’最頻値で補完 _df.Embarked.fillna(_df.Embarked.mode()[0], inplace=True)
#ちゃんと欠損値が補完されたか確認 _df.isnull().sum() ##output Pclass 0 Sex 0 Age 263 SibSp 0 Parch 0 Fare 0 Embarked 0 dtype: int64
大丈夫そうですね。
最後にカテゴリカル変数をOne-Hot Encodingします。
#’Pclass’を文字列に変換 _df['Pclass'] = _df['Pclass'].astype('str') #カテゴリカル変数をOneHotEncoder df = pd.get_dummies(_df) df
データの分割
前処理が完了しましたので、結合していた「train_data」と「test_data」を再び分離させ、trainデータをモデルに入れるように分割していきましょう。
#結合していた「train_data」と「test_data」を分離 train_df = df[:train_data.shape[0]] test_df = df[train_data.shape[0]:] #train_dfの教師データとして target = train_data['Survived'] #train_dfとtargetの分割 from sklearn.model_selection import train_test_split x_train, x_val, y_train, y_val = train_test_split(train_df, target, test_size=0.2, random_state=0, stratify=target)
#確認 x_train.shape, x_val.shape, y_train.shape, y_val.shape ##output ((712, 12), (179, 12), (712,), (179,))
モデルの構築
いよいよ学習を始めます。
ここまで長かったですね。
今回はみんな大好きな機械学習モデル「XGBoost」を使用いたします。
from xgboost import XGBClassifier model = XGBClassifier(random_state=0) model.fit(x_train, y_train)
##output XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1, gamma=0, learning_rate=0.1, max_delta_step=0, max_depth=3, min_child_weight=1, missing=None, n_estimators=100, n_jobs=1, nthread=None, objective='binary:logistic', random_state=0, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None, silent=None, subsample=1, verbosity=1)
スコアを確認します。
print(model.score(x_train, y_train)) print(model.score(x_val, y_val))
#output 0.8960674157303371 0.8268156424581006
おお・・・。
一発目にしては良い感じ、でしょうか?
本来ならここからハイパーパラメータのチューニングをするのが正しいのでしょうが、割愛。
予測結果の提出
ここからは予測結果を提出用のcsvファイルに書き出していきます。
#推論
pre = model.predict(test_df)
pre
##output array([0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0])
これが予測された結果です。
提出用のcsvファイルの中身はというと、
#提出ファイルの形式を確認 gender_submission = pd.read_csv('/content/drive/My Drive/04-15/gender_submission.csv') gender_submission
こんな形。
これと同じ形に整えていくので、まずはtestの「PassengerId」が必要ですね。
#testの「PassengerId」の抜出 PassengerId = np.array(test_data['PassengerId']).astype(int)
そして、先ほど出した予測結果と合わせましょう。
# predictで出した結果と一緒にデータフレームにします。 submission = pd.DataFrame(pre, PassengerId, columns = ["Survived"])
現在submissionはこんな感じです。
あれ、「PassengerId」の要素がインデックスになってると一瞬あわてたのですが、まだもう一段回ありました。
#csvファイルへの書き出し submission.to_csv('書き出し先/submission.csv', index_label=['PassengerId'])
出力された「submission.csv」を確認すると、
ちゃんと提出用の形に整いましたね。
結果
お、おおお。
初歩の初歩とはいえ、最後まで行くと達成感ありますね。
ハイパーパラメータのチューニングや学習方法を変えていけば更に向上させることもできそうですね。
Kaggleは「Norebooks」というタブから色々な方のコードを見ることができますので、そちらも読みながら改良方法を勉強していくことができます。
今回もだいぶお世話になりました。
全世界の先生の胸を借りれると思うと頼もしい限りですね。
では、これにて「Kaggleやってみよう【Titanic:生存者の予測】」終了です。
ここまで目を通していただき、ありがとうございました!