MGA
MGA

Reputation: 1668

Vectorizing a weighted sum of matrices in MATLAB

I'm trying to vectorize the following operation in MATLAB, but it's got me stumped. I've learned from experience that there usually is a way, so I'm not giving up just yet. Any help would be appreciated.

I have a collection of m row-vectors each of size n, arranged in an m x n matrix; call it X.

I also have an m-sized vector of weights, w.

I want to compute a weighted sum of the matrices formed by the self outer products of the vectors in X.

Here is a MWE using a for loop:

m = 100;
n = 5;

X = rand(m, n);
w = rand(1, m);

S = zeros(n, n);
for i = 1 : m
    S = S + (w(i) * X(i, :)' * X(i, :));
end

S

Upvotes: 4

Views: 1066

Answers (3)

RocketDocRyan
RocketDocRyan

Reputation: 11

Shortest answer, and probably fastest:

S = X'*diag(W)*X

Been using it for an unscented Kalman filter, works great.

Upvotes: 1

Luis Mendo
Luis Mendo

Reputation: 112669

This is probably the fastest approach:

S = X' * bsxfun(@times, X, w(:));

You could also do

S = squeeze(sum(bsxfun(@times, ...
    bsxfun(@times, conj(X), permute(X, [1 3 2])), w(:)), 1));

(or remove the complex conjugate if not needed).

Upvotes: 3

Divakar
Divakar

Reputation: 221554

You can employ two approaches here that use one bsxfun call and few permutes and reshapes. The reshaping trick basically allows us to use the efficient matrix multiplication and thus avoid any extra bsxfun call we might have required otherwise.

Approach #1

[m1,n1] = size(X);
XXmult = bsxfun(@times,X,permute(X,[1 3 2])); %// For X(i, :)' * X(i, :) step
S = reshape(reshape(permute(XXmult,[2 3 1]),[],m1)*w(:),n1,[]) %// multiply weights w

Approach #2

[m1,n1] = size(X);
XXmult = bsxfun(@times,permute(X,[2 3 1]),permute(X,[3 2 1]));
S = reshape(reshape(XXmult,[],m1)*w(:),n1,[])

Upvotes: 3

Related Questions