地面实况拟合比对噪声数据的交叉验证拟合更差?

数据挖掘 Python 回归 交叉验证
2021-09-29 20:20:13

在玩交叉验证时,我得到了这些奇怪的结果,如果有任何评论,我将不胜感激。

简而言之,在使用交叉验证 (CV) 进行回归(最小二乘)时,我的均方误差 (MSE) 比使用我用来生成数据的“真实权重”时要低。

但是请注意,我在噪声数据(生成的数据 + 噪声)上计算 MSE,因此对于高于 0 的噪声水平,不会期望 MSE 为 0。

奇怪的是,对于高噪声条件,使用交叉验证的最小二乘法得到的 MSE 低于用于生成干净数据的“地面”真值权重 - 然后我向输入 (X) 添加不同级别的噪声。相反,如果我在输出 (y) 中添加高斯噪声,“地面实况权重”的表现会更好。

更多细节如下。

数据模拟

从高斯生成beta ,从均匀分布生成X。然后我将要回归的y计算为 y = beta * X。python 3 代码:

def generate_data(noise_frac):
  X = np.random.rand(ntrials,nneurons)
  X = np.random.normal(size=(ntrials,nneurons))
  
  beta = np.random.randn(nneurons)
  y = X @ beta

  # not very important how I generated noise here
  noise_x = np.random.multivariate_normal(mean=zeros(nneurons), cov=diag(np.random.rand(nneurons)), size=ntrials)

                            
  X_noise = X + noise_x*noise_frac

  return X_noise, y, beta
  
  

如您所见,我还向X添加了噪音。

回归

然后,我将针对不同噪声值的噪声数据X_noise投影到beta上:

y_hat = (X_noise) @ beta

并计算 MSE:

mse = mean((y_hat - y)**2)

正如预期的那样,MSE 随着噪声的增加而增加(图中的蓝线)。

CV 和地面实况 beta 权重的 MSE

但是,如果我使用交叉验证的最小二乘法,我会得到更低的 MSE!现在这是图中的一条橙色线。

为了做 CV,我将X_noise 分成随机的 100 个训练集和测试集。从广义上讲,这就是我在 python 中做 CV 的方式:

beta_lsq = pinv(X_train) @ y_train
y_hat_lsq = (X_test) @ beta_lsq
mse = mean((y_hat_lsq - y_test)**2)

另一方面,如果我给 y 添加噪声而不是 X,那么一切都有意义:

在此处输入图像描述

PS:这是来自堆栈溢出的交叉帖子

2个回答

测试中的主要问题是您的 X 与您的噪声级别 (0-1) 具有相同的比例,因此,添加噪声会显着改变您的数据分布。

这是添加噪声前后的数据分布。

在此处输入图像描述

就像噪音比您的初始数据多 50-200%。这就是为什么使用 CV 比使用“ground truth weights”获得更好的结果的原因。因为 CV 的新拟合模型针对具有新分布的 X 进行了调整。

但是,如果您增加 X 值比例,例如100*np.random.rand(ntrials,neurons),您的数据在添加噪声之前和之后具有相同的分布。

在此处输入图像描述

现在,如果你运行你的代码,你会得到你所期望的。

结果

似乎您获得更好结果的原因与交叉验证无关,而是与在 train_decode 函数中计算交叉验证结果期间发生的权重调整有关。为了检查这一点,我使用了以下模拟,

results = {"beta": [], "folds": []}
noises =  np.arange(0,1,0.1)

for noise_frac in noises:
  print(noise_frac) 
  acc_folds = []
  acc_bests = []
  for _ in  range(1000):
    X, y, beta = generate_data(noise_frac)
    beta_prime = train_decode(X,y)
    acc_folds.append(test_decoder(beta_prime,X,y))
    acc_bests.append(test_decoder(beta,X,y))

  results["beta"].append(acc_bests)
  results["folds"].append(acc_folds)

和以前一样,误差遵循相同的趋势,并且具有大致相同的值,

错误图

在这里,beta-result 计算如下:

y=β×X

y=β×(X+noise)

MSE=mean((yy)2)

而将要交叉验证的结果是使用调整后的 β

y=β×X

β=(X+noise)1×y

y=β×(X+noise)

MSE=mean((yy)2)

总而言之,我可以说模拟表明调整后的权重 (beta) 使目标值的误差更接近于不可约误差。