我正在尝试使用MXNet的图形结构来加速某些计算,我目前正在尝试模仿我已经在PyTorch中实现的行为。但是,我对如何正确执行此操作感到困惑,无论是gluon.Trainer
还是其他方法。
为了解释一个例子,我在PyTorch中工作的是以下内容(略微修改以尝试给出最简单的示例),并且我想将其转换为MXNet。
import torch.optim
def unconstrained_fit(objective, data, pdf, init_pars, tolerance):
init_pars.requires_grad = True
optimizer = torch.optim.Adam([init_pars])
max_delta = None
n_epochs = 10000
for _ in range(n_epochs):
loss = objective(init_pars, data, pdf)
optimizer.zero_grad()
loss.backward()
init_old = init_pars.data.clone()
optimizer.step()
max_delta = (init_pars.data - init_old).abs().max()
if max_delta < tolerance:
break
return init_pars
作为The Straight Dope points out in the PyTorch to MXNet cheatsheet,在MXNet中,人们通常可以使用培训师,其中人们会使用optimizer in PyTorch。但是,我不明白如何在我的案例中正确初始化培训师,因为人们通常会按照
的方式做一些事情。trainer = gluon.Trainer(net.collect_params(), 'adam')
我认为我需要自己收集参数,因为我没有我想要使用的神经网络,而是我想要最小化的objective
。我对如何正确地做到这一点很困惑,因为下面显然不正确。
import mxnet as mx
from mxnet import gluon, autograd
def unconstrained_fit(self, objective, data, pdf, init_pars, tolerance):
ctx = mx.cpu()
# How to properly do this chunck?
init_pars = mx.gluon.Parameter('init_pars',
shape=init_pars.shape,
init=init_pars.asnumpy().all)
init_pars.initialize(ctx=ctx)
optimizer = mx.optimizer.Adam()
trainer = gluon.Trainer([init_pars], optimizer)
###
max_delta = None
n_epochs = 10000
for _ in range(n_epochs):
with autograd.record():
loss = objective(init_pars, data, pdf)
loss.backward()
init_old = init_pars.data.clone()
trainer.step(data.shape[0])
max_delta = (init_pars.data - init_old).abs().max()
if max_delta < tolerance:
break
return init_pars
我显然误解了一些基本的东西,所以如果有人能指出我澄清一些有用的东西。更有帮助的是,如果有人理解我的要求并且能够总结为什么我所做的是错误的。
答案 0 :(得分:1)
胶子中的训练师只是根据优化器更新一组参数。您需要将目标函数中要优化的参数传递给它。已经有几点了:
Trainer
需要ParameterDict
,而不是Parameter[]
。.data()
来获取参数的数据,而不是.data
。如果您发布了目标函数,错误日志,我可以帮助您。
同样使用Trainer
不是强制性的。请看一下本教程:https://github.com/zackchase/mxnet-the-straight-dope/blob/master/chapter02_supervised-learning/linear-regression-scratch.ipynb它仅从头开始执行线性回归优化,仅使用NDArray
和autograd
。
一个关键点是为参数附加一个渐变,以分配内存,以便在使用autograd.record()
时可以存储渐变(这里有两个参数,w
和b
):< / p>
w = nd.random_normal(shape=(num_inputs, num_outputs), ctx=model_ctx)
b = nd.random_normal(shape=num_outputs, ctx=model_ctx)
params = [w, b]
for param in params:
param.attach_grad()
然后在调用loss.backward()
之后,您可以访问每个参数的渐变并使用SGD公式更新它们,如下所示:
for param in params:
param[:] = param - lr * param.grad