Tensorflow:奇怪的广播行为

时间:2017-07-07 11:07:49

标签: python tensorflow deep-learning

我不太清楚广播机制在Tensorflow中是如何运作的。假设我们有以下代码:

W1_shape = [5, 5, 1, 32]
b1_shape = [32]
x = tf.placeholder(tf.float32)
initial_W1 = tf.truncated_normal(shape=W1_shape, stddev=0.1)
W1 = tf.Variable(initial_W1)
initial_b1 = tf.constant(0.1, shape=b1_shape)
b1 = tf.Variable(initial_b1)
conv1 = tf.nn.conv2d(x, W1, strides=[1, 1, 1, 1], padding='SAME')
conv1_sum = conv1 + b1
y = tf.placeholder(tf.float32)
z = conv1 + y

sess = tf.Session()
# Run init ops
init = tf.global_variables_initializer()
sess.run(init)

while True:
    samples, labels, indices = dataset.get_next_batch(batch_size=1000)
    samples = samples.reshape((1000, MnistDataSet.MNIST_SIZE, MnistDataSet.MNIST_SIZE, 1))
    y_data = np.ones(shape=(1000, 32))
    conv1_res, conv1_sum_res, b1_res, z_res=\
    sess.run([conv1, conv1_sum, b1, z], feed_dict={x: samples, y: y_data})

if dataset.isNewEpoch:
    break

因此,我加载了MNIST数据集,该数据集由28x28大小的图像组成。卷积运算符使用32个5x5大小的过滤器。我使用批量大小为1000,因此数据张量x具有形状(1000,28,28,1)。 tf.nn.conv2d操作输出形状的张量(1000,28,28,32)。 y是一个占位符,我添加一个变量来检查Tensorflow的广播机制,方法是将其添加到(1000,28,28,32)形状conv1张量。在y_data = np.ones(shape=(1000, 32))行中,我尝试了y的各种张量形状。形状(28,28),(1000,28)和(1000,32)不会添加到conv1,错误类型为:

  

InvalidArgumentError(参见上面的追溯):不兼容的形状:[1000,28,28,32]与[28,28]

形状(28,32)和(28,28,32)正常工作和播放。但是根据https://www.tensorflow.org/performance/xla/broadcasting中解释的广播语义,前三个形状也必须起作用,因为它们通过将尺寸与4D conv1张量匹配而具有正确的顺序。例如,尺寸1和2中的(28,28)匹配(1000,28,28,32),尺寸0和3中的(1000,32)匹配,正如链接中所述。我在这里遗漏或误解了什么吗?在这种情况下,Tensorflow的正确广播行为是什么?

1 个答案:

答案 0 :(得分:1)

这是真的,文档似乎暗示你说的话。但它看起来像numpy broadcsting rules

  

在两个阵列上操作时,NumPy会比较它们的形状   逐元素。它从尾随尺寸开始,并起作用   前进的方向。在以下情况下兼容两个维度:

     
      
  1. 他们是平等的,或
  2.   
  3. 其中一个是1
  4.   

所以通过上面的定义:

  • (28,28)不能播放到(1000,28,28,32),但是(28,28,1)可以播放。
  • (1000,28)不能(1000,1,28,1)或(1000,28,1,1)

  • (28,32)有效,因为尾随尺寸匹配。