Scikit-learn LinearRegression에서 p- 값 (의의) 찾기


154

각 계수의 p- 값 (의의)을 어떻게 찾을 수 있습니까?

lm = sklearn.linear_model.LinearRegression()
lm.fit(x,y)

2
아니 대답,하지만 어쩌면 다른 사람에 대한 답변 : scipy이 linregression에 pvalues을 제공 docs.scipy.org/doc/scipy-0.14.0/reference/generated/...
DaveRGP

1 차원과 1 차원에 대해서만 작동합니다.
Richard Liang

답변:


162

이것은 일종의 과잉이지만 가자. 먼저 statsmodel을 사용하여 p- 값이 무엇인지 확인하십시오.

import pandas as pd
import numpy as np
from sklearn import datasets, linear_model
from sklearn.linear_model import LinearRegression
import statsmodels.api as sm
from scipy import stats

diabetes = datasets.load_diabetes()
X = diabetes.data
y = diabetes.target

X2 = sm.add_constant(X)
est = sm.OLS(y, X2)
est2 = est.fit()
print(est2.summary())

그리고 우리는 얻는다

                         OLS Regression Results                            
==============================================================================
Dep. Variable:                      y   R-squared:                       0.518
Model:                            OLS   Adj. R-squared:                  0.507
Method:                 Least Squares   F-statistic:                     46.27
Date:                Wed, 08 Mar 2017   Prob (F-statistic):           3.83e-62
Time:                        10:08:24   Log-Likelihood:                -2386.0
No. Observations:                 442   AIC:                             4794.
Df Residuals:                     431   BIC:                             4839.
Df Model:                          10                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const        152.1335      2.576     59.061      0.000     147.071     157.196
x1           -10.0122     59.749     -0.168      0.867    -127.448     107.424
x2          -239.8191     61.222     -3.917      0.000    -360.151    -119.488
x3           519.8398     66.534      7.813      0.000     389.069     650.610
x4           324.3904     65.422      4.958      0.000     195.805     452.976
x5          -792.1842    416.684     -1.901      0.058   -1611.169      26.801
x6           476.7458    339.035      1.406      0.160    -189.621    1143.113
x7           101.0446    212.533      0.475      0.635    -316.685     518.774
x8           177.0642    161.476      1.097      0.273    -140.313     494.442
x9           751.2793    171.902      4.370      0.000     413.409    1089.150
x10           67.6254     65.984      1.025      0.306     -62.065     197.316
==============================================================================
Omnibus:                        1.506   Durbin-Watson:                   2.029
Prob(Omnibus):                  0.471   Jarque-Bera (JB):                1.404
Skew:                           0.017   Prob(JB):                        0.496
Kurtosis:                       2.726   Cond. No.                         227.
==============================================================================

좋아, 이것을 재현하자. Matrix Algebra를 사용하여 선형 회귀 분석을 거의 재현하기 때문에 일종의 과잉입니다. 그러나 도대체.

lm = LinearRegression()
lm.fit(X,y)
params = np.append(lm.intercept_,lm.coef_)
predictions = lm.predict(X)

newX = pd.DataFrame({"Constant":np.ones(len(X))}).join(pd.DataFrame(X))
MSE = (sum((y-predictions)**2))/(len(newX)-len(newX.columns))

# Note if you don't want to use a DataFrame replace the two lines above with
# newX = np.append(np.ones((len(X),1)), X, axis=1)
# MSE = (sum((y-predictions)**2))/(len(newX)-len(newX[0]))

var_b = MSE*(np.linalg.inv(np.dot(newX.T,newX)).diagonal())
sd_b = np.sqrt(var_b)
ts_b = params/ sd_b

p_values =[2*(1-stats.t.cdf(np.abs(i),(len(newX)-len(newX[0])))) for i in ts_b]

sd_b = np.round(sd_b,3)
ts_b = np.round(ts_b,3)
p_values = np.round(p_values,3)
params = np.round(params,4)

myDF3 = pd.DataFrame()
myDF3["Coefficients"],myDF3["Standard Errors"],myDF3["t values"],myDF3["Probabilities"] = [params,sd_b,ts_b,p_values]
print(myDF3)

그리고 이것은 우리에게줍니다.

    Coefficients  Standard Errors  t values  Probabilities
0       152.1335            2.576    59.061         0.000
1       -10.0122           59.749    -0.168         0.867
2      -239.8191           61.222    -3.917         0.000
3       519.8398           66.534     7.813         0.000
4       324.3904           65.422     4.958         0.000
5      -792.1842          416.684    -1.901         0.058
6       476.7458          339.035     1.406         0.160
7       101.0446          212.533     0.475         0.635
8       177.0642          161.476     1.097         0.273
9       751.2793          171.902     4.370         0.000
10       67.6254           65.984     1.025         0.306

statsmodel에서 값을 재현 할 수 있습니다.


2
내 var_b가 모두 Nans라는 것은 무엇을 의미합니까? 선형 대수 부분이 실패하는 근본적인 이유가 있습니까?
famargar

왜 그런지 추측하기가 정말 어렵습니다. 데이터 구조를 살펴보고 예제와 비교합니다. 단서가 될 수 있습니다.
JARH

1
code행렬이 반전 불가능한 경우에도 np.linalg.inv가 결과를 반환하는 것처럼 보입니다 . 문제가 될 수 있습니다.
JARH

7
@ famargar 나는 또한 모든 문제가있었습니다 nan. 나를 위해 X내 데이터 샘플이므로 인덱스가 해제 되었기 때문 입니다. 호출시 오류가 발생합니다 pd.DataFrame.join(). 나는이 한 줄을 바꾸 newX = pd.DataFrame({"Constant":np.ones(len(X))}).join(pd.DataFrame(X.reset_index(drop=True)))
었고

1
@ mLstudent33 "확률"열.
skeller88

52

scikit-learn의 LinearRegression은이 정보를 계산하지 않지만 클래스를 쉽게 확장하여 수행 할 수 있습니다.

from sklearn import linear_model
from scipy import stats
import numpy as np


class LinearRegression(linear_model.LinearRegression):
    """
    LinearRegression class after sklearn's, but calculate t-statistics
    and p-values for model coefficients (betas).
    Additional attributes available after .fit()
    are `t` and `p` which are of the shape (y.shape[1], X.shape[1])
    which is (n_features, n_coefs)
    This class sets the intercept to 0 by default, since usually we include it
    in X.
    """

    def __init__(self, *args, **kwargs):
        if not "fit_intercept" in kwargs:
            kwargs['fit_intercept'] = False
        super(LinearRegression, self)\
                .__init__(*args, **kwargs)

    def fit(self, X, y, n_jobs=1):
        self = super(LinearRegression, self).fit(X, y, n_jobs)

        sse = np.sum((self.predict(X) - y) ** 2, axis=0) / float(X.shape[0] - X.shape[1])
        se = np.array([
            np.sqrt(np.diagonal(sse[i] * np.linalg.inv(np.dot(X.T, X))))
                                                    for i in range(sse.shape[0])
                    ])

        self.t = self.coef_ / se
        self.p = 2 * (1 - stats.t.cdf(np.abs(self.t), y.shape[0] - X.shape[1]))
        return self

여기 에서 도난당했습니다 .

파이썬에서 이런 종류의 통계 분석을위한 statsmodels 를 살펴 봐야 합니다.


잘. sse는 스칼라이므로 sse.shape는 실제로 아무 의미가 없으므로 작동하지 않습니다.
ashu

15

편집 : 아마 올바른 방법이 아닙니다. 의견을 참조하십시오

sklearn.feature_selection.f_regression을 사용할 수 있습니다.

scikit-learn 페이지를 보시려면 여기를 클릭하십시오


1
F- 테스트입니까? 선형 회귀에 대한 p- 값이 일반적으로 각 개별 회귀에 대한 것이라고 생각했으며 계수의 null에 대한 테스트는 0입니까? 좋은 답변을 얻으려면 기능에 대한 자세한 설명이 필요합니다.
wordsforthewise

@wordsforthewise documentation 페이지는 반환 값이 p_value의 배열이라고 말합니다. 따라서 각 개별 회귀 변수에 대한 값입니다.
ashu

1
이 방법은 올바르지 않으므로 사용하지 마십시오! 그것은 단 변량 회귀 분석을 수행하지만, 당신은 아마 하나의 다변량 회귀하려는
user357269

1
아니요, f_regression을 사용하지 마십시오. 각 계수의 실제 p- 값은 데이터를 피팅 한 후 각 계수에 대한 t 검정에서 가져와야합니다. sklearn의 f_regression은 일 변량 회귀에서 비롯됩니다. 그것은 모드를 만들지 않고 각 변수에 대해 f 점수를 계산합니다. sklearn의 chi2 함수와 동일 이것은 맞습니다 : import statsmodels.api as sm mod = sm.OLS (Y, X)
Richard Liang

@RichardLiang, sm.OLS () 사용 알고리즘에 대한 p- 값 (다변량)을 계산하는 올바른 방법입니까? (의사 결정 트리, svm, k- 평균, 로지스틱 회귀 등)? p- 값을 얻는 일반적인 방법을 원합니다. 감사합니다
Gilian

11

elyase의 답변 https://stackoverflow.com/a/27928411/4240413 의 코드는 실제로 작동하지 않습니다. sse는 스칼라이며이를 통해 반복하려고합니다. 다음 코드는 수정 된 버전입니다. 놀랍도록 깨끗하지는 않지만 다소 효과가 있다고 생각합니다.

class LinearRegression(linear_model.LinearRegression):

    def __init__(self,*args,**kwargs):
        # *args is the list of arguments that might go into the LinearRegression object
        # that we don't know about and don't want to have to deal with. Similarly, **kwargs
        # is a dictionary of key words and values that might also need to go into the orginal
        # LinearRegression object. We put *args and **kwargs so that we don't have to look
        # these up and write them down explicitly here. Nice and easy.

        if not "fit_intercept" in kwargs:
            kwargs['fit_intercept'] = False

        super(LinearRegression,self).__init__(*args,**kwargs)

    # Adding in t-statistics for the coefficients.
    def fit(self,x,y):
        # This takes in numpy arrays (not matrices). Also assumes you are leaving out the column
        # of constants.

        # Not totally sure what 'super' does here and why you redefine self...
        self = super(LinearRegression, self).fit(x,y)
        n, k = x.shape
        yHat = np.matrix(self.predict(x)).T

        # Change X and Y into numpy matricies. x also has a column of ones added to it.
        x = np.hstack((np.ones((n,1)),np.matrix(x)))
        y = np.matrix(y).T

        # Degrees of freedom.
        df = float(n-k-1)

        # Sample variance.     
        sse = np.sum(np.square(yHat - y),axis=0)
        self.sampleVariance = sse/df

        # Sample variance for x.
        self.sampleVarianceX = x.T*x

        # Covariance Matrix = [(s^2)(X'X)^-1]^0.5. (sqrtm = matrix square root.  ugly)
        self.covarianceMatrix = sc.linalg.sqrtm(self.sampleVariance[0,0]*self.sampleVarianceX.I)

        # Standard erros for the difference coefficients: the diagonal elements of the covariance matrix.
        self.se = self.covarianceMatrix.diagonal()[1:]

        # T statistic for each beta.
        self.betasTStat = np.zeros(len(self.se))
        for i in xrange(len(self.se)):
            self.betasTStat[i] = self.coef_[0,i]/self.se[i]

        # P-value for each beta. This is a two sided t-test, since the betas can be 
        # positive or negative.
        self.betasPValue = 1 - t.cdf(abs(self.betasTStat),df)

8

p- 값을 가져 오는 쉬운 방법은 통계 모델 회귀를 사용하는 것입니다.

import statsmodels.api as sm
mod = sm.OLS(Y,X)
fii = mod.fit()
p_values = fii.summary2().tables[1]['P>|t|']

조작 할 수있는 일련의 p- 값을 얻습니다 (예 : 각 p- 값을 평가하여 유지하려는 순서 선택).

여기에 이미지 설명을 입력하십시오


sm.OLS () 사용하여 알고리즘의 p- 값 (다변량)을 계산하는 올바른 방법입니까? (의사 결정 트리, svm, k- 평균, 로지스틱 회귀 등)? p- 값을 얻는 일반적인 방법을 원합니다. 감사합니다
Gilian

7

p_value는 f 통계 중 하나입니다. 값을 얻으려면 다음 코드 줄을 사용하십시오.

import statsmodels.api as sm
from scipy import stats

diabetes = datasets.load_diabetes()
X = diabetes.data
y = diabetes.target

X2 = sm.add_constant(X)
est = sm.OLS(y, X2)
print(est.fit().f_pvalue)

3
언급 한 것과 다른 라이브러리를 사용하고 있기 때문에 질문에 대답하지 않습니다.
1'19

@gented 한 계산 방법이 다른 계산 방법보다 나은 시나리오는 무엇입니까?
Don Quixote

6

다 변수 회귀 분석의 경우 @JARH 의 대답에 실수가있을 수 있습니다 . (나는 논평 할만한 명성이 없다.)

다음 줄에서 :

p_values =[2*(1-stats.t.cdf(np.abs(i),(len(newX)-1))) for i in ts_b],

t- 값은 차의 제곱 분포len(newX)-1 를 따르는 대신 차의 제곱 분포 를 따릅니다 len(newX)-len(newX.columns)-1.

따라서 다음과 같아야합니다.

p_values =[2*(1-stats.t.cdf(np.abs(i),(len(newX)-len(newX.columns)-1))) for i in ts_b]

(자세한 내용 은 OLS 회귀에 대한 t- 값 참조)


5

p- 값에 scipy 를 사용할 수 있습니다 . 이 코드는 scipy 문서에서 가져온 것입니다.

>>> from scipy import stats
>>> import numpy as np
>>> x = np.random.random(10)
>>> y = np.random.random(10)
>>> slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)

1
나는 이것이 맞는 동안 사용되는 여러 벡터에 적용되지 않는다고 생각한다
O.rka

1

1 라이너의 경우 pingouin.linear_regression 함수 ( 면책 조항 : Pingouin 제작자)를 사용할 수 있습니다.이 기능 NumPy 배열 또는 Pandas DataFrame을 사용하여 단일 / 다변량 회귀와 함께 작동합니다.

import pingouin as pg
# Using a Pandas DataFrame `df`:
lm = pg.linear_regression(df[['x', 'z']], df['y'])
# Using a NumPy array:
lm = pg.linear_regression(X, y)

결과는 각 예측 변수에 대한 베타 계수, 표준 오류, T- 값, p- 값 및 신뢰 구간뿐만 아니라 적합도의 R ^ 2 및 조정 된 R ^ 2가있는 데이터 프레임입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.