OLS usando statsmodel.formula.api versus statsmodel.api

Alguém pode me explicar a diferença entre ols em statsmodel.formula.api versus ols em statsmodel.api?

Usando os dados de publicidade do texto do ISLR, executei um ols usando ambos e obtive resultados diferentes. Eu então comparei com o LinearRegression do 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_ 

A saída é a seguinte:

 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] 

O método statsmodel.api retorna um parâmetro diferente para TV dos methods statsmodel.formula.api e scikit-learn.

Que tipo de algoritmo ols é o statsmodel.api em execução que produziria um resultado diferente? Alguém tem um link para a documentação que poderia ajudar a responder a essa pergunta?

A diferença é devida à presença de interceptação ou não:

  • em statsmodels.formula.api , similarmente à abordagem R, uma constante é automaticamente adicionada aos seus dados e uma interceptação em
  • em statsmodels.api , você tem que adicionar uma constante você mesmo (veja a documentação aqui ). Tente usar add_constant de statsmodels.api

     x1 = sm.add_constant(x1) 

Chegou a esta questão hoje e queria elaborar a resposta do @ stellasia porque a documentação do statsmodels é talvez um pouco ambígua.

A menos que você esteja usando fórmulas reais de string no estilo R ao instanciar o OLS , você precisa adicionar uma constante (literalmente uma coluna de 1s) sob ambos statsmodels.formulas.api e plain statsmodels.api . @Chetan está usando a formatação em estilo R aqui ( formula='Sales ~ TV' ), então ele não vai se deparar com essa sutileza, mas para pessoas com algum conhecimento em Python, mas sem experiência em R, isso pode ser muito confuso.

Além disso, não importa se você especificou o parâmetro hasconst ao construir o modelo. (Que é meio bobo.) Em outras palavras, a menos que você esteja usando fórmulas de string no estilo R, hasconst é ignorado mesmo que seja suposto

[Indicar] se o RHS inclui uma constante fornecida pelo usuário

porque, nas notas de rodapé

Nenhuma constante é adicionada pelo modelo, a menos que você esteja usando fórmulas.

O exemplo abaixo mostra que tanto .formulas.api quanto .api exigirão um vetor de coluna de 1s adicionado pelo usuário, se não usar fórmulas de string no 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 

Agora lance x e y no Excel e execute Data> Data Analysis> Regression, certificando-se de que “Constant is zero” está desmarcada. Você obterá os seguintes coeficientes:

 Intercept 1.497761024 X Variable 1 0.012073045 X Variable 2 0.623936056 

Agora, tente executar esta regressão em x , não x_with_ones , em statsmodels.formula.api ou statsmodels.api com hasconst definido como None , True ou False . Você verá que em cada um desses 6 cenários, não há interceptação retornada. (Existem apenas 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 ] 

Agora executando as coisas corretamente com um vetor coluna de 1.0 s adicionado ao x . Você pode usar smf aqui, mas não é realmente necessário se você não estiver usando 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]