Улучшить производительность кода для решения уравнения

Я новичок в MATLAB, и я изо всех сил пытаюсь найти решение этого уравнения.

введите здесь описание изображения

Где размеры матриц: {λ} = N×K, {Y} = N×D, {π} = 1×K и {µ} = D×K.

То, что я создал, больше похоже на чудовище, чем на эффективный код MATLAB, и это из-за серьезного недостатка навыков работы с MATLAB.

На самом деле, я решил решить это шаг за шагом, чтобы ознакомиться с тем, как работает MATLAB. Я получил крайне неэффективный код, который я даже не могу комбинировать. Даже окончательный результат неверен, так как я хочу создать матрицу NxK. Любое руководство будет высоко оценено.

%Dimensions:
nn = 10;
dd = 7;
kk = 5;

%Initial variables:
lambda0 = rand(nn,kk);
sigma = rand(1);
Y = rand(nn,dd);
mu = rand(dd,kk);

%Calculate pies:
First_part = log(pie(:)./(1.-pie(:))); % Kx1 vector

%Calculate Second part:
for n = 1:nn
for d = 1:dd
lambda_mu(d,:) = lambda0(n,:).*mu(d,:); %lambdamu is a DxK matrix
end
lambda_mu2(n,:) = sum(lambda_mu,2); %This is a NXD matrix
end

%Y-lambdamu2:
for n = 1:nn
YY(n,:) = Y(n,:)-lambda_mu2(n,:); % This is a NxD vector
end

%YY*mu:
Second = (YY*mu)./sigma^2; % NxK

%Third:
Third = (mu'*mu)./2*sigma^2; % KxK

%Final:
for n=1:nn
Final_part = transpose(First_part(:))+Second(n,:)-Third;
end

Обновление1: Хорошо, я должен себе пиво. Итак, я добился некоторого прогресса в создании матрицы {λ} = N×K, изменив свой код следующим образом:

Обновление[2]: Вы слишком много времени тратите на программирование и упускаете детали. Я исправил ошибку, так как установил {Y} = D×K вместо {Y} = D×N.

%Dimensions:
nn = 10;
dd = 7;
kk = 5;

%Initial variables:
lambda0 = rand(nn,kk);
sigma = rand(1);
Y = rand(dd,nn);
mu = rand(dd,kk);
pie = rand(1,kk);
sigma = rand(1);

%Calculate the equation.
for n = 1:nn
for k = 1:kk
    lambda(n,k) = log(pie(k)/(1-pie(k))) + (transpose(Y(:,n)-... 
        (sum(lambda0(n,1:end ~= k).*mu(:,1:end ~= k),2)))*mu(:,k))/...
        sigma^2 - transpose(mu(:,k))*mu(:,k)/2*sigma^2;
end
end

Но теперь проблема в том, что это происходит только до n=5, когда я пытаюсь выполнить цикл для n=6, например, я получаю это сообщение: "Индекс превышает размеры матрицы", так что практически я получаю только 5× 5 матрица. Ваши предложения?

PS: я даже пытался изменить лямбду с лямбда (n, k) на лямбда (k, n), но результат тот же.


person Jespar    schedule 08.12.2016    source источник
comment
Спасибо за хорошо поставленный вопрос, я не понимаю, почему кто-то проголосовал за него - незаслуженно. К сожалению, в данный момент я ничем не могу помочь, но держитесь, кто-нибудь придет.   -  person Rody Oldenhuis    schedule 08.12.2016
comment
Вы уверены в указанных вами размерах? Мне кажется, это не имеет особого смысла. Можете ли вы дать какой-нибудь источник относительно того, что такое уравнение? Я бы хотел помочь, но то, что происходит на заднем плане, для меня немного загадка без какой-либо предыстории.   -  person Franz Hahn    schedule 08.12.2016
comment
Эй, @RodyOldenhuis, спасибо за редактирование!   -  person Jespar    schedule 08.12.2016
comment
@FranzHahn похожую проблему можно найти здесь: mlg.eng.cam. ac.uk/zoubin/course04/lect7var.pdf (страница 9), а расширение, которое я пытаюсь решить, находится на странице 10 в самом низу. Размеры правильные, но я борюсь в основном из-за того, что есть матрицы с разными размерами, которые мне приходится комбинировать в рамках одного вычисления. В любом случае, я все еще работаю над этим, и я опубликую свой прогресс.   -  person Jespar    schedule 08.12.2016
comment
Вы не можете добавлять/вычитать части Kx1, NxK и KxK. Это не имеет смысла ни в Matlab, ни в математике (или я что-то упустил).   -  person Solstad    schedule 08.12.2016
comment
Когда я прочитал уравнение, λ_i^(n) — скаляр, поэтому λ^(n) — вектор. First_part есть log чего-то (следовательно, скалярного). Таким образом (из Third_part) µ_i должно быть Kx1; и (из Second_part) y^(n) также является Kx1.   -  person Solstad    schedule 08.12.2016
comment
@Solstad Вот почему я так сбит с толку. На самом деле это не λ_i^n; λ — матрица размерности N×K с n строками и i столбцами. Если вы проверите ссылку, которую я отправил Францу, вы увидите исходное уравнение на странице 9, но я пытаюсь понять, как решить уравнение внизу страницы 10 (E-шаг, чтобы найти λ).   -  person Jespar    schedule 08.12.2016
comment
Я проверил ссылку, но слайды не добавляют больше информации. Но я думаю, я понял идею. Экв. описывает каждый элемент в λ, так что, например. First_part нужно умножить на ones(1,kk).   -  person Solstad    schedule 08.12.2016
comment
@Solstad, хахаха, расскажи мне об этом. Я знаю, слайды не идеальны, и я пытаюсь найти решение. Вы знаете, поскольку окончательное λ должно иметь форму матрицы N × K, я думаю, вместо того, чтобы держать n фиксированным и зацикливаться на K, чтобы сделать обратное и посмотреть, работает ли это. Тот факт, что вам нужно вычислить матрицы, которые также имеют D-размерность, не облегчает задачу. Я попытаюсь реализовать решение уравнения на странице 9, самое простое, а затем перейду к более высоким измерениям.   -  person Jespar    schedule 08.12.2016
comment
И ones(nn,kk) нужно умножить на Third_part и новый KxK First_part. Таким образом, давая матрицы NxK для сложения/вычитания.   -  person Solstad    schedule 08.12.2016


Ответы (1)


Чтобы получить рабочие размеры, умножьте на ones(nn,kk) и ones(1,kk)

nn = 10;
dd = 7;
kk = 5;

%Initial variables:
lambda0 = rand(nn,kk);
sigma = rand(1);
Y = rand(nn,dd);
mu = rand(dd,kk);
pie = rand(kk,1);

%Calculate pies:
First_part = ones(nn,kk)*log(pie./(1.-pie))*ones(1,kk); % Kx1 vector

%Calculate Second part:
for n = 1:nn
    for d = 1:dd
        lambda_mu(d,:) = lambda0(n,:).*mu(d,:); %lambdamu is a DxK matrix
    end
    lambda_mu2(n,:) = sum(lambda_mu,2); %This is a NXD matrix
end

%Y-lambdamu2:
for n = 1:nn
    YY(n,:) = Y(n,:)-lambda_mu2(n,:); % This is a NxD vector
end

%YY*mu:
Second_part = (YY*mu)./sigma^2; % NxK

%Third:
Third_part = ones(nn,kk)*(mu'*mu)./2*sigma^2; % KxK


%Final:
for n=1:nn
    Final_part(n,:) = First_part(n,:)+Second_part(n,:)-Third_part(n,:);
end

РЕДАКТИРОВАТЬ: я больше думал о:

%Initial variables:
lambda = rand(nn,kk);
sigma = rand(1);
y = rand(nn,1);
mu = rand(nn,kk);
pie = rand(1,kk);

%Calculate pies:
First_part = ones(nn,1)*log(pie./(1-pie)); % NxK vector

во избежание петель.

Возможно, используйте что-то вроде:

ones(kk)-diag([ones(kk,1)])

при выполнении сумма по i не равна j, или, скорее, использовать третье измерение для представления j.

person Solstad    schedule 08.12.2016
comment
Я только что заметил, что что-то не так с lambda0(n,:).*mu(d,:); %lambdamu is a DxK matrix. Вы поэлементно умножаете NxK на матрицы DxK. - person Solstad; 08.12.2016
comment
Можете ли вы объяснить, что такое измерение D (dd) в уравнении? - person Solstad; 08.12.2016
comment
Я бы переписал все это более систематически, чтобы n было первым измерением, i — вторым, а j — третьим, последовательно. Кроме того, я бы использовал матричную алгебру, а не цикл (для повышения производительности кода). - person Solstad; 08.12.2016
comment
Спасибо @Solstad, после неэффективно большого количества попыток и ошибок мне удалось создать код с как можно меньшим количеством строк. Пожалуйста, проверьте это и дайте мне знать ваше мнение. - person Jespar; 08.12.2016
comment
Теперь вы выполняете только цикл, так что это может быть не так эффективно, но, вероятно, его легче проверить. Вы знаете, получите ли вы правильный ответ или нет? - person Solstad; 13.12.2016