在玩交叉验证时,我得到了这些奇怪的结果,如果有任何评论,我将不胜感激。
简而言之,在使用交叉验证 (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 随着噪声的增加而增加(图中的蓝线)。
但是,如果我使用交叉验证的最小二乘法,我会得到更低的 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:这是来自堆栈溢出的交叉帖子