このノートブックでは,Kaggleのようなサイトにあるデータサイエンスコンペを解くための典型的なワークフローを一通り説明します.
いくつかの同様の素晴らしいノートブックがありますが,その多くは"ExpertがExpertのために作った"ようで,「その解決法がどのように構築されたのか」という点に対する説明がスキップされています. このノートブックの目的は,ワークフローの各ステップを順に追い,それぞれのステップを説明すると共に,問題解決の際に我々(Kaggle上級者)がとった全ての決定に対する理論的根拠を説明することです.
コンペに対するワークフローは,"Data Science Solutions book"で述べられている7つのステージからなります.
このワークフローは,「どのようにして,各ステージが他ステージを相補するか」に対する一般的な流れを提示していますが,例外的なユースケースもあります.
Kaggleのようなコンペ・サイトは,解決すべき問題や,モデルを訓練するためのtrainデータを提供するとき,およびモデルの予測結果をtestデータに対して検証するときに,問いかける質問を定めます. "Titanic Survival competition"における問題/質問の定義は,Kaggleで次のように述べらています..
タイタニック号事故に生存したor生存しなかった乗客を表形式にまとめたサンプルのtrainデータセットから,我々のモデルは,生存情報を含まないtestデータセットに基づいて,"testデータセットの乗客が生存したかor生存しなかったか",を決定することができる.
Knowing from a training set of samples listing passengers who survived or did not survive the Titanic disaster, can our model determine based on a given test dataset not containing the survival information, if these passengers in the test dataset survived or not.
我々は,問題の領域についての簡単な理解を構築したいとも思うかもしれません.これについては,Kaggle competition description pageで述べられています. 以下は,特筆すべきハイライトです.
データサイエンス・ワークフローは7つの主要目標を解決します.
分類する(Classifying)
我々はサンプルデータを分類/カテゴライズしたいと思うことでしょう.また,我々は異なるクラスどうしの背後関係or相関関係を理解したいと思うことでしょう.
関連づける(Correlating)
trainデータセットの中で利用可能な特徴量に基づいて問題にアプローチできます.データセットの中で,どの特徴量が我々の目標変数(Survived)に対して意義深く貢献するのか?統計的には,統計量と目標変数(Survived)との間に相関関係(Correlation)がないでしょうか?特徴量の値が変わるならば,解決状態も変わるのでしょうか?これは与えられたデータセットの中で数値変数/カテゴリ変数の両方に対して検証されます.
ワークフロー・ステージとその次の目標のために,我々は,"生存したか"以外の特徴量の中の相関関係を決定したいと思うことでしょう.特徴量を作成・補完・訂正する際に,ある特徴量を相関させることが役立つでしょう.
変換する(Converting)
モデリングを行う段階では,データを前処理する必要があります.モデル・アルゴリズムの選択に依存して,すべての特徴量を数値的に等しい値に変換させる(正規化する)必要があるかもしれない.たとえばテキスト・カテゴリ変数を数値変数に変換します.
補完する(Completing)
データの前処理として,特徴量の中のすべての欠損値を推定する必要があります.モデル・アルゴリズムは欠損値がない場合に最もよく働くでしょう.
訂正する(Correcting)
我々は,特徴量の中で欠損値or不正な値のために,trainデータセットを分析するでしょうし,これらの値を訂正しようとするor欠損をもつサンプルを排除しようとするでしょう.
これを行うための1つの方法は,サンプルor特徴量の中のすべての外れ値を区別することです.また,もしある特徴量が分析に寄与しないor結果を有意に歪めるかもしれないならば,我々はその特徴量を完全に捨てるでしょう.
作成する(Creating)
新しい特徴量が相関関係・変換・完全性に従うように,我々は既存の特徴量or特徴量集合から新しい特徴量を作成することができます.
可視化(Charting).
どのように正しい可視化の描画/図表を選択するかは,データの性質と目標変数(Survived)に依存します.
# data analysis and wrangling
import pandas as pd
import numpy as np
import random as rnd
# visualization
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
# machine learning
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC, LinearSVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import Perceptron
from sklearn.linear_model import SGDClassifier
from sklearn.tree import DecisionTreeClassifier
PythonのPandasパッケージはデータセットの処理することに役立ちます.まず,train/testデータセットをPandas DataFrameとして取得します.また,一定の処理のために,両方のデータセットを結合します.
train_df = pd.read_csv('../input/train.csv')
test_df = pd.read_csv('../input/test.csv')
combine = [train_df, test_df]
Pandasは,次の問いに簡単に答えるようにデータセットを要約することに役立ちます.
データセットの中で,どの特徴量が利用可能なのか?
特徴量を直接操作/分析するために,特徴量の名前を記録しておきます.これらの特徴量の名前は,Kaggle data pageで述べられています.
print(train_df.columns.values)
どの特徴量がカテゴリカル変数か?
これらの変数はサンプル全体を似たようなサンプル集合に分類します. カテゴリカル変数において,それぞれの特徴量は,名義・順序・比例・間隔のうちどの尺度に基づいているでしょうか? これは我々が可視化において適切なプロットを選択することに役立ちます.
どの特徴量が数値変数か?
どの特徴量が数値的でしょうか?数値変数の値はサンプル間で異なります.数値変数において,それぞれの特徴量は離散・連続・時系列のうちどれに基づいているでしょうか? これは我々が可視化において適切なプロットを選択することに役立ちます.
# preview the data
train_df.head()
どの特徴量が混合データ型なのか?
同じ特徴量の中の数値型/アルファベット+数値型のデータ.目標を修正するための候補がある.
どの特徴量が欠損値/誤植を含んでいるの?
これは,大きいデータセットに対してレビューを行うことは大変ですが,より小さいデータセットからの少量のサンプルの場合は,レビューを行うことで「どの特徴量が修正を必要とするのか」が即座にわかります.
どの特徴量が,空白(blank)/無効な値(null) or 空値(empty)なのか?
これらは修正が必要となります.
多様な特徴量のためのデータ型は何か?
目標変数を変換する際に役立ちます.
train_df.info()
print('_'*40)
test_df.info()
サンプルにわたって,数値型の特徴量の分布は何か?
実際の問題領域のtrainデータセットはどれくらい(母集団を)"表現"しているのか? This helps us determine, among other early insights, how representative is the training dataset of the actual problem domain.
train_df.describe()
# Review survived rate using `percentiles=[.61, .62]` knowing our problem description mentions 38% survival rate.
# Review Parch distribution using `percentiles=[.75, .8]`
# SibSp distribution `[.68, .69]`
# Age and Fare `[.1, .2, .3, .4, .5, .6, .7, .8, .9, .99]`
カテゴリカル変数の分布は何か?
train_df.describe(include=['O'])
我々は,データ分析が今まで行ってきたことに基づいて,以下の想定にたどり着きます.我々は,適切な行動をとる前に,これらの想定をさらに検証するかもしれません.
Correlating.
それぞれの特徴量がSurvivalとどの程度強く相関しているかを知りたいです.この即座にわかる相関関係と,モデル化された相関関係を後半で一致させます.
Completing.
Correcting.
Creating.
Classifying.
先ほど述べられた問題の記述に基づいて,以下を我々の想定に追加する.
データに対する観察/想定を確認するために,それぞれの特徴量を互いにピボットすることで,我々は特徴量の相関関係を即座位に分析することができる. 我々はこの段階では,空の値をもたない特徴量に対してのみ以下を実行する.これは,カテゴリカル型 (Sex), 順序型 (Pclass),離散型 (SibSp, Parch)の特徴量に対してのみ意味をなす.
# Pclass(乗客の階級)ごとの生存率
train_df[['Pclass', 'Survived']].groupby(['Pclass'], as_index=False).mean().sort_values(by='Survived', ascending=False)
# Sex(乗客の性別)ごとの生存率
train_df[["Sex", "Survived"]].groupby(['Sex'], as_index=False).mean().sort_values(by='Survived', ascending=False)
# SibSp(乗客の兄弟/配偶者)ごとの生存率
train_df[["SibSp", "Survived"]].groupby(['SibSp'], as_index=False).mean().sort_values(by='Survived', ascending=False)
# Parch(乗客の両親/子供)ごとの生存率
train_df[["Parch", "Survived"]].groupby(['Parch'], as_index=False).mean().sort_values(by='Survived', ascending=False)
さて,データ分析のための可視化を使って,我々の想定の確認を続けましょう.
数値型変数と目標変数(Survived)との相関関係を理解することによって,可視化をはじめましょう.
ヒストグラムは,Ageのような連続数値型変数の分析に対して有用です.Ageの値に従ってサンプルをまとめる/整列させることは,有益なパターンの特定することに役立ちます. ヒストグラムは,自動的に定義されるbins(分割数)/range band(分割幅)を使い,サンプルの分布を提示することができます. これによって,我々がAgeの特定の幅に関係する質問に答えることが容易になります.(ex. 乳幼児の生存率はよかったのか?)
※ ヒストグラムのx軸は,サンプルや乗客たちの総数を表すことに注意する.
観察
決定
この簡単な分析は,ワークフローの次の段階に対する決定として,以下の想定を承認します.
g = sns.FacetGrid(train_df, col='Survived')
g.map(plt.hist, 'Age', bins=20)
1つのプロットを使って相関関係を特定するために複数の特徴量を結合することができます.これは数的な値をとる数値変数/カテゴリカル変数によって片付けられます.
観察
決定
# grid = sns.FacetGrid(train_df, col='Pclass', hue='Survived')
grid = sns.FacetGrid(train_df, col='Survived', row='Pclass', size=2.2, aspect=1.6)
grid.map(plt.hist, 'Age', alpha=.5, bins=20)
grid.add_legend();
カテゴリカル変数と目標変数(Survived)との相関関係をみることができます.
観察
決定
# grid = sns.FacetGrid(train_df, col='Embarked')
grid = sns.FacetGrid(train_df, row='Embarked', size=2.2, aspect=1.6)
grid.map(sns.pointplot, 'Pclass', 'Survived', 'Sex', palette='deep')
grid.add_legend()
カテゴリカル変数と数値変数の相関関係を知りたいでしょう.
Embarked(カテゴリカル変数),Sex(カテゴリカル変数),Fare(数値変数)とSurvived(カテゴリカル変数)との相関関係を考慮できます.
観察
決定
# grid = sns.FacetGrid(train_df, col='Embarked', hue='Survived', palette={0: 'k', 1: 'w'})
grid = sns.FacetGrid(train_df, row='Embarked', col='Survived', size=2.2, aspect=1.6)
grid.map(sns.barplot, 'Sex', 'Fare', alpha=.5, ci=None)
grid.add_legend()
データセットと要求される問題解決について,いくつかの想定と決定を集計しました.
今までのところ1つの特徴量/変数を変えなければいけないことはなかったのです. ここで,データの修正(correcting)・作成(creating)と目標達成に対する想定と決定を実行しましょう.
少ないデータ点で処理する特徴量を排除することは,実行する最初の目標です.ノートブックを加速化させ,分析を軽減させます.
想定と決定に基づいて,我々はCabin (correcting #2) とTicket (correcting #1) を削除したいと思います.
※ train/test両方のデータセットを一貫して同時に処理することが可能か?に留意する.
print("Before", train_df.shape, test_df.shape, combine[0].shape, combine[1].shape)
train_df = train_df.drop(['Ticket', 'Cabin'], axis=1)
test_df = test_df.drop(['Ticket', 'Cabin'], axis=1)
combine = [train_df, test_df]
"After", train_df.shape, test_df.shape, combine[0].shape, combine[1].shape
NameとPassesngerIdを削除する前に,Nameは敬称(Title)と生存率(Survived)との相関を抽出するために設計された特徴量であると考えられます.
以下のコードの中で,標準的な表現を使ってTitleを抽出します.正規表現パターン (\w+\.)
は,Nameの中にあるドット文字 .
で終わる最初の単語にマッチします.expand=False
フラグはDataframeを返します.
観察
Title,Age,Survivedをプロットするとき,以下の観察事項に留意する.
決定
for dataset in combine:
dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=False)
pd.crosstab(train_df['Title'], train_df['Sex'])
多くのTitleをより一般的な名前で置き換えることができますし,TitleをRare
として分類することができます.
for dataset in combine:
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')
train_df[['Title', 'Survived']].groupby(['Title'], as_index=False).mean()
カテゴリカル変数であるTitleを順序変数に変換することもできます.
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
for dataset in combine:
dataset['Title'] = dataset['Title'].map(title_mapping)
dataset['Title'] = dataset['Title'].fillna(0)
train_df.head()
ここで,train/testデータからNameを安全に削除することができます.また,trainデータセットの中ではPassengerIdも必要ないです.
train_df = train_df.drop(['Name', 'PassengerId'], axis=1)
test_df = test_df.drop(['Name'], axis=1)
combine = [train_df, test_df]
train_df.shape, test_df.shape
ここで,string型を含む特徴量を数値型に変換します.この処理はほとんどのモデル・アルゴリズムから要求されます.数値型への変換は,特徴量補完の目標達成に役立ちます.
Sexを新しい特徴量Genderに変換しましょう.(female=1, male=0)
for dataset in combine:
dataset['Sex'] = dataset['Sex'].map( {'female': 1, 'male': 0} ).astype(int)
train_df.head()
ここで,空の値ornull値をもつ特徴量の推定/補完をはじめるべきです.まず,Ageに対してこれを行います.
連続変数に対する欠損値補完として3つの方法を考えることができます.
簡単な方法は,平均と標準偏差の間から乱数を生成することである.
欠損値を推測するためのより正確な方法は,他の相関する特徴量を使うことです.今回は,Age・Gender・Pclassの中の相関関係に留意します.PclassとGenderとの組み合わせにそって,Ageの値は中央値を使って推測する.すなわち,Pclass=1かつGender=0のサンプルでのAgeの中央値,Pclass=1かつGender=1のサンプルでのAgeの中央値, ...のようにAgeの補完する値を決めていく.
方法1と2を合わせる.たとえば,中央値からAgeの値を補完する,PclassとGenderの組み合わせに基づいてAgeの平均と標準偏差の間の乱数を使う,
方法1と3では,ランダムノイズをモデルに導入するので,(seedによって)複数の実行による結果は変わるかもしれません.我々は方法2を選好します.
# grid = sns.FacetGrid(train_df, col='Pclass', hue='Gender')
grid = sns.FacetGrid(train_df, row='Pclass', col='Sex', size=2.2, aspect=1.6)
grid.map(plt.hist, 'Age', alpha=.5, bins=20)
grid.add_legend()
guess_ages = np.zeros((2,3))
guess_ages
ここで,Sex (0 or 1) と Pclass (1, 2, 3) の6通りの組み合わせの中で,Ageの推測値を繰り返し計算します.
for dataset in combine:
for i in range(0, 2):
for j in range(0, 3):
guess_df = dataset[(dataset['Sex'] == i) & \
(dataset['Pclass'] == j+1)]['Age'].dropna()
# age_mean = guess_df.mean()
# age_std = guess_df.std()
# age_guess = rnd.uniform(age_mean - age_std, age_mean + age_std)
age_guess = guess_df.median()
# Convert random age float to nearest .5 age
guess_ages[i,j] = int( age_guess/0.5 + 0.5 ) * 0.5
for i in range(0, 2):
for j in range(0, 3):
dataset.loc[ (dataset.Age.isnull()) & (dataset.Sex == i) & (dataset.Pclass == j+1),\
'Age'] = guess_ages[i,j]
dataset['Age'] = dataset['Age'].astype(int)
train_df.head()
Ageのまとまりを作成して,Survivedとの相関を判断しましょう.
train_df['AgeBand'] = pd.cut(train_df['Age'], 5)
train_df[['AgeBand', 'Survived']].groupby(['AgeBand'], as_index=False).mean().sort_values(by='AgeBand', ascending=True)
これらのまとまりから,Ageを順序変数に置き換えましょう.
for dataset in combine:
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']
train_df.head()
AgeBandを置き換えることはできません.
train_df = train_df.drop(['AgeBand'], axis=1)
combine = [train_df, test_df]
train_df.head()
ParchとSibSpを組み合わせて,FamilySizeという新しい特徴量を作成できます.FamilySizeを作成することによって,ParchとSibSpをデータセットから削除することができます.
for dataset in combine:
dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1
train_df[['FamilySize', 'Survived']].groupby(['FamilySize'], as_index=False).mean().sort_values(by='Survived', ascending=False)
他の特徴量としてIsAloneを作ることができます.
for dataset in combine:
dataset['IsAlone'] = 0
dataset.loc[dataset['FamilySize'] == 1, 'IsAlone'] = 1
train_df[['IsAlone', 'Survived']].groupby(['IsAlone'], as_index=False).mean()
IsAloneによって置き換えることで,Parch, SibSp, FamilySizeを削除しましょう.
train_df = train_df.drop(['Parch', 'SibSp', 'FamilySize'], axis=1)
test_df = test_df.drop(['Parch', 'SibSp', 'FamilySize'], axis=1)
combine = [train_df, test_df]
train_df.head()
PclassとAgeを結合した人工的な特徴量を作成することもできます.
for dataset in combine:
dataset['Age*Class'] = dataset.Age * dataset.Pclass
train_df.loc[:, ['Age*Class', 'Age', 'Pclass']].head(10)
Embarkedは乗船ポートに基づいて S,Q,C という値をとります.trainデータセットは2つの欠損値を持ちます.単純に,欠損値を最も多く発生したものによって埋めます.
freq_port = train_df.Embarked.dropna().mode()[0]
freq_port
for dataset in combine:
dataset['Embarked'] = dataset['Embarked'].fillna(freq_port)
train_df[['Embarked', 'Survived']].groupby(['Embarked'], as_index=False).mean().sort_values(by='Survived', ascending=False)
新しい数値変数Portを作成することによって,EmbarkedFillを変換します.
for dataset in combine:
dataset['Embarked'] = dataset['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)
train_df.head()
Fareの補完を行います.testデータセットの中にある1つの欠損値は,Fareの最頻値(mode)を使って補完できます.この処理をコード1行で行います.
※ 1つの値のみを置き換えるので,中間の新しい特徴量を作成していないこと,および推測された欠損値との相関を追加検証していないことに留意してください.コンペの目標達成には,nullではない値を処理するモデル・アルゴリズムのための前提条件が求められます.
また,Fare(運賃)を,それぞれの通貨を代表する2つの10進概数として扱いたいと思うことでしょう.
test_df['Fare'].fillna(test_df['Fare'].dropna().median(), inplace=True)
test_df.head()
新しい特徴量,FareBandを作成しましょう
train_df['FareBand'] = pd.qcut(train_df['Fare'], 4)
train_df[['FareBand', 'Survived']].groupby(['FareBand'], as_index=False).mean().sort_values(by='FareBand', ascending=True)
FareBandに基づいて,Fareを順序変数に変換します.
for dataset in combine:
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)
train_df = train_df.drop(['FareBand'], axis=1)
combine = [train_df, test_df]
train_df.head(10)
testデータセットも確認します.
test_df.head(10)
さて,モデルを訓練し,要求された解答を予測するための準備が整いました.選ぶべき予測的モデル・アルゴリズムは60個以上あります.問題と要求される解答のタイプを理解しなければいけません. これによって,選択されるモデルを,我々が評価できる数少ないもの範疇に狭めることができます.今回の問題は,分類/回帰問題です.我々は,出力(Survived or not)と特徴量(Gender, Age, Port...)との間の関係を特定したいです. また我々は,教師あり学習と呼ばれる(与えられたデータセットからモデルを学習させる)機械学習のカテゴリーを行ないます.これらの2つの基準 (教師あり学習+分類/回帰) の中で,我々はモデル選択を少しの範囲に狭めることができます.すなわち,以下のモデルです:
X_train = train_df.drop("Survived", axis=1)
Y_train = train_df["Survived"]
X_test = test_df.drop("PassengerId", axis=1).copy()
X_train.shape, Y_train.shape, X_test.shape
ロジスティック回帰(Logistic regression)はワークフローの中で簡単に実行できる便利なモデルです.ロジスティック回帰は,ロジスティック関数(累積ロジスティック分布)を使って確率を推定して,従属変数(=カテゴリカル変数)と,いくつかの独立変数との関係を推測します.Wikipedia.
※ trainデータセットに基づいてモデルから生成された信頼係数に留意してください.
# Logistic Regression
logreg = LogisticRegression()
logreg.fit(X_train, Y_train)
Y_pred = logreg.predict(X_test)
acc_log = round(logreg.score(X_train, Y_train) * 100, 2)
acc_log
我々は,特徴量の作成と目標達成のための想定/決定を検証するために,ロジスティック回帰(Logistic Regression)を使うことができます.この検証は,決定関数(=モデル)の中で各特徴量の係数を導出することによって行われます.正の係数は,応答変数Survivedのlog-odds(すなわち生起確率)を増加させます.また,負の係数は応答変数Survivedのlog-odds(すなわち生起確率)を減少させます.
coeff_df = pd.DataFrame(train_df.columns.delete(0))
coeff_df.columns = ['Feature']
coeff_df["Correlation"] = pd.Series(logreg.coef_[0])
coeff_df.sort_values(by='Correlation', ascending=False)
次に,分類/回帰の分析のために使われるデータを解析する学習アルゴリズムである教師なし学習のモデル,Support Vector Machinesを使って,モデリングを行います. trainデータサンプルの集合を与えられた場合,これは2つのカテゴリのうちどちらかに分類されます.SVMの訓練アルゴリズムは,新しいtestサンプルを2つのカテゴリのどちらかに選別するようなモデル(非確率的な2クラス線形分類器)を形成します.Wikipedia.
※ このモデル(SVM)は,ロジスティック回帰モデルよりも高い信頼スコアを出した.
# Support Vector Machines
svc = SVC()
svc.fit(X_train, Y_train)
Y_pred = svc.predict(X_test)
acc_svc = round(svc.score(X_train, Y_train) * 100, 2)
acc_svc
パターン認識の中で,k-近傍法(K-NN)は分類/回帰に使われるノンパラメトリック法です.データサンプルは,隣接点からの過半票によって分類されます.すなわち,サンプルはk個の最近傍隣接点(kは正の整数で,典型的には小さい)の中で,平均的なクラスに割り当てられます.もしk=1ならば,注目サンプルは単に最も近い1つの隣接点のクラスに分類されます.Wikipedia.
※ KNNの信頼スコアは,ロジスティック回帰より良く,SVMよりも悪かった.
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, Y_train)
Y_pred = knn.predict(X_test)
acc_knn = round(knn.score(X_train, Y_train) * 100, 2)
acc_knn
機械学習の中で,ナイーブベイズ分類器(Naive Bayse classifier)は,特徴量間に強い(ナイーブな)独立性を想定して,ベイズの定理を適用した簡単な確率分類器族です.学習問題において,特徴量(変数)の数に対して,パラメータ数が線形であることを前提とするため,ナイーブベイズ分類器は高い拡張性をもちます.Wikipedia.
※ このモデルの信頼スコアは,今まで評価されたモデルの中で,最も低かった.
# Gaussian Naive Bayes
gaussian = GaussianNB()
gaussian.fit(X_train, Y_train)
Y_pred = gaussian.predict(X_test)
acc_gaussian = round(gaussian.score(X_train, Y_train) * 100, 2)
acc_gaussian
パーセプトロン(Perceptron)は,2クラス分類のための教師あり学習アルゴリズムです.(入力ベクトルが,ある特定のクラスに属するか否かを決定できる関数を学習する) これは,重み集合を結合した線形関数と特徴ベクトルから予測を行う,線形分類器,i.e.線形分類アルゴリズムのひとつです.このアルゴリズムでは,(訓練データセットの中で,それぞれの要素を一度に1つずつ処理する)オンライン学習を行うこともできます.Wikipedia.
# Perceptron
perceptron = Perceptron()
perceptron.fit(X_train, Y_train)
Y_pred = perceptron.predict(X_test)
acc_perceptron = round(perceptron.score(X_train, Y_train) * 100, 2)
acc_perceptron
# Linear SVC
linear_svc = LinearSVC()
linear_svc.fit(X_train, Y_train)
Y_pred = linear_svc.predict(X_test)
acc_linear_svc = round(linear_svc.score(X_train, Y_train) * 100, 2)
acc_linear_svc
# Stochastic Gradient Descent
sgd = SGDClassifier()
sgd.fit(X_train, Y_train)
Y_pred = sgd.predict(X_test)
acc_sgd = round(sgd.score(X_train, Y_train) * 100, 2)
acc_sgd
このモデルは,特徴量(木の分岐点)を目標変数(木の葉)へ写像させる予測モデルとして,決定木を使います.
目標変数が値として有限集合をもつ場合,決定木は分類木(Classification trees)と呼ばれます.木構造の中で,葉はクラスラベルを表していて,分岐点はクラスラベルにいたる特徴量の連接を表しています.目標変数が連続値(典型的には実数)をもつ場合,決定木は回帰木(Regression trees)と呼ばれます.Wikipedia.
※ このモデルの信頼スコアは,今まで評価されてきたモデルの中で最も高かった.
# Decision Tree
decision_tree = DecisionTreeClassifier()
decision_tree.fit(X_train, Y_train)
Y_pred = decision_tree.predict(X_test)
acc_decision_tree = round(decision_tree.score(X_train, Y_train) * 100, 2)
acc_decision_tree
次のモデルであるRandom Forestsは,最も知られたモデルのひとつです.Random Forests (or Random decision forests)は分類/回帰/他のためのアンサンブル学習法です.Random Forestsは訓練時に複数の決定木 (n_estimators=100) を形成して稼働させます.その出力クラスは,そのクラスに対応するモデル(分類)もしくは個々の予測値の平均(回帰)になります.Wikipedia.
※ Random Forestsモデルの信頼スコアは,これまでに評価されたモデルの中で最も高かった.よってコンペティションの提出物を作成するために,このモデルの出力(Y_pred)を使うことを決定した.
# Random Forest
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)
Y_pred = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
acc_random_forest
我々の問題に対して最善のモデルを選ぶために,すべてのモデルを評価してランク付けします. 決定木(Decision Tree)とランダムフォレスト(Random Forest)のスコアは同じですが,決定木はtrainデータセットに対して過学習しやすいという習慣から,ランダムフォレストを使うことに決めます.
models = pd.DataFrame({
'Model': ['Support Vector Machines', 'KNN', 'Logistic Regression',
'Random Forest', 'Naive Bayes', 'Perceptron',
'Stochastic Gradient Decent', 'Linear SVC',
'Decision Tree'],
'Score': [acc_svc, acc_knn, acc_log,
acc_random_forest, acc_gaussian, acc_perceptron,
acc_sgd, acc_linear_svc, acc_decision_tree]})
models.sort_values(by='Score', ascending=False)
submission = pd.DataFrame({
"PassengerId": test_df["PassengerId"],
"Survived": Y_pred
})
# submission.to_csv('../output/submission.csv', index=False)
このノートブックの提出は,コンペティション・サイトKaggleにおいて,6,082エントリーの中で3,883位として記録されます. この結果はコンペが開催されているかどうかを暗示しています.この結果は,提出されるデータセットの一部のみを占めています. 最初の試みとしては悪くないでしょう.このスコアを改善するための提案はどんなものであれ大歓迎です.
このノートブックは,Titanicコンペティションを解くために行われてきた偉大な仕事と,外部ソースに基づいて作成されました.