【问题标题】:K-fold cross validation modification to generated ANN code?对生成的 ANN 代码进行 K 折交叉验证修改?
【发布时间】:2017-08-29 08:45:22
【问题描述】:

我的数据集基本上是一个包含 3 个变量(输入)的矩阵和一个包含 1 个变量(目标)的矩阵。每个都有 50 个数据集(基本上是 50 个 f(x,y,z) = t 的样本)

我只使用 GUI 完成了 ANN 训练。从来没有真正使用过脚本/代码。

我现在最简单的目标是为每次训练测试运行手动拆分数据,这样我就可以煞费苦心地运行神经网络 5 次,但我什至不确定如何手动选择数据集的范围用于训练,哪个用于测试。

这是从 MATLAB 导出的完整脚本。焦点显示在代码墙下方。

% Solve an Input-Output Fitting problem with a Neural Network
% Script generated by NFTOOL
% Created Mon Jul 17 02:39:31 SGT 2017
%
% This script assumes these variables are defined:
%
%   DEinp - input data.
%   DEcgl - target data.

inputs = DEinp;
targets = DEcgl;

% Create a Fitting Network
hiddenLayerSize = 10;
net = fitnet(hiddenLayerSize);

% Choose Input and Output Pre/Post-Processing Functions
% For a list of all processing functions type: help nnprocess
net.inputs{1}.processFcns = {'removeconstantrows','mapminmax'};
net.outputs{2}.processFcns = {'removeconstantrows','mapminmax'};


% Setup Division of Data for Training, Validation, Testing
% For a list of all data division functions type: help nndivide
net.divideMode = 'sample';  % Divide up every sample
net.divideParam.trainRatio = 70/100;
net.divideParam.valRatio = 15/100;
net.divideParam.testRatio = 15/100;

% For help on training function 'trainlm' type: help trainlm
% For a list of all training functions type: help nntrain
net.trainFcn = 'trainlm';  % Levenberg-Marquardt

% Choose a Performance Function
% For a list of all performance functions type: help nnperformance
net.performFcn = 'mse';  % Mean squared error

% Choose Plot Functions
% For a list of all plot functions type: help nnplot
net.plotFcns = {'plotperform','plottrainstate','ploterrhist', ...
  'plotregression', 'plotfit'};


% Train the Network
[net,tr] = train(net,inputs,targets);

% Test the Network
outputs = net(inputs);
errors = gsubtract(targets,outputs);
performance = perform(net,targets,outputs)

% Recalculate Training, Validation and Test Performance
trainTargets = targets .* tr.trainMask{1};
valTargets = targets  .* tr.valMask{1};
testTargets = targets  .* tr.testMask{1};
trainPerformance = perform(net,trainTargets,outputs)
valPerformance = perform(net,valTargets,outputs)
testPerformance = perform(net,testTargets,outputs)

% View the Network
view(net)

% Plots
% Uncomment these lines to enable various plots.
%figure, plotperform(tr)
%figure, plottrainstate(tr)
%figure, plotfit(net,inputs,targets)
%figure, plotregression(targets,outputs)
%figure, ploterrhist(errors)

我认为我需要做的就是弄乱 net.divideMode 部分,但我真的不知道如何更改语法来完成我的目标。

【问题讨论】:

    标签: matlab neural-network


    【解决方案1】:

    网络参数

    将数据拆分为训练集、验证集和测试集的过程发生在您确定的部分。我将分解每一行。开始于:

    % Setup Division of Data for Training, Validation, Testing
    % For a list of all data division functions type: help nndivide
    net.divideMode = 'sample';  % Divide up every sample
    

    divideMode 在Neural Network Object Properties中有详细记录

    net.divideMode

    该属性定义了目标数据维度 在调用数据分割函数时进行分割。它的默认值 静态网络的值为“样本”,动态网络的值为“时间”。 它也可以设置为“sampletime”以将目标除以两个样本 和时间步长,“全部”,将目标除以每个标量值,或 'none' 根本不划分数据(在这种情况下,使用所有数据 用于训练,没有用于验证或测试)。

    因此,您的网络是一个静态网络,它将每个样本分成一个训练样本。对于您的交叉验证,这将保持不变。您有兴趣操纵的是训练、测试和验证拆分。

    net.divideParam.trainRatio = 70/100;
    net.divideParam.valRatio = 15/100;
    net.divideParam.testRatio = 15/100;
    

    好的,这里的变量名称看起来很有希望,但是您需要更多的控制,而不仅仅是选择比率大小。

    再次Neural Network Object Properties 指向我们了解更多信息

    net.divideParam

    这个属性定义了当前的参数和值 数据划分功能。要了解每个字段的含义, 输入以下命令:

    help(net.divideFcn)

    这将打印出有关您的数据集如何划分为训练、验证和测试拆分的信息。在您当前的配置中,消息显示为

    dividerand 使用随机索引将索引分成三组。

    [trainInd,valInd,testInd] = dividerand(Q,trainRatio,valRatio,testRatio) 需要多个 样本 Q 并在训练之间划分样本索引 1:Q, 验证和测试指标。

    dividerand根据三个比率将样本索引随机分配给三个集合。

    (...)

    另见divideblock、divideind、divideint、dividetrain。

    由于您想要更多地控制分区,您应该检查这些附加选项。

    我认为最有前途的是divideind。此选项允许您指定每个分区的索引。您可以计算 k 折叠交叉验证中每个折叠的索引,并使用此选项在每次迭代中重新分配分区。

    要设置此参数,请将上面的 net.divideParam 行替换为类似的内容,

    net.divideFcn = 'divideind';
    net.divideParam.Q = length(targets); %This is the total number of instances in your data 
    net.divideParam.trainInd = your_train_ind;
    net.divideParam.valInd = your_val_ind;
    net.divideParam.testInd = your_test_ind;
    

    K 折

    最后一个细节,如何选择索引?首先,快速回顾一下 k 折交叉验证。

    1. 数据被分成 k 个大小相等的子样本。
    2. 在交叉验证的每次迭代中,我们对 k-1 个子样本进行训练并在剩余的子样本上进行测试,每次轮换到一个新的测试子样本。

    实现草图可能如下所示

    k = 5; % As an example, let's let k = 5
    sample_size = length(targets)/k;
    
    %Make a vector of all the indices of your data from 1 to the total number of instances
    indices= 1:length(targets); 
    
    % Optional: Randomize samples
    indices = randperm(length(targets));
    
    % Iterate in steps of sample_size
    for ii = 1: sample_size:length(targets) - sample_size
    
        % Grab one subsample of indices for testing
        your_test_ind = indices( ii:ii + sample_size - 1);
    
        % Everything else
        your_train_ind = indices( [1:ii, ii + sample_size:end]);
    
        %Train and test your network here!
    end
    

    这只是一个实现草图,不能正确处理一些边缘情况。例如,第一个元素总是添加到训练集中,但它应该足以让你开始。

    【讨论】:

    • 所以呃...假设我想运行 5 的 k,使其 40/50 用于训练,10/50 用于测试(保持简单,我们不会使用任何用于验证)。我的代码会是什么样子?假设我的输入变量只是 x,目标是 y。老实说,我确实尝试过围绕不同的除法命令,但在我尝试的过程中它们对我没有反应。我至少假设它会像net.divideFcn = 'divideind'; net.divideParam.x = 5(50); net.divideParam.trainInd = 11:40; net.divideParam.testInd = 1:10; 我只是不知道长度(目标)是多少。
    • 我已经更新了我的答案。 length(target) 是变量target 中的元素个数。
    • 哇,注释代码!会试一试。希望一切顺利。过几天会回复你的。只是好奇,如果我有 53 个数据集怎么办?我想知道在这种情况下matlab如何处理不可分割的?
    • 刚试过。结束了相当不稳定...your_test_ind = indices( ii:ii+ sample_size ); 行是一个错误。原因是“索引超出矩阵维度”。我确实向另一个陌生人提出了这个问题,但仅仅因为它在 matlab 中,他无法帮助我。真的很感谢你的努力,但我会继续努力用你留给我的东西。如果可能的话,代码的不可扩展版本会好得多。我将手动替换参数并多次运行。无论如何,我要将结果保存在不同的 .m 文件中。
    • 抱歉,我并没有真正运行代码。这是一个错误。我已经编辑以消除该错误,但我的实现只是一个草图。您需要为边缘情况添加更多逻辑。你知道如何使用matlab debugger吗?超级好用。
    猜你喜欢
    • 2020-11-30
    • 2016-01-15
    • 2020-02-06
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2020-08-29
    相关资源
    最近更新 更多