Regresión logística: Scikit Learn vs Statsmodels

31

Estoy tratando de entender por qué el resultado de la regresión logística de estas dos bibliotecas da resultados diferentes.

Estoy usando el conjunto de datos del tutorial idre de UCLA , prediciendo en admitbase a gre, gpay rank. rankse trata como variable categórica, por lo que primero se convierte en variable ficticia con rank_1descarte. También se agrega una columna de intercepción.

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

# Output from scikit-learn
model = LogisticRegression(fit_intercept = False)
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]

# Output from statsmodels
logit = sm.Logit(y, X)
logit.fit().params
> Optimization terminated successfully.
     Current function value: 0.573147
     Iterations 6
Intercept      -3.989979
C(rank)[T.2]   -0.675443
C(rank)[T.3]   -1.340204
C(rank)[T.4]   -1.551464
gre             0.002264
gpa             0.804038
dtype: float64

La salida de statsmodelses la misma que se muestra en el sitio web idre, pero no estoy seguro de por qué scikit-learn produce un conjunto diferente de coeficientes. ¿Minimiza alguna función de pérdida diferente? ¿Existe alguna documentación que indique la implementación?

hurrikale
fuente

Respuestas:

28

Su pista para resolver esto debería ser que las estimaciones de los parámetros de la estimación de aprendizaje de scikit sean uniformemente más pequeñas en magnitud que la contraparte de statsmodels. Esto podría llevarlo a creer que scikit-learn aplica algún tipo de regularización de parámetros. Puede confirmar esto leyendo la documentación de scikit-learn .

No hay forma de desactivar la regularización en scikit-learn, pero puede hacerlo ineficaz estableciendo el parámetro de ajuste Cen un gran número. Así es como funciona en su caso:

# module imports
from patsy import dmatrices
import pandas as pd
from sklearn.linear_model import LogisticRegression
import statsmodels.discrete.discrete_model as sm

# read in the data & create matrices
df = pd.read_csv("http://www.ats.ucla.edu/stat/data/binary.csv")
y, X = dmatrices('admit ~ gre + gpa + C(rank)', df, return_type = 'dataframe')

# sklearn output
model = LogisticRegression(fit_intercept = False, C = 1e9)
mdl = model.fit(X, y)
model.coef_

# sm
logit = sm.Logit(y, X)
logit.fit().params
tchakravarty
fuente
¡Muchas gracias por la explicación! Con este resultado regularizado, estaba tratando de duplicar el resultado usando el glmnetpaquete en R, pero no pude obtener el mismo coeficiente. glmnet tiene una función de coste ligeramente diferente en comparación con sklearn , pero incluso si fijo alpha=0en glmnet(es decir, sólo utilice L2-penal) y el conjunto 1/(N*lambda)=C, todavía no consigo el mismo resultado?
hurrikale
Mi intuición es que si divido ambos términos de la función de costo glmnetentre lambday establezco la nueva constante en la fuente del log-verosimilitud, que es 1/(N*lambda)igual a eso en sklearn, las dos funciones de costo se vuelven idénticas, ¿o me estoy perdiendo algo?
hurrikale
@hurrikale Haga una nueva pregunta y vincúlela aquí, y la echaré un vistazo.
tchakravarty
¡Gracias! Publiqué la pregunta aquí .
hurrikale
Creo que la mejor manera de desactivar la regularización en scikit-learn es mediante la configuración penalty='none'.
Nzbuu
3

Otra diferencia es que ha configurado fit_intercept = False, que efectivamente es un modelo diferente. Puede ver que Statsmodel incluye la intercepción. No tener una intercepción seguramente cambia los pesos esperados en las características. Pruebe lo siguiente y vea cómo se compara:

model = LogisticRegression(C=1e9)

brian dalessandro
fuente