Titanic: Machine Learning from Disaster

Kaggleのタイタニック号乗客の生存予測をやってみました。データ分析の経験はないので今回は少し触ってみる程度でやってみます。とりあえずやったことをざっくり書いていきます。

実装はpythonです。

必要なモジュールの用意

まずはじめにモジュールのインポートする。

今回はscikit-learnとPyTorchを使って生存予測の分類をしてみます。

import csv
import numpy as np
import pandas as pd

# scikit-learn
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.utils import shuffle

# PyTorch
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as O
from torch.autograd import Variable

データの用意

ここからー>(Titanic: Machine Learning from Disaster | Kaggle)データを取ってくる。

データを読み込む

path = "train.csv"
data = pd.read_csv(path)

データの中身は以下のようになっています。

  • PassengerId : 乗客のID
  • Survived : 生存結果(0:死亡、1:生存)
  • Pclass : チケットのクラス (1=1st, 2=2nd, 3=3rd)
  • Name : 乗客の名前
  • Sex : 乗客の性別
  • Age : 乗客の年齢
  • SibSp : タイタニック号に乗船している兄弟と配偶者の数
  • Parch : タイタニック号に乗船している両親と子供の数
  • Ticket : チケット番号
  • Fare : 運賃
  • Cabin : 部屋番号
  • Embarked : 乗船した港

データの前処理

機械学習をする前にデータの前処理をしたり、あまり必要ではなさそうなデータを削除する。

文字列は数値に変換する必要があるので性別のところを男性は1に女性は0に変換する。 データのなかには欠損値があったりするので、今回は欠損値が含まれるデータはトレーニングデータから削除する。

# Change string to numerical in sex field
data = data.replace("male", 1).replace("female", 0)
# Remove some nonvaluable field
data = data.drop(["Name", "Ticket", "Embarked", "Cabin", "Fare"], axis=1)
# Remove missing value
data = data.dropna()

データセットをトレーニングデータとテストデータに分ける。

# Split dataset into training set and test one
X = data.values[:, 2:]
Y = data.values[:, 1].astype(dtype=np.int64)
train_x, test_x, train_t, test_t = train_test_split(X, Y, test_size=0.1) 

テスト

今回はnaive bayes, support vector machine, neural networkの3つの機械学習アルゴリズムを使って生存予測をしてみました。それぞれの結果は以下のようになります。

Naive Bayes

gnb = GaussianNB()
gnb.fit(train_x, train_t)

result = gnb.predict(test_x)
num_right = np.sum(result == test_t)
print("Accuracy {:.2f}".format(num_right / len(test_t)))

Accuracy 0.76

Support Vector Machine

clf = SVC()
clf.fit(train_x, train_t)

result = clf.predict(test_x)
num_right = np.sum(result == test_t)
print("Accuracy {:.2f}".format(num_right / len(test_t)))

Accuracy 0.78

Neural Network

class NeuralNetwork(nn.Module):
    def __init__(self, n_in, n_hidden, n_out):
        super(NeuralNetwork, self).__init__()
        self.input = nn.Linear(n_in, n_hidden)
        self.output = nn.Linear(n_hidden, n_out)
        
    def forward(self, x):
        h = F.sigmoid(self.input(x))
        y = F.sigmoid(self.output(h))
        return y
    

batchsize = 50
epochs = 4000
learning_rate = 0.01
n_batch = len(train_x) // batchsize
n_in = len(train_x[0])
n_hidden = 3
n_out = 2

network = NeuralNetwork(n_in, n_hidden, n_out)
criterion = nn.CrossEntropyLoss()
optimizer = O.Adam(network.parameters(), lr=learning_rate)

for epoch in range(epochs):
    if epoch % 100 == 0:
        print("Epoch {}".format(epoch))
    train_x, train_t = shuffle(train_x, train_t)
    # Mini batch learning
    for i in range(n_batch):
        start = i * batchsize
        end = start + batchsize
        x_var = Variable(torch.FloatTensor(train_x[start:end]))
        t_var = Variable(torch.LongTensor(train_t[start:end]))
        # Forward + Backward + Optimize
        optimizer.zero_grad()
        y_var = network(x_var)
        loss = criterion(y_var, t_var)
        loss.backward()
        optimizer.step()

# Test the model
test_var = Variable(torch.FloatTensor(test_x), volatile=True)
result = network(test_var)
values, labels = torch.max(result, 1)
num_right = np.sum(test_t == labels.data.numpy())
print("Accuracy {:.2f}".format(num_right / len(test_t)))

Accuracy 0.81

Submit

PyTorchのニューラルネットワークを使った生存予測の分類が一番うまくいっていたので、PyTorchで学習したモデルを使って実際のテストデータを分類しKaggleに提出しました。

結果は次のとおりです。

f:id:pytry3g:20180120135328p:plain

0.78468となりました。

まとめ

というわけでやったことをざっくり書きました。今回はあまり深く考えずにやったので、次回はもっと深堀して考えて高い精度で分類できるモデルを作ってみたいと思います。

コードを一応あげておきます。

github.com