OLS usando statsmodel.formula.api contra statsmodel.api

¿Puede alguien explicarme la diferencia entre ols en statsmodel.formula.api versus ols en statsmodel.api?

Usando los datos de publicidad del texto ISLR, corrí un historial usando ambos, y obtuve diferentes resultados. Luego comparé con la regresión lineal de scikit-learn.

import numpy as np import pandas as pd import statsmodels.formula.api as smf import statsmodels.api as sm from sklearn.linear_model import LinearRegression df = pd.read_csv("C:\...\Advertising.csv") x1 = df.loc[:,['TV']] y1 = df.loc[:,['Sales']] print "Statsmodel.Formula.Api Method" model1 = smf.ols(formula='Sales ~ TV', data=df).fit() print model1.params print "\nStatsmodel.Api Method" model2 = sm.OLS(y1, x1) results = model2.fit() print results.params print "\nSci-Kit Learn Method" model3 = LinearRegression() model3.fit(x1, y1) print model3.coef_ print model3.intercept_ 

La salida es la siguiente:

 Statsmodel.Formula.Api Method Intercept 7.032594 TV 0.047537 dtype: float64 Statsmodel.Api Method TV 0.08325 dtype: float64 Sci-Kit Learn Method [[ 0.04753664]] [ 7.03259355] 

El método statsmodel.api devuelve un parámetro diferente para TV desde statsmodel.formula.api y los métodos scikit-learn.

¿Qué tipo de algoritmo ols está ejecutando statsmodel.api que produciría un resultado diferente? ¿Alguien tiene un enlace a la documentación que pueda ayudar a responder esta pregunta?

    La diferencia se debe a la presencia de intercepción o no:

    • En statsmodels.formula.api , al igual que en el enfoque de R, se agrega automáticamente una constante a sus datos y se statsmodels.formula.api una intersección en
    • En statsmodels.api , debe agregar una constante (vea la documentación aquí ). Intenta usar add_constant desde statsmodels.api

       x1 = sm.add_constant(x1) 

    Encontré este tema hoy y quería elaborar la respuesta de @stellasia porque la documentación de statsmodels es quizás un poco ambigua.

    A menos que esté utilizando fórmulas de cadenas reales de estilo R al crear una instancia de OLS , debe agregar una constante (literalmente una columna de 1s) tanto en statsmodels.formulas.api como en statsmodels.formulas.api statsmodels.api . @Chetan está usando el formato de estilo R aquí ( formula='Sales ~ TV' ), por lo que no se encontrará con esta sutileza, pero para las personas con algún conocimiento de Python pero sin antecedentes en R, esto podría ser muy confuso.

    Además, no importa si especifica el parámetro hasconst al construir el modelo. (Lo que es un poco tonto). En otras palabras, a menos que esté utilizando fórmulas de cadena de estilo R, hasconst se ignora aunque se supone que

    [Indique] si el RHS incluye una constante suministrada por el usuario

    Porque, en las notas al pie.

    El modelo no agrega ninguna constante a menos que esté utilizando fórmulas.

    El ejemplo a continuación muestra que tanto .formulas.api como .api requerirán un vector de columna agregado por el usuario de 1s si no se utilizan fórmulas de cadena de estilo R.

     # Generate some relational data np.random.seed(123) nobs = 25 x = np.random.random((nobs, 2)) x_with_ones = sm.add_constant(x, prepend=False) beta = [.1, .5, 1] e = np.random.random(nobs) y = np.dot(x_with_ones, beta) + e 

    Ahora lance y en Excel y ejecute Datos> Análisis de datos> Regresión, asegurándose de que la “Constante es cero” no esté marcada. Obtendrás los siguientes coeficientes:

     Intercept 1.497761024 X Variable 1 0.012073045 X Variable 2 0.623936056 

    Ahora, intente ejecutar esta regresión en x , no x_with_ones , en statsmodels.formula.api o statsmodels.api con hasconst establecido en None , True o False . Verá que en cada uno de esos 6 escenarios, no se devuelve ninguna intercepción. (Solo hay 2 parámetros).

     import statsmodels.formula.api as smf import statsmodels.api as sm print('smf models') print('-' * 10) for hc in [None, True, False]: model = smf.OLS(endog=y, exog=x, hasconst=hc).fit() print(model.params) # smf models # ---------- # [ 1.46852293 1.8558273 ] # [ 1.46852293 1.8558273 ] # [ 1.46852293 1.8558273 ] 

    Ahora ejecutando las cosas correctamente con un vector de columna de 1.0 s agregado a x . Puedes usar smf aquí, pero realmente no es necesario si no estás utilizando fórmulas.

     print('sm models') print('-' * 10) for hc in [None, True, False]: model = sm.OLS(endog=y, exog=x_with_ones, hasconst=hc).fit() print(model.params) # sm models # ---------- # [ 0.01207304 0.62393606 1.49776102] # [ 0.01207304 0.62393606 1.49776102] # [ 0.01207304 0.62393606 1.49776102]