2013-06-18 3 views
3

У меня есть набор данных, X, то есть m x 2, и три вектора, хранящиеся в матрице C = [c1'; c2'; c3'], то есть 3 x 2. Я пытаюсь провести векторный код моего кода, который находит для каждой точки данных в X, какой вектор в C находится ближе всего (квадрат расстояния). Я хотел бы вычесть каждый вектор (строку) в C из каждого вектора (строки) в X, в результате получилась матрица различий между элементами X и элементами C. Моя текущая реализация делает эту одну строку в X в то время:Вычитание нескольких векторов из каждой строки массива (супервещание)

for i = 1:size(X, 1) 
    diffs = bsxfun(@minus, X(i,:), C); % gives a 3 x 2 matrix result 
    [~, idx(i)] = min(sumsq(diffs), 2); % returns the index of the closest vector 
              % in C to the ith vector in X 
end 

Я хочу, чтобы избавиться от этого for петли и просто векторизации все это, но bsxfun(@minus, X, C) дает мне ошибку в октаву:

error: bsxfun: nonconformant dimensions: 300x2 and 3x2

Любые идеи, как я могу «транслировать» мою операцию вычитания между этими двумя матрицами?

ответ

5

Ядро этой проблемы заключается в вычислении расстояния матрицы D размера m x 3, который содержит попарные расстояния между всеми точками данных в X и все точки данных в C. Евклидово расстояние между г-го вектора x_i в X и -го вектора c_j в C можно переписать в виде:

|x_i-c_j|^2 = |x_i|^2 - 2<x_i, c_j> + |c_j|^2 

<, где,> относится к внутреннему продукту. Правую часть этого уравнения можно легко векторизовать, так как скалярное произведение всех пар равно X * C', которое является операцией BLAS3. Этот способ вычисления матрицы расстояния известен как функция dist2 в книге «Распознавание образов и машинное обучение» Кристофера Бишопа. Я скопирую функцию ниже с небольшой модификацией.

function D = dist2(X, C)   
    tempx = full(sum(X.^2, 2)); 
    tempc = full(sum(C.^2, 2).'); 
    D = -2*(X * C.'); 
    D = bsxfun(@plus, D, tempx); 
    D = bsxfun(@plus, D, tempc); 

full здесь используется в случае X или C является разреженной матрицей.

Примечание: матрица расстояний D, рассчитанная таким образом, может иметь незначительные отрицательные значения из-за ошибки округления. Чтобы защититься от этого случая, используйте

D = max(D, 0); 

Индексы ближайшего вектора в C может быть получен из D:

[~, idx] = min(D, [], 2); 
+0

Из любопытства, у вас есть хороший способ избежать временных переменных в том случае, если мои данные очень велики? Будет ли это замедлять выполнение? Я использую это для алгоритма K, поэтому он должен его называть довольно часто. – Engineero

+0

Это замечательно. Я тестировал его, и это определенно ускоряет выполнение. Большое спасибо! Теперь мне просто нужно выяснить, как сделать аналогичную векторию для нахождения среднего значения всех точек, ближайших к каждой из центроидов в моей матрице 'C'. Этот цикл выполняется только один раз для каждого вектора в 'C', который обычно намного меньше, чем для' X'. – Engineero

+2

@ Engineero: Посмотрите на его [веб-страницу] (http://www.cc.gatech.edu/~dkuang3/software/kmeans3.html) - я думаю, вы найдете это интересным :) –

0

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

PDIST2 Pairwise distance between two sets of observations. D = PDIST2(X,Y) returns a matrix D containing the Euclidean distances between each pair of observations in the MX-by-N data matrix X and MY-by-N data matrix Y.

Так что в вашем случае,

[~, which_C] = min(pdist2(X,C), [], 2); 

- это то, что вы ищете.

В качестве альтернативы, вы можете использовать эту красоту:

[~, which_c] = min(sum(bsxfun(@minus, X, permute(C, [3 2 1])).^2, 2), [], 3); 

который бы не выиграть ни одного приза для удобочитаемости, надежности или управляемости, но вы получите некоторую скорость (и потребность в инструментарии, заметьте:)

+0

Если вы видите реализацию 'pdist' для евклидова расстояния, вы увидите, что оно не векторизовано. –

+0

@DaKuang: Хорошо, см. Мое последнее редактирование. –

+0

@DaKuang: Вы использовали время для обоих методов? Я предполагаю, что это не будет сильно отличаться (если у вас включен JIT) ... –