2017-06-28 15 views
4

Ich versuche MXNet Gradientenabstiegsoptimierer zu verwenden, um eine Funktion zu minimieren. Das äquivalente Beispiel in Tensorflow wäre:Einfacher Gradientabstieg mit mxnet

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)) 

Ich bin nicht sicher, wie man das gleiche in MxNet zu erreichen. Die Optimierer-API documentation scheint keine äquivalente Methode zu haben. Hier ist, was ich bisher versucht habe. Die Haupt Verwirrung um die Notwendigkeit, Trainingsdaten weitergeben müssen:

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 

Es scheint, wie die x Variable sollte irgendwie in als data_iter zurückgeführt werden, aber ich weiß nicht, wie dies zu erreichen.

Update: dank kevinthesun für ihre ausgezeichnete Antwort! Hier ist eine Arbeitsminimierungsroutine auf einer einzelnen versteckten Schicht des neuronalen Netzes gebaut:

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 

und dessen Verwendung:

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) 

und eine andere:

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) 

Antwort

4

Derzeit ist es nicht so einfach wie Tensorflow, eine einfache Funktion mit MXNet zu optimieren, aufgrund der fehlenden Unterstützung im Frontend.

Zuerst benötigen Sie eine Verlustfunktion als letzte Schicht Ihres Netzwerks. Hier ist es log_x_squared. Verwenden Sie MakeLoss, um eine Verlustfunktion zu erstellen.

Zweitens ist die Eingabe und Gewichte. Da derzeit in MXNet Variable nicht als trainierbares Gewicht gezählt wird, müssen Sie x als Gewicht festlegen. Hier ist ein Workaround: Setzen Sie eine 'falsche' Eingabevariable, die immer 1 sein soll. Nachdem Sie eine vollständig verbundene Ebene mit 1 versteckten Einheit und ohne Verzerrung hinzugefügt haben. Das gibt uns "1 * x". Jetzt ist unser x ein Gewicht.

Drittens, wenn Sie mehrere Male für einzelne Datenmuster optimieren möchten, ist module.fit möglicherweise nicht die beste Wahl. Nach dem Initialisieren des Optimierers. Sie müssen nur module.forward_backward() und module.update() mehrmals aufrufen. Für die Funktion forward_backward müssen Sie eine Datenübergabe übergeben, die im Vergleich zum Datenerfasser eine einfachere Schnittstelle ist. Hier müssen wir jedes Mal ein konstantes NDarray von 1 passieren.

Eigentlich konstruieren wir einen Berechnungsgraphen von log (1 * x)^2 und x wird zu einem Gewicht anstelle einer Variablen.

Wie auch immer, wir sollten überlegen, eine ähnliche Schnittstelle von Tensorflow zur Verfügung zu stellen, um Variable zu optimieren.

Hoffe das ist nützliche Info!

0

MxNet unterscheidet sich von Tensorfluss. Sie müssen dies lesen tutorial