Условный выбор всех возможных комбинаций параметров в MATLAB - PullRequest
0 голосов
/ 08 января 2019

Это продолжение вопроса Все возможные комбинации многих параметров MATLAB

В дополнение ко всем возможным комбинациям моего набора параметров у меня также есть условный параметр. Например, мне нужно включать параметр с именем «лямбда» только в том случае, если для параметра «corrAs» установлено значение «target».

Добейся этого, прямо сейчас я делаю следующее

%% All posible parameters
params.corrAs = {'objective', 'constraint'};
params.size = {'small', 'medium', 'large'};
params.density = {'uniform', 'non-uniform'};
params.k = {3,4,5,6};
params.constraintP = {'identity', 'none'};
params.Npoints_perJ = {2, 3};
params.sampling = {'hks', 'fps'};  

% If corrAs is 'objective', then also set lambda
params.lambda = {0.01, 0.1, 1, 10, 100};

%%%%%%%%%%%%% The solution posted on the link %%%%%%%%%%%
%% Get current parameter and evaluate
fields = fieldnames(params);
nFields = numel(fields);
sz = NaN(nFields, 1);

% Loop over all parameters to get sizes
for jj = 1:nFields
    sz(jj) = numel( params.(fields{jj}) );
end

% Loop for every combination of parameters
idx = cell(1,nFields);
for ii = 1:prod(sz)
    % Use ind2sub to switch from a linear index to the combination set
    [idx{:}] = ind2sub( sz, ii );
    % Create currentParam from the combination indices
    currentParam = struct();
    for jj = 1:nFields

        %%%%%%%%%%% My addition for conditional parameter %%%%%%%%%%%
        % lambda is valid only when corrAs is 'objective'
        if isfield(currentParam, 'corrAs') && strcmp(fields{jj}, 'lambda') && ~strcmp(currentParam.corrAs, 'objective')
            continue;
        end
        currentParam.(fields{jj}) = params.(fields{jj}){idx{jj}};
    end

    %% Do something with currentParam

end

Это работает, но число итераций для основного цикла for также включает лямбда-параметр, даже если corrAs не является «объективным». Таким образом, я в конечном итоге оцениваю с одним и тем же currentParam много раз, чем я должен.

Как я могу сделать это более эффективно?

1 Ответ

0 голосов
/ 09 января 2019

Простой способ думать об этом - разбить код на более функциональный

В приведенном ниже коде я просто поместил код комбинированной обработки в функцию paramProcessing. Эта функция вызывается дважды -

  1. Если params.corrAs равен 'constraint', все комбинации будут обработаны без поля lambda.

  2. Если params.corrAs только 'objective', все комбинации будут обрабатываться с дополнительным полем lambda.

Вы можете иметь выход для функции paramProcessing, если он есть в цикле.

Это означает, что вы делаете только те комбинации, которые хотите. Из вашего вопроса кажется, что каждая комбинация независима, поэтому не должно иметь значения, что вы закрываете комбинации в отдельных циклах. Использование функции означает, что вам не нужно иметь новое условие в цикле, и различные возможные значения для params.corrAs каждый раз гарантируют отсутствие перекрытия.

Функция paramProcessing может быть локальной функцией в главном файле функций, как показано, локальной в скрипте (для более новых версий MATLAB) или в своем собственном файле .m по вашему пути.

Код:

function main()
    %% All posible parameters, corrA is 'constraint' only.
    params.corrAs = {'constraint'};
    params.size = {'small', 'medium', 'large'};
    params.density = {'uniform', 'non-uniform'};
    params.k = {3,4,5,6};
    params.constraintP = {'identity', 'none'};
    params.Npoints_perJ = {2, 3};
    params.sampling = {'hks', 'fps'};  

    % First processing call, no 'lambda' field exists in 'params'
    paramProcessing( params );

    % Cover the cases where corrAs is 'objective', with 'lambda' field
    params.corrAs = {'objective'};
    params.lambda = {0.01, 0.1, 1, 10, 100};

    % Second processing call, with new settings
    paramsProcessing( params );    
end
function paramProcessing( params )
    %% Get current parameter and evaluate
    fields = fieldnames(params);
    nFields = numel(fields);
    sz = NaN(nFields, 1);

    % Loop over all parameters to get sizes
    for jj = 1:nFields
        sz(jj) = numel( params.(fields{jj}) );
    end

    % Loop for every combination of parameters
    idx = cell(1,nFields);
    for ii = 1:prod(sz)
        % Use ind2sub to switch from a linear index to the combination set
        [idx{:}] = ind2sub( sz, ii );
        % Create currentParam from the combination indices
        currentParam = struct();
        for jj = 1:nFields
            currentParam.(fields{jj}) = params.(fields{jj}){idx{jj}};
        end

        %% Do something with currentParam

    end
end    
...