LoginSignup
20
20

More than 3 years have passed since last update.

ColaboratoryでKaggleを始める

Last updated at Posted at 2019-06-02

Google ColaboratoryKaggleをサクッと試したいときのメモ。Colaboratoryは無料でGPU/TPUが使えるのがうれしい点。

本記事の要点は以下。

  1. ColaboratoryでKaggle APIを使えるように設定
  2. 簡単な問題「Titanic」に挑戦
  3. 予測モデルとしてNeural Networkを学習(機械学習フレームワークはTensorFlow)

必要なもの

  • Googleアカウント
  • Kaggleアカウント

ノートブックの準備

Colaboratoryにアクセスし、
ファイル > 新しいPython3ノートブック
で新しいノートブックを開く。

編集 > ノートブックの設定 > ハードウェアアクセラレータ > GPU > 保存
とすればGPUが使える。

Kaggle APIの導入

Kaggle APIはコマンドラインからKaggleのデータをダウンロードしたり予測結果をアップロードできるツール。

Kaggle APIをインストール

新しいセルを開いて下記コマンドを実行。

!pip install kaggle

これだけでは使えない。Kaggleアカウントと紐づける必要がある。

Kaggleアカウントと紐づけ

Kaggleにアクセス。
My Profile > Edit Profile > Create New API Token
としてkaggle.jsonをダウンロード。
Google driveを開いて適当な場所にkaggle.jsonをアップロード。

Colaboratoryから以下を実行。

# download API key from google drive
## Original: https://colab.research.google.com/drive/1eufc8aNCdjHbrBhuy7M7X6BGyzAyRbrF#scrollTo=y5_288BYp6H1
## When you run for the first time, you will see a link to authenticate.

from googleapiclient.discovery import build
import io, os
from googleapiclient.http import MediaIoBaseDownload
from google.colab import auth

auth.authenticate_user()

drive_service = build('drive', 'v3')
results = drive_service.files().list(
        q="name = 'kaggle.json'", fields="files(id)").execute()
kaggle_api_key = results.get('files', [])

filename = "/root/.kaggle/kaggle.json"
os.makedirs(os.path.dirname(filename), exist_ok=True)

request = drive_service.files().get_media(fileId=kaggle_api_key[0]['id'])
fh = io.FileIO(filename, 'wb')
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
    status, done = downloader.next_chunk()
    print("Download %d%%." % int(status.progress() * 100))
os.chmod(filename, 600)

初回実行時に認証が必要になるので、表示されるURLから認証コードを入手しコピペする。
オリジナルfilename = "/content/.kaggle/kaggle.json"となっているが、/root/.kaggle/に置けというエラーメッセージが出たのでfilename = "/root/.kaggle/kaggle.json"に変更

Download 100%.

と表示されれば成功。

動作確認

現在オープンなCompetitionの一覧を表示。

!kaggle competitions list

簡単なコンペティションに参加

今回はTitanicというコンペティションに参加。
Titanicは乗船者の年齢や性別といった属性情報から生存Yes/Noの二値を予測するタスク。データサイズも小さく、練習用として扱いやすいKaggleのHello world!的存在。

データのダウンロード

!kaggle competitions download -c titanic

colaboratoryの左カラムの「ファイル」や!lsなどで train.csv, test.csv, gender_submission.csv がダウンロードされていることを確認。
gender_submission.csvは提出する結果ファイルのサンプル。

データの前処理

与えられたCSVファイルには数値以外の文字列や欠損が含まれているので、一定の基準で画一的なベクトル表現に変換する必要がある。データをどう加工するかは予測精度に大きく影響するが、今回は動作確認が目的なので以下のような大雑把なルールで変換する。

  • 'Pclass', 'Sex', 'Fare','SibSp', 'Parch', 'Age', 'Embarked'の情報のみ使用
  • 3種類の'Embarked'(出港地)は0,1,2に置き換え
  • データの欠損は -1 に置き換え

また、学習状況のモニタリングのために学習データの一部を検証用(下記は10%)として使用。検証用データの精度は学習率、ネットワーク構造などのチューニングや過学習の判定に有用。

import numpy as np
import pandas as pd
import tensorflow as tf
import time

def parse(df):
    # Nan を -1 に置換
    df["Age"] = df["Age"].fillna(-1)
    df["Embarked"] = df["Embarked"].fillna(-1)
    # 文字列を数値に変換
    df["Sex"][df["Sex"] == "male"] = 0
    df["Sex"][df["Sex"] == "female"] = 1
    df["Embarked"][df["Embarked"] == "S" ] = 0
    df["Embarked"][df["Embarked"] == "C" ] = 1
    df["Embarked"][df["Embarked"] == "Q"] = 2
    return df

def split_val(x,y,rate,seed=None):
    # x,y の rate[%] をランダム分割
    N = x.shape[0]
    val_num = int(N*rate)
    if seed is not None:
        np.random.seed(seed)
    perm = np.random.permutation(N)
    ti = perm[:-val_num]
    vi = perm[-val_num:]
    return x[ti],y[ti],x[vi],y[vi]

def load_data():
    train_csv = pd.read_csv('train.csv')
    train_csv = parse(train_csv)
    train_x = train_csv[['Pclass', 'Sex', 'Fare','SibSp', 'Parch', 'Age', 'Embarked']].values
    train_y = train_csv['Survived'].values
    return split_val(train_x,train_y,0.1)

学習

予測のアルゴリズムは決定木やSVMなど数多く存在するが、折角なのでTensorFlowを使ってNeural Networkを学習させる。
ネットワーク構造はu_dim次元の中間層をlayer_numだけ繰り返すシンプルな多層パーセプトロン。中間層の出力にReLUとBatchNormalizationを適用。
モデル定義

def create_model(input_placeholder,u_dim,layer_num,y_dim,training):
    h = input_placeholder
    for i in range(layer_num):
        h = tf.layers.dense(inputs=h, units=u_dim,activation=tf.nn.relu)
        h = tf.layers.batch_normalization(h,training=training)  
    h = tf.layers.dense(inputs=h, units=y_dim)
    return h

学習。hyperparametersを調整していい感じのモデルを学習する。

np.random.seed(0)
tf.reset_default_graph()
y_dim     = 2
# hyperparameters
u_dim     = 100
layer_num = 2
epoch     = 1000
log_freq  = 100
batchsize = 200
lr        = 0.001

# data load
train_x,train_y,val_x,val_y = load_data()
N  = train_y.shape[0]
Nv = val_y.shape[0]
print('train num: {}, val num: {}'.format(N,Nv))

# calculation graph
x = tf.placeholder(tf.float32, [None, train_x.shape[1]],"input")
y = tf.placeholder(tf.int32, [None])

with tf.variable_scope("model"):
  train_z = create_model(x,u_dim,layer_num,y_dim,training=True)
with tf.variable_scope("model", reuse=True):
  z       = create_model(x,u_dim,layer_num,y_dim,training=False)

cross_entropy = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=train_z)

extra_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(extra_ops):
  train_step = tf.train.AdamOptimizer(lr).minimize(cross_entropy)

pred_y = tf.cast(tf.argmax(z, 1), tf.int32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(pred_y, y), tf.float32))

# main loop
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
T = time.time() 
for ep in range(1,epoch+1) :
  perm=np.random.permutation(N)
  for i in range(0,N,batchsize):
    batch_xs=train_x[perm[i:i+batchsize]]
    batch_ys=train_y[perm[i:i+batchsize]]
    sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})
  # monitor
  if ep%log_freq ==0 :      
    train_loss, train_acc = sess.run([cross_entropy, accuracy], feed_dict={x: train_x, y: train_y})
    val_loss, val_acc     = sess.run([cross_entropy, accuracy], feed_dict={x: val_x, y: val_y})
    epochT = time.time()-T
    print('Epoch: %d, Time :%.4f (s), train_loss: %f,  train_acc: %f, val_loss: %f,  val_acc: %f' % (ep, epochT, train_loss, train_acc, val_loss, val_acc))
    T = time.time()

以下は学習結果例。

Epoch: 100, Time :1.7708 (s), train_loss: 0.391779,  train_acc: 0.822943, val_loss: 0.405918,  val_acc: 0.797753
Epoch: 200, Time :1.7101 (s), train_loss: 0.426542,  train_acc: 0.704489, val_loss: 0.488159,  val_acc: 0.629214
Epoch: 300, Time :1.6960 (s), train_loss: 0.370545,  train_acc: 0.839152, val_loss: 0.441939,  val_acc: 0.775281
Epoch: 400, Time :1.7387 (s), train_loss: 0.403303,  train_acc: 0.816708, val_loss: 0.467801,  val_acc: 0.786517
Epoch: 500, Time :1.7077 (s), train_loss: 0.399253,  train_acc: 0.846633, val_loss: 0.431753,  val_acc: 0.808989
Epoch: 600, Time :1.6997 (s), train_loss: 0.393861,  train_acc: 0.825436, val_loss: 0.436137,  val_acc: 0.808989
Epoch: 700, Time :1.7178 (s), train_loss: 0.364453,  train_acc: 0.834165, val_loss: 0.432697,  val_acc: 0.820225
Epoch: 800, Time :1.7211 (s), train_loss: 0.355730,  train_acc: 0.840399, val_loss: 0.461115,  val_acc: 0.797753
Epoch: 900, Time :1.6965 (s), train_loss: 0.387813,  train_acc: 0.815461, val_loss: 0.436706,  val_acc: 0.820225
Epoch: 1000, Time :1.7431 (s), train_loss: 0.413756,  train_acc: 0.749377, val_loss: 0.415829,  val_acc: 0.752809

ちなみに、上記はGPU実行時の処理時間。この程度の計算ではGPUによる高速化の恩恵は小さい。

予測

テストデータも学習データと同様に前処理して、学習した予測モデルに入力。

# data
test_csv = pd.read_csv('test.csv')
test_csv = parse(test_csv)
test_x = test_csv[['Pclass', 'Sex', 'Fare','SibSp', 'Parch', 'Age', 'Embarked']].values
# predict
prediction = sess.run(pred_y, feed_dict={x: test_x})
# parse
PassengerId = np.array(test_csv["PassengerId"]).astype(int)
my_solution = pd.DataFrame(prediction, PassengerId, columns = ["Survived"])
# save
my_solution.to_csv("result.csv", index_label = ["PassengerId"])

result.csvが出力される。!cat result.csvなどで内容を確認できる。

予測結果の提出

!kaggle competitions submit -c titanic -f result.csv -m 'first submit'

1日の提出回数に上限があるので注意。

結果の確認

Kaggleにアクセス。
My Profile > Competitions > Titanic ... > My submissions
から結果を確認。
76.5% など妥当な値が得られていればOK。

参考

以下の記事を参考にさせていただいた。
Google Colaboratory で始める Kaggler 生活(データ入手と提出編)
【Kaggle初心者入門編】タイタニック号で生き残るのは誰?

20
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
20