Matlab удалить для цикла в матричных вычислениях

Я работаю над проблемой Matlab в соответствии с Matrix. Я думаю, что мой код можно улучшить, удалив цикл for. Но я действительно не знаю, как это исправить. Кто-нибудь может мне помочь? код:

K = 3;
X = [1 2; 3 4; 5 6; 7 8];
idx = [1;2;3;1];
for i = 1:K
    ids = (idx == i);
    centroids(i,:) = sum(bsxfun(@times, X, ids))./ sum(ids);
end

в этом коде точка данных X равна 4x2. Есть K=3 центроидов, поэтому центроиды представляют собой матрицу 3x2. Этот код является частью функции среднего значения, которая использует точки данных и их ближайшие центроиды, чтобы найти новое положение центроидов. Я хочу сделать код как что-то без цикла FOR, возможно, начиная с этого:

ids = bsxfun(@eq, idx, 1:K);
centroids = ..............

2 ответа

Решение

Вы можете избежать bsxfun с помощью логического индексирования это кажется значительным увеличением производительности, по крайней мере, для небольших матриц X, Это лучше для маленьких Kи для небольшого числа рядов X,

K = 3;
X = [1 2; 3 4; 5 6; 7 8];
idx = [1;2;3;1];
centroids=zeros(K,2);
for i = 1:K
    ids = (idx == i);
    centroids(i,:) = sum(X(ids,:),1)./sum(ids);
end

Если X имеет большое количество строк, этот метод самый быстрый:

K = 3;
X = [1 2; 3 4; 5 6; 7 8];
idx = [1;2;3;1];
centroids=zeros(K,2);
t=bsxfun(@eq,idx,1:K);
centroids=bsxfun(@rdivide,t.'*X,sum(t).');

И если K очень большой, Луис accumarray метод самый быстрый.

Вы можете подать заявку accumarray, Обратите внимание, что accumarray работает только когда X это столбец. Так что если X имеет две колонки, вы можете позвонить accumarray дважды:

centroids(:,1) = accumarray(idx, X(:,1), [], @mean)
centroids(:,2) = accumarray(idx, X(:,2), [], @mean)

В качестве альтернативы, если X содержит два столбца действительных чисел, вы можете использовать complex "упаковать" два столбца в один сложный столбец, а затем распаковать результаты:

centroids = accumarray(idx, complex(X(:,1),X(:,2)), [], @mean);
centroids = [ real(centroids) imag(centroids)];

Если X имеет произвольное количество столбцов, возможно, с комплексными числами, вы можете перебрать столбцы:

centroids = NaN(K, size(X,2)); %// preallocate
for col = 1:size(X,2);
    centroids(:,col) = accumarray(idx, X(:,col), [], @mean);
end
Другие вопросы по тегам