动态广播1D向量的最佳方法是什么,它可以使用提供的张量的行执行逐元素乘法?
目前,我有以下详细的“解决方案”,tf.tile
coef
(1D向量)在第二个参数的形状上逐个进行:< / p>
import tensorflow as tf
tf.reset_default_graph()
iterSession = tf.InteractiveSession()
coef = tf.constant([1., 2, 3]) # shape = (3,)
LL_grads = {
'a': tf.constant([[1.], [2], [3]]), # shape = (3, 1)
'b': tf.constant([[1., 2], [3, 4], [5, 6]]), # shape = (3, 2)
'c': tf.constant([[[1.], [2]], [[3], [4]], [[5], [6]]]) # shape = (3, 2, 1)
}
avg_grad_stacked = {}
for x in ['a', 'b', 'c']:
LL_grad = LL_grads[x]
dim = len(LL_grad.get_shape())
if dim == 1:
avg_grad_stacked[x] = LL_grad * coef
elif dim == 2:
# Manually broadcast to (3, 2)
avg_grad_stacked[x] = LL_grad * tf.tile(tf.reshape(coef, (-1, 1)),
[1, tf.shape(LL_grad)[1]])
elif dim == 3:
# Manually broadcast to (3, 2, 1)
avg_grad_stacked[x] = LL_grad * tf.tile(tf.reshape(coef, (-1, 1, 1)),
[1, tf.shape(LL_grad)[1], tf.shape(LL_grad)[2]])
理想情况下,我希望有一些简单的Pythonic:
avg_grad_stacked_2 = {x:coef * y for x, y in LL_grads.items()}
然而,这失败并出现错误:
ValueError:尺寸必须相等,但对于'mul_4'(op:'Mul'),输入形状为[3],[3,2]。
那么有一种自动播放矢量的方式吗?
答案 0 :(得分:2)
import tensorflow as tf
import string
tf.reset_default_graph()
iterSession = tf.InteractiveSession()
coef = tf.constant([1., 2, 3]) # shape = (3,)
LL_grads = {
'a': tf.constant([[1.], [2], [3]]), # shape = (3, 1)
'b': tf.constant([[1., 2], [3, 4], [5, 6]]), # shape = (3, 2)
'c': tf.constant([[[1.], [2]], [[3], [4]], [[5], [6]]]) # shape = (3, 2, 1)
}
avg_grad_stacked = {x: tf.transpose(tf.transpose(LL_grad) * coef) for x, LL_grad in LL_grads.items()}
<强>解释强>
您只需要在您的情况下手动进行平铺,因为您正在沿着第一维进行乘法运算。 Tensorflow在最后一个维度上乘以张量时自行处理广播。因此,解决方案只是在乘法之前转置张量,然后将结果转换回来。
它可能无法直接回答你的问题,因为它不是更多的pythonic,并且不使用平铺,但tf.einsum()是一个强大的工具,可以增加不同维度的张量(除其他外)。< / p>
在你的情况下,它可以以某种方式使用:
import tensorflow as tf
import string
tf.reset_default_graph()
iterSession = tf.InteractiveSession()
coef = tf.constant([1., 2, 3]) # shape = (3,)
LL_grads = {
'a': tf.constant([[1.], [2], [3]]), # shape = (3, 1)
'b': tf.constant([[1., 2], [3, 4], [5, 6]]), # shape = (3, 2)
'c': tf.constant([[[1.], [2]], [[3], [4]], [[5], [6]]]) # shape = (3, 2, 1)
}
avg_grad_stacked = {}
for x, LL_grad in LL_grads.items():
dim = len(LL_grad.get_shape())
coef_axis = string.ascii_lowercase[0] # "a"
LL_grads_axes = "".join(
[string.ascii_lowercase[i] for i in range(dim)]) # e.g. "abc" for dim==3
ein_equation = "{0},{1}->{0}".format(
LL_grads_axes, coef_axis) # e.g. "abc,a->abc"
avg_grad_stacked[x] = tf.einsum(ein_equation, LL_grad, coef)