KAIKETSU Developer's Diary

株式会社KAIKETSU エンジニアチームのブログです

kaggleやってみた

背景

データ分析を学んでみようということで社内エンジニアチームでkaggleをやってみようという話になったので軽く触ってみたことを書きます。

準備

始めるに当たってまず準備したのはkaggleのサイトへのユーザー登録と、Pythonとその周りの機械学習ライブラリのセットアップです。

$ brew install python3 pip3
$ pip3 install pandas numpy sklearn

ユーザー登録は以下のサイトからそれっぽいところをクリックしていけばできます。英語のサイトですがFacebook連携もできるので意外と楽。

Kaggle: Your Home for Data Science

とりあえずやってみる

あまり書くことがないのでやったことを一通り書いてみたいと思います。やったのはタイタニックと呼ばれる一番有名っぽいデータセット

Titanic: Machine Learning from Disaster | Kaggle

Dataと書いてあるタブから、トレーニングデータとテストデータをダウンロードします。

決定木を使う

まずは決定木を使ってやってみます。

データはcsv形式で降ってきているはずなのでpandasでよしなに処理して作成した決定木モデルに流し込みます。

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

train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

# 欠損しているデータを埋める
train["Age"] = train["Age"].fillna(train["Age"].median())
train["Embarked"] = train["Embarked"].fillna("S")
train["Sex"][train["Sex"] == "male"] = 0
train["Sex"][train["Sex"] == "female"] = 1
train["Embarked"][train["Embarked"] == "S" ] = 0
train["Embarked"][train["Embarked"] == "C" ] = 1
train["Embarked"][train["Embarked"] == "Q"] = 2

test["Age"] = test["Age"].fillna(test["Age"].median())
test["Sex"][test["Sex"] == "male"] = 0
test["Sex"][test["Sex"] == "female"] = 1
test["Embarked"][test["Embarked"] == "S"] = 0
test["Embarked"][test["Embarked"] == "C"] = 1
test["Embarked"][test["Embarked"] == "Q"] = 2
test.Fare[152] = test.Fare.median()

target = train["Survived"].values
# 追加となった項目も含めて予測モデルで使う値を取り出す
features_two = train[["Pclass","Age","Sex","Fare", "SibSp", "Parch", "Embarked"]].values
# 決定木の作成とアーギュメントの設定
max_depth = 10
min_samples_split = 5
my_tree_two = tree.DecisionTreeClassifier(max_depth = max_depth, min_samples_split = min_samples_split, random_state = 1)
my_tree_two = my_tree_two.fit(features_two, target)

# tsetから使う項目の値を取り出す
test_features_2 = test[["Pclass","Age", "Sex", "Fare", "SibSp", "Parch", "Embarked"]].values
# 決定木を使って予測をしてCSVへ書き出す
my_prediction_tree_two = my_tree_two.predict(test_features_2)
PassengerId = np.array(test["PassengerId"]).astype(int)
my_solution_tree_two = pd.DataFrame(my_prediction_tree_two, PassengerId, columns = ["Survived"])
my_solution_tree_two.to_csv("my_tree.csv", index_label = ["PassengerId"])

Submit Predictionを押して解答のCSVをサブミットしてみたところ、正答率は75%程度でした。

トレーニングデータの中身を見てみたところ、年齢欄の欠損が多かったので、年齢を説明変数から削除して再度予測してみた結果、正答率が76%と微増しました。

ランダムフォレストを使う

ソースコードを軽くいじって、予測モデルにランダムフォレストを使ってみます。

import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier

train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")


train["Age"] = train["Age"].fillna(train["Age"].median())
train["Embarked"] = train["Embarked"].fillna("S")
train["Sex"][train["Sex"] == "male"] = 0
train["Sex"][train["Sex"] == "female"] = 1
train["Embarked"][train["Embarked"] == "S" ] = 0
train["Embarked"][train["Embarked"] == "C" ] = 1
train["Embarked"][train["Embarked"] == "Q"] = 2

test["Age"] = test["Age"].fillna(test["Age"].median())
test["Sex"][test["Sex"] == "male"] = 0
test["Sex"][test["Sex"] == "female"] = 1
test["Embarked"][test["Embarked"] == "S"] = 0
test["Embarked"][test["Embarked"] == "C"] = 1
test["Embarked"][test["Embarked"] == "Q"] = 2
test.Fare[152] = test.Fare.median()

target = train["Survived"].values
features = train[["Pclass","Sex","Fare", "SibSp", "Parch", "Embarked"]].values

clf = RandomForestClassifier()
clf.fit(features, target)

test_features = test[["Pclass", "Sex", "Fare", "SibSp", "Parch", "Embarked"]].values

test_pred = clf.predict(test_features)
PassengerId = np.array(test["PassengerId"]).astype(int)
my_solution = pd.DataFrame(test_pred, PassengerId, columns = ["Survived"])
my_solution.to_csv("rf.csv", index_label = ["PassengerId"])

解答を提出しましたが、正答率は75%程度でした。

SVMを使う

今度は予測モデルにサポートベクターマシンを利用してみます。

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

train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")


train["Age"] = train["Age"].fillna(train["Age"].median())
train["Embarked"] = train["Embarked"].fillna("S")
train["Sex"][train["Sex"] == "male"] = 0
train["Sex"][train["Sex"] == "female"] = 1
train["Embarked"][train["Embarked"] == "S" ] = 0
train["Embarked"][train["Embarked"] == "C" ] = 1
train["Embarked"][train["Embarked"] == "Q"] = 2

test["Age"] = test["Age"].fillna(test["Age"].median())
test["Sex"][test["Sex"] == "male"] = 0
test["Sex"][test["Sex"] == "female"] = 1
test["Embarked"][test["Embarked"] == "S"] = 0
test["Embarked"][test["Embarked"] == "C"] = 1
test["Embarked"][test["Embarked"] == "Q"] = 2
test.Fare[152] = test.Fare.median()

target = train["Survived"].values
features = train[["Pclass","Age","Sex","Fare", "SibSp", "Parch", "Embarked"]].values

clf = svm.SVC()
clf.fit(features, target)

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

test_pred = clf.predict(test_features)
PassengerId = np.array(test["PassengerId"]).astype(int)
my_solution = pd.DataFrame(test_pred, PassengerId, columns = ["Survived"])
my_solution.to_csv("svm.csv", index_label = ["PassengerId"])

こちらの正答率はなんと60%台でした。。。

まとめ

kaggleのタイタニックデータセットを軽くいじってみましたが、なかなか正答率が上がらず大変です。このデータセットに限って言えば、モデルよりはデータの前処理が大変に感じました。少し触れましたが、年齢欄や乗船地の欠損が多かったですし、それらをどのように扱えば高い正答率が得られるかというのは、経験に基づくところがあるのではないかと思います。