复杂表达式的简化

Simplification of a complex expression

我有一个复杂的 MATLAB 表达式,我想对其进行简化,以便我能够真正理解它。

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

基本上这些 bsxfun 函数让我很困惑。我想用简单的 for 循环的形式来表达它。

我试过这样的事情:

[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

不太确定如何从这一点继续,主要是错误和错误的结果!

我会向您解释 bsxfun,因为将其换成 for 循环就像将汽车换成自行车在速度方面一样。

可以找到 bsxfun 的一般介绍 here in this fantastic answer by Divakar

让我们把你的程序一段一段地删减:

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

这只是告诉您 x 中的每个元素都从 mu(i,:) 中的每个元素中减去 (@minus)。现在这个 bsxfun 嵌套到另一个:

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

这个 bsxfun 分为两部分,因此 rdivide。前面讨论的bsxfun相减得到的每个元素除以2*sigma(i,:).^2中的每个元素,就是一个数组

最后对整个东西取sum,得到一个单一的值。对于 i.

的每个实例,从 g(:,i) 的原始条目中减去

请注意,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 是非常糟糕的做法,只需完全摆脱所有循环即可。

显然问题中的代码可以用作很好的 bsxfunpermute 练习来向量化所有内容。我知道这与问题中的要求相反,但将其作为替代解决方案。

回来,要实际矢量化所有内容,您需要使用 permute 扩展维度并继续使用 bsxfun。实现看起来像这样 -

%// 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));