我想使用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配对的正确方法是什么?
答案 0 :(得分:3)
Optimizer.apply_gradients
requires its first argument成为(梯度,变量)对的列表。
在上面的代码中,grads
和d
都不是列表(例如尝试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
希望有帮助!