如何修复Tensorflow中的“ValueError:操作数无法与形状(2592,)(4,)一起广播”?

Posted

技术标签:

【中文标题】如何修复Tensorflow中的“ValueError:操作数无法与形状(2592,)(4,)一起广播”?【英文标题】:How to fix "ValueError: Operands could not be broadcast together with shapes (2592,) (4,)" in Tensorflow? 【发布时间】:2019-09-27 20:58:55 【问题描述】:

我目前正在设计一个 NoisyNet 层,如下所示:"Noisy Networks for Exploration",在 Tensorflow 中并得到标题中所示的维度误差,而两个张量的维度在行中逐元素相乘filtered_output = keras.layers.merge.Multiply()([output, actions_input])在打印所涉及的两个张量filtered_outputactions_input 的尺寸时,应该(原则上)根据打印输出相互兼容,其中两个张量的尺寸似乎都是shape=(1, 4)

我在 Python3 中使用 Tensorflow 1.12.0。

相关代码如下:

import numpy as np
import tensorflow as tf
import keras

class NoisyLayer(keras.layers.Layer):

    def __init__(self, in_shape=(1,2592), out_units=256, activation=tf.identity): 
        super(NoisyLayer, self).__init__()
        self.in_shape = in_shape
        self.out_units = out_units
        self.mu_interval = 1.0/np.sqrt(float(self.out_units))
        self.sig_0 = 0.5
        self.activation = activation
        self.assign_resampling()

    def build(self, input_shape):
        # Initializer
        self.mu_initializer = tf.initializers.random_uniform(minval=-self.mu_interval, maxval=self.mu_interval) # Mu-initializer
        self.si_initializer = tf.initializers.constant(self.sig_0/np.sqrt(float(self.out_units)))      # Sigma-initializer

        # Weights
        self.w_mu = tf.Variable(initial_value=self.mu_initializer(shape=(self.in_shape[-1], self.out_units), dtype='float32'), trainable=True) # (1,2592)x(2592,4) = (1,4)
        self.w_si = tf.Variable(initial_value=self.si_initializer(shape=(self.in_shape[-1], self.out_units), dtype='float32'), trainable=True)

        # Biases
        self.b_mu = tf.Variable(initial_value=self.mu_initializer(shape=(self.in_shape[0], self.out_units), dtype='float32'), trainable=True)
        self.b_si = tf.Variable(initial_value=self.si_initializer(shape=(self.in_shape[0], self.out_units), dtype='float32'), trainable=True)

    def call(self, inputs, resample_noise_flag):
        if resample_noise_flag:
            self.assign_resampling()

        # Putting it all together
        self.w = tf.math.add(self.w_mu, tf.math.multiply(self.w_si, self.w_eps))
        self.b = tf.math.add(self.b_mu, tf.math.multiply(self.b_si, self.q_eps))

        return self.activation(tf.linalg.matmul(inputs, self.w) + self.b)

    def assign_resampling(self):
        self.p_eps = self.f(self.resample_noise([self.in_shape[-1], 1]))
        self.q_eps = self.f(self.resample_noise([1, self.out_units]))
        self.w_eps = self.p_eps * self.q_eps         # Cartesian product of input_noise x output_noise

    def resample_noise(self, shape):
        return tf.random.normal(shape, mean=0.0, stddev=1.0, seed=None, name=None)

    def f(self, x):
        return tf.math.multiply(tf.math.sign(x), tf.math.sqrt(tf.math.abs(x)))


frames_input = tf.ones((1, 84, 84, 4))  # Toy input

conv1 = keras.layers.Conv2D(16, (8, 8), strides=(4, 4), activation="relu")(frames_input)
conv2 = keras.layers.Conv2D(32, (4, 4), strides=(2, 2), activation="relu")(conv1)

flattened = keras.layers.Flatten()(conv2)

actionspace_size = 4  

# NoisyNet        
hidden = NoisyLayer(activation=tf.nn.relu)(inputs=flattened, resample_noise_flag=True)
output = NoisyLayer(in_shape=(1,256), out_units=actionspace_size)(inputs=hidden, resample_noise_flag=True)

actions_input = tf.ones((1,actionspace_size))

print('hidden:\n', hidden)
print('output:\n', output)
print('actions_input:\n', actions_input)

filtered_output = keras.layers.merge.Multiply()([output, actions_input])

当我运行代码时,输​​出如下所示:

hidden:
 Tensor("noisy_layer_5/Relu:0", shape=(1, 256), dtype=float32)
output:
 Tensor("noisy_layer_6/Identity:0", shape=(1, 4), dtype=float32)
actions_input:
 Tensor("ones_5:0", shape=(1, 4), dtype=float32)

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-4-f6df621eacab> in <module>()
     68 print('actions_input:\n', actions_input)
     69 
---> 70 filtered_output = keras.layers.merge.Multiply()([output, actions_input])

2 frames

/usr/local/lib/python3.6/dist-packages/keras/layers/merge.py in _compute_elemwise_op_output_shape(self, shape1, shape2)
     59                     raise ValueError('Operands could not be broadcast '
     60                                      'together with shapes ' +
---> 61                                      str(shape1) + ' ' + str(shape2))
     62                 output_shape.append(i)
     63         return tuple(output_shape)

ValueError: Operands could not be broadcast together with shapes (2592,) (4,)

特别是,我想知道Operands could not be broadcast together with shapes (2592,) (4,) 中的数字2592 来自哪里,因为该数字与第一个噪声层的扁平输入张量flattened 的长度一致,但在我看来是- - 不再是第二个噪声层output 的输出维度的一部分,而后者又用作上述错误行的输入。

有人知道怎么回事吗?

提前致谢,丹尼尔

【问题讨论】:

【参考方案1】:

如custom layer document中所说,需要实现compute_output_shape(input_shape)方法:

compute_output_shape(input_shape): 如果你的层修改了 其输入的形状,您应该在此处指定形状转换 逻辑。这允许 Keras 进行自动形状推断。

当您不应用此方法时,Keras 无法在不实际执行计算的情况下进行形状推断。

print(keras.backend.int_shape(hidden))
print(keras.backend.int_shape(output))

(1, 2592)
(1, 2592)

所以你需要添加如下:

def compute_output_shape(self, input_shape):
    return (input_shape[0], self.out_units)

另外build()方法必须在最后设置self.built = True,根据文档调用super(NoisyLayer, self).build(input_shape)即可。

【讨论】:

以上是关于如何修复Tensorflow中的“ValueError:操作数无法与形状(2592,)(4,)一起广播”?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复由 Pycharm 中的 Tensorflow 引起的 cudart64_110.dll 错误?

如何修复Tensorflow中的“ValueError:操作数无法与形状(2592,)(4,)一起广播”?

如何在TensorFlow中用深度学习修复图像

如何修复无法在 Conda 上加载本机 Tensorflow 运行时

如何使用 Tensorflow-GPU 和 Keras 修复低挥发性 GPU-Util?

如何修复 AttributeError:模块 'tensorflow' 没有属性 'keras'?