Реализация градиентного спуска по известной целевой функции - PullRequest
0 голосов
/ 03 мая 2020

У меня есть целевая функция из бумаги, которую я хотел бы минимизировать с помощью градиентного спуска. Мне еще не приходилось делать это «с нуля», и мне хотелось бы получить несколько советов о том, как кодировать это вручную. Целевая функция:

T (L) = tr (XT L ^ s X) - бета * || L ||.

где L - положительная полуопределенная матрица N x N, подлежащая оценке, X - матрица N x M, бета - константа регуляризации, XT = X транспонирование и ||. || это норма Фробениуса.

Кроме того, L ^ s - экспоненциальная матрица, где L ^ s = F Λ ^ s FT, где F - матрица собственных векторов L, а Λ - диагональная матрица собственных значений L.

Производная целевой функции:

dT / dL = sum_ {от r = 0 до r = s - 1} L ^ r (XX.T) L ^ (sr-1) - 2 * beta * L

Я сделал очень элементарные проблемы градиентного спуска (такие как факторизация матрицы), где оптимизация выполняется по каждому элементу матрицы или с использованием пакетов / библиотек. Такая проблема более сложна, к чему я привык, и я надеялся, что некоторые из вас, более опытные в подобных вещах, могут мне помочь.

Любой общий совет высоко ценится, а также конкретные c рекомендации, как закодировать это в python или R.

Вот ссылка на статью с этой функцией: https://journals.plos.org/plosone/article?id=10.1371 / journal.pone.0128136 # sec016

Большое спасибо за вашу помощь!

Пол

1 Ответ

0 голосов
/ 03 мая 2020

В целом, вероятно, было бы целесообразно использовать библиотеку машинного обучения, такую ​​как tenorflow или pytorch. Если вы go пошли по этому маршруту, у вас есть несколько преимуществ: 1) эффективная реализация операций Tensor на C ++ 2) автоматизация c дифференциация 3) легкий доступ к более сложным оптимизаторам (например, ADAM). `Если вы предпочитаете выполнять вычисление градиента самостоятельно, вы можете сделать это, установив градиент L.grad вручную перед этапом оптимизации

Простая реализация будет выглядеть следующим образом:

import torch

n=10
m=20
s = 3
b=1e-3
n_it=40

# L=torch.nn.Parameter(torch.rand(n,n))
F=torch.nn.Parameter(torch.rand(n,n))
D=torch.nn.Parameter(torch.rand(n))
X=torch.rand((n,m))
opt=torch.optim.SGD([F,D],lr=1e-4)


for i in range(n_it):
    loss = (X.T.matmul(F.matmul((D**s).unsqueeze(1)*F.T)).matmul(X)).trace() - b * F.matmul((D**s).unsqueeze(1)*F.T).norm(2)
    print(loss)
    opt.zero_grad()
    loss.backward()
    opt.step()
...