Python: Sklearn y StatsModels dan respuestas de regresión logística muy diferentes

CorePress2024-01-24  13

Estoy haciendo una regresión logística en un conjunto de datos booleano 0/1 (prediciendo la probabilidad de que una determinada edad le dé un salario superior a una determinada cantidad) y obtengo resultados muy diferentes con sklearn y StatsModels, donde sklearn está muy equivocado.

He establecido la penalización de sklearn en Ninguno y el término de intercepción en falso para que la función sea más similar a StatsModels, pero no veo cómo hacer que sklearn dé una respuesta sensata.

Las líneas grises son los puntos de datos originales en 0 o 1, simplemente reduje la escala de 1 a 0,1 en el gráfico para que sean visibles.

Variables:

# X and Y
X = df.age.values.reshape(-1,1)
X_poly = PolynomialFeatures(degree=4).fit_transform(X)
y_bool = np.array(df.wage.values > 250, dtype = "int")

# Generate a sequence of ages
age_grid = np.arange(X.min(), X.max()).reshape(-1,1)
age_grid_poly =  PolynomialFeatures(degree=4).fit_transform(age_grid)

El código es el siguiente:

# sklearn Model
clf = LogisticRegression(penalty = None, fit_intercept = False,max_iter = 300).fit(X=X_poly, y=y_bool)
preds = clf.predict_proba(age_grid_poly)

# Plot
fig, ax = plt.subplots(figsize=(8,6))
ax.scatter(X ,y_bool/10, s=30, c='grey', marker='|', alpha=0.7)
plt.plot(age_grid, preds[:,1], color = 'r', alpha = 1)
plt.xlabel('Age')
plt.ylabel('Wage')
plt.show()

resultado de sklearn

# StatsModels
log_reg = sm.Logit(y_bool, X_poly).fit()
preds = log_reg.predict(age_grid_poly)
# Plot
fig, ax = plt.subplots(figsize=(8,6))
ax.scatter(X ,y_bool/10, s=30, c='grey', marker='|', alpha=0.7)
plt.plot(age_grid, preds, color = 'r', alpha = 1)
plt.xlabel('Age')
plt.ylabel('Wage')
plt.show()

Resultado de StatsModels



------------------------------------

Esto parece deberse a que la implementación de sklearn depende mucho de la escala (y los términos polinomiales son bastante grandes). Al escalar los datos primero, obtengo cualitativamente el mismo resultado.

# sklearn Model
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

clf = Pipeline([
    ('scale', StandardScaler()),
    ('lr', LogisticRegression(penalty='none', fit_intercept=True, max_iter=1000)),
]).fit(X=X_poly, y=y_bool)
preds = clf.predict_proba(age_grid_poly)

# Plot
fig, ax = plt.subplots(figsize=(8,6))
ax.scatter(X ,y_bool/10, s=30, c='grey', marker='|', alpha=0.7)
plt.plot(age_grid, preds[:,1], color = 'r', alpha = 1)
plt.xlabel('Age')
plt.ylabel('Wage')
plt.show()

Tenga en cuenta que necesitamos establecer fit_intercept=True en este caso, porque StandardScaler elimina la columna constante (convirtiéndola en todo ceros) proveniente de PolynomialFeatures.



------------------------------------

No pude reproducir exactamente los resultados una vez que no tengo el conjunto de datos o las versiones específicas de scikit-learn y statsmodels. Sin embargo, no creo que hayas podido eliminar con éxito el parámetro de regularización en tu código. La documentación indica que debes pasar la cadena 'none', no la constante Ninguno.

Por favor, consulte la documentación de sklearn.linear_model.LogisticRegression:

penalización{'l1', 'l2', 'elasticnet', 'none'}, default='l2' Solía ​​​​para especificar la norma utilizada en la sanción. El 'newton-cg', el 'sag' y Los solucionadores de 'lbfgs' solo admiten penalizaciones de l2. 'elasticnet' es sólo apoyado por el solucionador 'saga'. Si "ninguno" (no respaldado por el solucionador liblinear), no se aplica ninguna regularización.

Creo que es más fácil entender la diferencia investigando el coeficiente, en lugar de utilizar un gráfico. Puedes investigarlo directamente usando la propiedad coef_ para el modelo scikit-learn yparams para el modelo statsmodels.

En términos lógicos, debería esperar que el coeficiente sea menor en el modelo scikit-learn si el parámetro de regularización no está correctamente deshabilitado.

2

1

He probado ambos con penalización = 'none' y un valor C muy grande, pero sigo teniendo el mismo gráfico. Sin embargo, los coeficientes parecen sospechosamente regularizados para sklearn: statsmodel tiene el coeficiente más grande alrededor de 200, mientras que sklearn tiene 0.02 (sklearn versión 0.24.0, statsmodels versión 0.12.1,conjunto de datos aquí si está interesado)

- szantamano

27/03/2021 a las 17:06

Esto podría deberse a las suposiciones que utiliza cada implementación para abordar la no linealidad generada por las características polinómicas. Intenté experimentar ambos modelos solo con la edad IV y configuré todas las demás circunstancias a continuación, y el resultado fue coeficientes similares: LogisticRegression(solver = 'lbfgs', penalización = ' ;ninguno', fit_intercept = False, max_iter = 300).fit(X = X,y = y_bool) Logit(y_bool, X).fit(método = 'lbfgs', maxiter=300, full_output=0, disp=0)

-Daniel Labbe

28/03/2021 a las 18:45

randomThread
javascript - ¿Cómo puedo encontrar el primer número mayor que la constante M?python - Cómo implementar pytest.approx() para clases de datosasp.net mvc - Entity Framework agrega registro dos vecesjavascript: mapea a través de objetos de objeto y envía no duplicadoscss - ¿Cómo puedo cambiar repetidamente el estilo de fondo de un div usando un evento de clic en Javascript?html: uso de consulta de medios para ejecutar