ロジスティック回帰

Rでのロジスティック回帰について復習しましょう。例えばRに

x = c(4,5,17,17,19,19,29,41,45,47,49,54,56,58,70,76,88,88,93,97)
y = c(0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,1,1,1,1)
glm(y ~ x, family=binomial(link="logit"))

と打ち込めば

Call:  glm(formula = y ~ x, family = binomial(link = "logit"))

Coefficients:
(Intercept)            x  
   -3.56668      0.08319  

Degrees of Freedom: 19 Total (i.e. Null);  18 Residual
Null Deviance:	    27.53 
Residual Deviance: 15.19 	AIC: 19.19

と出力されます。これは

\[ y \approx \frac{1}{1 + \exp(-(-3.56668 + 0.08319 x))} \]

という意味です(近似は最小二乗法ではなく最尤推定です)。

ちょっといたずらをしてみましょう。x の値を $1/1000$ にしてみます:

x = x / 1000
glm(y ~ x, family=binomial(link="logit"))

当然ながら,表示の誤差範囲内で x の係数が1000倍になったはずです。

同じことをPythonでやってみましょう。scikit-learnがインストールされているとします:

import numpy as np
from sklearn.linear_model import LogisticRegression

X = np.array([4,5,17,17,19,19,29,41,45,47,49,54,56,58,70,76,88,88,93,97]).reshape(-1,1)
y = np.array([0,0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,1,1,1,1])

model = LogisticRegression().fit(X, y)
print(model.coef_, model.intercept_)

結果は [[0.08308145]] [-3.5620736] で,係数がやや小さめに出たようです。

同じようないたずらとして,X を $1/1000$ にしてみます:

X = X / 1000
model = LogisticRegression().fit(X, y)
print(model.coef_, model.intercept_)

結果は [[0.20155727]] [0.19087727] で,Rとはまったく異なる結果になってしまいました。

この理由は,Rを作った統計屋とscikit-learnを作った機械学習屋の考え方の相違にあるようです。scikit-learnの LogisticRegression() では係数が 0 に近くなるような正則化(regularization)が行われます。ベイズ推定のことばでいえば,係数が 0 に近くなるような事前分布が設定されています。正則化のパラメータ C はデフォルトでは 1 に設定されており,この値が小さいほど強い正則化が行われます。ならば,C に $\infty$ を設定すれば正則化が行われなくなるはずです。やってみましょう:

model = LogisticRegression(C=np.inf).fit(X, y)
print(model.coef_, model.intercept_)

結果は [[83.18706659]] [-3.56667989] で,Rと同じになりました。

このような正則化の是非については Scikit-learn’s Defaults are WrongThe default prior for logistic regression coefficients in Scikit-learn をご覧ください。


Last modified: