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

У меня есть список параметров, и мне нужно оценить мой метод по этому списку. Прямо сейчас я делаю это так

% 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'};   

% Select the current parameter
for corrAs_iter = params.corrAs
    for size_iter = params.size
        for density_iter = params.density
            for k_iter = params.k
                for constraintP_iter = params.constraintP
                    for Npoints_perJ_iter = params.Npoints_perJ
                        for sampling_iter = params.sampling
                            currentParam.corrAs = corrAs_iter;
                            currentParam.size = size_iter;
                            currentParam.density = density_iter;
                            currentParam.k = k_iter;
                            currentParam.constraintP = constraintP_iter;
                            currentParam.Npoints_perJ = Npoints_perJ_iter;
                            currentParam.sampling = sampling_iter;
                            evaluateMethod(currentParam);
                        end
                    end
                end
            end
        end
    end
end

Я знаю, это выглядит некрасиво, и если я хочу добавить новый тип параметра, я должен написать еще один цикл for. Есть ли способ, я могу это векторизовать? Или, может быть, используйте 2 для циклов вместо многих.

Я попробовал следующее, но это не привело к тому, что мне нужно.

for i = 1:numel(fields)
%     if isempty(params.(fields{i}))
    param.(fields{i}) = params.(fields{i})(1);
    params.(fields{i})(1) = [];
end

Ответы [ 2 ]

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

Вот векторизованное решение:

names = fieldnames(params).';
paramGrid = cell(1,numel(names));

cp = struct2cell(params);

[paramGrid{:}] = ndgrid(cp{:});

ng = [names;paramGrid];
st = struct(ng{:});


for param = st(:).'
    currentParam = param;
end

Вместо вложенных циклов мы можем использовать ndgrid для создания декартового произведения записей в ячейках, чтобы мы могли найти все комбинации записей в ячейках без цикла.

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

Что вам нужно, это все комбинации ваших входных параметров. К сожалению, когда вы добавите больше параметров, требования к хранилищу будут быстро расти (и вам придется использовать большую матрицу индексации).

Вместо этого есть идея, которая использует линейные признаки (никогда не создаваемой) матрицы n1*n2*...*nm, где ni - количество элементов в каждом поле для полей m.

Он достаточно гибок, чтобы справиться с любым количеством полей, добавляемых в params. Не проверено на производительность, хотя, как и в случае любой операции «все комбинации», вам следует опасаться нелинейного увеличения времени вычислений, поскольку вы добавляете больше полей к params, примечание prod(sz)!

Код, который я показал, быстр, но производительность будет полностью зависеть от того, какие операции вы выполняете в цикле.

% Add parameters here
params.corrAs = {'objective', 'constraint'};
params.size = {'small', 'medium', 'large'};
params.density = {'uniform', 'non-uniform'};

% Setup
f = fieldnames( params );
nf = numel(f);
sz = NaN( nf, 1 );

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

% Loop for every combination of parameters
idx = cell(1,nf);
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:nf
        currentParam.(f{jj}) = params.(f{jj}){idx{jj}};
    end
    % Do something with currentParam here
    % ...
end

Asides:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...