如果对所有数据都进行特征选择,然后进行交叉验证,那么交叉验证过程的每一折中的测试数据也将用于选择特征,这就是性能分析的偏向。
考虑这个例子。我们通过翻转硬币10次并记录其落下是正面还是反面来生成一些目标数据。接下来,我们通过将每个特征抛硬币10次并写下我们得到的内容来生成20个特征。然后,我们通过选择尽可能与目标数据匹配的特征来执行特征选择,并将其用作我们的预测。然后,如果我们交叉验证,我们将获得略低于0.5的预期错误率。这是因为我们在交叉验证过程的每一步中都基于训练集和测试集两者之间的相关性来选择特征。但是,由于目标数据只是随机的,因此真正的错误率将为0.5。如果在交叉验证的每一折内独立执行特征选择,则错误率的期望值为0。
关键思想是交叉验证是一种评估构建模型的流程的泛化性能的方法,因此您需要在每一折中重复整个流程。否则,您最终将得到有偏差的估计值,或者估计值方差偏低的估计值(或两者兼有)。
高温超导
这是一些执行此设置的蒙特卡洛模拟的MATLAB代码,具有56个特征和259个案例,以匹配您的示例,它给出的输出为:
偏倚估算器:错误= 0.429210(0.397683-0.451737)
无偏估计量:错误= 0.499689(0.397683-0.590734)
偏向估计器是在交叉验证之前执行特征选择的一种,无偏估计器是在交叉验证的每一步中独立执行特征选择的一种。这表明,根据学习任务的性质,这种情况下的偏见可能非常严重。
NF = 56;
NC = 259;
NFOLD = 10;
NMC = 1e+4;
% perform Monte-Carlo simulation of biased estimator
erate = zeros(NMC,1);
for i=1:NMC
y = randn(NC,1) >= 0;
x = randn(NC,NF) >= 0;
% perform feature selection
err = mean(repmat(y,1,NF) ~= x);
[err,idx] = min(err);
% perform cross-validation
partition = mod(1:NC, NFOLD)+1;
y_xval = zeros(size(y));
for j=1:NFOLD
y_xval(partition==j) = x(partition==j,idx(1));
end
erate(i) = mean(y_xval ~= y);
plot(erate);
drawnow;
end
erate = sort(erate);
fprintf(1, ' Biased estimator: erate = %f (%f - %f)\n', mean(erate), erate(ceil(0.025*end)), erate(floor(0.975*end)));
% perform Monte-Carlo simulation of unbiased estimator
erate = zeros(NMC,1);
for i=1:NMC
y = randn(NC,1) >= 0;
x = randn(NC,NF) >= 0;
% perform cross-validation
partition = mod(1:NC, NFOLD)+1;
y_xval = zeros(size(y));
for j=1:NFOLD
% perform feature selection
err = mean(repmat(y(partition~=j),1,NF) ~= x(partition~=j,:));
[err,idx] = min(err);
y_xval(partition==j) = x(partition==j,idx(1));
end
erate(i) = mean(y_xval ~= y);
plot(erate);
drawnow;
end
erate = sort(erate);
fprintf(1, 'Unbiased estimator: erate = %f (%f - %f)\n', mean(erate), erate(ceil(0.025*end)), erate(floor(0.975*end)));