Kaggle事始め
概要
この記事は2019年度TUTアドベントカレンダーの23日目の記事です。
ええ、23日目です。 え?投稿日?許して....
はじめに
明日は今日はクリスマス・イブですね。
巷ではツリー飾ってお祭りをしているでしょうが、僕はNORADとGoogleのサンタ追跡でも見比べてゆっくりしてます。
でもNORADのページ重いんですよね
これ書いて寝ました。
ということで(?) ちょっと前から気になっていたKaggleに手を出してみたので記事にします。 と言っても、筆者はデータ分析なんぞさっぱりなのでいろいろな記事を見たりDiscassionを覗いたりして見様見真似でやってみるだけです。
Kaggleといったらまず始めにやるコンペがあるらしいので例にもれず Titanic: Machine Learning from Disaster をやっていきます。
ちなみにここ見ながらやったので普通にこっちのほうが詳しいです。
Kaggleってなに?
Kaggleを知らない人もいるかもしれないので軽く説明します。
Kaggleとはデータ分析コンペティションのプラットフォームの一つです。 簡単に言うとデータ分析競技の競技場です。 競技したり話し合ったり分析モデルを公開したり見たりできます。
ここで主催者から与えられたデータを用いて一個一個に紐付けられたラベルや値を予測する分析技術を競い合います。
ちなみにカグルって発音します。
コンペってなに
コンペティションのことです。 競技って意味です。
Kaggleには2つのコンペティションがあります。 通常のコンペとカーネルコンペです。
通常のコンペではデータを提出します。 カーネルコンペではデータ分析を行うコードを提出します。 競技プログラミングみたいな感じですね。
通常のコンペでもカーネルコンペでもルールが存在します。 このルールはコンペ毎に違うため、ある程度確認しておいたほうが良いです。
まあ普通に使っていれば引っかからないもんですけど。
以下はルールの例です。
- 複数アカウント保持の禁止
- 1日の提出回数制限
- 外部データの使用について
- チームについてのルール
- チーム以外の人にKaggleのKernelやDiscussion以外の場でコード等の共有、交換の禁止
参考文献
Titanic (タイタニック)
Titanic: Machine Learning from Disaster はKaggleが主催者となって常時公開しているコンペティションです。
タイトルで予想つくかもしれませんが、機械学習でTitanicの乗客の生死について予測を行います。
Titanicって何
知ってる方は読み飛ばしてもらって構いません。
Titanicは船の名前です。 正式名称はロイヤルメールシップ・タイタニックとか言うらしいです。
旅客数が全部で2453人、乗組員が899人で合計3352人ほど乗っていたらしいです。
処女航海で氷山に接触し、大体1500人強ぐらいの犠牲者がでました。
ちなみにこの事故が映画化して結構有名になりました。
参考文献
本題
さて、では早速Kaggleでデータ分析をしてみようと思います。 が、データ分析を始めるまでに以下のことが考えられます。
- まず分析を行うためにはデータが必要です。
- データを貰うためにはコンペに参加しなければいけません。
- コンペに参加するにはKaggleのアカウントが必要です。
アカウント取得
というわけでKaggleのアカウントを貰いに行きましょう。
Kaggleのページは以下です。 ここでなんやかんやしてアカウントを取得します。
ちなみに筆者はGoogleアカウントでさくっと取得しました。
コンペに参加
アカウントを取得したら、ログインしたまま以下のTitanicのコンペに飛びます。
左上らへんのアイコンをクリックすることで出せるメニューの検索バーからTitanicと検索しても見つかります。
ここのJoin Competitionとか書いてあるところをクリックすると規約・ルールの承認確認フォームが出ます。 同意して参加しましょう。
データの取得
参加したらデータを貰いましょう。
Dataと書いてある場所をクリックすることでデータに関するページに行けます。
Data Descriptionブロックではデータに関するお話が聞けます。
Dataブロックではデータのダウンロードやデータの中身を見ることができます。 右上あたりにあるDownload Allを押すとダウンロードができます。
ちなみにKaggle APIを使えば、APIと書いてあるところのコマンドを叩くことでダウンロードができます。 詳細は?ボタンからGithubに飛んでREADME.mdを見ると良いと思います。
やっと分析
データもらったので分析をしましょう。 今回はデータの前処理が比較的楽な部類の決定木を使って分析しましょう。
今回筆者はJupyterLabを使用しましたが、環境構築が面倒な方はgoogle colaboratoryがおすすめです。
今回は以下のmoduleを使います。
- numpy
- pandas
- sklearn.tree
とりあえず全部importしましょう。
import numpy as np import pandas as pd from sklearn import tree
決定木ってなに
今日が終わりそうで焦っているので参考文献だけ貼っておきます。\(^o^)/オワタ
データの読み込み
プログラムにもらったデータを読み込ませます。 pythonにはcsvという便利モジュールがありますが、pandasはそのcsvを使用して.csvファイルを読み込むことができます。
以下のコードで.csvファイルを読み込み表示させます。
train = pd.read_csv('データのパス/train.csv') test = pd.read_csv('データのパス/test.csv') train.head(3)
pandasはread_csvメソッドcsvファイルを読み込み、DataFrame型のObjectにして返します。
DataFrame型のObjectはheadメソッドで始めから5つ目までのレコードを返します。 引数にレコードを返す数を指定できます。
データの確認
DataFrame型のObjectはdescribe関数を使うことでデータの各列ごとの要約統計量を取得することができます。 まあ、データの雰囲気を掴むのに便利な関数ってことですね。
train.describe()
test.describe()
そして、データのnullチェックを行います。 データは基本的に値を損失しているものが多いので、今回のデータがどのくらい値が損失しているかをチェックします。 目grepでもできるのですが、せっかくpythonを使っているのでnullを数えてくれる関数を作成しましょう。
def check_missing_values(dataframe): sum_null = dataframe.isnull().sum() per = sum_null/len(dataframe) * 100 missing_values_table = pd.concat([sum_null, per], axis=1) missing_values_table = missing_values_table.rename(columns = {0: 'number of missing', 1: '%'}) return missing_values_table
nullの数は、isnullメソッドによって各要素がbooleanに変換されたDataFrame型objectの合計を求めることで算出できます。 また、合計値を要素数で割って100をかけることで百分率を算出することができます。
数値が計算できたら、後はpandasのconcatメソッドを使用してDataFrame型のObjectを作成します。
作成できたらチェックしましょう。
check_missing_values(train)
trainでは年齢を示すAgeが177個、客室番号を示すCabinが687個、乗船港を示すEmbarkedが2個損失しているのがわかります。
check_missing_values(test)
testではAgeが86個、旅客運賃を示すFareが1個、Cabinが327個損失していますね。
データの前処理
データ分析で一番面倒くさい 手間のかかるやりどころを感じる場所です。がんばりましょう。
trainデータ埋め
先程のデータの確認でデータの損失が確認されました。データが損失している場合、分析ができないので適当に埋めます。
train["Age"] = train["Age"].fillna(train["Age"].median()) train["Embarked"] = train["Embarked"].fillna("S")
今回はCabinは使わない予定なので触りません。
損失したAgeの値はとりあえず全部平均を入れておきます。
また、Embarkedの値は一番多かったSを入れておきましょう。
その後はちゃんと入ったかチェックしましょう。
check_missing_values(train)
数値に変換
データはすべて入りましたが、数値以外のデータでは分析ができません。 なのでデータに数をあてて数値にしましょう。
train["Sex"] = train["Sex"].map({"male": 0, "female": 1}).astype(int) train["Embarked"] = train["Embarked"].map({"S": 0, "C": 1, "Q": 2}).astype(int)
性別の値を男性を0, 女性を1に変換しました。 また、乗船港がSouthamptonの場合は0, Cherbourgの場合は1, Queenstownの場合は2に変換しました。
ちゃんと変換できたかチェックしましょう。
train.head()
testデータも同じく
testデータも同じく変換しましょう。
testデータではAgeとFare、Cabinの値が損失していました。 今回はCabinを使わないのでAgeとFareだけ埋めます。
test["Age"] = test["Age"].fillna(test["Age"].median()) test["Fare"] = test["Fare"].fillna(test["Fare"].median())
とりあえず両方共平均値を入れました。
次にSexとEmbarkedを数値に変換しましょう。
test["Sex"] = test["Sex"].map({"male": 0, "female": 1}).astype(int) test["Embarked"] = test["Embarked"].map({"S": 0, "C": 1, "Q": 2}).astype(int)
変換できたらチェックしましょう。
test.head()
学習機を回す
データ処理が終わったらいよいよ学習機を回します。 決定木はsklearnモジュールのDecisionTreeClassifierを使います。
target = train["Survived"].values train_feature_values = train[["Pclass", "Sex", "Age", "Fare"]].values decision_tree = tree.DecisionTreeClassifier() decision_tree = decision_tree.fit(train_feature_values, target) test_feature_values = test[["Pclass", "Sex", "Age", "Fare"]].values prediction_values = decision_tree.predict(test_feature_values)
目的値にtrainのSurvivedの値を、特徴量としてtrainのPclass, Sex, Age, Fareの値をそれぞれndarray型に変換して変数に格納します。
次に決定木インスタンスを作成し、変数に格納した特徴量と目的値を学習させます。
その後対応するtestの特徴量を変数に格納し、決定木で判別します。
判別した結果はprediction_values
に格納します。
これでprediction_values
に判別した結果が出力されました。
つまり、データ分析が完了しました。
あとは分析結果をPassengerIdに対応させ、csvファイルか何かに出力した後、提出すれば終わりです。
PassengerId = np.array(test["PassengerId"]).astype(int) solution = pd.DataFrame(prediction_values, PassengerId, columns = ["Survived"]) solution.to_csv("結果ファイルを出力するパス/自由な名前.csv", index_label=["PassengerId"])
提出
無事csvファイルに書き出せたら提出をしましょう。
と言っても以下の3ステップで提出できます。簡単ですね。
- 右側の青いSubmit Predictionsボタンを押し
- Upload submission fileに出したcsvファイルを投げ込み
- 下の方にあるMake Submissionボタンをクリック
終わりに
本当は決定木の説明カキコとか他の分析方法(AdaBoostやSVC等),他のモジュールの使用(XGBoostやLightGBM等)もやりたかったんですけど、知識と時間とやる気の問題でできませんでした。原因はコード書いているときのやる気だと思っている。
そしてクリスマスにちなんだ話題にしたかったのにもかかわらず謎にタイタニックの乗客の生死を予測してました。どうしてこうなった。
そんな筆者の都合なんてどうでもいいですね。次はリバースエンジニアリングについてなんか書こうかと思います。
良いクリスマスを!