-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2013be1
commit 71361f2
Showing
58 changed files
with
103,536 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
import numpy as np | ||
import pandas as pd | ||
|
||
# ----------------------------------- | ||
# 学習データ、テストデータの読み込み | ||
# ----------------------------------- | ||
# 学習データ、テストデータの読み込み | ||
train = pd.read_csv('../input/ch01-titanic/train.csv') | ||
test = pd.read_csv('../input/ch01-titanic/test.csv') | ||
|
||
# 学習データを特徴量と目的変数に分ける | ||
train_x = train.drop(['Survived'], axis=1) | ||
train_y = train['Survived'] | ||
|
||
# テストデータは特徴量のみなので、そのままでよい | ||
test_x = test.copy() | ||
|
||
# ----------------------------------- | ||
# 特徴量作成 | ||
# ----------------------------------- | ||
from sklearn.preprocessing import LabelEncoder | ||
|
||
# 変数PassengerIdを除外する | ||
train_x = train_x.drop(['PassengerId'], axis=1) | ||
test_x = test_x.drop(['PassengerId'], axis=1) | ||
|
||
# 変数Name, Ticket, Cabinを除外する | ||
train_x = train_x.drop(['Name', 'Ticket', 'Cabin'], axis=1) | ||
test_x = test_x.drop(['Name', 'Ticket', 'Cabin'], axis=1) | ||
|
||
# それぞれのカテゴリ変数にlabel encodingを適用する | ||
for c in ['Sex', 'Embarked']: | ||
# 学習データに基づいてどう変換するかを定める | ||
le = LabelEncoder() | ||
le.fit(train_x[c].fillna('NA')) | ||
|
||
# 学習データ、テストデータを変換する | ||
train_x[c] = le.transform(train_x[c].fillna('NA')) | ||
test_x[c] = le.transform(test_x[c].fillna('NA')) | ||
|
||
# ----------------------------------- | ||
# モデル作成 | ||
# ----------------------------------- | ||
from xgboost import XGBClassifier | ||
|
||
# モデルの作成および学習データを与えての学習 | ||
model = XGBClassifier(n_estimators=20, random_state=71) | ||
model.fit(train_x, train_y) | ||
|
||
# テストデータの予測値を確率で出力する | ||
pred = model.predict_proba(test_x)[:, 1] | ||
|
||
# テストデータの予測値を二値に変換する | ||
pred_label = np.where(pred > 0.5, 1, 0) | ||
|
||
# 提出用ファイルの作成 | ||
submission = pd.DataFrame({'PassengerId': test['PassengerId'], 'Survived': pred_label}) | ||
submission.to_csv('submission_first.csv', index=False) | ||
# スコア:0.7799(本書中の数値と異なる可能性があります) | ||
|
||
# ----------------------------------- | ||
# バリデーション | ||
# ----------------------------------- | ||
from sklearn.metrics import log_loss, accuracy_score | ||
from sklearn.model_selection import KFold | ||
|
||
# 各foldのスコアを保存するリスト | ||
scores_accuracy = [] | ||
scores_logloss = [] | ||
|
||
# クロスバリデーションを行う | ||
# 学習データを4つに分割し、うち1つをバリデーションデータとすることを、バリデーションデータを変えて繰り返す | ||
kf = KFold(n_splits=4, shuffle=True, random_state=71) | ||
for tr_idx, va_idx in kf.split(train_x): | ||
# 学習データを学習データとバリデーションデータに分ける | ||
tr_x, va_x = train_x.iloc[tr_idx], train_x.iloc[va_idx] | ||
tr_y, va_y = train_y.iloc[tr_idx], train_y.iloc[va_idx] | ||
|
||
# モデルの学習を行う | ||
model = XGBClassifier(n_estimators=20, random_state=71) | ||
model.fit(tr_x, tr_y) | ||
|
||
# バリデーションデータの予測値を確率で出力する | ||
va_pred = model.predict_proba(va_x)[:, 1] | ||
|
||
# バリデーションデータでのスコアを計算する | ||
logloss = log_loss(va_y, va_pred) | ||
accuracy = accuracy_score(va_y, va_pred > 0.5) | ||
|
||
# そのfoldのスコアを保存する | ||
scores_logloss.append(logloss) | ||
scores_accuracy.append(accuracy) | ||
|
||
# 各foldのスコアの平均を出力する | ||
logloss = np.mean(scores_logloss) | ||
accuracy = np.mean(scores_accuracy) | ||
print(f'logloss: {logloss:.4f}, accuracy: {accuracy:.4f}') | ||
# logloss: 0.4270, accuracy: 0.8148(本書中の数値と異なる可能性があります) | ||
|
||
# ----------------------------------- | ||
# モデルチューニング | ||
# ----------------------------------- | ||
import itertools | ||
|
||
# チューニング候補とするパラメータを準備する | ||
param_space = { | ||
'max_depth': [3, 5, 7], | ||
'min_child_weight': [1.0, 2.0, 4.0] | ||
} | ||
|
||
# 探索するハイパーパラメータの組み合わせ | ||
param_combinations = itertools.product(param_space['max_depth'], param_space['min_child_weight']) | ||
|
||
# 各パラメータの組み合わせ、それに対するスコアを保存するリスト | ||
params = [] | ||
scores = [] | ||
|
||
# 各パラメータの組み合わせごとに、クロスバリデーションで評価を行う | ||
for max_depth, min_child_weight in param_combinations: | ||
|
||
score_folds = [] | ||
# クロスバリデーションを行う | ||
# 学習データを4つに分割し、うち1つをバリデーションデータとすることを、バリデーションデータを変えて繰り返す | ||
kf = KFold(n_splits=4, shuffle=True, random_state=123456) | ||
for tr_idx, va_idx in kf.split(train_x): | ||
# 学習データを学習データとバリデーションデータに分ける | ||
tr_x, va_x = train_x.iloc[tr_idx], train_x.iloc[va_idx] | ||
tr_y, va_y = train_y.iloc[tr_idx], train_y.iloc[va_idx] | ||
|
||
# モデルの学習を行う | ||
model = XGBClassifier(n_estimators=20, random_state=71, | ||
max_depth=max_depth, min_child_weight=min_child_weight) | ||
model.fit(tr_x, tr_y) | ||
|
||
# バリデーションデータでのスコアを計算し、保存する | ||
va_pred = model.predict_proba(va_x)[:, 1] | ||
logloss = log_loss(va_y, va_pred) | ||
score_folds.append(logloss) | ||
|
||
# 各foldのスコアを平均する | ||
score_mean = np.mean(score_folds) | ||
|
||
# パラメータの組み合わせ、それに対するスコアを保存する | ||
params.append((max_depth, min_child_weight)) | ||
scores.append(score_mean) | ||
|
||
# 最もスコアが良いものをベストなパラメータとする | ||
best_idx = np.argsort(scores)[0] | ||
best_param = params[best_idx] | ||
print(f'max_depth: {best_param[0]}, min_child_weight: {best_param[1]}') | ||
# max_depth=7, min_child_weight=2.0のスコアが最もよかった | ||
|
||
|
||
# ----------------------------------- | ||
# ロジスティック回帰用の特徴量の作成 | ||
# ----------------------------------- | ||
from sklearn.preprocessing import OneHotEncoder | ||
|
||
# 元データをコピーする | ||
train_x2 = train.drop(['Survived'], axis=1) | ||
test_x2 = test.copy() | ||
|
||
# 変数PassengerIdを除外する | ||
train_x2 = train_x2.drop(['PassengerId'], axis=1) | ||
test_x2 = test_x2.drop(['PassengerId'], axis=1) | ||
|
||
# 変数Name, Ticket, Cabinを除外する | ||
train_x2 = train_x2.drop(['Name', 'Ticket', 'Cabin'], axis=1) | ||
test_x2 = test_x2.drop(['Name', 'Ticket', 'Cabin'], axis=1) | ||
|
||
# one-hot encodingを行う | ||
cat_cols = ['Sex', 'Embarked', 'Pclass'] | ||
ohe = OneHotEncoder(categories='auto', sparse=False) | ||
ohe.fit(train_x2[cat_cols].fillna('NA')) | ||
|
||
# one-hot encodingのダミー変数の列名を作成する | ||
ohe_columns = [] | ||
for i, c in enumerate(cat_cols): | ||
ohe_columns += [f'{c}_{v}' for v in ohe.categories_[i]] | ||
|
||
# one-hot encodingによる変換を行う | ||
ohe_train_x2 = pd.DataFrame(ohe.transform(train_x2[cat_cols].fillna('NA')), columns=ohe_columns) | ||
ohe_test_x2 = pd.DataFrame(ohe.transform(test_x2[cat_cols].fillna('NA')), columns=ohe_columns) | ||
|
||
# one-hot encoding済みの変数を除外する | ||
train_x2 = train_x2.drop(cat_cols, axis=1) | ||
test_x2 = test_x2.drop(cat_cols, axis=1) | ||
|
||
# one-hot encodingで変換された変数を結合する | ||
train_x2 = pd.concat([train_x2, ohe_train_x2], axis=1) | ||
test_x2 = pd.concat([test_x2, ohe_test_x2], axis=1) | ||
|
||
# 数値変数の欠損値を学習データの平均で埋める | ||
num_cols = ['Age', 'SibSp', 'Parch', 'Fare'] | ||
for col in num_cols: | ||
train_x2[col].fillna(train_x2[col].mean(), inplace=True) | ||
test_x2[col].fillna(train_x2[col].mean(), inplace=True) | ||
|
||
# 変数Fareを対数変換する | ||
train_x2['Fare'] = np.log1p(train_x2['Fare']) | ||
test_x2['Fare'] = np.log1p(test_x2['Fare']) | ||
|
||
# ----------------------------------- | ||
# アンサンブル | ||
# ----------------------------------- | ||
from sklearn.linear_model import LogisticRegression | ||
|
||
# xgboostモデル | ||
model_xgb = XGBClassifier(n_estimators=20, random_state=71) | ||
model_xgb.fit(train_x, train_y) | ||
pred_xgb = model_xgb.predict_proba(test_x)[:, 1] | ||
|
||
# ロジスティック回帰モデル | ||
# xgboostモデルとは異なる特徴量を入れる必要があるので、別途train_x2, test_x2を作成した | ||
model_lr = LogisticRegression(solver='lbfgs', max_iter=300) | ||
model_lr.fit(train_x2, train_y) | ||
pred_lr = model_lr.predict_proba(test_x2)[:, 1] | ||
|
||
# 予測値の加重平均をとる | ||
pred = pred_xgb * 0.8 + pred_lr * 0.2 | ||
pred_label = np.where(pred > 0.5, 1, 0) |
Oops, something went wrong.