Быстрые альтернативы fmincon для логарифмического правдоподобия

В настоящее время я использую fmincon для минимизации функции логарифмического правдоподобия в отношении матрицы 18 * 18. В то время как на небольших проблемах алгоритм очень быстр, для сходимости в текущей настройке требуется около 2 часов - поскольку я повторяю эту проблему минимизации, выполнение кода может занять до 2 недель.

Существует ли бесплатная альтернатива fmincon на основе Matlab, которая повышает скорость решения таких конкретных задач? (Дорогие решения обсуждаются здесь, решения, не относящиеся к Matlab, здесь.) Или мне нужно будет вызвать, например. скрипт на питоне из матлаба?

Функция, которую я хочу минимизировать:

function [L] = logL(A, U, Sigma_e, T, lags)
% A - parameters to optimize w.r.t

logL = 0;
for t = 1 : T - lags
   logL(t, 1) = 0.5*(log(det(A * diag(Sigma_e(t,:)) * A' ) ) + ...
                U(t,:) * (A * diag(Sigma_e(t,:))  * A' )^(-1) *  U(t,:)' );

end
L = sum(logL);

и вызывая его:

Options = optimset('Algorithm', 'active-set', 'Display', 'off', 'Hessian','bfgs', ...
'DerivativeCheck','on','Diagnostics','off','GradObj','off','LargeScale','off'); 


A = fmincon( @(A0)logL(A0, U, Sigma_e, T, lags), A0 , [], [] , [] , [] , [] , [] , [], Options); 

(Я пробовал разные алгоритмы fmincon без особых улучшений). Обратите внимание, T довольно велико ~ 3000. A и A0 — матрицы 18*18, Sigma_e равно T*18, U это Т * 18

Загадки Python - Генерация простых чисел!
Загадки Python - Генерация простых чисел!
Обычно существует несколько способов решения задач даже пограничной сложности. Как же определить оптимальное и эффективное решение?
0
0
150
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не знаю какой-либо быстрой альтернативы fminconst, но вы можете векторизовать функцию logL, чтобы ускорить алгоритм. Вот векторизованная версия:

function [L] = logL(A, U, Sigma_e, T, lags)
    ia = inv(A);
    iat = ia.';
    N = T - lags;
    UU = zeros(N,1); 
    for t = 1: N
        UU (t) = U(t,:) * (iat .* 1./Sigma_e(t,:) * ia) * U(t,:)';
    end

    L =  0.5 *sum( log(det(A) ^ 2  .* prod(Sigma_e(1:N,:),2)) + UU);
end

В некоторых тестах в Octave это почти в 10 раз быстрее, чем ваше решение.

Обратите внимание, что если некоторые элементы Sigma_e равны нулю, вам нужно вычислить UU как:

UU (t)=U(t,:) * (A * diag(Sigma_e(t,:))  * A' )^(-1) *  U(t,:)';

Эти отношения используются для преобразования решения цикла в векторизованное:

det(a * b * c) == det(a) * det(b) * det(c)

det(a) == det(a.')

det(diag(a)) == prod(a)

(a * b * c)^-1 == c^-1 * b^-1 * a^-1

a * diag(b) == a .* b

inv(diag(a)) == diag(1./a)

Обратите внимание: этот подход работает только для версий Matlab 2016 и выше. Для версий ниже поэлементное умножение первого уравнения UU(t) необходимо будет переписать, используя, например, bsxfun.

Luks 22.05.2019 18:37

Другие вопросы по теме