使用mxnet的简单梯度下降
gradient-descent
mxnet
python
11
0

我正在尝试使用MXNet的梯度下降优化器来最小化功能。 Tensorflow中的等效示例将是:

import tensorflow as tf

x = tf.Variable(2, name='x', dtype=tf.float32)
log_x = tf.log(x)
log_x_squared = tf.square(log_x)

optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(log_x_squared)

init = tf.initialize_all_variables()

def optimize():
  with tf.Session() as session:
    session.run(init)
    print("starting at", "x:", session.run(x), "log(x)^2:", session.run(log_x_squared))
    for step in range(10):  
      session.run(train)
      print("step", step, "x:", session.run(x), "log(x)^2:", session.run(log_x_squared))

我不确定如何在MXNet中完成相同的任务。优化器API 文档似乎没有等效的方法。到目前为止,这是我尝试过的。主要的困惑在于需要传递训练数据:

import mxnet as mx

x = mx.sym.Variable('data')
log_x = mx.sym.log(x)
log_x_squared = mx.sym.square(log_x)

mod = mx.mod.Module(log_x_squared)  # Create a module where the loss function
                                    # is the one we want to optimize
mod.bind(data_shapes=[('data', (1,1))])  # ?? not sure if this is correct - we
                                         # are saying our input is a scalar
mod.init_params()
mod.init_optimizer()  # SGD is default

mod.fit()  # ?? must pass data_iter to fit

似乎应该以某种方式将x变量作为data_iter反馈回来,但我不知道该如何完成。

更新:感谢kevinthesun的出色回答!这是建立在单个隐藏层神经网络之上的工作最小化例程:

import mxnet as mx
import numpy as np


def minimize(objective_function,
             initial_params,
             max_iters=1000,
             optimizer='sgd',
             optimizer_params=(('learning_rate', 0.1),),
             tol=1e-8):

    class InitialParam(mx.init.Initializer):

        def __init__(self, vals):
            super(InitialParam, self).__init__()
            self._vals = vals

        def _init_weight(self, _, arr):
            arr[:] = self._vals.asnumpy()[:, np.newaxis]


    x = mx.sym.Variable('data')
    params_len = initial_params.shape[0]
    fc = mx.sym.FullyConnected(data=x, name='fc1',
                               num_hidden=params_len,
                               no_bias=True)

    # Passing the FullyConnected layer into the objective function
    # is difficult to manipulate. If the fully connected layer represents
    # [x, y] for optimizing a 2 dimensional function f(x, y) it is easier
    # to work with x, and y. So we split the fully connected layer into a
    # number of symbols for each parameter:
    param_syms = []
    for i in range(params_len):
        ps = mx.sym.slice(fc, begin=(0, i), end=(1, i + 1))
        param_syms.append(ps)

    # The loss function for the network is our objective function.
    loss = mx.sym.MakeLoss(objective_function(param_syms))
    mod = mx.mod.Module(loss)

    mod.bind(data_shapes=[('data', (1,))])
    mod.init_params(InitialParam(initial_params))
    mod.init_optimizer(optimizer=optimizer,
                       optimizer_params=optimizer_params)

    (o_name, o_shape), = mod.output_shapes

    i = 0
    params = initial_params
    old_val = np.full(o_shape, np.nan)
    while i < max_iters:
        mod.forward_backward(mx.io.DataBatch(
            data=[mx.nd.ones((1,))])) 
        mod.update()
        params = mod.get_params()[0]['fc1_weight']
        val = mod.get_outputs()[0].asnumpy()
        if np.allclose(old_val, val, atol=tol):
            print 'Function value: {}'.format(val)
            print 'Iterations: {}'.format(i)
            return params

        old_val = val
        i += 1

    return params

并使用它:

def my_func(x):
    return (x[0] + 1) ** 2

p = minimize(my_func, mx.nd.array([1.0]))
p.asnumpy()

>>> array([[-0.99999988]], dtype=float32)

另一个:

def my_func(x):
    return (x[0] + 1) ** 2 + (x[1] - 2) ** 2 + (x[2] + 3) ** 2

p = minimize(my_func, mx.nd.array([1.0, 1.5, 2.0]))
p.asnumpy()

>>> array([[-0.99996436],
           [ 1.99999106],
           [-2.99991083]], dtype=float32)
参考资料:
Stack Overflow
收藏
评论
共 1 个回答
高赞 时间 活跃

当前,由于缺少前端的支持,使用MXNet优化简单功能并不像张量流那样容易。

首先,您需要一个损失功能作为网络的最后一层。在这里是log_x_squared。使用MakeLoss创建损失函数。

其次是投入和权重。由于当前MXNet变量中的变量不算作可训练的重量,因此您需要将x设置为重量。这是一种解决方法:设置“ fake”输入变量,该变量始终为1。之后,添加具有1个隐藏单元且无偏差的完全连接的层。这给我们“ 1 * x”。现在我们的x是一个权重。

第三,如果您想对单个数据样本进行多次优化,那么module.fit可能不是最佳选择。初始化优化器后。您只需要多次调用module.forward_backward()和module.update()。对于forward_backward函数,您需要传递一个databatch,与dataiter相比,它是一个更简单的接口。在这里,我们只需要每次传递一个常数ndarray 1。

实际上,我们构建了一个log(1 * x)^ 2的计算图,并且x变成了权重而不是变量。

无论如何,我们应该考虑提供一个类似的张量流接口来优化变量。

希望这是有用的信息!

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号