#はじめに
就職間近(大学4年の春休み)になって、急遽データサイエンティストになりたいと思い、とりあえずKaggleに取り組み始めました。
今回取り組んだのは、Kaggleのチュートリアルである「Titanic」の問題です。
研究で統計解析の経験はあるが、機械学習は全くわからない状態からなので、めちゃくちゃ優秀な方のコードを参考にして勉強することにしました!
ちなみに、参考にしたのがこちら
✔︎Introduction to Ensembling/Stacking in Python
Notebookで「Most voted」と評されていたコードです。(2020.3.10時点)
あと、上記のコードを参考にしたこちらの記事も参考にしました笑
Pythonでアンサンブル(スタッキング)学習 & 機械学習チュートリアル in Kaggle
#Introduction
今回取り組むタイタニック号のコンペの内容は、年齢、性別、同室者数、部屋のクラス、生死などの乗客に関するデータが与えれます。
そのデータを元に、
データの前処理
→データの可視化
→スタッキングモデル構築
→テストデータ
→評価
といった流れで、最後にはテストデータから構築したモデルを使って乗客の生死の予測をします。この予測がどれくらいあっているかもスコアの基準になります。
かなりボリュームがあるので本記事では**「前処理」・「データの可視化」**に絞ります!
モデル構築以降は次回の記事に載せます!
続編記事はこちら↓↓↓
【Python】初めての データ分析・機械学習(Kaggle)〜Part2〜
では、早速データの前処理に取り掛かります!!
#データの前処理
###ライブラリのインポート
今回使用するライブラリをざっくり
- 数学的、統計的処理: numpy, pundas
- 正規表現操作(指定した形の言葉や数値の検索だったり置き換えだったり): re
- いろんなモデルを持ってるよ~: sklearn
- 勾配ブースティング決定木のアルゴリズム: XGboost
- グラフや図: matplotlib, seaborn, plotly
- 警告の表示/非表示: warnings
- 5つの基礎モデル
- これらの5つのモデルライブラリを同時に適応するのがKfold
import pandas as pd
import numpy as np
import re
import sklearn
import xgboost as xgb
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
import plotly.offline as py
py.init_notebook_mode(connected=True)
import plotly.graph_objs as go
import plotly.tools as tls
import warnings
warnings.filterwarnings('ignore')
# 5つのモデル
from sklearn.ensemble import (RandomForestClassifier, AdaBoostClassifier,
GradientBoostingClassifier, ExtraTreesClassifier)
from sklearn.svm import SVC
#複数の機械学習ライブラリを同時に適応する
from sklearn.cross_validation import KFold
###データの取得
train = pd.read_csv('../input/train.csv')
test = pd.read_csv('../input/test.csv')
#乗客のIDをPassengerIDに保持させる
PassengerId = test['PassengerId']
train.head(3)
データの説明
- PassengerId:乗客のID
- Survived:生死フラグ(生き残った場合:1, 亡くなった場合:0)
- Pclass:チケットクラス
- Name:乗客の名前
- Sex:性別
- Age:年齢
- SibSp:同乗している兄弟/配偶者
- Parch:同乗している両親/子供
- fare:料金
- cabin:客室番号
- Embarked:乗船した港
###特徴量エンジニアリング
取得したデータを分析しやすいように加工していきます。
機械学習において、この前処理はかなり重要らしいので、長いけど頑張ります!!
基本的には、欠損値(値がない)や文字データを全て数値データに変換します。
full_data = [train, test]
#乗客の名前の長さ
train['name_length'] = train['name'].apply(len)
test['name_length'] = test['name'].apply(len)
#客室番号データがあるなら1を、欠損値なら0を
train['Has_Cabin'] = train['Cabin'].apply(lambda x: 0 if type(x) == float else 1)
test['Has_Cabin'] = test['Cabin'].apply(lambda x: 0 if type(x) == float else 1)
#家族の大きさをタイタニックに同乗している"兄弟/配偶者の数"と"親/子供の数"から定義する
for dataset in full_data:
dataset ['FamilySize'] = dataset['Sibsp'] + dataset['Parch'] +1
#家族がいないなら"IsAlone"が1
for dataset in full_data:
dataset['IsAlone'] = 0
dataset.loc[dataset['FamilySize'] == 1, 'IsAlone'] = 1
#出港地の欠損値を一番多い'S'としておく
for dataset in full_data:
dataset['Embarked'] = dataset['Embarked'].fillna('S')
#料金の欠損値を中央値としておく
#料金を大きく4つのグループに分ける
for dataset in full_data:
dataset['Fare'] = dataset['Fare'].fillna(train['Fare'].median())
train['CategoricalFare'] = pd.qcut(train['Fare'], 4)
#年齢を5つのグループに分ける
for dataset in full_data:
age_avg = dataset['Age'].mean()
age_std = dataset['Age'].std()
age_null_count = dataset['Age'].isnull().sum()
#欠損値に入れるランダム値のリスト
#平均値から偏差分だけ大きいor小さい値を用いる
age_null_random_list = np.random.randint(age_avg - age_std, age_avg + age_std, size = age_null_count)
dataset['Age'][np.isnan(dataset['Age'])] = age_null_random_list
#データをint型に変換
dataset['Age'] = dataset['Age'].astype(int)
train['CategoricalAge'] = pd.qcut(train['Age'],5)
#名前を取り出す関数get_titleの定義
def get_title(name):
title_search = re.search('([A-Za-z]+)\.',name)
#名前があれば取り出して返す
if title_search:
return title_search.group(1)
return ""
#関数get_titleを使う
for dataset in ftll_data:
dataset['Title'] = dataset['Name'].apply(get_title)
#名前の記入ミス部分の修正
dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col','Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
for dataset in full_data:
# 女なら0、男なら1
dataset['Sex'] = dataset['Sex'].map( {'female': 0, 'male': 1} ).astype(int)
# 名前の5種類にラベル付
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
dataset['Title'] = dataset['Title'].map(title_mapping)
dataset['Title'] = dataset['Title'].fillna(0)
# 出港地の3種類にラベル付
dataset['Embarked'] = dataset['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)
# 料金を4つのグループに分ける
dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0
dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare'] = 2
dataset.loc[ dataset['Fare'] > 31, 'Fare'] = 3
dataset['Fare'] = dataset['Fare'].astype(int)
# 年齢を5つのグループに分ける
dataset.loc[ dataset['Age'] <= 16, 'Age'] = 0
dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 32), 'Age'] = 1
dataset.loc[(dataset['Age'] > 32) & (dataset['Age'] <= 48), 'Age'] = 2
dataset.loc[(dataset['Age'] > 48) & (dataset['Age'] <= 64), 'Age'] = 3
dataset.loc[ dataset['Age'] > 64, 'Age'] = 4 ;
# 必要ない特徴を削除
drop_elements = ['PassengerId', 'Name', 'Ticket', 'Cabin', 'SibSp']
train = train.drop(drop_elements, axis = 1)
train = train.drop(['CategoricalAge', 'CategoricalFare'], axis = 1)
test = test.drop(drop_elements, axis = 1)
勉強になったコーディング
- lambda関数の使い方
- fillna()
- pandasのqcut
- map関数
- if文を使わず、loc[]の[]内でTrueの場合のみ値を入力
- axis = 1
#データの可視化
やっと前処理が終わりました!!
ちゃんと全てのデータが数値データになっているか確認してみましょう!
train.head(3)
###ピアソン相関ヒートマップ(Peason Correlation Heatmap)
特徴量同士の相関をヒートマップにて確認します。
colormap = plt.cm.RdBu
plt.figure(figsize = (14,12))
plt.title('Peason Correlation of Features', y = 1.05, size = 15)
sns.heatmap(train.astype(float).corr(), linewidths=0.1, vmax=1.0, square = True, cmap=colormap, linecolor='white', annot=True)
このプロットから、そこまで特徴量が互いに強く相関していないことがわかります。
特徴量が互いに独立
→無駄な特徴がない
→学習モデルを構築する上で重要
(ParchとFamilySizeは比較的相関が強いですが、そのまま残しておきます。)
###ペアプロット(PairPlot)
ある特徴から別の特徴へのデータの分布
g = sns.pairplot(train[[u'Survived', u'Pclass', u'Sex', u'Age', u'Parch', u'Fare', u'Embarked',
u'FamilySize', u'Title']], hue='Survived', palette = 'seismic',size=1.2,diag_kind = 'kde',diag_kws=dict(shade=True),plot_kws=dict(s=10) )
g.set(xticklabels=[])
#まとめ
本記事では、Kaggleのチュートリアルの「Titanic」に取り組みました。
流れとしては、
- ライブラリのインポート
- データの取得
- データの前処理
- 欠損値をなくす(平均値に近い値をランダムに挿入等)
- データの等分
- カテゴリーデータを数値に変換
- データの可視化
- ピアソン相関ヒートマップ
- ペアプロット
ここまででも結構大変でしたが、ここからがモデル構築の本番なので引き続き頑張ります!!