(7)自动微分求解最大本征问题

基于自动微分的基态变分算法

对于优化问题,可以使用自动微分技术求解,该技术在机器学习中具有广泛的应用,被用于计算模型变分参数关于损失函数的梯度(程序中自我计算的),称之为反向传播算法(back propagation,BP)


例:利用自动微分求解实对称矩阵最大本征向量,即求解如下极大值问题
max ⁡ ∣ v ∣ = 1 ∣ v T M v ∣ \max_{|v| = 1}|v^TMv| v=1maxvTMv
定义损失函数 f = − v T M v ∣ v ∣ 2 f = -\frac{v^TMv}{|v|^2} f=v2vTMv,则上述极大化问题被化为损失函数的极小化问题。
计算v关于的 f f f 梯度 d f d v , \frac{d f}{d v}, dvdf, 要使得 f f f 减小, 需将v沿负梯度方向更新
v ← v − η d f d v v \leftarrow v-\eta \frac{d f}{d v} vvηdvdf其中, η \eta η 为人为给定的常数,被称为更新步长学习率

进行多次迭代更新之后,得到收敛的𝑣,则最大本征向量 v ˇ \check{v} vˇ与最大本征值𝜆
满足:
v ~ = v ∣ v ∣ , λ = v ~ T M v ~ \tilde{v}=\frac{v}{|v|}, \quad \lambda=\tilde{v}^{\mathrm{T}} M \tilde{v} v~=vv,λ=v~TMv~


其中, d f d v \frac{d f}{d v} dvdf 梯度可直接使用自动微分技术计算
可使用Pytorch实现自动微分
更新过程中,可使用优化器(optimizer,例如Adam),让程序自适应地控制学习率,以达到较好的稳定性和收敛速率。
上述例子太过简单,其效率显然不如传统的本征值分解算法。但在更为复杂的问题中,自动微分的优势就会被体现出来。

代码

import torch as tc
from scipy.sparse.linalg import eigsh
from BasicFun import eigs_AD

def eigs_AD(mat, lr=1e-2, v0=None, it_time=500, tol=1e-15):
    """
    :param mat: 带分解矩阵
    :param lr: 初始学习率
    :param v0: 初始向量
    :param it_time: 最大迭代次数
    :param tol: 收敛阈值
    :return lm: 最大本征值
    :return v0: 最大本征向量
    """
    # 初始化及预处理v0
    if v0 is None:
        v0 = tc.randn(mat.shape[0], )
    v0 /= v0.norm()
    v0.requires_grad = True#v0是否请求梯度
    # 建立优化器,这里使用Adam优化器,可自动动态控制学习率
    optimizer = tc.optim.Adam([v0], lr=lr)
    v1 = copy.deepcopy(v0.data)#判断收敛性
    # 进入主循环
    for t in range(it_time):
        # 计算损失函数
        f = -v0.matmul(mat).matmul(v0) / v0.matmul(v0)
        f.backward()  # 进行反向传播,计算梯度
        optimizer.step()  # 更新参数
        optimizer.zero_grad()  # 清空梯度
        conv = tc.norm(v0.data - v1) / v1.numel()  # 计算收敛性
        if conv < tol:
            break
        else:
            v1 = copy.deepcopy(v0.data)
    with tc.no_grad():
        v0 = v0 / tc.norm(v0)  # 归一化,计算本征向量
        lm = v0.matmul(mat).max() / v0.max()  # 计算本征值
    return lm, v0

# 自动微分求解实对称矩阵的本征值与本征向量

# 构建随机实对称矩阵
dim = 6
M = tc.randn(dim, dim)
M = M + M.t()


print('利用scipy中的本征值分解求解最大本征值与本征向量')
lm0, v0 = eigsh(M.numpy(), k=1, which='LA')
print('矩阵的最大本征值为:')
print(lm0[0])
print('矩阵的最大本征向量为:')
print(v0.reshape(-1, ))

print('\n利用自动微分求解最大本征值与本征向量')
lm1, v1 = eigs_AD(M)
print('矩阵的最大本征值为:')
print(lm1.item())
print('矩阵的最大本征向量为:')
print(v1.data.to('cpu').numpy().reshape(-1, ))

总结为三步:
1.把需要变分的参数v0设好,把requires_grad打开,把需要变分的东西放入优化器中
2.定义损失函数
3.f.backward() # 进行反向传播,计算梯度
optimizer.step() # 更新参数
optimizer.zero_grad() # 清空梯度


根据最大本征值问题与基态问题的等价性,显然,自动微分方法可用于求解多体系统基态,对应的优化问题可写为:
E = min ⁡ { A ( n ) } ⟨ φ ∣ H ^ ∣ φ ⟩ ⟨ φ ∣ φ ⟩ E=\min _{\left\{A^{(n)}\right\}} \frac{\langle\varphi|\widehat{H}| \varphi\rangle}{\langle\varphi \mid \varphi\rangle} E={A(n)}minφφφH φ其中,变分参数为MPS中的各个张量 { A ( n ) } , \left\{A^{(n)}\right\}, {A(n)}, 梯度更新公式为:
A ( n ) ← A ( n ) − η ∂ E ∂ A ( n ) A^{(n)} \leftarrow A^{(n)}-\eta \frac{\partial E}{\partial A^{(n)}} A(n)A(n)ηA(n)E相比于DMRG中MPS的“重整化群”解释,这里可以更加直接地将MPS看作
是对基态的一种特殊的参数化形式,能量即为变分的损失函数。
可使用BP算法及各种优化器进行梯度更新。

第八节为前面的知识总结

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值