📚旁征博引

振荡 谐波生成 自动微分 神经形态计算 梯度学习 反向传播 雅可比矩阵

🎯要点

🎯使用受控物理变换序列实现可训练分层物理计算 | 🎯多模机械振荡、非线性电子振荡器和光学二次谐波生成神经算法验证 | 🎯训练输入数据,物理系统变换产生输出和可微分数字模型估计损失的梯度 | 🎯多模振荡对输入数据进行可控卷积 | 🎯物理神经算法数学表示、可微分数学模型 | 🎯MNIST和元音数据集评估算法。

🍪语言内容分比

pie title 语言分比
 "Python":90
 "PyTorch":80
 "C++":20
 "C":10
pie title 内容分比
"算法模型":90
"数学":50
"物理":30
"多模机械振荡、非线性电子振荡和光学谐波":50
"神经网络":60
"分类器":60
"自动微分":40
"雅可比向量积":20

✂️梗概

🍇PyTorch可微分优化

假设张量$x$是元参数,a是普通参数(例如网络参数)。我们有内部损失 $L ^{\text {in }}=a_0 \cdot x^2$ 并且我们使用梯度 $\frac{\partial L ^{\text {in }}}{\partial a_0}=x^2$ 更新 $a$和 $a_1=a_0-\eta \frac{\partial L ^{\text {in }}}{\partial a_0}=a_0-\eta x^2$。然后我们计算外部损失 $L ^{\text {out }}=a_1 \cdot x^2$。因此外部损失到 x 的梯度为:

$$ \begin{aligned} \frac{\partial L ^{\text {out }}}{\partial x} & =\frac{\partial\left(a_1 \cdot x^2\right)}{\partial x} \\ & =\frac{\partial a_1}{\partial x} \cdot x^2+a_1 \cdot \frac{\partial\left(x^2\right)}{\partial x} \\ & =\frac{\partial\left(a_0-\eta x^2\right)}{\partial x} \cdot x^2+\left(a_0-\eta x^2\right) \cdot 2 x \\ & =(-\eta \cdot 2 x) \cdot x^2+\left(a_0-\eta x^2\right) \cdot 2 x \\ & =-4 \eta x^3+2 a_0 x \end{aligned} $$

鉴于上述分析解,让我们使用 TorchOpt 中的 MetaOptimizer 对其进行验证。MetaOptimizer 是我们可微分优化器的主类。它与功能优化器 torchopt.sgdtorchopt.adam 相结合,定义了我们的高级 API torchopt.MetaSGDtorchopt.MetaAdam

首先,定义网络。

 from IPython.display import display
 ​
 import torch
 import torch.nn as nn
 import torch.nn.functional as F
 ​
 import torchopt
 ​
 ​
 class Net(nn.Module):
     def __init__(self):
         super().__init__()
         self.a = nn.Parameter(torch.tensor(1.0), requires_grad=True)
 ​
     def forward(self, x):
         return self.a * (x**2)

然后我们声明网络(由 a 参数化)和元参数 x。不要忘记为 x 设置标志 require_grad=True

 net = Net()
 x = nn.Parameter(torch.tensor(2.0), requires_grad=True)

接下来我们声明元优化器。这里我们展示了定义元优化器的两种等效方法。


 optim = torchopt.MetaOptimizer(net, torchopt.sgd(lr=1.0))
 optim = torchopt.MetaSGD(net, lr=1.0)

元优化器将网络作为输入并使用方法步骤来更新网络(由a参数化)。最后,我们展示双层流程的工作原理。

 inner_loss = net(x)
 optim.step(inner_loss)
 ​
 outer_loss = net(x)
 outer_loss.backward()
 # x.grad = - 4 * lr * x^3 + 2 * a_0 * x
 #        = - 4 * 1 * 2^3 + 2 * 1 * 2
 #        = -32 + 4
 #        = -28
 print(f'x.grad = {x.grad!r}')