2015-10-11 2 views
3

У меня есть это сложное выражение 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 

Не совсем уверен, как продолжить с этой точки, в основном ошибки и неправильные результаты!

ответ

3

Видимо, код в вопросе может быть использован как хороший 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)); 
+0

Путь к сэнсэю, векторизация его 'bsxfun' еще больше! – Adriaan

+0

@Adriaan Эта первая строка предназначена для вас :) – Divakar

+0

Мысль столько. Завтра я освою! – Adriaan

4

Я просто объясню вам bsxfun, так как замена этого на петлю for похожа на перестановку вашего автомобиля на велосипед с точки зрения скорости.

Общее введение в bsxfun можно найти here в этом фантастическом ответе Divakar.

Давайте сократить вашу программу вниз по кусочкам:

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.

Обратите внимание, что это очень плохая практика для use i or j as a variable, поэтому одним из улучшений этого кода должно быть изменение i, например. ii или n или независимо от встроенной функции; или, поскольку Дивакар был достаточно любезен, чтобы показать в his answer, просто полностью избавиться от всех петель.

Смежные вопросы