数理的手法を使いやすくするためのソフトウェア開発

科学技術計算とデータサイエンスについて

データ分析入門としてのKaggleコンペ「タイタニック乗客の生存予測」

これまで、Kaggleコンペティション ^1 ,^13 ,^14 は初心者には関係のない場所だと思っていましたが、 そうではありませんでした。 もちろん、賞金付きのコンペでは専門家がデータ解析で競い合っているのですが、 その他の賞金なしのコンペのなかには初心者が楽しめるものがあるのです。 特に、"Titanic: Machine Learning from Disaster"^2というコンペは入門レベルであり、 予備知識としてpython機械学習の基本を理解していれば、 kaggleコンペのプロセスをひととおり体験できます (ただ、賞金獲得だけは体験できません)。

以下で、その体験の内容をかいつまんで紹介します。

"Titanic: Machine Learning from Disaster"とは

このコンペは、1912年4月15日の大惨事にちなんでいます。 タイタニック号は氷山に衝突して沈没し、 2224人の乗員乗客のうち1502人が亡くなりました。 彼らの生死を分けたのは何だったのでしょうか? 幸運でしょうか?それだけではありません。 実は、ある種の属性を持つ人々はそうでない人々よりも生き延びやすかったのです。 例えば、女性、子供、一等船室の人々は生存確率が高かったことが知られています。

なので、乗客の性別、年齢、船室等級が分かれば、 ある程度はその乗客の生死が予測できるのです。 そして、他の属性も考慮すれば、 その生存予測の正確さを更に向上させられるかもしれません。

コンペ参加者は、このように予測の正確さを向上させて、 他の参加者とその正確さを競います。

このコンペは学習用なので、この予測の仕方を様々なチュートリアル ^3 ,^4 ,^5 ,^6 ,^7 ,^8 が指南してくれます。 このなかで私はインタラクティブなチュートアル^8

A free interactive Machine Learning tutorial in Python

をやってみました。 インタラクティブの良いところは、ゲームでステージを次々にクリアしていくように、 チュートリアルを学んでいけるところです。 そのチュートリアルのwebサイトにアクセスすると、セクションごとに説明が現れて、 pythonスクリプトを書いて提出するように求められ、 スクリプトが間違っていればヒントが表示され、 正しければ次のセクションに進めます。 そして、このようにチュートリアルを進んでいくうちに、以下のデータ分析のプロセス

  1. データ加工
  2. モデリング、トレーニングデータによる学習
  3. テストデータによる検証
  4. 特徴エンジニアリング

を体験できます。

必要な予備知識と使用するライブラリ

チュートリアルをこなすためには、pythonについては基本的な構文を理解していて、 機械学習については何らかのモデルを訓練データから作った経験があれば、 問題ないと思います。

3つのPythonライブラリ

  • NumPy  数値計算 (インポートするときはnumpy と表記)
  • Pandas データ加工 (pandas
  • scikit-learn 機械学習 (sklearn) 

を使いますが、それらを使ったことがなくともチュートリアルの説明を読めば、 課題のpythonスクリプトを書くことができますので、 問題なく最後のセクションまで進めます。

また、課題のpythonスクリプトのなかで、3つのライブラリを

import pandas as pd
import numpy as np
from sklearn import tree

のようにインポートすることになりますが、 こうしたスクリプトはwebサイトのなかで実行されるので、 手元のPCにpythonやそのライブラリを用意する必要はありません。

データ加工

訓練データはコンペ主催者によって収集され、csvファイルとして提供されています。 チュートリアルでは、この訓練データを後でモデルの学習に使いますので、 ここではcsvファイルをpython に読み込ませて、 DataFrameオブジェクトを生成します。 DataFrameオブジェクトは表形式のデータ構造を持っていて、データ加工に使うことができます ^9 ,^10

train_url = "http://s3.amazonaws.com/assets.datacamp.com/course/Kaggle/train.csv"
train = pd.read_csv(train_url)

例えば、与えられた訓練データtrainのフィールド(列)"Embarked"には欠けているところがありますので、その欠損値を次のように穴埋めします。

train["Embarked"] = train["Embarked"].fillna("S")

また、trainのフィールド(列)"Embarked"には、はじめは文字型の値"S","C","Q"が入っていますので、それらを機械学習で扱える数値型の値に変換します。

train["Embarked"][train["Embarked"] == "S"] = 0
train["Embarked"][train["Embarked"] == "C"] = 1
train["Embarked"][train["Embarked"] == "Q"] = 2

モデリング、トレーニングデータによる学習

モデリングには様々なやりかたがあるのですが、ここでは決定木を使います。 決定木は、scikit-learnライブラリではDecisionTreeClassifierクラスとして用意されていますので、 そのインスタンスを作成してmy_tree_oneに代入します。

my_tree_one = tree.DecisionTreeClassifier()

決定木モデルを学習させるためには、モデルへの入力となる特徴量ベクトルと、モデルからの出力と照合できるターゲットデータが必要です。 そこで、まず、特徴量として乗客属性"Pclass","Sex","Age","Fare"を使うことにして、それらを訓練データtrainから取り出して、feature_oneに代入します。

features_one = train[ ["Pclass", "Sex", "Age", "Fare"] ].values

次に、ターゲットデータとなる乗客の生死を訓練データtrainから取り出して、targetに代入します。

target = train["Survived"].values

こうして、ターゲットと特徴量ベクトルが揃ったので、 それらを使ってモデルを学習させます。

my_tree_one = my_tree_one.fit( features_one, target)

これで、機械学習によりモデルmy_tree_oneが出来上がりました。

テストデータによる検証

テストデータも訓練データと同様に主催者によってcsvファイルとして用意されています。 しかし、このcsvファイルには乗客の生死のデータは入っておらず、乗客の属性データだけが入っています。 なので、チュートリアルでは検証プロセスのうち、テストデータの乗客の属性データを上で作成したモデルに入力して、乗客の生存予測を出力させるところまでを行います。

実際の検証プロセスであれば、テストデータには乗客の生死データも含まれていて、 これらの生死データとモデルの出力を比較します。 しかし、コンペティションではこの比較をコンペ主催者が行うので、 csvファイルには生死のデータが入っていないのです。

コードは省略しますが、まず、 テストデータのcvsファイルを読み込んでDataFrameオブジェクトtestへと変換して、 欠損値を穴埋めしておきます。 そして、テストデータtestから特徴量ベクトルを取り出します。

test_features = test[ ["Pclass","Sex", "Age", "Fare"] ].values

そのテストデータの特徴量に基づいて、乗客の生死を予測させます。

my_prediction = my_tree_one.predict(test_features)

この予測結果をkaggleに提出するには、csvファイルでなければなりませんので、 予測結果my_predictionを所定のフォーマットのcsvファイルに変換します。

PassengerId =np.array(test["PassengerId"]).astype(int)
my_solution = pd.DataFrame(my_prediction, PassengerId, columns = ["Survived"])
my_solution.to_csv("my_solution_one.csv", index_label = ["PassengerId"])

この生存予測ファイルmy_solution_one.csvチュートリアルのwebサイトからダウンロードできますので、 それをkaggleに提出すると、 実際の乗客の生死データを比較して順位をつけてくれます。

私がやってみたところ、 順位は5,838チームのうちで5,692番目で、スコア(正確さ)は 0.569 でした。 順位が底辺に近いのは、何の工夫もしていないからです。 そこで、 次は特徴エンジニアリングを行います。

特徴エンジニアリング

これまでは、乗客の生死を左右するの属性は、 客室の等級"Pclass",性別"Sex",年齢"Age",運賃"Fare"だけであると 考えてきました。 しかし、他にも重要な属性があるかもしれません。 例えば、一緒に乗船している家族の人数もまた生死を左右していたと考えられます ^11 。 というのは、家族で一緒に旅をしていた人は、救命ボートに乗る順番が回ってきたとしても、 家族全員が揃っていなければ、ボートで脱出せずにタイタニック号に留まっていたのではないかと想像できるからです。 この仮説が正しければ、 大家族であればあるほど救命ボート乗り場に集合するまでに時間がかかるので、 それだけ生存確率が下がるはずです。

この仮説にそって、乗船している家族の人数を訓練データに加えます。

train_two = train.copy()
train_two["family_size"] = train_two["SibSp"] + train_two["Parch"] + 1

こうして更新した訓練データを使って、新たに決定木モデルを学習させます。

features_three = train_two[ ["Pclass", "Sex", "Age", "Fare", "SibSp", "Parch", "family_size"] ].values

my_tree_three = tree.DecisionTreeClassifier()
my_tree_three = my_tree_three.fit( features_three, target)

さて、この新しいモデルmy_tree_threeでは、どのくらい順位が上がるのでしょうか?

このmy_tree_threeにテストデータを入力して、 出力をkaggleに提出してみました。 順位は5,838チームのうちで4,760番目、スコア(正確さ)は 0.756 と、 すこし良くなりました。 しかし、順位はまだまだ悪いです。 それで、上位に入っている人の記事^12を読みますと、 非常に感心させられます。

まとめ

以上で紹介したように、コンペ"Titanic: Machine Learning from Disaster"チュートリアル^8で、主要なデータ解析のプロセス、データ解析、モデリング、学習、検証、特徴エンジニアリング、をひととおり体験できます。 ちなみに、モデリングとして、このブログ記事では、決定木を使う場合だけを書きましたが、 その他に、決定木で過学習を抑制するためのテクニックや、ランダムフォレストを使う場合についても体験できます。

私はやってみて、機械学習アプリ開発だけでなく、 データ解析もけっこう面白いのではないかと思いました。 おすすめです。


参考

^1:Kaggle Competitions

^2:"Titanic: Machine Learning from Disaster"

^3:Getting Started with Excel: Kaggle's Titanic Competition

^4:Getting Started with Python: ...

^5:Getting Started With Python II: ...

^6:Getting Started With Random Forests: ...

^7:Getting Started with R: ...

^8:A free interactive Machine Learning tutorial in Python

^9:Qiita pandasでよく使う文法まとめ

^10:pandas 0.19.1 documentation » API Reference » pandas.DataFrame

^11:Large families not good for Survival - Kaggle

^12:Kaggleのtitanic問題で上位10%に入るまでのデータ解析と所感

^13:賞金稼ぎから仕事探しまで、世界のデータサイエンティストが「Kaggle」に集まる理由

^14:世界のデータサイエンティストが集う「Kaggle」とは?ビッグデータ分析を競い合え!