Python scikit-learn线性模型参数标准误差
我正在使用sklearn,特别是linear_model模块。在进行简单线性回归后,如下所示:
import pandas as pd
import numpy as np
from sklearn import linear_model
randn = np.random.randn
X = pd.DataFrame(randn(10,3), columns=['X1','X2','X3'])
y = pd.DataFrame(randn(10,1), columns=['Y'])
model = linear_model.LinearRegression()
model.fit(X=X, y=y)
我可以通过coef_和intercept_来获取模型的系数和截距,预测也很简单。不过,我想获取这个简单模型的方差-协方差矩阵,以及这些参数的标准误差。我对R语言和vcov()函数比较熟悉,似乎scipy.optimize有一些相关的功能(使用optimize.leastsq方法获取拟合参数的标准误差)——那么sklearn有没有类似的功能来获取这些统计数据呢?
感谢任何帮助。
-Ryan
3 个回答
每个预测器的列格式都是随机的。所以,这就像是在进行三次模拟:
import pandas as pd
import numpy as np
from sklearn import linear_model
randn = np.random.randn
X = pd.DataFrame(randn(10,1))
y = pd.DataFrame(randn(10,1))
model = linear_model.LinearRegression()
model.fit(X=X, y=y)
y_pred = model.predict(X)
print(y)
print(y_pred)
residuals = y - y_pred
residuals['c'] = residuals.iloc[:, 0]**2
sq = residuals['c']
print(sq)
standard_error = (sum(sq)/(10-2))**0.5
print(standard_error)
不,scikit-learn 这个库没有提供用于推断的错误估计。不过,Statsmodels 这个库是有的。
import statsmodels.api as sm
ols = sm.OLS(y, X)
ols_result = ols.fit()
# Now you have at your disposition several error estimates, e.g.
ols_result.HC0_se
# and covariance estimates
ols_result.cov_HC0
可以查看 文档
简要说明
用scikit-learn不能直接做到,但你可以通过一些线性代数手动计算。我会在下面的例子中展示这个过程。
另外,这里有一个包含代码的jupyter笔记本:https://gist.github.com/grisaitis/cf481034bb413a14d3ea851dab201d31
什么和为什么
你估计值的标准误差就是你估计值方差的平方根。那么,什么是你估计值的方差呢?如果你假设你的模型有高斯误差,它的计算方式是:
Var(beta_hat) = inverse(X.T @ X) * sigma_squared_hat
然后,beta_hat[i]
的标准误差就是Var(beta_hat)[i, i] ** 0.5
。
你只需要计算sigma_squared_hat
。这就是你模型的高斯误差的估计值。这个值不是事先已知的,但可以通过你的残差的样本方差来估计。
另外,你还需要在数据矩阵中添加一个截距项。scikit-learn的LinearRegression
类会自动处理这个问题。所以如果你想自己计算,就需要把这个截距项加到你的X矩阵或数据框中。
怎么做
在你的代码之后开始:
展示你的scikit-learn结果
print(model.intercept_)
print(model.coef_)
[-0.28671532]
[[ 0.17501115 -0.6928708 0.22336584]]
用线性代数重现这个结果
N = len(X)
p = len(X.columns) + 1 # plus one because LinearRegression adds an intercept term
X_with_intercept = np.empty(shape=(N, p), dtype=np.float)
X_with_intercept[:, 0] = 1
X_with_intercept[:, 1:p] = X.values
beta_hat = np.linalg.inv(X_with_intercept.T @ X_with_intercept) @ X_with_intercept.T @ y.values
print(beta_hat)
[[-0.28671532]
[ 0.17501115]
[-0.6928708 ]
[ 0.22336584]]
计算参数估计的标准误差
y_hat = model.predict(X)
residuals = y.values - y_hat
residual_sum_of_squares = residuals.T @ residuals
sigma_squared_hat = residual_sum_of_squares[0, 0] / (N - p)
var_beta_hat = np.linalg.inv(X_with_intercept.T @ X_with_intercept) * sigma_squared_hat
for p_ in range(p):
standard_error = var_beta_hat[p_, p_] ** 0.5
print(f"SE(beta_hat[{p_}]): {standard_error}")
SE(beta_hat[0]): 0.2468580488280805
SE(beta_hat[1]): 0.2965501221823944
SE(beta_hat[2]): 0.3518847753610169
SE(beta_hat[3]): 0.3250760291745124
用statsmodels
确认结果
import statsmodels.api as sm
ols = sm.OLS(y.values, X_with_intercept)
ols_result = ols.fit()
ols_result.summary()
...
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const -0.2867 0.247 -1.161 0.290 -0.891 0.317
x1 0.1750 0.297 0.590 0.577 -0.551 0.901
x2 -0.6929 0.352 -1.969 0.096 -1.554 0.168
x3 0.2234 0.325 0.687 0.518 -0.572 1.019
==============================================================================
太好了,完成了!