未分類

ロジスティック回帰と確率

ロジスティック回帰を再勉強中です。

ロジスティック回帰(ロジスティックかいき、英: Logistic regression)は、ベルヌーイ分布に従う変数の統計的回帰モデルの一種である。連結関数としてロジットを使用する一般化線形モデル (GLM) の一種でもある。1958年に David Cox が発表した。確率の回帰であり、統計学の分類に主に使われる。医学や社会科学でもよく使われる。[ロジスティック回帰 – Wikipedia]

  • ベルヌーイ分布に従う => 属性Aであるかないか、つまり0 または 1のカテゴリカルな変数の判別に使える
  • 確率の回帰である => 回帰によって、属性Aである確率を求められる

無限空間(-∞, ∞)を区間(0, 1)に写像する [平井有三 はじめてのパターン認識 p89]

\sigma = \frac{1}{1 + exp(-\alpha)}

y = ax + b単純な線形回帰モデルの結果をシグモイド関数で、エイヤと0と1にしちゃうのは理解していたんだけど、そこからでた値がカテゴリの確率になるっていうのがイマイチ腑に落ちていないところです。

scikit-learnにもsklearn.linear_model.LogisticRegressionというロジスティック回帰の機能があって、predict_probaというメソッドを使えば、確率を返してくれます。

とりあえず理論は置いといて実験。

1つの変数によって2つのクラスに分けられるデータセットを用いて、ロジスティック回帰で学習を行い、適切な確率でクラス判別ができているのか確認する。

 

%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression

# サンプル数
N = 1000

# データセットをつくる
# 平均が異なる正規分布2つからデータを作り、その分類を試みる
df = pd.concat([
    # クラス0のデータ(平均-1.5, 分散1)
    pd.DataFrame({
        "class": np.zeros(N),
        "value": np.random.normal(-1.5, 1.0, N)
    }),
    # クラス1のデータ(平均1.5, 分散1)
    pd.DataFrame({
        "class": np.ones(N),
        "value": np.random.normal(1.5, 1.0, N)
    }),
])

# 標準化
mu = df['value'].mean()
sigma = df['value'].std()
df['value_std'] = (df['value'] - mu) / sigma

# 分布の重なり具合をヒストグラムで描画
plt.ylim(0, 500)
plt.hist(df[df['class'] == 0]['value'], range=(-5, 5), bins=20, alpha=0.5)
plt.hist(df[df['class'] == 1]['value'], range=(-5, 5), bins=20, alpha=0.5)
plt.show()

# ロジスティック回帰で学習する
lr = LogisticRegression()
lr.fit(df[['value_std']], df['class'])

# クラスごとに整数区間ごとの割合を見る
# 値をint型に変換
df['num'] = df['value'].astype(int)

# ピボットして、クラスごとに区間の値をカウント
df_result = df.pivot_table(
    values='value',
    index='num',
    columns='class',
    aggfunc=lambda x: len(x.unique())
).fillna(0).apply(lambda x : x/sum(x), axis=1)

# 区間の値からその区間の確率を表示
ary = (np.array(df_result.index).reshape(-1, 1) - mu)/ sigma
df_result['prob'] = lr.predict_proba(ary)[:, 0]
df_result

上記コードは、クラス0(平均 -1.5、分散 1の正規分布)とクラス1(平均1.5、分散1の正規分布)から生成されたデータセットを作った。図に示すと下のようになる。

dist

区間毎ごとのクラス0とクラス1の割合(足して1)と、ロジスティック回帰で計算したクラス0になる確率を示した、表のような結果となった。

クラス クラス0 クラス1 ロジスティック回帰で計算したクラス0になる確率
区間
-5 1.00 0.00 1.00
-4 1.00 0.00 1.00
-3 1.00 0.00 1.00
-2 1.00 0.00 1.00
-1 0.99 0.01 0.95
0 0.48 0.51 0.47
1 0.02 0.98 0.04
2 0.00 1.00 0.00
3 0.00 1.00 0.00
4 0.00 1.00 0.00

クラス0の割合と、ロジスティック回帰で計算したクラス0になる確率が一致するかどうかを確認。変数1つでシンプルなデータセットで、概ね期待した結果になったが、-1〜1の区間で、実際の割合と2〜3%のズレがある結果となった。

変数が増えるとよりブレは大きくなりそう。てか、なんで確率が計算できるの?もう少し勉強が必要。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中