さぁやって参りました。
Kaggle入門編第一回目。
Kaggleを制するにはKernelを制すべし。って誰かが言っていたので、適当なKernelを動かしてみることにしました。
今回は、Samson Qian氏(きっとスゴイ人)のKernelである
Titanic: Beginner's Guide with sklearn
をはじめから丁寧に。やっていきましょう。
はじめに
scikit-learn (pythonの機械学習フレームワーク) を使用してタイタニック号に乗船していた乗客それぞれについて、 生存していたか否かを推測してやろうという取り組みです。
データの可視化、解析、機械学習の入門に最適な内容です。
データのダウンロード
mkdir titanic cd titanic kaggle competitions download -c titanic
titanicディレクトリを作成して、その中に必要なデータをダウンロードしましょう。
データはKernelのData
カラムから取得可能です。
今回はwget
コマンドでダウンロードしますが、KaggleのAPIを使ってダウンロードもできちゃうみたいです。
ライブラリ、パッケージの読み込み
import numpy as np import pandas as pd import seaborn as sns from matplotlib import pyplot as plt %matplotlib inline sns.set_style("whitegrid") import warnings warnings.filterwarnings("ignore")
%matplotlib inline
は、ipython notebookで使用することが前提となってますね。
以下を参考に%matplotlib inline
は自動で設定されるようにしておきましょう。
参考:%matplotlib inlineを毎回書かなくて済む方法 - Qiita
warnings.filterwarnings("ignore")
では、警告文を無視するような設定を行っています。
データの読み込み、閲覧
training = pd.read_csv("../input/train.csv") testing = pd.read_csv("../input/test.csv") training.head() # PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked #0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S #1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C #2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S #3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S #4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
機械学習では、モデルの学習に使用するデータを学習データ (Train Data)、検証に使用するデータをテストデータ (Test Data)といいます。
基本的にこの2つのデータセットは用意されているものと思って問題ないです。
今回の場合、training
は学習データ、testing
はテストデータを意味しています。
head()
モジュールで先頭5行のデータを出力しています。
training.describe() # PassengerId Survived Pclass Age SibSp Parch Fare #count 891.000000 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000 #mean 446.000000 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208 #std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429 #min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000 #25% 223.500000 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400 #50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200 #75% 668.500000 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000 #max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200
describe()
モジュールを使えば、データの詳細な統計値を知ることができます。
Rのsummary()
関数と同じですね。
欠損値の扱い (Imputation)
def null_table(training, testing): print("Training Data Frame") print(pd.isnull(training).sum()) print(" ") print("Testing Data Frame") print(pd.isnull(testing).sum()) null_table(training, testing) #Training Data Frame #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 # #Testing Data Fra #PassengerId 0 #Pclass 0 #Name 0 #Sex 0 #Age 86 #SibSp 0 #Parch 0 #Ticket 0 #Fare 1 #Cabin 327 #Embarked 0 #dtype: int64
null_table
関数を定義します。 この関数内で、pd.isnull(training).sum()
では、各カラムごとに欠損値の数をカウントしています。
出力結果から、Cabin
カラムは欠損値が多いようです。
また、Ticket
変数に関しては、生存者数の推定に使用する変数として不適切なので、データフレームから取り除きます。
変数の除去には、drop
関数を用います。
training.drop(labels = ["Cabin", "Ticket"], axis = 1, inplace = True) testing.drop(labels = ["Cabin", "Ticket"], axis = 1, inplace = True) null_table(training, testing) #Training Data Frame #PassengerId 0 #Survived 0 #Pclass 0 #Name 0 #Sex 0 #Age 177 #SibSp 0 #Parch 0 #Fare 0 #Embarked 2 #dtype: int64 # #Testing Data Frame #PassengerId 0 #Pclass 0 #Name 0 #Sex 0 #Age 86 #SibSp 0 #Parch 0 #Fare 1 #Embarked 0 #dtype: int64
ここで一度、欠損値を抜いた場合のデータの分布を見ます。
copy
変数に一時的なデータのコピーを用意し、dropna
関数で欠損値の除去、seaborn.distplot
関数でデータの分布を可視化します。
copy = training.copy() copy.dropna(inplace = True) sns.distplot(copy["Age"])
中央値(median)で欠損値を埋めます。欠損値の置き換えには、fillna
モジュールを用います。
training["Age"].fillna(training["Age"].median(), inplace = True) testing["Age"].fillna(testing["Age"].median(), inplace = True) training["Embarked"].fillna("S", inplace = True) testing["Fare"].fillna(testing["Fare"].median(), inplace = True) null_table(training, testing) #Training Data Frame #PassengerId 0 #Survived 0 #Pclass 0 #Name 0 #Sex 0 #Age 0 #SibSp 0 #Parch 0 #Fare 0 #Embarked 0 #dtype: int64 # #Testing Data Frame #PassengerId 0 #Pclass 0 #Name 0 #Sex 0 #Age 0 #SibSp 0 #Parch 0 #Fare 0 #Embarked 0 #dtype: int64
データのプロット、可視化
機械学習のモデルに用いるデータを理解し、可視化することは、 データの傾向を知ることができ、
性別 (Sex)
生存者の数を、男女別に可視化します。
sns.barplot(x="Sex", y="Survived", data=training) plt.title("Distribution of Survival based on Gender") plt.show()
total_survived_females = training[training.Sex == "female"]["Survived"].sum() total_survived_males = training[training.Sex == "male"]["Survived"].sum() print("Total people survived is: " + str((total_survived_females + total_survived_males))) print("Proportion of Females who survived:") print(total_survived_females/(total_survived_females + total_survived_males)) print("Proportion of Males who survived:") print(total_survived_males/(total_survived_females + total_survived_males)) #Total people survived is: 342 #Proportion of Females who survived: #0.6812865497076024 #Proportion of Males who survived: #0.31871345029239767
棒グラフでは生存者だけでなく全体に対する割合を、標準出力では生存者中の割合を出力していることに注意してください。
結果から、性別の違いが生存率に大きな影響を与えていることが示唆されます。 これを見ると、性別は良い特微量であると判断できそうです。
同様にして、ほかの変数に関しても、特微量として適切かどうか、検討していきましょう。
階級 (PClass)
乗客の階級ごとの生存者数を棒グラフでプロットします。
sns.barplot(x="Pclass", y="Survived", data=training) plt.ylabel("Survival Rate") plt.title("Distribution of Survival Based on Class") plt.show()
total_survived_one = training[training.Pclass == 1]["Survived"].sum() total_survived_two = training[training.Pclass == 2]["Survived"].sum() total_survived_three = training[training.Pclass == 3]["Survived"].sum() total_survived_class = total_survived_one + total_survived_two + total_survived_three print("Total people survived is: " + str(total_survived_class)) print("Proportion of Class 1 Passengers who survived:") print(total_survived_one/total_survived_class) print("Proportion of Class 2 Passengers who survived:") print(total_survived_two/total_survived_class) print("Proportion of Class 3 Passengers who survived:") print(total_survived_three/total_survived_class) #Total people survived is: 342 #Proportion of Class 1 Passengers who survived: #0.39766081871345027 #Proportion of Class 2 Passengers who survived: #0.2543859649122807 #Proportion of Class 3 Passengers who survived: #0.347953216374269
先ほど同様に、棒グラフでは生存者だけでなく全体に対する割合を、標準出力では生存者中の割合を出力しています。
性別ごとに分けて生存者数の棒グラフをプロットします。
sns.barplot(x="Pclass", y="Survived", hue="Sex", data=training) plt.ylabel("Survival Rate") plt.title("Survival Rates Based on Gender and Class")
sns.barplot(x="Sex", y="Survived", hue="Pclass", data=training) plt.ylabel("Survival Rate") plt.title("Survival Rates Based on Gender and Class")
結果から、Pclass 1の人は、他の2つのPclassの人より生存率が高くなることが示唆されました。
年齢 (Age)
年齢が生存率に与えている影響があるか確かめるため、生存者、非生存者で分けてヒストグラムを描きます。
survived_ages = training[training.Survived == 1]["Age"] not_survived_ages = training[training.Survived == 0]["Age"] plt.subplot(1, 2, 1) sns.distplot(survived_ages, kde=False) plt.axis([0, 100, 0, 100]) plt.title("Survived") plt.ylabel("Proportion") plt.subplot(1, 2, 2) sns.distplot(not_survived_ages, kde=False) plt.axis([0, 100, 0, 100]) plt.title("Didn't Survive") plt.show()
分布をプロットするには、seaborn.stripplot
を使います。
結果から、若い年齢の人は、高齢の人より生存率が高くなる傾向があることが示唆されます。
変数同士の相関を見る
それぞれの変数同士の相関を見たい場合は、seaborn.pairplot
を用います。
sns.pairplot(training)
とりあえず
続きは