我想在不使用内置函数的情况下进行10折交叉验证,以训练和识别0到9的数字。我有500张图片的样本(每个数字50张用于训练和测试)。我尝试实现MATLAB: 10折交叉验证不使用现有函数和其他网站上的答案,但这些帮助不大。主要是因为我对MATLAB还不熟悉,所以不知道该如何调整。这是我目前的代码。
c=zeros(10,size(x,2),size(x,3)); K=10; k=10; test= 1:50/K; for fold =1:K if(test(1)~=1) train = x(1:test(1)-1,:,:); if (test(5) ~=50) train=[train ; x(test(end):50,:,:)]; end else train = x(test(1):50,:,:); end test = test+ones(1,50/K)*50/K; end for i =0:9 test=test+50/K*ones(1,5); c(i+1,:,:)=cal_likelihood(x(1+i*50:50+i*50,:,:),50/k*(k-1)); end
变量解释
- x 是一个500x28x28的双精度数组,保存了所有500张数字图片。
- test 是测试集。
- train 是训练集。
为了进行10折交叉验证,我需要像下面这样更改训练集:
- 第1折:1:5 用于测试,6:45 用于训练
- 第2折:6:10 用于测试,1:5 和 11:50 用于训练,以此类推
问题是我不知道如何将训练集从一组转换到另一组,比如从6:45转换到1:5和11:50。或者我能写一个比这更好的循环吗?
PSS. 如果回答这个问题的人不介意的话,500x28x28的双精度数组到底是什么意思?
回答:
有几种方法可以编写这个代码,其中一些比其他的更容易理解。MATLAB编写起来非常方便,因为像1:3
这样的表达式会评估为[1,2,3]
,而1:0
这样的表达式会评估为一个空集。因此,生成这些集合时无需使用if语句就非常简单。
我会这样开始循环:
samples_per_digit=50;block_sze=samples_per_digit/K;for fold =1:K test_ind = 1+(fold-1)*block_sze:fold*block_sze; train_ind = [1:(fold-1)*block_sze, (fold*block_sze+1):samples_per_digit]; for i=0:9 train=x(train_ind+i*samples_per_digit,:,:); test=x(test_ind+i*samples_per_digit,:,:); % 在这里对数字i的这一折进行训练和验证
你可以验证test_ind
和train_ind
是否对应你需要的训练和验证的子集块。只有在最内层循环中,这些索引才转换为对应数字图片的矩阵,使用i
的值来计算偏移量。当然,如果你愿意,你可以交换循环的顺序,计算单个数字的所有折数。这完全取决于你希望如何存储结果。