一から始める機械学習(Kaggleで学ぶ機械学習)

  • 12
    いいね
  • 0
    コメント

このページの対象読者、目的

対象読者

・機械学習の概要がわかっている方 
・もしくは一から始める機械学習(機械学習概要)を読んだ方が対象です

目的

 ・Kaggleについて理解する
 ・機械学習について実際の流れを理解する
 ・Kaggleのチュートリアルを用いて実践を行う
 ・scikit-learnを用いて実践を行う

アジェンダ

  1. Kaggleとは
  2. なぜKaggle?
  3. Kaggleチュートリアル(Titanic: Machine Learning from Disaster)
  4. データの中でどれを使う?
  5. データ前処理
  6. 使用データ
  7. 使用する学習手法
  8. 学習実行と交差検証
  9. 最適化
  10. 機械学習の流れ
  11. 企業のコンテストを一部紹介

このページはプレゼンテーションを再編集したものです。
オリジナルであるプレゼンテーションをみたい方はこちらをどうぞ
https://speakerdeck.com/tflare/machine-learning-to-learn-at-kaggle

1. Kaggleとは

誤解を恐れずにまとめれば
「Kaggleは企業や研究家が、データサイエンス、機械学習関連のお題をだしてそれを解くサイトです。賞金がつくものもあり(さらにそれを解くためのコードを公開しかつ説明する。その説明についてコメント等でコミュニケーションを行う機能もあり)

2. なぜKaggle?

・本などの説明では、説明のためのデータセットが使われていることが多く、実感が湧きにくい。
・本などの説明では端折られる箇所も、実施する必要があるため機械学習の実際の流れが理解できる。
・順位が出るためやる気が出る。(全世界のデータ分析家と勝負できますし、協力もできます)
・賞金がでます(150万ドルの賞金が出るものもあり)

3. Kaggleチュートリアル(Titanic: Machine Learning from Disaster)

・乗客がタイタニックの沈没を生き延びたかどうかを予測
・訓練用データ(891行 × 12列のcsv) データに一部欠損あり
・テストデータ(418行 × 11列のcsv) データに一部欠損あり
・訓練用データで学習し、テストデータに対して、生き延びたかどうかを予測する。

4. データの中でどれを使う?

・PassengerId:データにシーケンシャルでついている番号
・Survived:生存(0 = No, 1 = Yes) 訓練用データにのみ存在
・Pclass:チケットのクラス(1 = 1st, 2 = 2nd, 3 = 3rd)
・Name:名前
・Sex:性別
・Age:年齢
・SibSp:タイタニック号に乗っていた兄弟と配偶者の数
・Parch:タイタニック号に乗っていた両親と子どもの数
・Ticket:チケット番号
・Fare:旅客運賃
・Cabin:船室番号
・Embarked:乗船場(C = Cherbourg, Q = Queenstown, S = Southampton)

実行コード
import numpy as np
import pandas as pd
train = pd.read_csv("train.csv", dtype={"Age": np.float64}, )
test  = pd.read_csv("test.csv", dtype={"Age": np.float64}, )
train.head(10)

kaggle_titanic1.png

実行コード
train_corr = train.corr()
train_corr

kaggle_titanic3.png

5. データ前処理

PassengerId以外は使えそうです。
現在解析に使えていないデータがあるので使えるデータ(数値)に変換します。
また欠損データがあるので補正します。

実行コード
def correct_data(titanic_data):

    titanic_data.Age = titanic_data.Age.fillna(titanic_data.Age.median())

    titanic_data.Sex = titanic_data.Sex.replace(['male', 'female'], [0, 1])

    titanic_data.Embarked = titanic_data.Embarked.fillna("S")
    titanic_data.Embarked = titanic_data.Embarked.replace(['C', 'S', 'Q'], [0, 1, 2])

    titanic_data.Fare = titanic_data.Fare.fillna(titanic_data.Fare.median())

    return titanic_data

train_data = correct_data(train)
test_data  = correct_data(test)
実行コード
train_corr = train.corr()
train_corr

kaggle_titanic.png

6. 使用データ

今回は以下項目を使用します。
・チケットのクラス
・性別
・年齢
・タイタニック号に乗っていた兄弟と配偶者の数
・タイタニック号に乗っていた両親と子どもの数
・旅客運賃
・乗船場

7. 使用する学習手法

・ロジスティック回帰
・サポートベクターマシン
・k-最近傍法
・決定木
・ランダムフォレスト
・ニューラルネットワーク

参考文献
学習手法の詳細は以下を参照ください。
Pythonではじめる機械学習 scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎
https://www.oreilly.co.jp/books/9784873117980/

8. 学習実行と交差検証

データと学習手法を指定します。

実行コード
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC, LinearSVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier

from sklearn.model_selection import cross_val_score

predictors = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]

models = []

models.append(("LogisticRegression",LogisticRegression()))
models.append(("SVC",SVC()))
models.append(("LinearSVC",LinearSVC()))
models.append(("KNeighbors",KNeighborsClassifier()))
models.append(("DecisionTree",DecisionTreeClassifier()))
models.append(("RandomForest",RandomForestClassifier()))
models.append(("MLPClassifier",MLPClassifier(solver='lbfgs', random_state=0)))

交差検証を実施します。

交差検証ではデータセットを訓練データとテストデータに分割し(ここでは3分割)、
それぞれで評価することで精度を安定させる方法です

一から始める機械学習(Kaggleで学ぶ機械学習)__Machine_learning_to_learn_at_Kaggle_key.png

実行コード
results = []
names = []
for name,model in models:
    result = cross_val_score(model, train_data[predictors], train_data["Survived"],  cv=3)
    names.append(name)
    results.append(result)

3分割されている結果を平均し、評価を出します。
ランダムフォレストが良い結果を出しました。

実行コード
for i in range(len(names)):
    print(names[i],results[i].mean())

LogisticRegression 0.785634118967
SVC 0.687991021324
LinearSVC 0.58810325477
KNeighbors 0.701459034792
DecisionTree 0.766554433221
RandomForest 0.796857463524
MLPClassifier 0.785634118967

ランダムフォレストで学習したものを元に、
テストデータで予想をし、その結果をcsvにして送ります。

実行コード
alg = RandomForestClassifier()
alg.fit(train_data[predictors], train_data["Survived"])

predictions = alg.predict(test_data[predictors])

submission = pd.DataFrame({
        "PassengerId": test_data["PassengerId"],
        "Survived": predictions
    })

submission.to_csv('submission.csv', index=False)

9. 最適化

正解率

正解率0.74163
7922人中7043位でした。ちょっと悔しいので最適化します。

最適化

grid searchを使用すればハイパーパラメータを自動的に最適化してくれます。
ただし実行時間がかかることに注意して下さい。

実行コード
parameters = {
        'n_estimators'      : [5, 10, 20, 30, 50, 100, 300],
        'max_depth'         : [3, 5, 10, 15, 20, 25, 30, 40, 50, 100]
        'random_state'      : [0],
}
gsc = GridSearchCV(RandomForestClassifier(), parameters,cv=3)
gsc.fit(train_data[predictors], train_data["Survived"])

上記等で最適化した結果を適応してみます。

正解率0.77990
7922人中4129位まで行きました。

Titanic__Machine_Learning_from_Disaster___Kaggle.png

データ前処理変更による最適化

先程のコードをKaggleに公開するとコメントがつきました。
欠損値を訓練用データからではなくテストデータから求めるようにしたほうが良いとのことでした。やってみました。
修正後のコードを以下に記載します。

実行コード
def correct_data(train_data, test_data):

    # Make missing values ​​for training data from test data as well
    train_data.Age = train_data.Age.fillna(test_data.Age.median())
    train_data.Fare = train_data.Fare.fillna(test_data.Fare.median())

    test_data.Age = test_data.Age.fillna(test_data.Age.median())
    test_data.Fare = test_data.Fare.fillna(test_data.Fare.median())    

    train_data = correct_data_common(train_data)
    test_data = correct_data_common(test_data)    

    return train_data,  test_data

def correct_data_common(titanic_data):
    titanic_data.Sex = titanic_data.Sex.replace(['male', 'female'], [0, 1])
    titanic_data.Embarked = titanic_data.Embarked.fillna("S")
    titanic_data.Embarked = titanic_data.Embarked.replace(['C', 'S', 'Q'], [0, 1, 2])

    return titanic_data

train_data,  test_data = correct_data(train, test)

正解率0.79426
7922人中2189位まで行きました。

Titanic__Machine_Learning_from_Disaster___Kaggle2.png

さらなる最適化の案

・名前の解析をする。(Mr. Mrs. Miss等があるためここから推測できないか等)

kaggle_titanic1.png

・別の学習手法を使用する(例えばXGBoost、LightGBM)を使用する

10. 機械学習の流れ

一から始める機械学習(Kaggleで学ぶ機械学習)__Machine_learning_to_learn_at_Kaggle_key2.png

手法選択はアルゴリズム チートシート

Choosing_the_right_estimator_—_scikit-learn_0_19_0_documentation.png

ハイパーパラメータ選択

grid search

モデルの評価

交差検証

11. 企業のコンテストを一部紹介

Prudential Life Insurance Assessment

・Can you make buying life insurance easier?
・生命保険申請者の属性からリスクレベルを算出する
・賞金3万ドル
・既に終了済み(コードが参照できる)
https://www.kaggle.com/c/prudential-life-insurance-assessment

Zillow Prize: Zillow’s Home Value Prediction (Zestimate)

・Can you improve the algorithm that changed the world of real estate?
・自宅のすべての機能を考慮して、Zestimateと実際の販売価格との間の誤差を予測する
・賞金120万ドル
・4ヶ月後に終了
https://www.kaggle.com/c/zillow-prize-1