使用已知 objective 函数实现梯度下降
Implementing gradient descent on with known objective function
我有一篇论文中的 objective 函数,我想用梯度下降法将其最小化。我还没有必须这样做 "from scratch" 并且想要一些关于如何手动编码的建议。 objective函数是:
T(L) = tr(X.T L^s X) - beta * ||L||。
其中 L 是待估计的 N x N 矩阵半正定矩阵,X 是 N x M 矩阵,beta 是正则化常数,X.T = X 转置,||。||是弗罗贝尼乌斯范数。
此外,L^s 是矩阵指数,其中 L^s = F Λ^s F.T,其中 F 是 L 的特征向量的矩阵,Λ 是 L 的特征值的对角矩阵。
objective函数的导数是:
dT/dL = sum_{from r = 0 to r = s - 1} L^r (XX.T) L^(s-r-1) - 2 * beta * L
我已经完成了非常基本的梯度下降问题(例如矩阵分解),其中对矩阵的每个元素进行了优化,或者使用 packages/libraries。这种问题比较复杂,我已经习惯了,我希望你们中一些对这类事情更有经验的人可以帮助我。
非常感谢任何一般性建议以及关于如何在 python 或 R 中对此进行编码的具体建议。
这是具有此功能的论文的link:
https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0128136#sec016
非常感谢您的帮助!
保罗
一般来说,最好使用机器学习库,例如 tensorflow 或 pytorch。如果你沿着这条路走下去,你有几个优势 1)张量操作的高效 C++ 实现 2)自动微分 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()
我有一篇论文中的 objective 函数,我想用梯度下降法将其最小化。我还没有必须这样做 "from scratch" 并且想要一些关于如何手动编码的建议。 objective函数是:
T(L) = tr(X.T L^s X) - beta * ||L||。
其中 L 是待估计的 N x N 矩阵半正定矩阵,X 是 N x M 矩阵,beta 是正则化常数,X.T = X 转置,||。||是弗罗贝尼乌斯范数。
此外,L^s 是矩阵指数,其中 L^s = F Λ^s F.T,其中 F 是 L 的特征向量的矩阵,Λ 是 L 的特征值的对角矩阵。
objective函数的导数是:
dT/dL = sum_{from r = 0 to r = s - 1} L^r (XX.T) L^(s-r-1) - 2 * beta * L
我已经完成了非常基本的梯度下降问题(例如矩阵分解),其中对矩阵的每个元素进行了优化,或者使用 packages/libraries。这种问题比较复杂,我已经习惯了,我希望你们中一些对这类事情更有经验的人可以帮助我。
非常感谢任何一般性建议以及关于如何在 python 或 R 中对此进行编码的具体建议。
这是具有此功能的论文的link: https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0128136#sec016
非常感谢您的帮助!
保罗
一般来说,最好使用机器学习库,例如 tensorflow 或 pytorch。如果你沿着这条路走下去,你有几个优势 1)张量操作的高效 C++ 实现 2)自动微分 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()