Smile Engineering Blog

ジェイエスピーからTipsや技術特集、プロジェクト物語を発信します

Pythonで機械学習(kaggle入門)

はじめに

データ分析や機械学習について、実践的な学習ができる「kaggle」というものがあります。 kaggleで初心者向けチュートリアルとして代表的な課題「Titanic: Machine Learning from Disaster」を実際にPythonを使ってやってみたので書いていきます。

kaggleとはなにか?

kaggle(カグル)と呼び、世界中の機械学習・データサイエンスに携わっているエンジニアを繋げるプラットフォームです。 そのkaggleでもっとも目玉になっているのがコンペです。 企業がコンペ形式で課題を提示し、参加者は様々な手法を使って分析モデルを構築して、順位を競います。 コンペによっては、上位者に賞金がでるものもあります。

kaggleの良い点として

  • 会員登録は無料(コンペに参加可能)。
  • 難易度が低めなチュートリアルの課題も用意されている。
  • 「Kernels(カーネル)」という他のユーザが構築したモデルのコードが公開されており、コードを読むだけでも勉強になる。
  • 英語の勉強にもなる

これから機械学習を学ぶ方、すでに学び始めている方はkaggleへ参加をすることで、 スキルアップができるかと思います。

「Titanic: Machine Learning from Disaster」をやってみる

今回は、「タイタニック号:災害からの機械学習」について、 課題データの取得~Python機械学習・予測~予測データの提出・スコア確認を実施する。

【概要】

タイタニック号の乗客が沈没を生き延びたかどうかを予測するもの。 訓練用データで学習して、テストデータに対して、生き延びたかどうかを予測する。 予測したテストデータを提出することでスコア(正解率)とランキングがわかる。

【環境】

  • 開発言語

    • Python3.7
  • ライブラリ

    • jupyter
    • pandas
    • matplotlib
    • seaborn
    • scikit-learn
    • numpy

インストール手順は、他でも書かれているので割愛。 ツールは「jupypter notebook」を使用。 (ノートブック形式で段階的にプログラムを実行できる対話型ブラウザ実行環境)

【課題データの取得】

Titanic: Machine Learning from Disaster | Kaggle

上記ページより以下のファイルをダウンロードする。

  • train.csv (訓練用データ)
  • test.csv(テストデータ)

■ファイルの内容

  • PassengerId:番号
  • Survived:生存(0[死亡], 1[生存]) ※訓練用データのみ
  • Pclass:チケットのクラス(1[上層クラス], 2[中層クラス], 3[下層クラス])
  • Name:名前
  • Sex:性別
  • Age:年齢
  • SibSp:乗船した兄弟と配偶者の数
  • Parch:乗船した両親と子どもの数
  • Ticket:チケット番号
  • Fare:旅客運賃
  • Cabin:船室番号
  • Embarked:乗船場(C[Cherbourg], Q[Queenstown], S[Southampton])

Python機械学習・予測】

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier

1.入力データの読み込み

train = pd.read_csv('../input/train.csv') # 訓練用データの読み込み
test = pd.read_csv('../input/test.csv') # テストデータ読み込み

2.訓練用データの項目、型、欠損値確認

train.info() 
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

3.欠損値の補完

「Age」「Embarked」「Cabin」には欠損値が存在することが分かったため欠損値を補完する。 今回は、「Age」は平均値、「Embarked」は最頻値で補完。 ※「Cabin」はモデル作成時は落とすため未処理。

train['Age'].fillna(train.Age.mean(), inplace=True) # 平均値で補完
train['Embarked'].fillna('S', inplace=True)         # 'S'で補完

4.特徴量の分布

生存率に有意な特徴量と思われるデータを確認。 性別について確認すると女性平均の生存率が約74%、男性平均が約18%。 女性は優先的に避難したため性別で差が出ているようだ。

train_data =train[['Sex', 'Survived']].groupby(['Sex'])
train_data.describe()

f:id:jspnet:20190708235146p:plain

ヒストグラムでも確認。

sns.countplot('Sex', data=train, hue='Survived')

f:id:jspnet:20190708235153p:plain

訓練データの変数と乗客の生存と相関がありそうなものを確認。 相関係数を算出するにはcorrメソッドを使用。 算出対象にするにはObject型から数値型に変換する必要がある。

train['Sex'] = train['Sex'].map({'male': 0, 'female': 1})
train['Embarked'] = train['Embarked'].map({'S': 0, 'C': 1, 'Q': 2})
train.corr()

f:id:jspnet:20190708235150p:plain

※1.0、‐1.0に近いほど強い相関がある 結果から 「Pclass」「Sex」「Age」「Parch」「Embarked」 は相関がありそうなのでこの変数を説明変数として予測モデルを構築する。 手法を「決定木」「ランダムフォレスト」「ロジスティック回帰」でモデルを作成。

5.モデル投入データの事前準備

x_train = train[['Pclass','Sex','Age','Parch','Embarked']].copy() #訓練用データから説明変数を取得
y_train = train['Survived'].copy() #訓練用データから目的変数を取得
x_test  = test.copy()
x_test['Embarked'].fillna('S', inplace=True)
x_test['Age'].fillna(x_test.Age.mean(), inplace=True) 
x_test['Sex'] = x_test['Sex'].map({'male': 0, 'female': 1})
x_test['Embarked'] = x_test['Embarked'].map({'S': 0, 'C': 1, 'Q': 2})
x_test = x_test[['Pclass','Sex','Age','Parch','Embarked']].copy()

6.予測モデルの作成

・決定木

decision_tree = DecisionTreeClassifier(random_state=0)
decision_tree = decision_tree.fit(x_train, y_train) # 決定木モデル作成
y_pred = decision_tree.predict(x_test) # モデルにテストデータを投入し予測
passengerId = np.array(test["PassengerId"]).astype(int)
result = pd.DataFrame(y_pred, passengerId, columns = ["Survived"])
result.to_csv("decision_tree_result.csv", index_label = ["PassengerId"]) # 予測データをCSV出力

・ランダムフォレスト

random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(x_train, y_train) # ランダムフォレストモデル作成
y_pred = random_forest.predict(x_test) # モデルにテストデータを投入し予測
passengerId = np.array(test["PassengerId"]).astype(int)
result = pd.DataFrame(y_pred, passengerId, columns = ["Survived"])
result.to_csv("random_forest_result.csv", index_label = ["PassengerId"]) # 予測データをCSV出力

・ロジスティック回帰

logistic_regression = LogisticRegression()
logistic_regression.fit(x_train, y_train) # ロジスティック回帰モデル作成
y_pred = logistic_regression.predict(x_test) # モデルにテストデータを投入し予測
passengerId = np.array(test["PassengerId"]).astype(int)
result = pd.DataFrame(y_pred, passengerId, columns = ["Survived"])
result.to_csv("logistic_regression_result.csv", index_label = ["PassengerId"]) # 予測データをCSV出力

7.スコア確認

予測データを以下のページにアップすることでスコアが計算され表示される。 https://www.kaggle.com/c/titanic/submissions

各モデルのスコア結果は、以下となった。 ・決定木:0.75598 ・ランダムフォレスト:0.75119 ・ロジスティック回帰:0.77511

スコアが一番良かったモデルは、ロジスティック回帰で約77.5%の確率で正解を予測。

おわりに

他にも手書き数字認識やGoogle Street Viewの画像からの文字識別などのチュートリアルもあり、 賞金が出るコンペも実施されているので興味があるようなら挑戦してみては。