chappa
chappa

Reputation: 95

Subtracting a row vector from every Row in a matrix

I was trying out something in an assignment I had. I wanted to subtract a row vector from every row of matrix(and then do further computations on it). I have a matrix "X" of dimensions m X n and another one centroid of dimension K x n. I tried two varients,

function idx = findClosestCentroids(X, centroids)
K = size(centroids, 1);
m=size(X,1);
n=size(X,2);
idx = zeros(size(X,1), 1);

% ====================== CODE ======================
% Instructions: Go over every example, find its closest centroid, and store
%               the index inside idx at the appropriate location.
%               Concretely, idx(i) should contain the index of the centroid
%               closest to example i. Hence, it should be a value in the 
%               range 1..K


%This Doesnt Work
% for i=1:m
        % temp=ones(size(centroids))*diag(X(i))-centroids;
        % temp=temp.^2;
        % [x,y]=min(sum(temp,2));
        % idx(i)=y;
% endfor


%This works!
for i=1:m
    mini=1e10;
    minin=-1;
    for j=1:K
        temp=X(i,:)-centroids(j,:);
        temp=temp.^2;
        sumx=sum(temp);
        if (sumx<mini)
            mini=sumx;
            minin=j;
        endif
    endfor
    idx(i)=minin;
endfor

% =============================================================

end

The first one works while the second one doesn't even though acc. to what I tried, second is just the vectorized version of the first one. Please guide me through the vectorization.

Upvotes: 0

Views: 1259

Answers (2)

Megh Parikh
Megh Parikh

Reputation: 964

Less parallelized than the other answer but much more easier to read:

for i = 1:size(X,1)
  % z = centroids .- X(i, :); // Only Octave compatible
  z = bsxfun(@minus, centroids, X(i, :));
  zy = sum(z.^2, 2);
  [~, idx(i)] = min(zy);
end

Upvotes: 0

Divakar
Divakar

Reputation: 221524

If you are looking for a MATLAB implementation, think this might serve your vectorization needs -

%%// Spread out centroids to the third dimension so that the singleton
%%// second dimension thus created could be used with bsxfun for expansion in
%%// that dimension
centroids1 = permute(centroids,[3 2 1]);

%%// Perform the much-needed subtraction 
t1 = bsxfun(@minus,X,centroids1)

%%// Perform element-wise squaring and then min-finding as required too
t2 = t1.^2
t3 = sum(t2,2)

%%// Since the expansion resulted in data in third dimension, min-finding
%%// must be along it
[mini_array,idx] = min(t3,[],3)

Also, allow me to suggest an edit in your loop code. If you are interested in storing the minimum values as well at the end of each outer loop iteration, you might as well store it with something like min_array(i) = mini, just like you did when storing the indices.

Upvotes: 2

Related Questions