3

I have this complicated MATLAB expression that I would like to simplify, so that I can actually understand it.

g = repmat(log(p), [size(x, 1), 1])
    for i = 1:size(mu, 1)
        g(:, i) = g(:, i) - sum(log(sigma(i, :)));
        g(:, i) = g(:, i) - sum(bsxfun(@rdivide, bsxfun(@minus, x, mu(i, :)).^2, 2*sigma(i, :).^2), 2);
    end

p=1x2
sigma=2x2
mu=2x2
x=30x2

Basically these bsxfun functions confuse me a lot. I would like to express it in the form of simple for loops.

I tried something like this:

[m,n] = size(x)
for i=1:m
        for j=1:n
            g(i,j)= log(p(j)) - sum(log(sigma(j))) - sum(data(i,j))... ;
        end
    end

Not quite sure how to continue from this point, mostly errors and wrong results!

Adriaan
  • 17,741
  • 7
  • 42
  • 75
Th. Mtt.
  • 55
  • 3

2 Answers2

4

I'll just explain you bsxfun, since interchanging that for a for loop is like interchanging your car for a bicycle in terms of speed.

A general introduction to bsxfun can be found here in this fantastic answer by Divakar.

Let's cut your program down piece by piece:

bsxfun(@minus, x, mu(i, :))

This simply tells you that each element in x is subtracted (@minus) from each element in mu(i,:). Now this bsxfun is nested into another:

bsxfun(@rdivide, bsxfun(@minus, x, mu(i, :)).^2, 2*sigma(i, :).^2)

this bsxfun divides two things, hence the rdivide. Each element obtained by the subtraction of the previously discussed bsxfun is divided by each element in 2*sigma(i,:).^2, which is an array.

Finally, the sum of the entire thing is taken to obtain a single value. That's subtracted from the original entry for g(:,i) for every instance of i.

Note that it is very bad practise to use i or j as a variable, so one of the improvements of that code should be to change i to e.g. ii or n or whatever not built-in function; or, as Divakar was kind enough to show in his answer, just get rid of all the loops entirely.

Community
  • 1
  • 1
Adriaan
  • 17,741
  • 7
  • 42
  • 75
3

Apparently the code in the question could be used as a nice bsxfun and permute practice session to vectorize everything. I understand this is going the other way from what's asked in the question, but take it as an alternative solution.

Coming back, to actually vectorize everything, you need to extend dimensions with permute and continue on using bsxfun. The implementation would look like this -

%// Vectorize : "g(:, i) = g(:, i) - sum(log(sigma(i, :)))"
parte1 = bsxfun(@minus,g,sum(log(sigma),2).'); %//'

%// Vectorize : "bsxfun(@minus, x, mu(i, :)).^2"
parte2_1 = bsxfun(@minus,x,permute(mu,[3 2 1])).^2;

%// Vectorize : "bsxfun(@rdivide, ...*sigma(i, :).^2)"
parte2 = bsxfun(@rdivide,parte2_1,2*permute(sigma,[3 2 1]).^2);

%// Squeeze in dimensions of the BSXFUN extended array and subtract from parte1
g = parte1 - squeeze(sum(parte2,2));
Divakar
  • 218,885
  • 19
  • 262
  • 358