使用急切执行来优化向量

时间:2018-12-01 22:00:59

标签: python python-3.x tensorflow

我想使用TensorFlow的急切执行功能来优化向量的分量。在所有记录的示例中,每个可训练变量都只是一个标量,其集合由这些列表表示。但是,我想到的损失函数涉及对这些组件执行矢量操作,因此很不方便。

例如,让我们使用Adam优化器对3分量向量进行归一化:

 import tensorflow as tf
 import tensorflow.contrib.eager as tfe
 import numpy as np
 tf.enable_eager_execution()                                                                         
 def normalize(din=[2.0,1.0,0.0], lr=0.001, 
                nsteps=100):

     d = tfe.Variable(din)
     def loss(dvec):
            return tf.sqrt((1.0 - tf.tensordot(dvec, dvec, 1))**2)                                          
     def grad(dvec):
           with tf.GradientTape() as tape:
                 loss_val = loss(dvec)
           return tape.gradient(loss_val, dvec)

     optimizer = tf.train.AdamOptimizer(learning_rate=lr)
     for i in range(nsteps):
        grads = grad(d)
        optimizer.apply_gradients(zip(grads, d))  #Throws error                                                         
     return d

此代码正确计算所需的渐变。但是,“ optimizer.apply_gradients”行抛出某种错误,似乎不管我做什么,主要是因为tfe.Variable不是可迭代的。

在此特定示例中,错误为“ AttributeError:启用急切执行时,Tensor.name无意义”。例如,我们也可以尝试

  zip(grads, [d[i] for i in range(3)])

代替d,但随后解释器抱怨d不可迭代。

将d与d配对的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

Optimizer.apply_gradients requires its first argument成为(梯度,变量)对的列表。

在上面的代码中,gradsd都不是列表(例如尝试print(type(grads))),因此错误是由于对zip的调用。我想您想要的是:

optimizer.apply_gradients(zip([grads], [d]))

或更简单地说:

optimizer.apply_gradients([(grads, d)])

此外,仅供参考,由于急切的执行稳定了更多事物,这​​些新事物正从实验性的“ contrib”命名空间中移出,因此您无需为示例使用tfe模块(tf.Variable可以正常工作如果您使用的是TensorFlow的最新版本(1.11、1.12等)。使整个程序看起来像这样:

import tensorflow as tf
import numpy as np
tf.enable_eager_execution()                                                                         
def normalize(din=[2.0,1.0,0.0], lr=0.001, 
              nsteps=100):

    d = tf.Variable(din)
    def loss(dvec):
           return tf.sqrt((1.0 - tf.tensordot(dvec, dvec, 1))**2)                                          
    def grad(dvec):
          with tf.GradientTape() as tape:
                loss_val = loss(dvec)
          return tape.gradient(loss_val, dvec)

    optimizer = tf.train.AdamOptimizer(learning_rate=lr)
    for i in range(nsteps):
       dd = grad(d)
       optimizer.apply_gradients([(dd, d)])                                                       
    return d

希望有帮助!