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