OLS 适合 python,具有系数误差和转换目标
OLS fit for python with coefficient error and transformed target
在 python 中似乎有两种 OLS 拟合方法。 Sklearn 一个和 Statsmodel 一个。我更喜欢 statsmodel 模型,因为它通过 summary() 函数给出了系数误差。但是,我想使用 sklearn 中的 TransformedTargetRegressor 来记录我的目标。看来我需要在获取 statsmodel 中的拟合系数误差和能够在 statsmodel 中转换目标之间做出选择。有什么好的方法可以在任一系统中同时执行这两项操作吗?
在统计模型中,它会像这样完成
import statsmodels.api as sm
X = sm.add_constant(X)
ols = sm.OLS(y, X)
ols_result = ols.fit()
print(ols_result.summary())
到return与系数的拟合及其误差
对于 Sklearn,您可以使用 TransformedTargetRegressor
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
regr = TransformedTargetRegressor(regressor=LinearRegression(),func=np.log1p, inverse_func=np.expm1)
regr.fit(X, y)
print('Coefficients: \n', regr.coef_)
但是如果不自己计算,就无法得到系数的误差。有什么两全其美的好方法吗?
编辑
我在这里为我关心的特殊情况找到了一个很好的例子
简而言之,Scikit learn 无法帮助您计算系数标准误差。但是,如果您选择使用它,您可以自己计算误差。在问题 Python scikit learn Linear Model Parameter Standard Error 中,@grisaitis 提供了一个很好的答案,解释了它背后的主要概念。
如果您只想使用与 sciait-learn 一起使用的即插即用功能,您可以使用这个:
def get_coef_std_errors(reg: 'sklearn.linear_model.LinearRegression',
y_true: 'np.ndarray', X: 'np.ndarray'):
"""Function that calculates the standard deviation of the coefficients of
a linear regression.
Parameters
----------
reg : sklearn.linear_model.LinearRegression
LinearRegression object which has been fitted
y_true : np.ndarray
array containing the target variable
X : np.ndarray
array containing the features used in the regression
Returns
-------
beta_std
Standard deviation of the regression coefficients
"""
y_pred = reg.predict(X) # get predictions
errors = y_true - y_pred # calculate residuals
sigma_sq_hat = np.var(errors) # calculate residuals std error
sigma_beta_hat = sigma_sq_hat * np.linalg.inv(X.T @ X)
return np.sqrt(np.diagonal(sigma_beta_hat)) # diagonal to recover variances
只是在这里添加一个冗长的评论,我相信 TransformedTargetRegressor
并没有按照您的想法去做。据我所知,逆变换功能仅在调用 predict
方法时应用。它不以未转换结果的单位表示系数。
示例:
import pandas as pd
import statsmodels.api as sm
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
import numpy as np
from sklearn import datasets
创建一些示例数据:
df = pd.DataFrame(datasets.load_iris().data)
df.columns = datasets.load_iris().feature_names
X = df.loc[:,['sepal length (cm)', 'sepal width (cm)']]
y = df.loc[:, 'petal width (cm)']
首先学习Sklearn:
regr = TransformedTargetRegressor(regressor=LinearRegression(),func=np.log1p, inverse_func=np.expm1)
regr.fit(X, y)
print(regr.regressor_.intercept_)
for coef in regr.regressor_.coef_:
print(coef)
#-0.45867804195769357
# 0.3567583897503805
# -0.2962942997303887
转化结果的统计模型:
X = sm.add_constant(X)
ols_trans = sm.OLS(np.log1p(y), X).fit()
print(ols_trans.params)
#const -0.458678
#sepal length (cm) 0.356758
#sepal width (cm) -0.296294
#dtype: float64
您会看到,在这两种情况下,系数都是 identical.That,使用带有 TransformedTargetRegressor
的回归会产生与带有转换结果的 statsmodels.OLS
相同的系数。 TransformedTargetRegressor
不会将系数回译为原始未转换的 space。请注意,系数在原始 space 中将是非线性的,除非变换本身是线性的,在这种情况下这是微不足道的(与常数相加和相乘)。 This discussion 这里指向一个相似的方向 - 在 most/many 情况下反向转换 beta 是不可行的。
该怎么做?
如果解释是您的目标,我相信您最接近您希望实现的目标是使用预测值,其中您改变回归量或系数。因此,让我举个例子:如果您的目标是说明 sepal length
的一个标准误差较高对未转换结果的影响是什么,您可以创建拟合的预测值以及1-sigma 场景(通过调整系数,或通过调整 X 中的相应列)。
示例:
# Toy example to add one sigma to sepal length coefficient
coeffs = ols_trans.params.copy()
coeffs['sepal length (cm)'] += 0.018 # this is one sigma
# function to predict and translate predictions back:
def get_predicted_backtransformed(coeffs, data, inv_func):
return inv_func(data.dot(coeffs))
# get standard predicted values, backtransformed:
original = get_predicted_backtransformed(ols_trans.params, X, np.expm1)
# get counterfactual predicted values, backtransformed:
variant1 = get_predicted_backtransformed(coeffs, X, np.expm1)
然后你可以说例如关于未转换结果的均值偏移:
variant1.mean()-original.mean()
#0.2523083548367202
在 python 中似乎有两种 OLS 拟合方法。 Sklearn 一个和 Statsmodel 一个。我更喜欢 statsmodel 模型,因为它通过 summary() 函数给出了系数误差。但是,我想使用 sklearn 中的 TransformedTargetRegressor 来记录我的目标。看来我需要在获取 statsmodel 中的拟合系数误差和能够在 statsmodel 中转换目标之间做出选择。有什么好的方法可以在任一系统中同时执行这两项操作吗?
在统计模型中,它会像这样完成
import statsmodels.api as sm
X = sm.add_constant(X)
ols = sm.OLS(y, X)
ols_result = ols.fit()
print(ols_result.summary())
到return与系数的拟合及其误差
对于 Sklearn,您可以使用 TransformedTargetRegressor
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
regr = TransformedTargetRegressor(regressor=LinearRegression(),func=np.log1p, inverse_func=np.expm1)
regr.fit(X, y)
print('Coefficients: \n', regr.coef_)
但是如果不自己计算,就无法得到系数的误差。有什么两全其美的好方法吗?
编辑
我在这里为我关心的特殊情况找到了一个很好的例子
简而言之,Scikit learn 无法帮助您计算系数标准误差。但是,如果您选择使用它,您可以自己计算误差。在问题 Python scikit learn Linear Model Parameter Standard Error 中,@grisaitis 提供了一个很好的答案,解释了它背后的主要概念。
如果您只想使用与 sciait-learn 一起使用的即插即用功能,您可以使用这个:
def get_coef_std_errors(reg: 'sklearn.linear_model.LinearRegression',
y_true: 'np.ndarray', X: 'np.ndarray'):
"""Function that calculates the standard deviation of the coefficients of
a linear regression.
Parameters
----------
reg : sklearn.linear_model.LinearRegression
LinearRegression object which has been fitted
y_true : np.ndarray
array containing the target variable
X : np.ndarray
array containing the features used in the regression
Returns
-------
beta_std
Standard deviation of the regression coefficients
"""
y_pred = reg.predict(X) # get predictions
errors = y_true - y_pred # calculate residuals
sigma_sq_hat = np.var(errors) # calculate residuals std error
sigma_beta_hat = sigma_sq_hat * np.linalg.inv(X.T @ X)
return np.sqrt(np.diagonal(sigma_beta_hat)) # diagonal to recover variances
只是在这里添加一个冗长的评论,我相信 TransformedTargetRegressor
并没有按照您的想法去做。据我所知,逆变换功能仅在调用 predict
方法时应用。它不以未转换结果的单位表示系数。
示例:
import pandas as pd
import statsmodels.api as sm
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
import numpy as np
from sklearn import datasets
创建一些示例数据:
df = pd.DataFrame(datasets.load_iris().data)
df.columns = datasets.load_iris().feature_names
X = df.loc[:,['sepal length (cm)', 'sepal width (cm)']]
y = df.loc[:, 'petal width (cm)']
首先学习Sklearn:
regr = TransformedTargetRegressor(regressor=LinearRegression(),func=np.log1p, inverse_func=np.expm1)
regr.fit(X, y)
print(regr.regressor_.intercept_)
for coef in regr.regressor_.coef_:
print(coef)
#-0.45867804195769357
# 0.3567583897503805
# -0.2962942997303887
转化结果的统计模型:
X = sm.add_constant(X)
ols_trans = sm.OLS(np.log1p(y), X).fit()
print(ols_trans.params)
#const -0.458678
#sepal length (cm) 0.356758
#sepal width (cm) -0.296294
#dtype: float64
您会看到,在这两种情况下,系数都是 identical.That,使用带有 TransformedTargetRegressor
的回归会产生与带有转换结果的 statsmodels.OLS
相同的系数。 TransformedTargetRegressor
不会将系数回译为原始未转换的 space。请注意,系数在原始 space 中将是非线性的,除非变换本身是线性的,在这种情况下这是微不足道的(与常数相加和相乘)。 This discussion 这里指向一个相似的方向 - 在 most/many 情况下反向转换 beta 是不可行的。
该怎么做?
如果解释是您的目标,我相信您最接近您希望实现的目标是使用预测值,其中您改变回归量或系数。因此,让我举个例子:如果您的目标是说明 sepal length
的一个标准误差较高对未转换结果的影响是什么,您可以创建拟合的预测值以及1-sigma 场景(通过调整系数,或通过调整 X 中的相应列)。
示例:
# Toy example to add one sigma to sepal length coefficient
coeffs = ols_trans.params.copy()
coeffs['sepal length (cm)'] += 0.018 # this is one sigma
# function to predict and translate predictions back:
def get_predicted_backtransformed(coeffs, data, inv_func):
return inv_func(data.dot(coeffs))
# get standard predicted values, backtransformed:
original = get_predicted_backtransformed(ols_trans.params, X, np.expm1)
# get counterfactual predicted values, backtransformed:
variant1 = get_predicted_backtransformed(coeffs, X, np.expm1)
然后你可以说例如关于未转换结果的均值偏移:
variant1.mean()-original.mean()
#0.2523083548367202