Estou tentando duplicar os resultados da sklearn
biblioteca de regressão logística usando o glmnet
pacote em R.
A partir da documentação dasklearn
regressão logística , ele está tentando minimizar a função de custo sob pena de l2
min w , c 1
Das vinhetas de glmnet
, sua implementação minimiza uma função de custo ligeiramente diferente
Com alguns ajustes na segunda equação, e definindo , λ min β , β 0 1
#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
A R
saída está de alguma forma próxima da regressão logística sem regularização, como pode ser visto aqui . Estou perdendo alguma coisa ou fazendo algo obviamente errado?
Atualização: Eu também tentei usar o LiblineaR
pacote R
para conduzir o mesmo processo, e ainda recebi outro conjunto de estimativas diferente ( liblinear
também é o solucionador 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
Atualização 2: desativar a padronização no glmnet
fornece:
> 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
Respostas:
Especialmente porque o seu
gre
termo está em uma escala tão maior que as outras variáveis, isso alterará os custos relativos do uso das diferentes variáveis para pesos.Observe também que, ao incluir um termo de interceptação explícito nos recursos, você está regularizando a interceptação do modelo. Isso geralmente não é feito, pois significa que seu modelo não é mais covariável para mudar todos os rótulos por uma constante.
fonte
glmnet
permite desativar a padronização das entradas, mas os coeficientes estimados são ainda mais diferentes, veja acima. Além disso, incluí explicitamente o termo de interceptação,sklearn
porqueglmnet
inclui um automaticamente, para garantir que as entradas para os dois modelos sejam as mesmas.X
e passefit_intercept=True
(o padrão) paraLogisticRegression
. Provavelmente há algo mais acontecendo também.[-1.873, -0.0606, -1.175, -1.378, 0.00182, 0.2435]
parasklearn
e[-2.8181, 0.0001269, -0.0002259, -0.00020288, 0.00344, 0.000188]
paraglmnet
em ordem de[Intercept, rank_2, rank_3, rank_4, gre, gpa]
. Minha preocupação é que eles diferem tanto em magnitude quanto em afetar positivamente / negativamente a probabilidade; portanto, sem saber por que eles diferem, é difícil escolher um para interpretar. E se houver algum erro em uma das implementações, é particularmente importante que eu saiba em qual delas confiar.A resposta de Dougal está correta, você regulariza a interceptação em
sklearn
mas não em R. Certifique-se de usar,solver='newton-cg'
pois o solver padrão ('liblinear'
) sempre regulariza a interceptação.cf https://github.com/scikit-learn/scikit-learn/issues/6595
fonte
solver='newton-cg'
fez os resultadossklearn
estatsmodels
consistente. Muito obrigado.Você também deve usar o
L1_wt=0
argumento junto comalpha
nafit_regularized()
chamada.Este código em
statsmodels
:é equivalente ao seguinte código de
sklearn
:Espero que ajude!
fonte