将统计模型预测与实际 y 值进行比较(索引问题)



目标:我想计算拟合多元线性回归模型所做预测的检验误差。

问题:这是我的代码。它旨在将线性回归模型拟合到训练数据,然后根据X_test变量预测 y 值(价格):

X.insert(0, 'constant', 1)   # insert constant column
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)
lm_sm = sm.OLS(y_train, X_train).fit()
y_pred = pd.DataFrame()   # dataframe for predictions vs actual y-values
y_pred['predictions'] = lm_sm.predict(X_test)
print y_test.sort_index().head()
print y_pred.sort_index().head()

代码输出以下内容:

price
6   257500.0
17  485000.0
23  252700.0
25  233000.0
26  937000.0
predictions
0  509428.615367
1  324403.584917
2  477385.431339
3  484962.235105
4  827039.820936

比较预测价格和实际价格,这显然是不对的。predict()方法不会保留我的训练/测试拆分中的索引。因此,当我将预测价格与实际价格进行比较时,我无法确定我是否比较了正确的值。

我想到的唯一解决方案(我不确定这是否是正确的想法)是在进行预测时对X_test进行排序,即y_pred['predictions'] = lm_sm.predict(X_test.sort_index()).预测看起来更符合我的期望(请注意,这是第一个线性回归/基准,因此尚未应用特征工程):

price
6   257500.0
12  310000.0
18  189000.0
25  233000.0
29  719000.0
predictions
0  259985.788272
1  590648.478023
2  339621.126287
3  316402.199424
4  635513.611634

然后,我将根据这些排序的数据帧执行测试误差计算。这是对的吗?有没有更清洁的方法可以做到这一点?我不知道的方法?任何帮助/想法将不胜感激,谢谢!

我实际上不认为排序有什么问题。y_test的混合指数,与y_pred的干净指数相比,是混淆的根源。

当你在数据集上使用train_test_split(X, y),它显然会打乱事情,这就是为什么y_test有一个洗牌的索引子集。

当你做lm_sm.predict(X_test)时,输出是一个普通的numpy数组。它不是带有索引的 pandas 对象,因此索引信息已经丢失。此外,在代码中,将结果存储在新的y_pred数据帧中。在那个新的y_pred,索引将是一个新的自动增量:0、1、2 ...

所以只是不要使用sort_index(),您可以确定y_pred,因为它将与X_testy_test对齐。

希望这能更好地说明事情。

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from statsmodels.regression.linear_model import OLS
X = pd.DataFrame(np.random.random((60, 3)))
y = pd.DataFrame(np.random.random((60, 1)))
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)
print(X_test)

测试集的功能:

0         1         2
2   0.547993  0.479149  0.495539
48  0.332964  0.857635  0.501391
23  0.380500  0.377257  0.088766
35  0.045725  0.432096  0.239523
52  0.254861  0.207215  0.985722
37  0.099525  0.205250  0.054000
22  0.426227  0.253524  0.336110
43  0.716443  0.006443  0.423447
49  0.146820  0.803366  0.390921
6   0.127666  0.848561  0.936604
46  0.303034  0.548064  0.852688
33  0.516726  0.977396  0.829725

测试集的目标print(y_test)

0
2   0.123253
48  0.494307
23  0.312021
35  0.939558
52  0.958955
37  0.681215
22  0.181427
43  0.907552
49  0.589316
6   0.613305
46  0.947220
33  0.696609

指数被洗牌,但他们同意。现在做:

lm_sm = OLS(y_train, X_train).fit()
y_pred = pd.DataFrame()   # dataframe for predictions vs actual y-values
y_pred['predictions'] = lm_sm.predict(X_test)
# Print this directly
print(lm_sm.predict(X_test))

最后一行只是一个普通的 numpy 数组:

[ 0.44549342  0.44973765  0.24465328  0.17840542  0.42329909  0.09567253
0.30675321  0.38496281  0.33836597  0.49959203  0.47488055  0.63751567]

当您查看新的y_pred数据帧时,索引是新的 0、1、2 ...print(y_pred)

predictions
0      0.445493
1      0.449738
2      0.244653
3      0.178405
4      0.423299
5      0.095673
6      0.306753
7      0.384963
8      0.338366
9      0.499592
10     0.474881
11     0.637516

您可能会惊讶于这些索引与y_test的索引不匹配,但正如我所展示的,predict()函数返回一个普通的 numpy 数组,并且没有任何东西将生成的y_pred连接到原始索引。不过,您可以确定一切都是一致的。

请注意,train_test_split现在具有可选的参数shuffle=False以避免随机播放。 这应该可以解决您在 df 中的对齐问题。

最新更新