2016-03-22 3 views
1

Мне интересно, если можно использовать двойной bsxfun или что-то подобное. У меня этот кусок кода:Могу ли я избежать двойного forcycle by bsxfun?

N = 5; 
prob = [0.1 0.2 0 0.1; 0 0 0.05 0.1; 0.2 0.2 0 0.1]; 
r = rand(size(prob,1),N); 

P = zeros(N, size(prob,1)); 
csm = cumsum(normP([zeros(size(prob,1),1),prob]),2); 

for i = 1:N 
P(i,:) = sum(bsxfun(@ge,r(:,i),csm),2); 
end 

Проб матрица содержит строки с элементами между 0 и 1, каждая строка распределения вероятностей (после нормализации, проводимой normP). Первая строка матрицы вероятностей используется для генерации первого элемента вектора P (значения 1,2 или 4), второй строки для второго элемента (значения 3 или 4) и т. Д.

e.g.: P = 

     2  4  2 
     4  4  1 
     2  4  2 
     2  4  4 
     2  3  1 

Я уже векторизовал генерирующие элементы для одного вектора P, но мне нужно сгенерировать несколько (N) векторов. Должен быть способ избежать цикла for.

В приложении, есть функция normP. Я буду рад за помощь, спасибо.

Michal Roubalik

P.S. Кодекс normP здесь:

function nP = normP(P) 
% 
% Probability matrix normalization to hold sum of rows be equal to one 
% i.e. sum(nP,2) = ones(N,1) 
% 
% No dependencies 
srowP = sum(P,2); 
good = srowP>0; 
bad = ~good; 
nP = zeros(size(P)); 

% good case 
if any(good) 
    nP(good,:) = bsxfun(@rdivide, P(good,:), srowP(good)); 
end 
% bad case 
if any(bad) 
    nP(bad,:) = nan(size(P(bad,:))); 
end 
+1

Перед тем, как коснуться каких-либо продвинутых материалов, таких как 'bsxfun', сделайте простые оптимизации. 'cumsum (normP ([zeros (size (prob, 1), 1), prob]), 2))' - выражение, которое вы снова и снова оцениваете в своем цикле, предварительно вычислите его за пределами своего цикла. – Daniel

+0

И замените 'nP = нули (размер (P));' с 'nP = nan (size (P));', тогда вы можете удалить '% bad case' – Daniel

+0

спасибо, я изменил код, также Я редактировал код в вопросе. Это примерно на 30% быстрее. :) –

ответ

4

Вот один из способов завершения векторизации с permute -

P = squeeze(sum(bsxfun(@ge,permute(r,[1 3 2]),csm),2)).' 

Объяснения

1) Нажмите тускло-2 r в dim-3 положения приносящего singleton-dim на dim=2. Таким образом, когда в пару с csm для bsxfun(@ge работы, мы получили бы 3D массива в качестве вывода, у которого:

dim-1 : r, csm 's dim-1 
dim-2 : csm's dim-2 
dim-3 : r's dim-2 

2) Оригинальная операция была итеративный выход с dim-2 еще представляющего csm's dim-2 и sum-reduction вдоль нее. Таким образом, в нашем 3D-массиве нам нужно суммировать также по dim-2.

3) Заключительные шаги включают в себя squeeze -инг и транспонирование в соответствии с тем, как мы итерационно сохраняем вывод P.