Tìm giá trị p (mức ý nghĩa) trong scikit-learn linearRegression


154

Làm thế nào tôi có thể tìm thấy giá trị p (ý nghĩa) của từng hệ số?

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

2
Không phải câu trả lời của bạn, nhưng có thể là câu trả lời cho người khác: scipy cung cấp giá trị trong linregression: docs.scipy.org/doc/scipy-0.14.0/reference/generated/ tựa
DaveRGP

nó chỉ hoạt động cho một chiều so với một chiều.
Richard Liang

Câu trả lời:


162

Đây là loại quá mức cần thiết nhưng hãy thử xem. Trước tiên, hãy sử dụng statsmodel để tìm hiểu giá trị p phải là gì

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())

và chúng tôi nhận được

                         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.
==============================================================================

Ok, hãy tái tạo điều này. Đó là loại quá mức cần thiết vì chúng ta gần như tái tạo một phân tích hồi quy tuyến tính bằng cách sử dụng Đại số ma trận. Nhưng cái quái gì thế.

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)

Và điều này mang lại cho chúng ta.

    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

Vì vậy, chúng tôi có thể tái tạo các giá trị từ statsmodel.


2
Điều đó có nghĩa là var_b của tôi đều là Nans? Có bất kỳ lý do cơ bản tại sao phần đại số tuyến tính thất bại?
đình

Thực sự khó đoán tại sao có thể như vậy. Tôi sẽ xem xét cấu trúc dữ liệu của bạn và so sánh nó với ví dụ. Điều đó có thể cung cấp một manh mối.
JARH

1
Có vẻ như codenp.linalg.inv đôi khi có thể trả về một kết quả ngay cả khi ma trận không thể đảo ngược. Đó có thể là vấn đề.
JARH

7
@famargar Mình cũng có vấn đề của tất cả nans. Đối với tôi đó là vì Xdữ liệu của tôi là một mẫu dữ liệu của tôi nên chỉ mục bị tắt. Điều này gây ra lỗi khi gọi pd.DataFrame.join(). Tôi đã thực hiện thay đổi một dòng này và nó dường như hoạt động ngay bây giờ:newX = pd.DataFrame({"Constant":np.ones(len(X))}).join(pd.DataFrame(X.reset_index(drop=True)))
pault

1
@ mLstudent33 Cột "xác suất".
skeller88

52

linearRegression của scikit-learn không tính toán thông tin này nhưng bạn có thể dễ dàng mở rộng lớp để thực hiện:

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

Bị đánh cắp từ đây .

Bạn nên có một cái nhìn tại statsmodels cho các loại hình phân tích thống kê bằng Python.


Tốt. Điều này không thấm để hoạt động vì sse là vô hướng nên sse.shape không thực sự có ý nghĩa gì.
ashu

15

EDIT: Có lẽ không phải là cách đúng đắn để làm điều đó, xem ý kiến

Bạn có thể sử dụng sklearn.feature_selection.f_regression.

bấm vào đây để trang scikit-learn


1
Vậy đó là những bài kiểm tra F? Tôi nghĩ rằng các giá trị p cho hồi quy tuyến tính thường dành cho mỗi hồi quy riêng lẻ và đó là một phép thử so với null của hệ số là 0? Giải thích thêm về chức năng sẽ là cần thiết cho một câu trả lời tốt.
lời giới thiệu

Trang tài liệu @wordsforthewise nói rằng giá trị được trả về là một mảng p_values. Vì vậy, nó thực sự là một giá trị cho mỗi hồi quy cá nhân.
ashu

1
Đừng sử dụng phương pháp này vì nó không đúng! Nó thực hiện hồi quy đơn biến, nhưng bạn có thể muốn một hồi quy đa biến duy nhất
user357269

1
Không, không sử dụng f_regression. Giá trị p thực tế của từng hệ số phải đến từ phép thử t cho từng hệ số sau khi khớp dữ liệu. f_regression trong sklearn xuất phát từ hồi quy đơn biến. Nó không xây dựng chế độ, chỉ tính điểm f cho mỗi biến. Tương tự như hàm chi2 trong sklearn Điều này là chính xác: nhập statsmodels.api dưới dạng sm mod = sm.OLS (Y, X)
Richard Liang

@RichardLiang, sử dụng sm.OLS () là cách chính xác để tính giá trị p (đa biến) cho thuật toán nào? (như cây quyết định, svm, k-nghĩa, hồi quy logistic, v.v.)? Tôi muốn một phương pháp chung để lấy giá trị p. Cảm ơn
Gilian

11

Mã trong câu trả lời của elyase https://stackoverflow.com/a/27928411/4240413 không thực sự hoạt động. Lưu ý rằng sse là một vô hướng, và sau đó nó cố gắng lặp qua nó. Các mã sau đây là một phiên bản sửa đổi. Không tuyệt vời sạch sẽ, nhưng tôi nghĩ rằng nó hoạt động ít nhiều.

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

Một cách dễ dàng để lấy các giá trị p là sử dụng hồi quy statsmodels:

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

Bạn nhận được một loạt các giá trị p mà bạn có thể thao tác (ví dụ: chọn thứ tự bạn muốn giữ bằng cách đánh giá từng giá trị p):

nhập mô tả hình ảnh ở đây


Sử dụng sm.OLS () là cách chính xác để tính giá trị p (đa biến) cho thuật toán nào? (như cây quyết định, svm, k-nghĩa, hồi quy logistic, v.v.)? Tôi muốn một phương pháp chung để lấy giá trị p. Cảm ơn
Gilian

7

p_value nằm trong số thống kê f. nếu bạn muốn nhận giá trị, chỉ cần sử dụng vài dòng mã này:

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
Điều này không trả lời câu hỏi vì bạn đang sử dụng một thư viện khác với thư viện được đề cập.
gents

@gents Các kịch bản trong đó một phương pháp tính toán sẽ tốt hơn các phương pháp khác là gì?
Don Quixote

6

Có thể có một lỗi trong câu trả lời của @JARH trong trường hợp hồi quy đa biến. (Tôi không có đủ danh tiếng để bình luận.)

Trong dòng sau:

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

các giá trị t tuân theo phân phối mức độ bình phươnglen(newX)-1 thay vì tuân theo phân phối mức độ bình phương len(newX)-len(newX.columns)-1.

Vì vậy, điều này nên là:

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

(Xem giá trị t cho hồi quy OLS để biết thêm chi tiết)


5

Bạn có thể sử dụng scipy cho giá trị p. Mã này là từ tài liệu 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
Tôi không nghĩ rằng điều này áp dụng cho nhiều vectơ đang được sử dụng trong thời gian phù hợp
O.rka

1

Đối với một lớp lót, bạn có thể sử dụng hàm pingouin.linear_regression ( từ chối trách nhiệm: Tôi là người tạo ra Pingouin ), hoạt động với hồi quy đơn biến / đa biến bằng cách sử dụng mảng NumPy hoặc Pandas DataFrame, ví dụ:

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)

Đầu ra là một khung dữ liệu với các hệ số beta, lỗi tiêu chuẩn, giá trị T, giá trị p và khoảng tin cậy cho từng yếu tố dự đoán, cũng như R ^ 2 và R ^ 2 được điều chỉnh phù hợp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.