【问题标题】:K-Fold Cross Validation in MATLABMATLAB 中的 K 折交叉验证
【发布时间】:2017-06-09 23:32:57
【问题描述】:

我有 36 个用户的数据

如代码所示(MATLAB)将数据加载到一个名为Feat_Vec1的矩阵中

 clear;
  for nc = 1 : 36  % nc number of users
              % Load data into MATLAB
      data{nc} = load( sprintf('U%02d_Acc_TimeD_FreqD_FDay.mat', nc) );  

             % assign data into Matrix
      Feat_Vec1{nc} = data{nc}.Acc_TD_Feat_Vec(:,:);   

 end

对于每个用户,结果我有 36 行和 143 列,Feat_Vec1 包含 36 个单元格(用户数),每个单元格包含 36 行和 143 列

我想使用 9 折交叉验证 将我的数据集划分为训练和测试。

我看过这个documentation in MATLAB help 但不明白! 想知道是否有人帮助我为每个用户编写 9 折交叉验证的编码?

【问题讨论】:

  • 你想要独立于主题的交叉验证吗?
  • 亲爱的杰夫,是的,我想独立地划分每个用户的数据。问候。
  • 那么 crossvalind 还不够,AFAIK。但由于您已经将数据分开,您可以创建一个看起来像 [1, 1, ..., 1, 2, 2, ..., 2, 3, ...] 的折叠向量
  • 亲爱的@jeff 我不明白你的意思是什么?你能帮我写代码吗?

标签: matlab


【解决方案1】:

我将修改您的代码,以展示如何为每个用户独立完成 9 折交叉验证。这意味着,每个用户都有自己的训练测试折叠。首先,9 折交叉验证意味着用户使用 8/9 的数据进行训练,使用 1/9 的数据进行测试。重复九次。

clear;
for nc = 1:36  % nc number of users
    % probably you don't need to save data in a cell - like data{nc}
    data = load( sprintf('U%02d_Acc_TimeD_FreqD_FDay.mat', nc));
    data = data.Acc_TD_Feat_Vec(:,:);
    ind = crossvalind('Kfold', 36, 9);
    for fold = 1:9
        Feat_Vec1_train{nc}{fold} = data(ind ~= fold, :)  
        Feat_Vec1_test{nc}{fold} = data(ind == fold, :)    
    end
end

在上面的代码中,每个用户有 9 对训练集和测试集。例如,第 3 个用户的第 8 次训练-测试对可以访问为:

Feat_Vec1_train{3}{8}
Feat_Vec1_test{3}{8}

【讨论】:

  • 请注意,将每个用户分成训练测试折叠不是用户独立的交叉验证。这就是为什么我说crossvalind 还不够。
  • 那么,我应该怎么做@jeff?我知道我在打扰你,但你能帮我解决吗?
  • 亲爱的@Parag S. Chandakkar 我非常感谢您为我提供的帮助。实际上,上面的代码有两个问题。首先,训练数据与原始用户数据的大小相同。(这意味着当我运行您的代码时,user1 的 Feat_Vec1_train 包含每列 36 个值,而 Feat_Vec1_test 为空)。假设 Feat_Vec1_train 每列包含 32 个值(重复 9 次),Feat_Vec1_test 包含 4 个值(重复 9 次)
  • 好的,但是在这种情况下,您有来自训练集中看到的主题的测试样本。尽管样本是独一无二的,但主题却不是。您将在训练集中看到来自同一主题的其他样本,这可以乐观地改变您的结果。
  • 亲爱的@jeff ,出于身份验证的目的,您需要将同一用户的样本分为训练样本和测试样本两部分。如果没有测试样本,你怎么知道用户是否会被系统认证?顺便问一下,你能不能快速看一下这个? stackoverflow.com/questions/42040037/…
【解决方案2】:

对上面的代码稍作修正

clear;
for nc = 1:36  % nc number of users
    % probably you don't need to save data in a cell - like data{nc}
    data = load( sprintf('U%02d_Acc_TimeD_FreqD_FDay.mat', nc));
    data = data.Acc_TD_Feat_Vec(:,:);
    ind = crossvalind('Kfold', 36, 9);
    for fold = 1:9
        Feat_Vec1_train{nc}{fold} = data(ind ~= fold, :)  
        Feat_Vec1_test{nc}{fold} = data(ind == fold, :)    
    end
end

【讨论】:

    【解决方案3】:

    继续你的代码:

    % Combine data into a single matrix:
    data = []; % sorry for the dynamic allocation
    for i=1:36
        data = [data; Feat_Vec1{nc}];
    end
    
    N = size(data, 1); % should be 36^2 = 1296
    K = 9;
    % create a vector that have K (=9) blocks of length N/K, such as [1 1 ... 1 2 2 ... 2 ... 9 9 ... 9 ]
    folds = []; % again, sorry for the dynamic allocation
    for i=1:K
        folds = [folds; repmat(i, N/K, 1)];
    end
    

    现在您确定了折叠指数。此时不需要将数据收集到单个矩阵中,因为我们已经知道N。但是,当在 for 循环中使用您的数据进行训练和测试时,此变量可能很有用:

    accuracies = zeros(1, K);
    for fold = 1:K
       testIds = find(folds==fold);
       trainIds = find(folds~=fold);
       % train your algorithm
       model = train(data(trainIds,:), label(trainIds,:), etc);
       % evaluate on the testing fold
       accuracies(fold) = test(model, data(testIds,:), label(testIds,:), etc);
    end
    mean(accuracy)
    

    希望对你有帮助

    【讨论】:

    • 亲爱的@jeff 非常感谢您的帮助和支持。实际上,您将所有用户的数据混合到一个矩阵中吗?我不想那样做。我想分别拥有每个用户的数据。例如,user1 每列有 36 个值,我想做 9 个交叉验证(这意味着对于 user1,每列的 9 个值将被存储用于测试,每列的 27 个值将用于训练他的模型。这个程序将重复 9 次,最后我将取 9 个不同测试的平均值)。请问这有意义吗?再次感谢您的帮助
    • 是的,这正是我在 for 循环中尝试做的 :)
    • @NeamahAl-Naffakh 如果适合您的需要,请查看我的回答。
    • Dear@jaff 真的很抱歉再次打扰您,但我没有收到您的代码!当我运行它给我错误!代码你请再试一次好吗?
    • 是的,我假设您还有一个大小为 1296 x 1 的标签向量。你没有?
    猜你喜欢
    • 2019-04-11
    • 2016-01-15
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    • 2016-11-15
    • 2017-07-02
    相关资源
    最近更新 更多