ロジスティック回帰:Scikit Learn対glmnet


15

Rのパッケージをsklearn使用してロジスティック回帰ライブラリの結果を複製しようとしていglmnetます。

sklearn

wc12wTw+C=1NログexpyバツTw+c+1

ビネットからglmnet、その実装はわずかに異なるコスト関数を最小化します

ββ0[1N=1Nyβ0+バツTβログ1+eβ0+バツTβ]+λ[α1||β||22/2+α||β||1]

2番目の式を少し調整し、設定して、\ lambda \ min _ {\ beta、\ beta_0} \ frac1 {N \ lambda} \ sum_ {i = 1} ^ N \ left [-y_i(\ beta_0 + x_i ^ T \ beta)+ \ log(1 + e ^ {(\ beta_0 + x_i ^ T \ beta)})\ right] + || \ beta || _2 ^ 2/2α=0

λββ01Nλ=1N[yβ0+バツTβ+ログ1+eβ0+バツTβ]+||β||22/2

\ frac1 {N \ lambda} = Cに設定されている場合sklearn、コスト関数とは\ lambdaの係数だけ異なるため、2つのパッケージから同じ係数推定が期待されていました。しかし、それらは異なります。私は、UCLAのidreのからのデータセットを使用していますチュートリアル予測、に基づいて、と。400個の観測値があるため、C = 1の場合、\ lambda = 0.0025です。λ1Nλ=CadmitgregparankC=1λ=0.0025

#python sklearn
df = pd.read_csv("https://stats.idre.ucla.edu/stat/data/binary.csv")
y, X = dmatrices('admit ~ gre + gpa + C(rank)', df, return_type = 'dataframe')
X.head()
>  Intercept  C(rank)[T.2]  C(rank)[T.3]  C(rank)[T.4]  gre   gpa
0          1             0             1             0  380  3.61
1          1             0             1             0  660  3.67
2          1             0             0             0  800  4.00
3          1             0             0             1  640  3.19
4          1             0             0             1  520  2.93

model = LogisticRegression(fit_intercept = False, C = 1)
mdl = model.fit(X, y)
model.coef_
> array([[-1.35417783, -0.71628751, -1.26038726, -1.49762706,  0.00169198,
     0.13992661]]) 
# corresponding to predictors [Intercept, rank_2, rank_3, rank_4, gre, gpa]


> # R glmnet
> df = fread("https://stats.idre.ucla.edu/stat/data/binary.csv")
> X = as.matrix(model.matrix(admit~gre+gpa+as.factor(rank), data=df))[,2:6]
> y = df[, admit]
> mylogit <- glmnet(X, y, family = "binomial", alpha = 0)
> coef(mylogit, s = 0.0025)
6 x 1 sparse Matrix of class "dgCMatrix"
                    1
(Intercept)      -3.984226893
gre               0.002216795
gpa               0.772048342
as.factor(rank)2 -0.530731081
as.factor(rank)3 -1.164306231
as.factor(rank)4 -1.354160642

R見ることができるように、出力は、正則化なしでロジスティック回帰に何とか近くにあり、ここで。私は何かを見逃したり、明らかに何か間違ったことをしていませんか?

更新:LiblineaRパッケージを使用しRて同じプロセスを実行しようとしましたが、別の異なる推定値セットも取得しました(liblinearのソルバーでもありますsklearn)。

> fit = LiblineaR(X, y, type = 0, cost = 1)
> print(fit)
$TypeDetail
[1] "L2-regularized logistic regression primal (L2R_LR)"
$Type
[1] 0
$W
            gre          gpa as.factor(rank)2 as.factor(rank)3 as.factor(rank)4         Bias
[1,] 0.00113215 7.321421e-06     5.354841e-07     1.353818e-06      9.59564e-07 2.395513e-06

更新2:で標準化をオフにすると、以下glmnetが得られます。

> mylogit <- glmnet(X, y, family = "binomial", alpha = 0, standardize = F)
> coef(mylogit, s = 0.0025)
6 x 1 sparse Matrix of class "dgCMatrix"
                     1
(Intercept)      -2.8180677693
gre               0.0034434192
gpa               0.0001882333
as.factor(rank)2  0.0001268816
as.factor(rank)3 -0.0002259491
as.factor(rank)4 -0.0002028832

これを理解したことがありますか?
ヒューイ

回答:


8

sklearnのロジスティック回帰はデフォルトで入力を標準化しません。これにより、正則化用語の意味が変わります。おそらくglmnetが行います。L2

特に、あなたのgre用語は他の変数よりも非常に大きなスケールにあるため、これは重みに異なる変数を使用する相対的なコストを変更します。

また、機能に明示的なインターセプト用語を含めることにより、モデルのインターセプトを正規化することに注意してください。これは、モデルがすべてのラベルを定数だけシフトしても共変ではなくなることを意味するため、通常は行われません。


glmnet入力の標準化をオフにできますが、推定係数はさらに異なります。上記を参照してください。また、インターセプト項を自動的に含めるsklearnため、明示的にインターセプト項を含めました。glmnetこれは、両方のモデルへの入力が同じであることを確認するためです。
ハリケール

2
@hurrikale glmnetはおそらくインターセプトを正規化していないと思いますが、sklearnはそうです。からインターセプト列を削除し、(デフォルト)にX渡しfit_intercept=TrueますLogisticRegression。しかし、おそらく他にも何かが起こっています。
ドゥーガル

私はあなたが提案したものを試しましたが、係数の異なるセットを得ました:[-1.873, -0.0606, -1.175, -1.378, 0.00182, 0.2435]for sklearn[-2.8181, 0.0001269, -0.0002259, -0.00020288, 0.00344, 0.000188]forのglmnet順に[Intercept, rank_2, rank_3, rank_4, gre, gpa]。私の懸念は、大きさと確率の正/負の影響の両方が異なるため、それらが異なる理由を知らずに、解釈するものを選択することは困難です。また、実装の1つに万が一バグがある場合は、どのバグに依存するかを知ることが特に重要です。
ハリケール

7

Dougalの答えは正解です。インターセプトは正規化されますsklearnが、R では正規化されません。solver='newton-cg'デフォルトのソルバー('liblinear')は常にインターセプトを正規化するため、必ず使用してください。

cf https://github.com/scikit-learn/scikit-learn/issues/6595


設定はsolver='newton-cg'からの結果を作ったsklearnし、statsmodels一貫性のあります。どうもありがとう。
アイリーン

0

またL1_wt=0alphain fit_regularized()call と一緒に引数を使用する必要があります。

このコードstatsmodels

import statsmodels.api as sm
res = sm.GLM(y, X, family=sm.families.Binomial()).fit_regularized(alpha=1/(y.shape[0]*C), L1_wt=0)

は、次のコードと同等ですsklearn

from sklearn import linear_model
clf = linear_model.LogisticRegression(C = C)
clf.fit(X, y)

それが役に立てば幸い!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.