Wielokrotna regresja liniowa w Pythonie

129

Nie mogę znaleźć żadnych bibliotek Pythona, które wykonują regresję wielokrotną. Jedyne, co widzę, to tylko prosta regresja. Muszę dokonać regresji mojej zmiennej zależnej (y) względem kilku zmiennych niezależnych (x1, x2, x3 itd.).

Na przykład z tymi danymi:

print 'y        x1      x2       x3       x4      x5     x6       x7'
for t in texts:
    print "{:>7.1f}{:>10.2f}{:>9.2f}{:>9.2f}{:>10.2f}{:>7.2f}{:>7.2f}{:>9.2f}" /
   .format(t.y,t.x1,t.x2,t.x3,t.x4,t.x5,t.x6,t.x7)

(wyjście powyżej :)

      y        x1       x2       x3        x4     x5     x6       x7
   -6.0     -4.95    -5.87    -0.76     14.73   4.02   0.20     0.45
   -5.0     -4.55    -4.52    -0.71     13.74   4.47   0.16     0.50
  -10.0    -10.96   -11.64    -0.98     15.49   4.18   0.19     0.53
   -5.0     -1.08    -3.36     0.75     24.72   4.96   0.16     0.60
   -8.0     -6.52    -7.45    -0.86     16.59   4.29   0.10     0.48
   -3.0     -0.81    -2.36    -0.50     22.44   4.81   0.15     0.53
   -6.0     -7.01    -7.33    -0.33     13.93   4.32   0.21     0.50
   -8.0     -4.46    -7.65    -0.94     11.40   4.43   0.16     0.49
   -8.0    -11.54   -10.03    -1.03     18.18   4.28   0.21     0.55

Jak mógłbym je cofnąć w Pythonie, aby uzyskać wzór regresji liniowej:

Y = a1x1 + a2x2 + a3x3 + a4x4 + a5x5 + a6x6 + + a7x7 + c

Zach
źródło
nie jesteś ekspertem, ale jeśli zmienne są niezależne, czy nie możesz po prostu przeprowadzić prostej regresji dla każdej z nich i zsumować wynik?
Hugh Bothwell,
8
@HughBothwell Nie możesz jednak zakładać, że zmienne są niezależne. W rzeczywistości, jeśli zakładasz, że zmienne są niezależne, możesz potencjalnie nieprawidłowo modelować swoje dane. Innymi słowy, odpowiedzi Ymogą być ze sobą skorelowane, ale założenie niezależności nie pozwala dokładnie modelować zbioru danych.
hlin117
@HughBothwell, przepraszam, jeśli to pytanie dum, ale dlaczego ma to znaczenie, czy surowe zmienne funkcji x_i są niezależne, czy nie? Jak to wpływa na predyktor (= model)?
Charlie Parker

Odpowiedzi:

100

sklearn.linear_model.LinearRegression zrobię to:

from sklearn import linear_model
clf = linear_model.LinearRegression()
clf.fit([[getattr(t, 'x%d' % i) for i in range(1, 8)] for t in texts],
        [t.y for t in texts])

Wtedy clf.coef_będą miały współczynniki regresji.

sklearn.linear_model ma również podobne interfejsy do wykonywania różnego rodzaju regularyzacji regresji.

Dougal
źródło
2
Zwraca to błąd przy pewnych danych wejściowych . Czy są dostępne inne rozwiązania?
Zach,
@Dougal czy sklearn.linear_model.LinearRegression może być również używany do ważonej regresji wielowymiarowej?
user961627
1
Aby dopasować stały termin: clf = linear_model.LinearRegression (fit_intercept = True)
Imran,
2
Kontynuuj, czy wiesz, jak uzyskać poziom pewności za pomocą sklearn.linear_model.LinearRegression? Dzięki.
Huanian Zhang
1
@HuanianZhang co masz na myśli mówiąc o poziomie zaufania? Jeśli chcesz mieć współczynnik determinacji, scoremetoda to zrobi; sklearn.metricsma inne kryteria oceny modelu. Jeśli chcesz czegoś takiego jak w odpowiedzi Akavalla, modele statystyczne mają więcej diagnostyki podobnej do R.
Dougal
60

Oto mała praca, którą stworzyłem. Sprawdziłem R i działa poprawnie.

import numpy as np
import statsmodels.api as sm

y = [1,2,3,4,3,4,5,4,5,5,4,5,4,5,4,5,6,5,4,5,4,3,4]

x = [
     [4,2,3,4,5,4,5,6,7,4,8,9,8,8,6,6,5,5,5,5,5,5,5],
     [4,1,2,3,4,5,6,7,5,8,7,8,7,8,7,8,7,7,7,7,7,6,5],
     [4,1,2,5,6,7,8,9,7,8,7,8,7,7,7,7,7,7,6,6,4,4,4]
     ]

def reg_m(y, x):
    ones = np.ones(len(x[0]))
    X = sm.add_constant(np.column_stack((x[0], ones)))
    for ele in x[1:]:
        X = sm.add_constant(np.column_stack((ele, X)))
    results = sm.OLS(y, X).fit()
    return results

Wynik:

print reg_m(y, x).summary()

Wynik:

                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       0.535
Model:                            OLS   Adj. R-squared:                  0.461
Method:                 Least Squares   F-statistic:                     7.281
Date:                Tue, 19 Feb 2013   Prob (F-statistic):            0.00191
Time:                        21:51:28   Log-Likelihood:                -26.025
No. Observations:                  23   AIC:                             60.05
Df Residuals:                      19   BIC:                             64.59
Df Model:                           3                                         
==============================================================================
                 coef    std err          t      P>|t|      [95.0% Conf. Int.]
------------------------------------------------------------------------------
x1             0.2424      0.139      1.739      0.098        -0.049     0.534
x2             0.2360      0.149      1.587      0.129        -0.075     0.547
x3            -0.0618      0.145     -0.427      0.674        -0.365     0.241
const          1.5704      0.633      2.481      0.023         0.245     2.895

==============================================================================
Omnibus:                        6.904   Durbin-Watson:                   1.905
Prob(Omnibus):                  0.032   Jarque-Bera (JB):                4.708
Skew:                          -0.849   Prob(JB):                       0.0950
Kurtosis:                       4.426   Cond. No.                         38.6

pandas zapewnia wygodny sposób uruchamiania OLS, jak podano w tej odpowiedzi:

Uruchom regresję OLS z ramką danych Pandas

Akavall
źródło
18
reg_mFunkcja jest niepotrzebnie skomplikowane. x = np.array(x).T, x = sm.add_constant(x)I results = sm.OLS(endog=y, exog=x).fit()to wystarczy.
cd98
1
To fajne narzędzie. Wystarczy zadać jedno pytanie: w tym przypadku wartość t jest poza przedziałem ufności 95,5%, więc oznacza to, że to dopasowanie w ogóle nie jest dokładne, albo jak to wyjaśnić?
Huanian Zhang
2
Właśnie zauważyłeś, że twoje x1, x2, x3 są w odwrotnej kolejności na twojej oryginalnej liście predyktorów, tj. X = [x3, x2, x1]?
sophiadw
@sophiadw możesz po prostu dodać x = x[::-1]w definicji funkcji, aby uzyskać odpowiednią kolejność
Ashrith
@HuanianZhang "wartość t" to tylko, o ile odchyleń standardowych współczynnik jest od zera, podczas gdy 95% CI jest w przybliżeniu coef +- 2 * std err(w rzeczywistości rozkład t Studenta sparametryzowany stopniami swobody reszt). tj. większe bezwzględne wartości t oznaczają CI dalej od zera, ale nie należy ich bezpośrednio porównywać. wyjaśnienie jest trochę spóźnione, ale mam nadzieję, że komuś się przyda
Sam Mason
47

Właśnie w celu wyjaśnienia, przykład dałeś jest wielokrotnością regresja liniowa, nie wieloczynnikowej regresji liniowej odnoszą. Różnica :

Najprostszy przypadek pojedynczej skalarnej zmiennej predykcyjnej x i pojedynczej skalarnej zmiennej odpowiedzi y jest znany jako prosta regresja liniowa. Rozszerzenie na zmienne predykcyjne o wartościach wielokrotnych i / lub wektorów (oznaczane przez duże X) jest znane jako wielokrotna regresja liniowa, znana również jako regresja liniowa wielu zmiennych. Prawie wszystkie rzeczywiste modele regresji obejmują wiele predyktorów, a podstawowe opisy regresji liniowej są często formułowane za pomocą modelu regresji wielorakiej. Należy jednak zauważyć, że w tych przypadkach zmienna odpowiedzi y nadal jest skalarem. Inny termin wielowymiarowa regresja liniowa odnosi się do przypadków, w których y jest wektorem, tj. To samo co ogólna regresja liniowa.

W skrócie:

  • wielokrotna regresja liniowa: odpowiedź y jest skalarem.
  • wielowymiarowa regresja liniowa: odpowiedź y jest wektorem.

(Inne źródło .)

Franck Dernoncourt
źródło
5
Może to być przydatna informacja, ale nie widzę odpowiedzi na pytanie.
Akavall
7
@Akavall używając poprawnej terminologii to pierwszy krok do znalezienia odpowiedzi.
Franck Dernoncourt
1
@FranckDernoncourt ale wartość Y OP JEST wektorem?
alwaysaskingquestions
@FranckDernoncourt: „użycie właściwej terminologii jest pierwszym krokiem do znalezienia odpowiedzi” . Świetnie, więc oboje możemy się zgodzić: to samo w sobie nie jest w rzeczywistości odpowiedzią. Użytkownicy powinni mieć możliwość rozwiązania swojego problemu bezpośrednio na podstawie odpowiedzi, bez konieczności wyszukiwania innych zasobów .
Mac
28

Możesz użyć numpy.linalg.lstsq :

import numpy as np
y = np.array([-6,-5,-10,-5,-8,-3,-6,-8,-8])
X = np.array([[-4.95,-4.55,-10.96,-1.08,-6.52,-0.81,-7.01,-4.46,-11.54],[-5.87,-4.52,-11.64,-3.36,-7.45,-2.36,-7.33,-7.65,-10.03],[-0.76,-0.71,-0.98,0.75,-0.86,-0.50,-0.33,-0.94,-1.03],[14.73,13.74,15.49,24.72,16.59,22.44,13.93,11.40,18.18],[4.02,4.47,4.18,4.96,4.29,4.81,4.32,4.43,4.28],[0.20,0.16,0.19,0.16,0.10,0.15,0.21,0.16,0.21],[0.45,0.50,0.53,0.60,0.48,0.53,0.50,0.49,0.55]])
X = X.T # transpose so input vectors are along the rows
X = np.c_[X, np.ones(X.shape[0])] # add bias term
beta_hat = np.linalg.lstsq(X,y)[0]
print beta_hat

Wynik:

[ -0.49104607   0.83271938   0.0860167    0.1326091    6.85681762  22.98163883 -41.08437805 -19.08085066]

Możesz zobaczyć szacowaną wydajność za pomocą:

print np.dot(X,beta_hat)

Wynik:

[ -5.97751163,  -5.06465759, -10.16873217,  -4.96959788,  -7.96356915,  -3.06176313,  -6.01818435,  -7.90878145,  -7.86720264]
Imran
źródło
czy mogę wiedzieć, jaka jest różnica między print np.dot (X, beta_hat) ... i mod_wls = sm.WLS (y, X, weights = weights) res = mod_wls.fit () predsY = res.predict () one all zwraca wynik Y
dd90p,
13

Użyj scipy.optimize.curve_fit. I to nie tylko do liniowego dopasowania.

from scipy.optimize import curve_fit
import scipy

def fn(x, a, b, c):
    return a + b*x[0] + c*x[1]

# y(x0,x1) data:
#    x0=0 1 2
# ___________
# x1=0 |0 1 2
# x1=1 |1 2 3
# x1=2 |2 3 4

x = scipy.array([[0,1,2,0,1,2,0,1,2,],[0,0,0,1,1,1,2,2,2]])
y = scipy.array([0,1,2,1,2,3,2,3,4])
popt, pcov = curve_fit(fn, x, y)
print popt
Volodimir Kopey
źródło
8

Po przekonwertowaniu danych na pandas dataframe ( df),

import statsmodels.formula.api as smf
lm = smf.ols(formula='y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7', data=df).fit()
print(lm.params)

Termin przechwycenia jest uwzględniony domyślnie.

Więcej przykładów znajdziesz w tym notatniku .

canary_in_the_data_mine
źródło
Ten notatnik jest niesamowity. pokazuje, jak cofnąć wiele niezależnych zmiennych (x1, x2, x3 ...) do Y za pomocą zaledwie 3 linii kodu i używając scikit learn.
jxn
@canary_in_the_data_mine dzięki za notatnik. jak wykreślić regresję liniową, która ma wiele cech? Nie mogłem znaleźć w zeszycie. wszelkie wskazówki będą bardzo mile widziane. - Dzięki
Jai Prakash
Czy dodaje punkt przecięcia, ponieważ musimy dodać punkt przecięcia, przekazując smf.add_intercept () jako parametr do ols ()
bluedroid
4

Myślę, że to najłatwiejszy sposób na dokończenie tej pracy:

from random import random
from pandas import DataFrame
from statsmodels.api import OLS
lr = lambda : [random() for i in range(100)]
x = DataFrame({'x1': lr(), 'x2':lr(), 'x3':lr()})
x['b'] = 1
y = x.x1 + x.x2 * 2 + x.x3 * 3 + 4

print x.head()

         x1        x2        x3  b
0  0.433681  0.946723  0.103422  1
1  0.400423  0.527179  0.131674  1
2  0.992441  0.900678  0.360140  1
3  0.413757  0.099319  0.825181  1
4  0.796491  0.862593  0.193554  1

print y.head()

0    6.637392
1    5.849802
2    7.874218
3    7.087938
4    7.102337
dtype: float64

model = OLS(y, x)
result = model.fit()
print result.summary()

                            OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       1.000
Model:                            OLS   Adj. R-squared:                  1.000
Method:                 Least Squares   F-statistic:                 5.859e+30
Date:                Wed, 09 Dec 2015   Prob (F-statistic):               0.00
Time:                        15:17:32   Log-Likelihood:                 3224.9
No. Observations:                 100   AIC:                            -6442.
Df Residuals:                      96   BIC:                            -6431.
Df Model:                           3                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [95.0% Conf. Int.]
------------------------------------------------------------------------------
x1             1.0000   8.98e-16   1.11e+15      0.000         1.000     1.000
x2             2.0000   8.28e-16   2.41e+15      0.000         2.000     2.000
x3             3.0000   8.34e-16    3.6e+15      0.000         3.000     3.000
b              4.0000   8.51e-16    4.7e+15      0.000         4.000     4.000
==============================================================================
Omnibus:                        7.675   Durbin-Watson:                   1.614
Prob(Omnibus):                  0.022   Jarque-Bera (JB):                3.118
Skew:                           0.045   Prob(JB):                        0.210
Kurtosis:                       2.140   Cond. No.                         6.89
==============================================================================
xmduhan
źródło
4

Wielokrotna regresja liniowa może być obsługiwana za pomocą biblioteki sklearn, jak wspomniano powyżej. Używam instalacji Anaconda Pythona 3.6.

Utwórz model w następujący sposób:

from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X, y)

# display coefficients
print(regressor.coef_)
Eric C. Bohn
źródło
3

Możesz użyć numpy.linalg.lstsq

Moukden
źródło
6
Jak możesz tego użyć, aby uzyskać współczynniki regresji wieloczynnikowej? Widzę tylko, jak zrobić prostą regresję ... i nie wiem, jak obliczyć współczynniki ...
Zach
1

Możesz użyć poniższej funkcji i przekazać jej DataFrame:

def linear(x, y=None, show=True):
    """
    @param x: pd.DataFrame
    @param y: pd.DataFrame or pd.Series or None
              if None, then use last column of x as y
    @param show: if show regression summary
    """
    import statsmodels.api as sm

    xy = sm.add_constant(x if y is None else pd.concat([x, y], axis=1))
    res = sm.OLS(xy.ix[:, -1], xy.ix[:, :-1], missing='drop').fit()

    if show: print res.summary()
    return res
Alfa
źródło
1

Scikit-learn to biblioteka uczenia maszynowego dla Pythona, która może wykonać to zadanie za Ciebie. Po prostu zaimportuj moduł sklearn.linear_model do swojego skryptu.

Znajdź szablon kodu dla wielokrotnej regresji liniowej za pomocą sklearn w Pythonie:

import numpy as np
import matplotlib.pyplot as plt #to plot visualizations
import pandas as pd

# Importing the dataset
df = pd.read_csv(<Your-dataset-path>)
# Assigning feature and target variables
X = df.iloc[:,:-1]
y = df.iloc[:,-1]

# Use label encoders, if you have any categorical variable
from sklearn.preprocessing import LabelEncoder
labelencoder = LabelEncoder()
X['<column-name>'] = labelencoder.fit_transform(X['<column-name>'])

from sklearn.preprocessing import OneHotEncoder
onehotencoder = OneHotEncoder(categorical_features = ['<index-value>'])
X = onehotencoder.fit_transform(X).toarray()

# Avoiding the dummy variable trap
X = X[:,1:] # Usually done by the algorithm itself

#Spliting the data into test and train set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y, random_state = 0, test_size = 0.2)

# Fitting the model
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X_train, y_train)

# Predicting the test set results
y_pred = regressor.predict(X_test)

Otóż ​​to. Możesz użyć tego kodu jako szablonu do implementowania wielokrotnej regresji liniowej w dowolnym zbiorze danych. Aby lepiej zrozumieć przykład, odwiedź: Regresja liniowa z przykładem

kowsalya_ckar
źródło
0

Oto alternatywna i podstawowa metoda:

from patsy import dmatrices
import statsmodels.api as sm

y,x = dmatrices("y_data ~ x_1 + x_2 ", data = my_data)
### y_data is the name of the dependent variable in your data ### 
model_fit = sm.OLS(y,x)
results = model_fit.fit()
print(results.summary())

Zamiast sm.OLSciebie możesz również użyć sm.Logitlub sm.Probiti itp.

nowicjusz
źródło