スタートページJavaScript他言語Python 目次

ロジスティック回帰・予測 scikit-learn


ロジスティック回帰(Logistic Regression)とは、重相関分析に似た統計分析手法ですが、重相関分析の判別分析がグループ0とグループ1のどちらに属するかの判別関数を求めるのに対して、1になる確率を求めることを目的にしています。

例えば、通常の線形回帰分析である重相関では、過去の研究から、喫煙本数、食生活。病歴など量的・質的要因と、ガンの発病の統計データを用いて、各要因が与える度合いを求めたり、「ガンにかかるグル-プとかからないグループのどちらに属するか」(0か1か)の判別関数を求めることが目的です。 それらの要因を持つ人のガン発病確率を求めようとするものです。
ロジスティック回帰でもそのような分析もできますが、主な用途は、それらの要因を持つ人がガンを発病する確率(1になる確率)を求めることにあります。

重相関では、説明変数は正規分布に従う数量データであることを前提にしていますが、ロジスティック回帰では性別や病歴の有無といった分布には無関係の2値データを扱うのに適しています。しかし、被説明変数は0と1の2値であるという制約があります。

「ロジスティック」回帰の名称については後述します。


ロジスティック回帰による実現確率

# ============== 使用拡張モジュール
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression      # ロジスティック回帰のモデル構築のため

# シグモイド関数
def sigmoid(x):
    y = 1 / (1 + np.exp(-x))
    return y

# ============== 入力データ  [x0,x1,x2, y(正解)]
df = pd.DataFrame([[5, 12, 0,   0], [2, 11, 0,   0], [2, 14, 0,   0], [1, 11, 0,   0], [2, 12, 0,   0],
                   [3, 16, 0,   0], [4, 13, 0,   0], [2, 13, 0,   0], [3, 15, 0,   0], [5, 16, 0,   1],
                   [5, 15, 1,   1], [2, 17, 1,   1], [2, 17, 1,   1], [2, 12, 1,   0], [6, 14, 1,   1],
                   [5, 11, 1,   1], [8, 14, 1,   1], [8, 15, 1,   1], [9, 14, 1,   1], [1, 11, 1,   0],
                   [2, 13, 0,   0], [2, 16, 0,   0], [1, 13, 0,   0], [7, 13, 0,   1], [3, 17, 0,   1],
                   [5, 11, 1,   1], [1, 11, 1,   0], [5, 15, 1,   1], [7, 17, 1,   1], [7, 13, 1,   1]],
                  columns = ['x0','x1','x2','y']
                 )
X = df.drop('y',axis=1)
Y = df.y.to_numpy() 

# ============= ロジスティック回帰
LR = LogisticRegression()
LR.fit(X,Y)

# 判別式の計算
a = LR.coef_[0]
b = LR.intercept_
print("係数:", a)
print("切片:", b)
# 判別式の値
df['yr'] = a[0]*df.x0 + a[1]*df.x1 + a[2]*df.x2 + b

# ============= ジグモイド関数による発生確率(odds)への変換
df['odds'] = sigmoid(df['LR']) 
df['odds-rate'] = df['odds']/(1-df['odds'])
print(df)
print("精度:", LR.score(X,Y))

結果

判別式
    係数: [1.17515699 0.64695875 1.42317334]
    切片: [-13.96031998]
   判別式:yr = 1.175*x0 + 0.647*x1 + 1.423*x2 - 13.96

df の内容
          入力データ        分析結果
        x0  x1  x2    y        yr      odds    odds-rate
    0    5  12   0    0      -0.321   0.420     0.725401
    1    2  11   0    0      -4.493   0.011     0.011182 ★
    2    2  14   0    0      -2.553   0.072     0.077880
    3    1  11   0    0      -5.669   0.003     0.003453
    4    2  12   0    0      -3.847   0.021     0.021354
    …
    25   5  11   1    1       0.455   0.612     1.576464
    26   1  11   1    0      -4.245   0.014     0.014329
    27   5  15   1    1       3.043   0.954    20.968464
    28   7  17   1    1       6.687   0.999   802.114277 ★
    29   7  13   1    1       4.099   0.984    60.305064

    精度: 1.0

結果出力の説明

yr 判別式の値
    通常の重回帰での判別式と同じ性格のものです。
  この値が負なら0グループ、正なら1グループだと判別します。
  上の例では判別結果がすべて y と一致したので、「精度=1」になりました。

odds 実現確率
  ロジスティック回帰の目的は、判別ではなく、実現確率(y=1 となる確率)を求めることにあります。
  この例では、28はほぼ間違いなくグループになるし、1では1になることは稀だとなります。
  この実現確率をオッズといいます。
  これを計算するための手段が LogisticRegression、sigmoid です。その概要は後述します。
odds-rate オッズ比
  odds/(1-odds) すなわち「実現する確率/実現しない確率」です。
    オッズ比は医学の臨床試験の結果を示す方法や競馬の当選支払の算出方法などで広く用いられています。

ロジスティック回帰の概要

ロジスティック回帰の目的は実現確率を求めることにあります。
通常の重回帰による線形回帰(判別式)では、図の黒い直線のようになります。これを確率の0~1の範囲に変換する方法はいろいろありますが、その代表的なのが、図の赤い曲線に変換する方法です。このような曲線はロジスティック曲線(群)と呼ばれます。「ロジスティック回帰」というのはそのためです。

シグモイド(sigmoid)曲線は、ロジスティック曲線の最も単純な形式の一つです。ここではそれを sigmoid(x) として定義しましたが、このように単純な式です。

線形回帰(判別式)を求めるのは重回帰とほぼ同じだといいましたが、かなり乱暴な表現です。
これには、LogisticRegression を用います。ここでは LR = LogisticRegression() としましたが、多様なパラメタ指定があり、それによりモデル(計算の方法)がいろいろと変化するのです。実際には入力データの特徴や分析の目的により設定する必要があります。
パラメタと省略時解釈を説明なしに(私はほとんど理解していない)掲げます。

    LogisticRegression(
        C=1.0,
        class_weight=None,
        dual=False,
        fit_intercept=True,
        intercept_scaling=1,
        l1_ratio=None,
        max_iter=100,
        multi_class='auto',
        n_jobs=None,
        penalty='l2',
        random_state=None,
        solver='lbfgs',
        tol=0.0001,
        verbose=0,
        warm_start=False
    )

ロジスティック回帰による予測

教師あり機械学習の一つです。入力データを学習用(train)と予測(テスト)用(test)に分割し、学習用データからモデルを作成し、このモデルにより予測データのオッズ(実現確率)やオッズ比を計算します。

# ============== 使用拡張モジュール
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression      # ロジスティック回帰のモデル構築のため


# シグモイド関数
def sigmoid(x):
    y = 1 / (1 + np.exp(-x))
    return y

# ============== 入力データ  [x1,x2,x3, y]
df = pd.DataFrame([[5, 12, 0,   0], [2, 11, 0,   0], [2, 14, 0,   0], [1, 11, 0,   0], [2, 12, 0,   0],
                   [3, 16, 0,   0], [4, 13, 0,   0], [2, 13, 0,   0], [3, 15, 0,   0], [5, 16, 0,   1],
                   [5, 15, 1,   1], [2, 17, 1,   1], [2, 17, 1,   1], [2, 12, 1,   0], [6, 14, 1,   1],
                   [5, 11, 1,   1], [8, 14, 1,   1], [8, 15, 1,   1], [9, 14, 1,   1], [1, 11, 1,   0],
                   [2, 13, 0,   0], [2, 16, 0,   0], [1, 13, 0,   0], [7, 13, 0,   1], [3, 17, 0,   1],
                   [5, 11, 1,   1], [1, 11, 1,   0], [5, 15, 1,   1], [7, 17, 1,   1], [7, 13, 1,   1]],
                  columns = ['x0','x1','x2','y']
                 )

# ======== 機械学習用データに変換
#   本来はランダムに分割するのだが、ここでは説明の都合から事前に分割した

df_train = df.loc[ 0:19]              # 前半の20件を学習用データ(train)とする
X_train  = df_train.drop('y',axis=1)
Y_train  = df_train.y

df_test = df.loc[20:29]              # 後半の10件を予測用データ(test)とする
X_test  = df_test.drop('y',axis=1)
Y_test  = df_test.y

# =================== ロジスティック回帰
LR = LogisticRegression()

# 学習用データでモデル作成
LR.fit(X_train, Y_train)

# モデル精度を評価 ここで判別式が作成される
LR.score(X_train, Y_train)

# 判別式に予測用データを入れて判別式の値 yr を作成
a = LR.coef_[0]
b = LR.intercept_
print("係数:", a)
print("切片:", b)
df_test['yr'] = a[0]*df_test.x0 + a[1]*df_test.x1 + a[2]*df_test.x2 + b

# yr が負なら0、正なら1と判別して Y_pred を作成
Y_pred = LR.predict(X_test)  # あえて判別式を明示せずに、これで計算できる
df_test['pred'] = Y_pred

# ============= ジグモイド関数による発生確率(odds)への変換
df_test['odds'] = sigmoid(df_test['yr']) 
df_test['odds-rate'] = df_test['odds']/(1-df_test['odds'])

print(df_test)

# ============= 結果の評価尺度
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score 

print('confusion matrix = \n', confusion_matrix(Y_test, Y_pred))
print('accuracy = ',           accuracy_score(  Y_test, Y_pred))
print('precision = ',          precision_score( Y_test, Y_pred))
print('recall = ',             recall_score(    Y_test, Y_pred))
print('f1 score = ',           f1_score(        Y_test, Y_pred))

結果と説明

判別式
    係数: [0.90178196 0.62620708 1.27798779]
    切片: [-12.93784464]
    判別式 yr = 0.902*x0 + 0.626*x1 + 1.278*x2 - 12.94
        # 「実現確率」の結果とやや違うのは前半の20データだけで計算したから

df_test
          入力データ          分析結果                 注記
        x0  x1  x2    y        yr   pred   odds    odds-rate  
    20   2  13   0    0      -2.993   0    0.048    0.050107      TN
    21   2  16   0    0      -1.115   0    0.247    0.327926      TN
    22   1  13   0    0      -3.895   0    0.020    0.020336      TN
    23   7  13   0    1       1.515   1    0.820    4.550882      TP
    24   3  17   0    1       0.413   1    0.602    1.511378      TP
    25   5  11   1    1      -0.263   0    0.435    0.768996  × FN
    26   1  11   1    0      -3.867   0    0.020    0.020863      TN
    27   5  15   1    1       2.242   1    0.904    9.413635      TP
    28   7  17   1    1       5.298   1    0.995  199.963972      TP
    29   7  13   1    1       2.793   1    0.942   16.334981      TP

結果の評価尺度
    df_test のデータ数が大のときは上の表を表示・分析できないので、次の尺度で判断する
  confusion matrix(混同行列)
     [[4 0]      #  [[TN FP]    
      [1 5]]     #   [FN TP]]
                 # TN(True Negative、 真陰性)y=0 で正しく pred=0 に分類されたデータ数    
                 # FP(False Positive、偽陽性)y=0 だが誤って pred=1 に分類されたデータ数
                 # FN(False Negative、偽陰性)y=1 だが誤って pred=0 に分類されたデータ数
                 # TP(True Positive、 真陽性)y=1 で正しく pred=1 に分類されたデータ数
  accuracy(正解率)
  0.9  # (TP+TN)/(TP+FN+FP+TN) 全体のうち y=pred になった割合(9/10)
  precision(適合率)
    1.0   # TP/(TP+FP) クラス1に分類されたデータのうち、実際にクラス1であるデータ数の割合
  recall(再現率)
    0.833 # TP/(TP+FN) 実際にクラス1であるデータのうち、クラス1に分類されたデータ数の割合
  f1 score (F1スコア)
    0.909 # 適合率と再現率の調和平均。適合率と再現率のバランスを評価するための指標