Упрощение сложного выражения
У меня есть это сложное выражение 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
Не совсем уверен, как продолжить с этого момента, в основном ошибки и неправильные результаты!
2 ответа:
По-видимому, код в вопросе может быть использован в качестве хорошей
bsxfun
иpermute
практической сессии для векторизации всего. Я понимаю, что это идет в другую сторону от того, что задано в вопросе, но примите это как альтернативное решение.Возвращаясь назад, чтобы фактически векторизовать все, вам нужно расширить размеры с помощью
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));
Я просто объясню тебе.
bsxfun
, поскольку замена этого для петлиfor
похожа на замену вашего автомобиля на велосипед с точки зрения скорости.Общее введение в
bsxfun
можно найтиздесь в этом фантастическом ответеДивакара .Давайте сократим вашу программу по частям:
Это просто говорит вам, что каждый элемент вbsxfun(@minus, x, mu(i, :))
x
вычитается (@minus
) из каждого элемента вmu(i,:)
. Теперь этоbsxfun
вложено в другой:bsxfun(@rdivide, bsxfun(@minus, x, mu(i, :)).^2, 2*sigma(i, :).^2)
Это
bsxfun
разделяет две вещи, следовательно,rdivide
. Каждый элемент, полученный вычитанием из ранее рассмотренногоbsxfun
, делится на каждый элемент в2*sigma(i,:).^2
, который является массивом.Наконец,
sum
всей вещи берется для получения одного значения. Это вычитается из исходной записи дляg(:,i)
для каждого экземпляраi
.Обратите внимание, что это очень плохая практика использовать
i
илиj
в качестве переменной , так что один из улучшений этого кода следует изменитьi
на, например,ii
илиn
или любую другую не встроенную функцию; или, как Дивакар любезно показал в своем ответе, просто полностью избавиться от всех циклов.