【Python】ロジスティック回帰による2値分類|scikit-learnを用いた機械学習モデル開発実践

こんにちは、Kosei(@kay_diacc2)です!

こんな方におすすめ
  • Pythonでロジスティック回帰モデルを構築する方法が知りたい
  • ロジスティック回帰モデルの評価方法が知りたい
目次

ロジスティック回帰モデルとは

ロジスティック回帰分析とは、ある事象の発生確率Pを予測する統計学的手法になります。多変量解析や機械学習における教師あり学習の2値分類問題として取り扱われます。上記のように、説明変数を入力した際、ロジスティック関数をもとに発生確率Pを求め、最終的に0か1を返すモデルをロジスティック回帰モデルと呼びます。

ロジスティック回帰についてもっと詳しく知りたい方向けにこちらの記事も配信しています。

【Python×機械学習】scikit-learnでロジスティック回帰モデルを構築・評価

PythonのScikit-learnライブラリを用い、ロジスティック回帰モデルを構築する方法について解説します。

具体的に下記の手順でプログラムを構築していきます。

  • データセットの説明
  • データの準備
  • データの加工
  • 特徴量選択
  • モデル学習
  • モデルの学習結果確認
  • モデル推論
  • モデル性能評価

データセットの説明

利用するデータセットは、タイタニック号の乗客員データになります。

このデータセットはKaggle Titanic – Machine Learning from Disasterよりダウンロードできます。

タイタニックのデータセットには次のような変数が格納されています。

変数名概要キー
survived生存有無0 = No
1 = Yes
pclassチケットクラス1 = 1st
2 = 2nd
3 = 3rd
sex性別
Age年齢
sibsp一緒に乗船した兄弟/配偶者の数
parch一緒に乗船した親/子どもの数
ticketチケット番号
fare旅客運賃
cabinキャビン番号
embarked乗船港C = Cherbourg
Q = Queenstown
S = Southampton

機械学習モデルを用いて、難破船を生き延びた乗客(Servived=1)を予測するモデルを作成します。

データの準備

前述したタイタニック号のデータセット読込のために、次のようなコードを実行します。

コード

import numpy as np
import pandas as pd
from sklearn import datasets

# データセット(train.csvを利用)
df = pd.read_csv("titanic/train.csv")

データ出力結果(df)

データ加工

モデルが学習しやすいように、あらかじめデータセットを加工することとします。

次のようなデータ加工を実行してみましょう。

データ加工|数値変換

次に示すような文字列の変数を数値変換します。

# 性別を[0,1]変換
def gender_convert(x):
    if x == 'male':
        return 0
    elif x == 'female':
        return 1

# 港を数値変換
def embarked_convert(x):
    if x == 'C':
        return 0
    elif x == 'Q':
        return 1
    elif x == 'S':
        return 2


# 性別を数値変換
df["Sex"] = df["Sex"].apply(gender_convert)

# 港を数値変換
df["Embarked"] = df["Embarked"].apply(embarked_convert)

データ加工|特徴量スケーリング(標準化)

次に示すような変数の尺度を揃えるために、特徴量スケーリングを実施します。

from sklearn.preprocessing import StandardScaler

# 標準化インスタンス (平均=0, 標準偏差=1)
standard_sc = StandardScaler()

# 年齢と運賃を標準化
X = df.loc[:, ['Age','Fare']]
X = standard_sc.fit_transform(X)

#標準化後のデータ出力
df.loc[:, ['Age','Fare']] = X

特徴量スケーリングについて具体的に知りたい方向けに次のような記事も配信しています。

データ加工|欠損値の除去

今回の例では欠損値を含むデータを行毎削除することとします。

# 各種特徴量における欠損値数の確認
df.isnull().sum()

# 出力イメージ
# PassengerId      0
# Survived         0
# Pclass           0
# Name             0
# Sex              0
# Age            177
# SibSp            0
# Parch            0
# Ticket           0
# Fare             0
# Cabin          687
# Embarked         2
# dtype: int64
# 欠損値がある行を除去
df = df.dropna(axis=0).reset_index(drop=True)

# 欠損値がある行が除去されたことを再確認
df.isnull().sum()

# 出力イメージ
# PassengerId    0
# Survived       0
# Pclass         0
# Name           0
# Sex            0
# Age            0
# SibSp          0
# Parch          0
# Ticket         0
# Fare           0
# Cabin          0
# Embarked       0
# dtype: int64

欠損値の取り扱いについて詳しく知りたい方向けに次のような記事も配信しています。

  • 【Python】欠損値の確認方法:こちら
  • 【Python】欠損値の除外方法:こちら
  • 【Python】欠損値の補完方法:こちら

データ加工後のデータイメージ

特徴量選択

ロジスティック回帰モデルに用いるインプットとして、説明変数と目的変数をセットします。

今回は次のような変数を選択しています。

説明変数Pclass, Sex, Age, SibSp, Embarked, Fare
目的変数Survived

説明変数X、目的変数yとした次のようなコードを実行しましょう。

# 説明変数
X = df[["Pclass","Sex","Age","SibSp","Embarked","Fare"]]

# 目的変数
y = df["Survived"]

モデル学習|ロジスティック回帰

ロジスティック回帰のインスタンスを作成し、モデル学習を行います。

モデル学習用コード

from sklearn.linear_model    import LogisticRegression
from sklearn.model_selection import train_test_split

# トレーニングデータおよびテストデータ分割
X_train,X_test,Y_train,Y_test = train_test_split(X,y, test_size=0.3, shuffle=True, random_state=3)


# ロジスティック回帰のインスタンス
model = LogisticRegression(penalty='l2',          # 正則化項(L1正則化 or L2正則化が選択可能)
                           dual=False,            # Dual or primal
                           tol=0.0001,            # 計算を停止するための基準値
                           C=1.0,                 # 正則化の強さ
                           fit_intercept=True,    # バイアス項の計算要否
                           intercept_scaling=1,   # solver=‘liblinear’の際に有効なスケーリング基準値
                           class_weight=None,     # クラスに付与された重み
                           random_state=None,     # 乱数シード
                           solver='lbfgs',        # ハイパーパラメータ探索アルゴリズム
                           max_iter=100,          # 最大イテレーション数
                           multi_class='auto',    # クラスラベルの分類問題(2値問題の場合'auto'を指定)
                           verbose=0,             # liblinearおよびlbfgsがsolverに指定されている場合、冗長性のためにverboseを任意の正の数に設定
                           warm_start=False,      # Trueの場合、モデル学習の初期化に前の呼出情報を利用
                           n_jobs=None,           # 学習時に並列して動かすスレッドの数
                           l1_ratio=None          # L1/L2正則化比率(penaltyでElastic Netを指定した場合のみ)
                          )

# モデル学習
model.fit(X_train, Y_train)

ロジスティック回帰メソッドに指定する引数情報

スクロールできます
引数名概要デフォルト
penalty正則化パラメータを指定。以下の選択肢あり。
'none': 正則化パラメータなし
'l2': L2正則化
'l1': L1正則化
'elasticnet': Elastic Net(L1+L2正則化)
‘l2’
dual双対問題(dual)を解くか主問題(primal)を解くか指定。0.5
tol計算を停止するための基準値。小さいほど探索に時間を要する。0.0001
C正則化の強さを指定。Cの値が小さいほど正則化の強さが増す。1.0
fit_interceptモデルのバイアス項(切片)を最適化する場合はTrue、しない場合はFalseを指定。True
intercept_scalingパラメータ最適化アルゴリズムsolver=‘liblinear’が指定され、
fit_intercept=Trueの際に有効なスケーリング基準値。
1
class_weightクラスに対する重みを辞書形式{class_label:weight}として指定。
指定しない場合、全てのクラスの重みが1になる。
1
random_state乱数生成器のシードを指定するパラメータ。1000
solverハイパーパラメータの最適化の際に使用するアルゴリズム。
・小さなデータセットの場合は「liblinear」が適切
・大きなデータセットの場合は「sag」と「saga」が高速。
・2値ではなく多クラス分類の場合、「newton-cg」「sag」「saga」「lbfgs」のみが多項ロジットを処理可能。
‘lbfgs’
max_iterイテレーションの最大値100
multi_class2値分類では’ovr’ 、多クラス分類の場合は’multinomial’を指定。
‘auto’を指定すれば2値か多クラスか自動で区別してくれる。
‘auto’
verboseliblinearおよびlbfgsがsolverに指定されている場合、冗長性のためにverboseを任意の正の数に設定0
warm_startTrueの場合、モデル学習の初期化に前の呼出情報を利用。False
n_jobs学習時に並列して動かすスレッドの数。False
li_ratio正則化パラメータpenalty=’elasticnet’の場合に設定するl1/l2正則化の比率。None

正則化について詳しく知りたい方向けに次のような記事も配信しています。

モデルの学習結果確認

前述のモデルの学習結果について考察してみましょう。

偏回帰係数の確認

モデルの偏回帰係数は以下で確認できます。偏回帰係数の絶対値が大きい程、その説明変数がモデルの精度向上に際して重要な役割を果たしていることを意味します。重要度の低い説明変数の係数は、その説明変数の影響を打ち消すために0に近い値を取るのが特徴です。

df_model = pd.DataFrame(index=["Pclass","Sex","Age","SibSp","Embarked","Fare"])
df_model["偏回帰係数"] = model.coef_[0]

# 出力イメージ
#               偏回帰係数
# b1  Pclass   -0.418780
# b2  Sex       2.363631
# b3  Age      -0.607834
# b4  SibSp     0.195629
# b5  Embarked -0.428897
# b6  Fare      0.015289

バイアス項(切片)の確認

print("intercept: ", model.intercept_)

# 出力イメージ
# intercept:  [1.0597535]

モデル推論

前述のロジスティック回帰モデルにテストデータを渡し、予測値を得るための方法を解説します。

目的変数の正事象の発生確率を出力値する方法

タイタニックでの生存率を確率で出力値したい場合は、次のように記述します。

# 確率算出の際は、predict_proba()メソッドを利用
Y_pred_proba = model.predict_proba(X_test)

# データ出力
df_proba     = pd.DataFrame()
df_proba["非生存率(Surviced=0)"] = Y_pred_proba[:,0]
df_proba["生存率(Surviced=1)"] = Y_pred_proba[:,1]
print(df_proba)

# 出力イメージ
#     非生存率(Surviced=0)  生存率(Surviced=1)
# 0          0.715506          0.284494
# 1          0.070686          0.929314
# 2          0.327845          0.672155
# 3          0.108550          0.891450
# 4          0.065910          0.934090
# 5          0.294308          0.705692
# 6          0.536102          0.463898
# 7          0.055910          0.944090
# 8          0.123385          0.876615
# 9          0.176352          0.823648
# 10         0.024932          0.975068

2値(0または1)で結果を出力する方法

# 推論
Y_pred = model.predict(X_test)
print(Y_pred)

# 出力イメージ
# [0 1 1 1 1 1 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 1 1 
# 1 1 0 1 0 0 0 1 1 1 1 1 1 1 0 1 0 0 1 0 0 0 0 0 1 1 0]

上記は別解として次のように記載しても同じ結果が得られます。

# 推論
model.predict_proba(X_test).argmax(axis=1)

モデル性能評価|ロジスティック回帰

この章では前述で作成したモデルの性能評価方法について解説します。

混合行列・正解率・適合率・再現率・F1の評価

以下代表的な評価指標を用いて学習済みモデルを評価します。

混合行列

from sklearn.metrics import confusion_matrix

# 混合行列
print(confusion_matrix(y_true=Y_test, # 実測値
                       y_pred=Y_pred  # 予測値
                      ))

# 出力イメージ
# [[ 9  9]
#  [12 25]]

混合行列・正解率・適合率・再現率

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# 正解率
print('accuracy: ',  round(accuracy_score(y_true=Y_test, y_pred=Y_pred),2))
# 適合率
print('precision: ', round(precision_score(y_true=Y_test, y_pred=Y_pred),2))
# 再現率
print('recall: ',    round(recall_score(y_true=Y_test, y_pred=Y_pred),2))
# f1スコア
print('f1 score: ',  round(f1_score(y_true=Y_test, y_pred=Y_pred),2))

# 出力イメージ
# accuracy:   0.62
# precision:  0.74
# recall:     0.68
# f1 score:   0.7

【参考】上記指標のレポート出力

from sklearn.metrics import classification_report

# 分類問題における評価レポート
print(classification_report(Y_test, Y_pred))

# 出力イメージ
#               precision    recall  f1-score   support

#            0       0.43      0.50      0.46        18
#            1       0.74      0.68      0.70        37

#     accuracy                           0.62        55
#    macro avg       0.58      0.59      0.58        55
# weighted avg       0.63      0.62      0.62        55

前述した機械学習の分類問題の評価指標について詳しく知りたい方向けに、次のような記事も配信しています。

ROC曲線

ロジスティック回帰モデルを用いてROC曲線を描き、AUCを評価した結果を示します。

ROC曲線:コード

ROC曲線を可視化する場合、次のように記述します。

from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt

# テストデータがクラス1(Survived=1)に属する確率
Y_score = model.predict_proba(X_test)[:, 1]

# ROC曲線の算出(左から偽陽性率:FPR、再現率:TPR、閾値:thresholds)
FPR, TPR, thresholds = roc_curve(y_true=Y_test, y_score=Y_score)


# 理想線
plt.plot([0, 0, 1], [0, 1, 1], linestyle='--', label='Ideal')
# ランダムな推定線
plt.plot([0, 1], [0, 1], linestyle='--', label='Random')
# ROC曲線
plt.plot(FPR, TPR, label='ROC(area = %0.2f)' % auc(FPR, TPR))

plt.legend()
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.show()

ROC曲線:出力イメージ

また、AUCは次のように記述しても算出可能です。

from sklearn.metrics import roc_auc_score

# AUC
print('AUC: ', roc_auc_score(y_true  = Y_test,                            # 実測値
                             y_score = model.predict_proba(X_test)[:, 1]  # クラスラベル正事象の発生確率
                            ))

# 出力イメージ
# AUC:  0.73

ROC曲線およびAUCについて詳しく知りたい方向けに次のような記事も解説しています。

AI・機械学習まとめ

最後までご覧いただきありがとうございました。当サイトでは機械学習・深層学習における理論やPythonを用いた実装方法の解説記事を多数取り扱っております。

【初学者向け】データサイエンス・人工知能(AI)開発のおすすめ学習方法も解説してます。

ディープラーニングを学ぶ上でおすすめの教材はこちらで紹介しています。

最後に

この記事が気に入ったら
フォローしてね!

本記事をシェア!
URLをコピーする
URLをコピーしました!
目次
閉じる