機械学習を勉強する機会があったので、メモがてらブログにて記録しておこうと思います。僕は全くの機械学習初心者なのですが、kaggleでも導入として紹介されている「タイタニック号の生存者予測」が初学者向けの分析ということで、今回はそれにチャレンジしていこうと思います。
目次
kaggle「カグル」とは
機械学習が流行し始めて結構な期間が過ぎた気がしますが、日本でも最近このkaggle「カグル」が定着してきている様です。これは世界中の機械学習やデータ分析エンジニアが集うコミュニティの名前で、コミュニティの機能のみならず「コンペ」と呼ばれる競争が行われるのも特徴です。
コンペは政府や企業が問題を配布し、賞金と引き換えに最も精度の高いモデルを買い取るという形式だそうです。
初心者向けにカーネルとか、ディスカッション等の機能もあるみたいですが、それはまた別記事にしてまとめていこうと思います。とりあえず分析したい。
kaggleからデータを取得する
kaggle公式ページから登録を済ませたら、こちらのタイタニックのページからデータをダウンロードできます。それぞれ必要なデータセットがcsv形式となっているのでそれぞれ確認していきましょう。
・gender_submission.csv :生存の是非の予測の例です。これを参考にしてcsvファイルを作成して、kaggleに提出します。
・test.csv :テストデータです。顧客情報が記載されています。この情報を元に生存の是非を予測します。
・train.csv :トレーニングデータです。顧客情報と生存の是非が記載されています。これを学習用データとして利用します。
基本的に必要なデータはtest.csv とtrain.csv のデータです。コンペとは違い、初学者学習用の問題なのでファイルサイズも非常に小さく、扱いやすいデータとなっています。
これらをダウンロードしておきます。
Pythonの仮想環境を作る
この項目は任意です。僕は練習がてら仮想環境の作成も体験したかったので
$ python -m venv titanic
として仮想環境を作成しました。titanicディレクトリに移動して、
$ source bin/activate
これで仮想環境構築は終了です。簡単。モジュールをインストールします。
#pipのアップグレード $ pip install --upgrade pip #NumPy(数値計算ライブラリ) $ pip install numpy #SciPy(科学計算ライブラリ) $ pip install scipy #matplotlib(グラフ描画ライブラリ) $ pip install matplotlib #pandas(データフレームを扱うためのライブラリ) $ pip install pandas #scikit-learn(基本的な機械学習) $ pip install scikit-learn #flake8(コードチェッカー) $ pip install flake8
とりあえずこのくらい入れておけば大丈夫だろうという事で。
データを確認する
手始めにデータをpandas使って読み込みます。
import pandas as pd import numpy as np train = pd.read_csv("train.csv") test = pd.read_csv("test.csv") print(train.head())
head()は上から5行分だけデータを取ってくるメソッドです。以下、出力結果。
PassengerId Survived Pclass ... Fare Cabin Embarked 0 1 0 3 ... 7.2500 NaN S 1 2 1 1 ... 71.2833 C85 C 2 3 1 3 ... 7.9250 NaN S 3 4 1 1 ... 53.1000 C123 S 4 5 0 3 ... 8.0500 NaN S
それぞれ項目を確認しておきます。
PassengerId – 乗客識別連番ID
Survived – 生存フラグ(0=死亡、1=生存)
Pclass – チケットクラス(1=上層クラス、2=一般クラス、3=下層クラス)
Name – 乗客の名前
Sex – 性別(male=男性、female=女性)
Age – 年齢
SibSp – タイタニックに同乗している兄弟/配偶者の数
Parch – タイタニックに同乗している親/子供の数
Ticket – チケット番号
Fare – 料金(おそらく単位は$)
Cabin – 客室番号
Embarked – 出港地(タイタニックへ乗った港。C = Cherbourg、Q = Queenstown、S = Southamptonらしい。)
これがトレーニングデータとして与えられている項目の一覧です。そして今一度、トレーニングデータとテストデータの違いについて理解しておきましょう。
※トレーニングデータとテストデータの違い
統計学、特にパターン認識や機械学習において、テストデータとは、統計手法や、学習されたモデル等の評価・検証を行うためのデータのことである。評価データとも呼ばれる。対義語に、トレーニングデータ、訓練データ、学習データ等がある。
統計学や機械学習において何らかの推定を行う際に、トレーニングデータだけでは学習されたモデルを十分に評価できないという問題がある。この問題は過剰適合や過学習と呼ばれる。この問題を解決するために、学習に用いないデータを用意し、いくつかの学習モデルの評価を行うことがある。この、評価を行うためのデータがテストデータと呼ばれる。交差検証においては、標本データをあらかじめトレーニングデータとテストデータに分割し、トレーニングデータで学習し、テストデータに学習モデルを適用させることで性能の評価を行う。
様々な学習モデルがそれぞれ別々のデータで学習している状況では、モデル同士の性能の優劣を正しく評価できない。そのため、共通のテストデータに対して性能の評価を行うことで、モデル同士の性能を比較することが行われている。
(Wikipedia「テストデータ」より引用)
よってテストデータには「Survived(生存したかどうか)」の項目がありません。tarins.csvで学習したものをtest.csvに適応させることで機械学習のスコアを算出します。なるほど。
それぞれのデータの基本統計情報の確認
pandasのdescribe() メソッドを使って基本統計情報の確認が可能です。
import pandas as pd import numpy as np train = pd.read_csv("train.csv") test = pd.read_csv("test.csv") print(train.describe()) print(test.describe())
以下、出力結果です。
#train.csv PassengerId Survived Pclass Age SibSp Parch Fare count 891.000000 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000 mean 446.000000 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208 std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429 min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000 25% 223.500000 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400 50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200 75% 668.500000 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000 max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200 #test.csv PassengerId Pclass Age SibSp Parch Fare count 418.000000 418.000000 332.000000 418.000000 418.000000 417.000000 mean 1100.500000 2.265550 30.272590 0.447368 0.392344 35.627188 std 120.810458 0.841838 14.181209 0.896760 0.981429 55.907576 min 892.000000 1.000000 0.170000 0.000000 0.000000 0.000000 25% 996.250000 1.000000 21.000000 0.000000 0.000000 7.895800 50% 1100.500000 3.000000 27.000000 0.000000 0.000000 14.454200 75% 1204.750000 3.000000 39.000000 1.000000 0.000000 31.500000 max 1309.000000 3.000000 76.000000 8.000000 9.000000 512.329200
countはデータのそのカラムの件数を表しており、train.csv ではAgeカラム、test.csv ではAgeカラムとFareカラムに欠損データ(データの抜け落ち)があることがわかります。まずはこのデータセットの欠損値の確認から作業していきます。
データ欠損を関数を作成して確認する
このデータ欠損を関数を作成して確認します。
pandas.DataFrame およびpandas.Series には欠損値の確認をするisnull() メソッドが用意されています(便利すぎないか)。欠損値NaN (数値型)であればTrue 、そうでなければFalse が返ります。元のオブジェクトと同じサイズのオブジェクトを返すので欠損値の確認に使うにはもってこいの関数です。
isnull() からそのままを出力すると膨大なテーブルデータが返ってくるので関数を使ってデータを整形します。
def missing_value_table(df): #欠損値がそのカラムにいくつあるかを出力する null_val = df.isnull().sum() #それぞれのカラムで欠損値がどのくらいの割合を占めているかを計算する percent = 100 * df.isnull().sum()/len(df) #pandasのconcatメソッドで欠損数とその割合をaxis=1方向に連結する missing_table = pd.concat([null_val, percent], axis=1) #pandas.DataFrameの行名・列名を変更する missing_table_ren_columns = missing_table.rename( columns = {0 : '欠損数', 1 : '%'}) return missing_table_ren_columns
プログラムを以下の様に修正して動作するか確認します
import pandas as pd import numpy as np train = pd.read_csv("train.csv") test = pd.read_csv("test.csv") def missing_value_table(df): #欠損値がそのカラムにいくつあるかを出力する null_val = df.isnull().sum() #それぞれのカラムで欠損値がどのくらいの割合を占めているかを計算する percent = 100 * df.isnull().sum()/len(df) #pandasのconcatメソッドで欠損数とその割合をaxis=1方向に連結する missing_table = pd.concat([null_val, percent], axis=1) #pandas.DataFrameの行名・列名を変更する missing_table_ren_columns = missing_table.rename( columns = {0 : '欠損数', 1 : '%'}) return missing_table_ren_columns print(missing_value_table(train)) print(missing_value_table(test))
以下出力結果。
欠損数 % PassengerId 0 0.000000 Survived 0 0.000000 Pclass 0 0.000000 Name 0 0.000000 Sex 0 0.000000 Age 177 19.865320 SibSp 0 0.000000 Parch 0 0.000000 Ticket 0 0.000000 Fare 0 0.000000 Cabin 687 77.104377 Embarked 2 0.224467 欠損数 % PassengerId 0 0.000000 Pclass 0 0.000000 Name 0 0.000000 Sex 0 0.000000 Age 86 20.574163 SibSp 0 0.000000 Parch 0 0.000000 Ticket 0 0.000000 Fare 1 0.239234 Cabin 327 78.229665 Embarked 0 0.000000
この結果からどちらのデータもAgeとCabinの項目に特に欠損値が多いことが目立つことがわかります。一目瞭然ですね!
データセットの事前処理をする
さて、データの確認ができたところで機械学習の肝とも言える「データの事前処理・整形」についてやっていこうと思います。機械学習をしていく上で非常に重要なフェーズです。
今回は
・欠損データを自分で決めた代理データに入れ替える
・文字列カテゴリカルデータを数値へ変換する
この2つをやっていこうと思います。
train.csvの欠損データに代理データを入れる
trainデータでは、「Age(年齢)」「Cabin(客室番号)」「Embarked(出港地)」の項目に欠損値がありました。うち、予測データに必要ないと思われるのは「Cabin」カラムです。(部屋番号は生存確率に関係しないと考えて。予測モデルに使用しても問題ない。)今回は「Age」と「Embarked」カラムの欠損値に代理データを入れていきます。
・「Age」にはtrainデータの全データの中央値を入れてみます。
・「Embarked」には最頻値であるSを代入します。
今回は単純にこのようなルールで欠損値を埋めていきます。コードは以下。
# 欠損値を穴埋めする train["Age"] = train["Age"].fillna(train["Age"].median()) train["Embarked"] = train["Embarked"].fillna("S")
pandasのfillna() メソッドで欠損値の穴埋めを行うことができます。
欠損数 % PassengerId 0 0.000000 Survived 0 0.000000 Pclass 0 0.000000 Name 0 0.000000 Sex 0 0.000000 Age 0 0.000000 SibSp 0 0.000000 Parch 0 0.000000 Ticket 0 0.000000 Fare 0 0.000000 Cabin 687 77.104377 Embarked 0 0.000000
Cabinカラム以外の欠損値がなくなったことが確認できます。
文字列を数値に変換する
欠損データの修正が終わったので、次にカテゴリカルデータの文字列を数値に変換するという作業を行います。こうすることでカラムに使われている文字列を数値で定義できるので、それらのカラムを機械学習に利用できる様になります。
#文字列を数値に変換する train["Sex"][train["Sex"] == "male"] = 0 train["Sex"][train["Sex"] == "female"] = 1 train["Embarked"][train["Embarked"] == "S" ] = 0 train["Embarked"][train["Embarked"] == "C" ] = 1 train["Embarked"][train["Embarked"] == "Q"] = 2
to_csv() を使って確認してみました。きちんと数値に変換されています。
test.csvにも同様の作業をする
train.csv に行なった作業をtest.csv に対しても同様に適用します。
#testデータに対しても同様に処理を行う test["Age"] = test["Age"].fillna(test["Age"].median()) test["Sex"][test["Sex"] == "male"] = 0 test["Sex"][test["Sex"] == "female"] = 1 test["Embarked"][test["Embarked"] == "S"] = 0 test["Embarked"][test["Embarked"] == "C"] = 1 test["Embarked"][test["Embarked"] == "Q"] = 2 #Fareには同様に中央値で欠損データを補完 test.Fare[152] = test.Fare.median()
testデータには1つだけ欠損値があったので、それに対して直接同カラムの中央値を入れておきます。
これでデータの前処理は終わりです!正解はないので、あくまでも一例として捉えてみて下さい。
予測モデルの決定
データの整形が終わったので、予測モデルを決定します。今回は機械学習のベースともなる予測モデルである「決定木」を使って機械学習をします。決定木は、Python機械学習の有名ライブラリである「scikit-learn(サイキット・ラーン)」を使うと手軽に実装できます。
from sklearn import tree としてscikit-learnをインポートしておきます。tree は、決定木による分類が実装されているクラスです。
説明変数と目的変数
訓練データから説明変数と目的変数を決定します。
説明変数とは、目的変数を説明する変数のことで「独立変数」とも呼ばれます。物事の原因と捉えることもできます。
対して目的変数とは、予測したい変数のことです。「従属変数」「外的基準」とも呼ばれます。物事の結果とする変数なので、今回のケースでは「Survived(生存したかどうか)」が目的変数に対応するカラムになります。
#目的変数と説明変数を決定して取得 target = train["Survived"].values explain = train[["Pclass", "Sex", "Age", "Fare"]].values
決定木の作成をして、学習させる
scikit-learnでは決定木を用いた分類器は、sklearn.tree.DecisionTreeClassifierというクラスで実装されています。これを使うだけで勝手に決定木を作成してくれるので楽チン。
#決定木の作成 d_tree = tree.DecisionTreeClassifier() #fit()で学習させる。第一引数に説明変数、第二引数に目的変数 d_tree = d_tree.fit(explain, target)
fit() メソッドで決定木を用いて学習させます。
決定木を用いて予測する
予測モデルを作成したので、これをテストデータに適応させます。
#testデータから説明変数を抽出 test_explain = test[["Pclass", "Sex", "Age", "Fare"]].values #predict()メソッドで予測する prediction = d_tree.predict(test_explain) #出力結果を確認する #予測データのサイズ print(prediction.shape) #予測データの中身 print(prediction)
出力結果は以下の様になりました。
(418,) [0 0 1 1 1 0 0 0 1 0 0 0 1 1 1 1 0 1 1 0 0 1 1 1 1 0 1 1 1 0 0 0 1 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 1 1 0 1 1 1 0 0 0 1 1 0 0 0 1 0 0 1 0 0 1 1 0 1 0 1 0 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 1 0 1 1 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 0 1 0 0 1 0 0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 1 0 1 1 0 1 1 0 0 1 0 1 0 1 0 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 1 0 1 0 1 1 1 0 0 1 0 0 0 1 0 0 1 0 0 1 1 1 1 1 1 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 1 1 0 1 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 1 0 1 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 0 1 1 1 1 0 0 0 1 0 0 1 0 0 1 1 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0]
0と1で生存のチェックをしています。
予測データをkaggleに提出する
とりあえず簡単に予測データが取得できたので、これをCSVファイルに出力してkaggleに提出し、スコアを見てみます!要求されるデータフレームのカラムにはPassengerIdが必要なので、それを合わせてCSVファイルに出力します。
# PassengerIdを取得 PassengerId = np.array(test["PassengerId"]).astype(int) # 予測データとPassengerIdをデータフレームにて結合 result = pd.DataFrame(prediction, PassengerId, columns = ["Survived"]) # result.csvとして書き出し result.to_csv("result.csv", index_label = ["PassengerId"])
出力されたresult.csv をkaggleに提出します。
「Submit Predictions」からCSVファイルを提出するページに遷移できます。
提出するとスコアリングが始まります。
ファイルがkaggleの投稿基準を満たしていると、スコアリングを自動的に実行し、スコアを算出してくれます。今回の結果はスコア0.72248で、順位は9226位でした(案外上の方の順位と思ったのですが笑)
すなわち今回は72.248%の確率で正解を予測できたことと同値です。機械学習ではデータの整形とアルゴリズムの決定によりより高い精度でスコアを叩き出すのが競い合う点であり、かつ魅力的な点です。
おわりに
今回は簡単なモデルを用いて、機械学習を学びました。いかがだったでしょうか。
実際にkaggleの「タイタニック号の生存者予測」の課題からスコアを算出することで機械学習の流れも掴めたので良かったと思います。
時間のある時にスコアを上げる努力をしてみます。本記事が機械学習の勉強の足がかりにでもなれば幸いです!
⇨より深い分析をしてスコアを上げる努力をしてみました。
kaggleのタイタニック号生存者予測を、より深い分析を使ってスコアを上げる
機械学習(AI)を学べるプログラミンングスクールとして「テックブースト 」さんが挙げられます。
一人では理解が難しい機械学習のアルゴリズムやライブラリの使い方まで分かりやすく受講する事ができますよ!無料カウンセリングも行なっているので気になる方は是非。
また、AIエンジニアの登竜門の資格としてG検定というものがあります。【2021年度最新】AIエンジニアやデータサイエンティストの登竜門、「G検定」とは?難易度や取得メリットについて徹底解説!で詳しく解説されていますので、気になる方は是非ご覧ください。
スポンサードリンク
コメントを残す