読者です 読者をやめる 読者になる 読者になる

Deep Learning Tutorial

chainer and python

Kaggle - Titanic: Machine Learning from Disaster

chainer Kaggle DeepLearning

まずは使いそうなライブラリ群をインポート。

import numpy as np
import scipy as sp
import pandas as pd
from pandas import DataFrame as DF

pandasのread_csv()モジュールを使い.csvデータを読み込む。

test_data = pd.read_csv("kaggle/titanic/test.csv")
test_data = DF(test_data)
train_data = pd.read_csv("kaggle/titanic/train.csv")
train_data = DF(train_data)
train_y = train_data['Survived']

使えなさそうなデータ列は削除します。

del test_data['Name']
del train_data['Name']
del train_data['PassengerId']
del test_data['PassengerId']
del train_data['Cabin']
del test_data['Cabin']
del train_data['Ticket']
del test_data['Ticket']
del train_data['Survived']

次に、性別を数字に変換します。
maleの場合は1,femaleの場合は0にします。

def toNumSex(data):
    for i in range(data.shape[0]):
        if data['Sex'][i] == "male":
            data['Sex'][i] = 1
        elif data['Sex'][i] = "female":
            data['Sex'][i] = 0
        else:
            print(i)

toNumSex(test_data)
toNumSex(test_data)

そして、Embarkedを数字にします。
C:1,Q:2、S:3とします。

def toNumEmbarked(data):
    for i in range(data.shape[0]):
        if data['Embarked'][i] == "C":
            data['Embarked'][i] = 1
        elif data['Embarked'][i] == "Q":
            data['Embarked'][i] = 2
        elif data['Embarked'][i] == "S":
            data['Embarked'][i] = 3
        else:
            print(i)

toNumEmbarked(test_data)
toNumEmbarked(train_data)

ここで、出力に数字が...

>>> 61
>>> 829

どうやら、61行目と829行目はnanらしい。
再頻出な3で埋めておきます。


成形したデータをcsv形式で保存しておきます。

train_data.to_csv("kaggle/titanic/train_data.csv")
test_data.to_csv("kaggle/titanic/test_data.csv")
train_y.to_csv("kaggle/titanic/train_y.csv")

とりあえず、データの前処理完了です!!
さっそく、chainerでニューラルネットワークを組みましょう。
今回は3層で行きます。
ささっと作ったのでコードは汚いです笑

ニューラルネットワーク

import scipy as sp
import pandas as pd
import argparse
import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, Variable, optimizers, serializers, utils
from chainer import Link, Chain, ChainList, FunctionSet
import chainer.functions as F
import chainer.links as L
import matplotlib.pyplot as plt
from pandas import DataFrame as DF
from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import StandardScaler


# GPU設定
parser = argparse.ArgumentParser(description='Chainer example: CIFAR-10')
parser.add_argument('--gpu', '-gpu', default=-1, type=int,
                    help='GPU ID (negative value indicates CPU)')


# GPUが使えるか確認
args = parser.parse_args()
if args.gpu >= 0:
    cuda.check_cuda_available()
xp = cuda.cupy if args.gpu >= 0 else np

# データの読み込みと整理
X = pd.read_csv("kaggle/titanic/train_data_1.csv")
y = pd.read_csv("kaggle/titanic/train_y.csv", header=None)
predict = pd.read_csv("kaggle/titanic/test_data.csv")
X = np.array(X)
y = np.array(y)
predict = np.array(predict)
X = X.astype(np.float32)
y = y.astype(np.int32)

train_X, test_X, train_y, test_y = train_test_split(X, y, train_size=702/891, random_state=0)

predict = predict.astype(np.float32)

model = chainer.FunctionSet(l1 = L.Linear(6, 256),
                            l2 = L.Linear(256,256),
                            l3 = L.Linear(256, 2))

# GPU使用のときはGPUにモデルを転送
if args.gpu >= 0:
    cuda.get_device(args.gpu).use()
    model.to_gpu()

# 順伝播
def forward(X_data, y_data):
    x, t = chainer.Variable(X_data), chainer.Variable(y_data)
    h = F.tanh(model.l1(x))
    h = F.tanh(model.l2(h))
    y = F.tanh(model.l3(h))

    return F.softmax_cross_entropy(y, t), F.accuracy(y, t)

# Setup optimizer
optimizer = optimizers.Adam()
optimizer.setup(model)


# parameter
n_epoch = 500
N = train_X.shape[0]
N_test = test_X.shape[0]
batchsize = 27

l = []
a = []

# Learning loop
for epoch in range(1, n_epoch + 1):
    print('epoch', epoch)

    # training
    perm = np.random.permutation(N)
    sum_accuracy = 0
    sum_loss = 0
    for i in range(0, N, batchsize):
        X_batch = xp.asarray(train_X[perm[i:i + batchsize]])
        y_batch = xp.asarray(train_y[perm[i:i + batchsize]])
        
        y_batch = y_batch.reshape(y_batch.shape[0], )

        # 勾配を初期化
        optimizer.zero_grads()
        # 順伝播させて誤差と精度を計算
        loss, acc = forward(X_batch, y_batch)
        # バックプロパゲーション
        loss.backward()
        # 最適化ルーティーンを実行
        optimizer.update()

        sum_loss += float(loss.data) * batchsize
        sum_accuracy += float(acc.data) * batchsize

    print('train mean loss={}, accuracy={}'.format(sum_loss / N, sum_accuracy / N))
    l.append(sum_loss/N)
    a.append(sum_accuracy/N)

    # evaluation
    sum_accuracy = 0
    sum_loss = 0
    for i in range(0, N_test, batchsize):
        X_batch = xp.asarray(test_X[i:i + batchsize])
        y_batch = xp.asarray(test_y[i:i + batchsize])

        y_batch = y_batch.reshape(y_batch.shape[0], )
        # 順伝播させて誤差と精度を計算
        loss, acc = forward(X_batch, y_batch)

        sum_loss += float(loss.data) * batchsize
        sum_accuracy += float(acc.data) * batchsize

    print('test  mean loss={}, accuracy={}'.format(sum_loss / N_test, sum_accuracy / N_test))

結果

最初は3層で試しましたが、いろいろな試行錯誤をした結果スコアは...

0.78469

もうこれ以上上がる気がしない...
ニューラルネットワークで予想するにはデータ数が少なすぎるのだろう。
うん。
そう信じたい。