scikit-learnを使ったロジスティック回帰

投稿者: | 2019-09-21
Table of Content

scikit-learnを使ったロジスティック回帰

scikit-learnを使ってロジスティック回帰でのクラス分類をやっていきたいと思います。

ロジスティック回帰とは

ロジスティック回帰(logistic regression)は線形分類問題と二値分類問題に対する単純ながら強力なアルゴリズムです。
実際の機械学習の問題でもクラス分類であれば、ロジスティック回帰を試して、ベースとなる精度を確認します。
また、ロジスティック回帰の学習で得られた各係数の重みから重要な変数を見つけたりします。

以下ではタイタニックのサンプルデータを用いて、scikit-learnのロジスティック回帰を用いた学習のコードサンプルを紹介します。

ライブラリのインポート

必要なライブラリをインポートします。

In [1]:
# ロジスティック回帰を行うクラス
from sklearn.linear_model import LogisticRegression
# 特徴量のスケーリングに使用
from sklearn.preprocessing import MinMaxScaler 
# トレーニングデータと検証データの分割に使用
from sklearn.model_selection import train_test_split
# 特徴量のスケーリングから学習モデルまでの入力のパイプラインを作成します。
from sklearn.pipeline import make_pipeline
# モデルの結果を評価する指標
from sklearn.metrics import accuracy_score, roc_auc_score, confusion_matrix, precision_score, recall_score 
from seaborn import load_dataset
import pandas as pd
import numpy as  np
import warnings
warnings.filterwarnings('ignore')

データセットのロードとデータの確認

関数load_datasetを使ってタイタニックの生存者についてのデータを読み込みます。
このデータを使って、性別や年齢、客室の等級などの乗船者のデータからその人が生存したかどうかを分類するモデルを作成します。

In [2]:
df = load_dataset('titanic')
#df.head()

データセットのデータ型の確認

データを見た所カテゴリカルなデータが含まれているので、各カラムのデータ型を確認します。

In [3]:
df.dtypes
Out[3]:
survived          int64
pclass            int64
sex              object
age             float64
sibsp             int64
parch             int64
fare            float64
embarked         object
class          category
who              object
adult_male         bool
deck           category
embark_town      object
alive            object
alone              bool
dtype: object

データの前処理

ロジスティック回帰には数値のデータを入力する必要があります。

そのため、pandasのget_dummies関数を使ってone hot encoding(各カテゴリを列にわけてそれぞれの0,1でどのカテゴリかを表すデータに変換すること)
を行います。

また、Null(Nan)が入力されるとロジスティック回帰ではエラーになってしまうので、Nullは0埋めをします。

In [4]:
# カテゴリ変数をone hot encoding
df_category = pd.get_dummies(df, columns=['sex', 'embarked', 'class', 'who', 'adult_male', 'deck', 'embark_town', 'alone'])
# 「pclass」カラムは客室の等級を表す「class」カラムと同じなので削除、「alive」カラムは答えそのものになってしまうので、削除します。
df_category = df_category.drop(['pclass', 'alive'], axis=1)
# データ内のNullを0で置換します。
df_category = df_category.fillna(0) 
#df_category.head()

トレーニングデータの作成

「survived」を教師カラムに、そのほかのカラムを特徴量に学習データを作成します。

In [5]:
y = df_category['survived']
X = df_category.drop('survived', axis=1)
print(y.shape)
print(X.shape)
(891,)
(891, 29)

トレーニングデータと検証用データの分割

scikit-learnのtrain_test_splitを使って、トレーニングデータの一部を検証用データとして分けておきます。

In [6]:
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

学習パイプラインの作成

モデルの学習パイプラインを作成します。
今回はロジスティック回帰に特徴量を入れる前にMinMaxScalerでスケーリングを行います。
MinMaxScalerを使うことで全ての入力値が0から1の間に正規化されます。

また、ロジスティック回帰で設定できるパラメーターでよく使うものには以下のものがあります。

パラメーター変数 概要 設定可能な値
penalty 正則化の方法 文字列で、'l1','l2','elasticnet','none'のいずれかを入力(デフォルトはl2)
C 正則化の強さを設定する 0以上の実数値で数字を大きくするほど正則化が強くなる(デフォルト値は1.0)
class_weight クラスの数に偏りがある場合に、クラスごとの重みを調整する変数 {class_label: weight}のdict形式か'balanced'が設定できる(デフォルトはNone(全てのクラスが同じ重み))
multi_class マルチクラス分類の場合に設定する変数 二値分類の時は'ovr'、多クラス分類は'multinomial'

そのほかの設定値は公式ドキュメント
に詳しく載っています。

In [7]:
pipe_lr = make_pipeline(MinMaxScaler(), LogisticRegression(C=5.0))  

学習の実行

学習を実行します。

In [8]:
pipe_lr.fit(X_train, y_train)
Out[8]:
Pipeline(memory=None,
         steps=[('minmaxscaler', MinMaxScaler(copy=True, feature_range=(0, 1))),
                ('logisticregression',
                 LogisticRegression(C=5.0, class_weight=None, dual=False,
                                    fit_intercept=True, intercept_scaling=1,
                                    l1_ratio=None, max_iter=100,
                                    multi_class='warn', n_jobs=None,
                                    penalty='l2', random_state=None,
                                    solver='warn', tol=0.0001, verbose=0,
                                    warm_start=False))],
         verbose=False)

検証データでの精度の検証

検証データを使ってモデルの精度を検証します。
今回は正解率を出してみます。

In [9]:
y_pred = pipe_lr.predict(X_val)
accuracy_score(y_val, y_pred)
Out[9]:
0.7988826815642458

検証データでの正解率はおよそ79.8%でした。

ロジスティック回帰の係数の学習結果から変数ごとの重要度を分析する

ロジスティック回帰でモデルを学習させると変数ごとに回帰係数が求まります。
この回帰係数を変数ごとにどのような値になっているかを確認することで、各変数が分類結果にどのように寄与しているかを見ることができます。

In [10]:
for col in np.argsort(pipe_lr.steps[1][1].coef_[0])[::-1]:
    print("coef {0}: {1}".format(X.columns[col], pipe_lr.steps[1][1].coef_[0][col]))
coef deck_E: 1.958272975447006
coef deck_D: 1.5668130861359435
coef fare: 1.5478138603861322
coef deck_B: 1.177152296477878
coef adult_male_False: 0.9683785142350856
coef deck_F: 0.6575429255170138
coef deck_C: 0.616788487244781
coef class_Second: 0.5213728108788491
coef deck_A: 0.49185505340375746
coef who_child: 0.48832298049933937
coef who_woman: 0.4800555337356685
coef class_First: 0.23174785433387243
coef alone_False: 0.2197158846412489
coef sex_female: 0.13081595765657614
coef embark_town_Cherbourg: 0.08210227694566896
coef embarked_C: 0.08210227694566896
coef sex_male: 0.029774243803624468
coef alone_True: -0.05912568318101775
coef embarked_Q: -0.11905958229108671
coef embark_town_Queenstown: -0.11905958229108671
coef embarked_S: -0.20854239888145437
coef embark_town_Southampton: -0.20854239888145437
coef age: -0.27341604107074957
coef class_Third: -0.5925304637524366
coef who_man: -0.8077883127747442
coef adult_male_True: -0.8077883127747442
coef deck_G: -0.8312892557486407
coef parch: -1.845882583708361
coef sibsp: -3.4698627948241976

変数ごとの回帰係数は上記のようになっています。

係数がプラスの場合は、その変数が大きいほどクラス1に分類されやすいということになります。

例えば、deckのEやDにいた人は分類結果が1になりやすい(生存しやすい)ということがわかります。

逆にsibspが1の人はクラスが0に分類されやすい(生存しにくい)ということがわかります。

まとめ

この記事ではscikit-learnを使ったクラス分類をタイタニックのサンプルデータを使って紹介しました。

ロジスティック回帰は機械学習でクラス分類を行う時に良く使うアルゴリズムなので、しっかりと使えるようになりましょう。

また、モデルの学習と予測だけでなく、学習結果を使った変数ごとの重みの分析方法についても紹介しました。

【世界で30万人が受講】データサイエンティストを目指すあなたへ〜データサイエンス25時間ブートキャンプ〜



コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です