复制 Hastie、Tibshirani 和 Friedman 的线性回归示例

机器算法验证 回归 Python
2022-04-11 23:40:22

Hastie、Tibshirani 和 Friedman(以下称为HTF )一书中的常设示例之一使用来自Stamey等人的一项研究的前列腺癌数据(可在此处获得并在此处描述)。(1989 年)。

我试图重现 HTF(第二版)中引用的普通线性回归的结果,它们报告了以下系数(表 3.2,第 50 页):

Intercept:  2.45
lcavol   :  0.72
weight   :  0.29
age      : -0.14
lbph     :  0.21
svi      :  0.31
lip      : -0.29
gleason  : -0.02
egg45    :  0.28

然而,我自己的分析给出了可悲的不同数字(使用scikit-learn's LinearRegressionstatsmodels'sOLS并使用 HTF 中的公式 3.6 手动计算系数)。我明白了

Intercept:  0.429
lcavol   :  0.577
lweight  :  0.614
age      : -0.019
lbph     :  0.145
svi      :  0.737
lcp      : -0.206
gleason  : -0.030
pgg45    :  0.009

使用以下(Python 3)代码:

# Import data
# -----------
import pandas as pd

df = pd.read_csv('prostate.data', sep='\t', usecols=range(1, 11))

# Extract training set used by HTF
# --------------------------------
train_mask = (df['train'] == 'T')
cols_X = [col for col in df.columns if col not in ['lpsa', 'train']]
cols_y = ['lpsa']

X_train = df.loc[train_mask, cols_X]
y_train = df.loc[train_mask, cols_y]

# Use scikit-learn's LinearRegression
# -----------------------------------
from sklearn import linear_model

ols = linear_model.LinearRegression(normalize=True)
ols.fit(X_train, y_train)

print('Intercept: {:6.3f}'.format(ols.intercept_[0]))
for i, col in enumerate(X_train.columns):
    print('{:9s}: {:6.3f}'.format(col, ols.coef_[0, i]))

# Use statsmodels OLS
# -------------------
import statsmodels.api as sm

result = sm.OLS(y_train, sm.add_constant(X_train)).fit()
print(result.summary())

# Use formula 3.6 of HTF
# ----------------------
X_ext = np.hstack([np.ones((X_train.shape[0], 1)), X_train.values])
np.matmul(np.matmul(np.linalg.inv(np.matmul(X_ext.T, X_ext)), X_ext.T), y_train)

我做错了什么,还是书中报告的数字有误?

编辑:重新定义

X_train = (X_train - X_train.mean(axis=0)) / (X_train.std(axis=0))

在任何拟合导致系数与 HTF 中报告的系数一致之前:

Intercept:  2.4523
lcavol:     0.7164
weight:     0.2926
age:       -0.1425
lbph:       0.2120
svi:        0.3096
lip:       -0.2890
gleason:   -0.0209
pgg45:      0.2773

这本书可能会受益于使这一点更清晰(我见过其他人对同样的问题感到困惑)。感谢所有回复!

2个回答

正如他们在文中所说:

在首先将预测变量标准化为具有单位方差后,我们将线性模型拟合到前列腺特异性抗原 lpsa 的对数。我们将数据集随机分成大小为 67 的训练集和大小为 30 的测试集。我们对训练集应用最小二乘估计,产生的估计值、标准误差和 Z 分数如表 3.2 所示

您尚未标准化预测变量。

当我标准化预测变量(即减去均值并除以标准差),然后对标记为属于训练集的观察值执行标准 OLS 时,我得到:

   2.464932922123745
   0.679528141237975
   0.263053065732544
  -0.141464833536172
   0.210146557221827
   0.305200597125098
  -0.288492772453546
  -0.021305038802948
   0.266955762119924

这与文本中描述的基本相同(仍然存在细微差别,但可能没有什么重要的,我不应该花这么多时间了!)