【Python初心者】データを前処理から機械学習までを実行する|タイタニックデータセット

スポンサーリンク
Python
初心者に人気のプログラミング言語Pythonは独学可能か?
Pythonは非常に人気のあるプログラミング言語で、まったくの初心者でも独学が可能と言われています。 Pythonはさまざまな目的に使える、汎用性のあるプログラミング言語です。 プログラミングは「独学が難しい」と言われていま...
ゼロ知識の初心者がデータサイエンスを完全無料で学習する方法5選
データサイエンスの知識や技術、またはPythonについて学びたい。でも「大学に行くほど本気度がない」、「スクールに行くほどお金がない」、なんせ「時間がない」という方も多いはずです。というよりほとんどの方がそうだと思います(当然わたし...

今回は、データの前処理から機械学習までを一貫して解説していきます。データを目の前にして、いきなり機械学習もモデルを作成することはありえません。データの前処理や可視化、特徴量エンジニアリングなどをしてから、モデルの作成、モデルの評価を行っていきます。
データはタイタニックのデータセットを使って、実際のコードで解説していきます。
タイタニックデータセットは機械学習を学ぶ上で、もっとも基本的で、もっとも最初に扱うデータをいわれています。
Pythonの環境構築はAnacondaをインストールし、Jupyter Labを使っていきます。
以下の過去記事を参照して下さい。

【2021年最新】M1 mac でanacondaをインストールする方法

【2021年最新】WindowsでAnacondaをインストールする方法

必要なライブラリをインポート

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
plt.style.use('ggplot')
# 警告メッセージを出さないようにする
import warnings
warnings.filterwarnings('ignore')

タイタニックのデータセットを読み込む

titanic = sns.load_dataset('titanic')   # seabornにある titanicのデータセットを読み込む
titanic

出力:

訓練用とテスト用にデータを分割する

データの前処理や可視化のまえに、訓練用とテスト用にデータを分割します。そして、訓練用のデータのみを使ってデータの詳細を確認します。

X = titanic.iloc[:,1:]  # 2列目以降の変数を説明変数に指定
y = titanic.iloc[:,0]   # 1列目の変数を目的変数に指定

# データを訓練用とテスト用に分割する
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size = 0.25,      # もとのデータの 0.25をテストデータ
    random_state = 1,
    stratify = y)

訓練用のデータを確認する

df_train = pd.concat([y_train,X_train], axis=1)   # 目的変数を説明変数を合体
df_train

出力:

【Python初心者】 直感的に理解できるデータの結合 concat・merge

各変数の詳細

  • survived:生死(1=生存、0=死亡)
  • pclass:チケットクラス(1=上級、2=中級、3=下級)
  • sex:性別(male=男性、female=女性)
  • age:年齢
  • sibsp:同乗している兄弟/配偶者の数
  • parch:同乗している親/子の数
  • fare:乗船料金
  • embarked:出港地(C=Cherbourg、S=Southampton、Q=Queenstown)
  • who:性別(man=男性、woman=女性)
  • adult_male:成人男性であるかどうか(True=成人男性、False=成人男性以外)
  • deck:乗船していたデッキ(First=上級、Second=中級、Third=下級)
  • embarck_town:出港地
  • alive:生死(no=0、yes=1)
  • alone:一人であったかどうか

「adult_male」は成人男性かどうかですが、何歳からを成人としているかを確認してみましょう。

df_train[df_train["adult_male"]==True]["age"].min()  # 「adult_male」の年齢の最小値を確認

出力:
16.0

「adult_male」の最少年齢は 16 です。

sum(df_train[df_train["adult_male"]==True]["sex"]=="female")  # 「adult_male」が女性であるデータ数

出力:
0

「adult_male」に女性がいないことが確認できました。
つまり、「adult_male」は「age」と「sex」で説明できるため、情報が重複しています。

「alone」が一人であるかを、「sibsp」と「parch」から確認してみましょう。

len(df_train[(df_train["sibsp"]+df_train["parch"])==0])==len(df_train[df_train["alone"]==True])  # 「sibsp」と「parch」が Oと、「alone」である場合の真偽

出力:
True

「sibsp」と「parch」の合計が0(同乗者なし)であれば、「alone」であることが確認できました。

つまり、「alone」は情報が重複しています。

訓練データの前処理

このタイタニックのデータセットは生存が目的になります。なので、生存に関係なさそうな変数や、情報が重複している変数を削除します。

必要なデータを削除する

df = df_train.drop(["pclass","deck","alive","adult_male","who","embark_town","alone"],axis=1) # 必要のない変数を削除
df

出力:

Python初心者でも直感的にできるデータの抽出方法

欠損値の処理

欠損値の種類と対処方法

【Python初心者】直感的に分かる欠損値の取り扱い(削除・補完)

df.isnull().sum()   # 欠損値の個数を確認

出力:

「age」に 133の欠損値が、「embarked」に 2も欠損値があります。

まずは、「age」の欠損を平均値で補完してみましょう。また、「embarked」の内容を確認してみましょう。

df["age"] = df["age"].fillna(df["age"].mean())  # 「age」の欠損値を平均値で補完

print(df.isnull().sum())             # 欠損値の個数を確認
print(df["embarked"].value_counts())# 欠損値の個数を確認

出力:

「age」を補完した結果、欠損値が0になりました。また、「embarked」はSが485、Cが127、Qが54でした。では、「embarked」を最頻値であるSで補完してみましょう。

df.fillna({"embarked":"S"},inplace=True)  # 「enbarked」の欠損値を最頻値であった「S」で補完

print(df.isnull().sum())             # 欠損値の個数を確認
print(df["embarked"].value_counts()) # 欠損値の個数を確認

出力:

欠損値がなくなりました。また、「embarked」のSが485から487になり、補完できました。

【Python初心者】直感的に分かる欠損値の取り扱い(削除・補完)

データの可視化

生存の有無を棒グラフにしてみます。

print(df["survived"].value_counts()) # 「survived」のデータ数を確認

plt.figure(figsize=(7,5))

sns.countplot(x="survived",data=df,palette="hls")
plt.show()

出力:

生存の有無を「embarked」別で棒グラフを作成してみましょう。

print(pd.crosstab(df["survived"], df["embarked"])) # 「survived」のデータ数を「embarked」別でデータ数を確認

plt.figure(figsize=(10,5))
sns.countplot(x="embarked", data=df, hue="survived",palette="hls")

plt.show()

出力:

今度は、「class」別で生存の有無を確認してみます。

print(pd.crosstab(df["survived"], df["class"])) # 「survived」のデータ数を「class」別でデータ数を確認

plt.figure(figsize=(10,5))
sns.countplot(x="class", data=df, hue="survived",palette="hls")

plt.show()

出力:

次は、生存の有無で分けた年齢をヒストグラムにしてみましょう。

plt.figure(figsize=(10,5))

sns.distplot(df[df["survived"]==0]["age"], bins=30, color='g') # 「survived」が0、つまり死亡したデータの「age」
sns.distplot(df[df["survived"]==1]["age"], bins=30, color='r') # 「survived」が1、つまり生存したデータの「age」
plt.xlabel("Age",fontsize=15)
plt.show()

出力:

生存の有無で分けた「fare」(乗船料金)をヒストグラムで確認する

plt.figure(figsize=(10,5))

sns.distplot(df[df["survived"]==0]["fare"], bins=30, color='g') # 「survived」が0、つまり死亡したデータの「fare」
sns.distplot(df[df["survived"]==1]["fare"], bins=30, color='r') # 「survived」が0、つまり死亡したデータの「fare」
plt.xlabel("Fare",fontsize=15)
plt.show()

出力:

いろいろしましたが、以下のコードでは簡単にデータの可視化ができます。データと目的変数を引数に指定するだけです。

import dabl
dabl.plot(df, target_col = 'survived')  # データフレーム、目的変数を引数に指定

出力:

【Python初心者】簡単なヒストグラムの描き方

【Python初心者】matplotlibとseabornで散布図を描いてみよう(データの可視化)

【Python初心者が知らない】ドットプロットでデータを可視化する簡単な方法

訓練データの前処理

機械学習の精度を上げるために、変数のデータを変換します。

具体的には、カテゴリ変数をダミー変数に、連続変数を標準化(平均値が0、標準偏差が1)します。

df = pd.get_dummies(df,drop_first=True)      # カテゴリ変数をダミー変数に変換する

from sklearn.preprocessing import StandardScaler
std = StandardScaler()
df["fare"] = std.fit_transform(df[["fare"]]) # 「fare」を標準化する
df["age"] = std.fit_transform(df[["age"]])   # 「age」を標準化する
df

出力:

【Python初心者】カテゴリ変数をダミー変数に置き変える方法|機械学習に必要な前処理

【Python初心者】正規化・標準化する方法|機械学習に必要な前処理

X_train = df.iloc[:,1:].values  # 2列目以降の変数を説明変数に指定
y_train = df.iloc[:,0].values   # 1列目の変数を目的変数に指定

テストデータの前処理

テストデータも訓練データを同じように前処理します。

X_test = X_test.drop(["pclass","deck","alive","adult_male","who","embark_town","alone"],axis=1)  # 必要ない変数を削除する
X_test["age"] = X_test["age"].fillna(X_test.groupby("sex")["age"].transform("mean"))             # 「age」の欠損値を補完する(性別の平均値)
X_test.fillna({"embarked":"S"},inplace=True)                                                     # 「embarked」の欠損値を補完する(最頻値:S)
X_test = pd.get_dummies(X_test,drop_first=True)                                                  # ダミー変数へ
X_test["fare"] = std.fit_transform(X_test[["fare"]])                                             # 「fare」を標準化する
X_test["age"] = std.fit_transform(X_test[["age"]])                                               # 「age」を標準化する
X_test = X_test.values
y_test = y_test.values

機械学習(確率的勾配降下法)

【初心者】機械学習を使って、予測モデルを作成するまでの手順

機械学習のアルゴリズムは深層学習(一応)の確率的勾配降下法を使います。

学習モデルを作成しましょう。比較的単純なコードだと思います。

from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import SGD

model=Sequential()

model.add(Dense(200,
                activation="relu",
                input_dim=X_train.shape[1]))
model.add(Dropout(0.2))
model.add(Dense(200,
                kernel_initializer="uniform",
                activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(1,activation="sigmoid"))
model.summary()

出力:

モデルの内容が出力されています。少し難しいですね。まあこのコードはコピペで大丈夫です。

では、作成したモデルを実行していきましょう。

sgd=SGD(lr=0.01,momentum=0.9,decay=1e-7)
model.compile(optimizer=sgd,
              loss="binary_crossentropy",
              metrics=["accuracy"])
history=model.fit(X_train,
                  y_train,
                  batch_size=64,
                  epochs=50,
                  verbose=1,
                  validation_split=0.2)

出力:

テストデータを使って予測精度を評価

print('訓練データの正解率 :{0}'.format(round(history.history['accuracy'][-1],4)))
results = model.evaluate(X_test, y_test, verbose=0)
print('テストデータの正解率:{0}'.format(round(results[1],4)))

出力:
訓練データの正解率 :0.8296
テストデータの正解率:0.8296

マトリクスで結果を確認しましょう。

from sklearn.metrics import confusion_matrix
y_pred = model.predict_classes(X_test, verbose=0) # 予測データを作成
# テストと予測のデータから混合行列を生成
confmat = confusion_matrix(y_true=y_test,
                           y_pred=y_pred)

plt.style.use('default')

fig, ax = plt.subplots(figsize=(4, 4),dpi=100)
# matshow関数で行列からヒートマップを描画
ax.matshow(confmat, cmap=plt.cm.Blues, alpha=0.3)
for i in range(confmat.shape[0]):                 # クラス0の繰り返し処理
    for j in range(confmat.shape[1]):             # クラス1の繰り返し処理
        ax.text(x=j, y=i, s=confmat[i, j],
                va='center', ha='center')         # 件数を表示

plt.xlabel('Predicte label')
plt.ylabel('True label')
plt.tight_layout()
plt.show()

出力:

from sklearn.metrics import precision_score, recall_score, f1_score, roc_auc_score
print('Test accuracy: %.3f' % model.evaluate(X_test, y_test, verbose=0)[1])
print('Precision: %.3f' % precision_score(y_test, y_pred))
print('Recall: %.3f' % recall_score(y_test, y_pred))
print('F1: %.3f' % f1_score(y_test, y_pred))
print('roc_auc: %.3f' % roc_auc_score(y_test, y_pred))

出力:

【基礎】分類モデルの評価方法

【おすすめ】Pythonの独学で必要な書籍

テストデータの結果は正解率が0.839でした。データ解析のコンペティションであるkaggleでもタイタニックデータセットを使った機械学習があります。0.839はなかなかの正解率です(実際はKaggleのデータセットとseabornのデータセットは少し違いますが)

【初心者】はじめての深層学習による手書き文字認識(MNIST)
今回は、機械学習を学び始めるなら、必ず通る道である「手書き文字認識」です。 手書き文字認識は、MNIST(Modified National Institute of Standards and Technology database...

コメント

タイトルとURLをコピーしました