【Kaggle】タイタニック生存予想をとりあえずsubmit

機械学習勉強中の文系Webディレクターです。
文系のくせにずっと機械学習に興味があり、本格的に手を出し始めました。
近いうちにゴリゴリとモデル構築とかを行える人になりたい。

なにはともあれとりあえずKaggleという流れがあるらしいのでやってみました。
Submitまでは正直簡単です。問題はこの後の精度向上。

大枠の流れは下記のようになります。

- IDデータ、正解ラベル、特徴データに分類する
- カテゴリ変数（データが文字のもの）をOneHotEncodingで数値データとして扱えるようにする
- 欠損値（NaN）はそのままでは支障が出るため、欠損値は補完する
- 色々なモデル・パラメーターでベストなモデルを探す
- 訓練データと同じ前処理をテストデータにも行う
- テストデータに対して予測を実行


訓練データを使ったモデル構築

```python:train.py
# 関連ライブラリのインポート
import numpy as np
import pandas as pd
from pprint import pprint

#未知データ対策のため、データ型を指定して読み込み
df = pd.read_csv('train.csv', header=0,
                dtype={'Name':object,
                        'Sex':object,
                        'Ticket':object,
                        'Fare':object,
                        'Cabin':object,
                        'Embarked':object})

# set variable roles
ID = df.loc[:, ['PassengerId']]
X  = df.drop(['PassengerId', 'Ticket', 'Cabin','Name' ,'Survived'], axis=1) #学習に不要そうなものは削除
y  = df.loc[:, ['Survived']]

## 前処理
from sklearn.preprocessing import Imputer # 欠損処理
# one-hotエンコーディングでカテゴリ変数を数値に変換
OHE_COLS = ['Sex', 'Embarked']
X_ohe = pd.get_dummies(X, dummy_na=True, columns=OHE_COLS)
# Imputer(欠損値補完※今回は中央値を使用)
imp = Imputer(missing_values='NaN',strategy='mean',axis=0)
imp.fit(X_ohe)

X_ohe_columns = X_ohe.columns.values
X_ohe = pd.DataFrame(imp.transform(X_ohe), columns=X_ohe_columns)
X_fin = X_ohe #特徴量が膨大ならRFEなどで絞り込むが、今回はなし

#グリッドサーチでの最適解らしきものを探す
from sklearn.preprocessing import StandardScaler # 標準化
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC, LinearSVC #サポートベクタマシン
from sklearn.linear_model import LogisticRegression,RidgeClassifier # リッジ回帰
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier #アンサンブル
from sklearn.pipeline import Pipeline # パイプライン
from sklearn.metrics import r2_score,f1_score #R2スコア

# パイプラインの設定
pipe_RidgeClassifier = Pipeline([('scl',StandardScaler()),('est',RidgeClassifier(random_state=0))])
pipe_RandomForestClassifier = Pipeline([('scl',StandardScaler()),('est',RandomForestClassifier(random_state=0))])
pipe_GradientBoostingClassifier = Pipeline([('scl',StandardScaler()),('est',GradientBoostingClassifier(random_state=0))])
pipe_SVC = Pipeline([('scl', StandardScaler()),('est',SVC(random_state=0))])
pipe_LinearSVC = Pipeline([('scl', StandardScaler()),('est',LinearSVC(random_state=0))])

# パラメータグリッドの設定
param_grid_RidgeClassifier = {'est__solver':['auto', 'svd', 'cholesky', 'lsqr', 'sparse_cg', 'sag', 'saga']}
param_grid_RandomForestClassifier = {'est__n_estimators':[10,25,50,100],'est__max_depth' : [5, 20, 50, 100]}
param_grid_GradientBoostingClassifier = {'est__n_estimators':[50,100],'est__subsample':[0.8, 1.0]}
param_grid_SVC = {'est__C':[0.1,1.0,10.0,100.0], 'est__degree':[1,3,5]}
param_grid_LinearSVC = {'est__C':[0.1,1.0,10.0,100.0], 'est__loss':['hinge','squared_hinge']}

# # 学習
algs = [
    {
        'name' : 'RidgeClassifier',
        'pipe' : pipe_RidgeClassifier,
        'param': param_grid_RidgeClassifier
    },
    {
        'name': 'RandomForestClassifier',
        'pipe' : pipe_RandomForestClassifier,
        'param': param_grid_RandomForestClassifier
    },
    {
        'name': 'GradientBoostingClassifier',
        'pipe' : pipe_GradientBoostingClassifier,
        'param' : param_grid_GradientBoostingClassifier
    },
    {
        'name': 'SVC',
        'pipe' : pipe_SVC,
        'param' : param_grid_SVC
    },
    {
        'name': 'LinearSVC',
        'pipe' : pipe_LinearSVC,
        'param' : param_grid_LinearSVC
    }
]

best_estimator = []

for alg in algs:
    print('----------------------------------------------------------------------------------------------')
    name, pipe, param = alg['name'], alg['pipe'], alg['param']
    print('アルゴリズム:%s' % name)
#     print('探索空間:%s' % param)
    gs = GridSearchCV(estimator=pipe, param_grid=param, scoring='f1', cv=3)
    gs = gs.fit(X_fin, y.as_matrix().ravel())
    best_estimator.append([gs.best_estimator_, gs.best_score_])   # gs.best_estimator_でベストモデルを呼び出せる
    print('Best Score %.6f\n' % gs.best_score_) # gs.best_score_で上記ベストモデルのCV評価値（ここではf1スコア）を呼び出せる
```

テストデータを使って検証

```python:test.py
#テストデータ前処理
df_s = pd.read_csv('/Users/kamitaku/Desktop/Kaggke_Titanic/test.csv', header=0,
                dtype={'Name':object,
                        'Sex':object,
                        'Ticket':object,
                        'Fare':object,
                        'Cabin':object,
                        'Embarked':object})

ID_s = df_s.loc[:, ['PassengerId']]
X_s  = df_s.drop(['PassengerId', 'Ticket', 'Cabin','Name'], axis=1) # Loan_IDはKey情報なので特徴量ベクトルから削除

X_ohe_s = pd.get_dummies(X_s, dummy_na=True, columns=OHE_COLS)
X_fin_s = pd.DataFrame(imp.transform(X_ohe_s), columns=X_ohe_columns)

#予測
from datetime import datetime
best_model = best_estimator[0][0] #ベストなモデルを選択
predictions = best_model.predict(X_fin_s)

submission = pd.DataFrame({
        "PassengerId": ID_s['PassengerId'],
        "Survived": predictions
    })
now = '{0:%Y%m%d%H%M%S}'.format(datetime.now())
submission.to_csv('submission' + now + '.csv', index=False)
```
結果としては、75.8%の正解率で4260/10606 でした。
精進せねば。