Tensorflow中的自动广播

时间:2018-04-07 09:23:00

标签: python tensorflow

动态广播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]。

那么有一种自动播放矢量的方式吗?

1 个答案:

答案 0 :(得分:2)

“Pythonic”答案:

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在最后一个维度上乘以张量时自行处理广播。因此,解决方案只是在乘法之前转置张量,然后将结果转换回来。

tf.einsum()的先前答案:

它可能无法直接回答你的问题,因为它不是更多的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)