Tensorflow 稍微不同的形状收敛到错误的数字-为什么?

Tensorflow 稍微不同的形状收敛到错误的数字-为什么?,tensorflow,Tensorflow,我想弄明白为什么TensorFlow做了一些令人惊讶的事情。我已经把它归结为一个测试用例,尝试对一个简单的问题进行线性回归,只需将两个输入相加。权重会收敛到1.0,偏差也会收敛到0.0 对于此版本的培训输出: train_y = [2., 3., 4.] 成本应收敛到0.0,但使用此版本: train_y = [[2.], [3.], [4.]] 成本收敛到4.0。如果第二个版本出现错误消息,我也不会感到惊讶;令人惊讶的是,它默默地给出了一个错误的答案。为什么要这样做 测试用例的完整代码:

我想弄明白为什么TensorFlow做了一些令人惊讶的事情。我已经把它归结为一个测试用例,尝试对一个简单的问题进行线性回归,只需将两个输入相加。权重会收敛到1.0,偏差也会收敛到0.0

对于此版本的培训输出:

train_y = [2., 3., 4.]
成本应收敛到0.0,但使用此版本:

train_y = [[2.], [3.], [4.]]
成本收敛到4.0。如果第二个版本出现错误消息,我也不会感到惊讶;令人惊讶的是,它默默地给出了一个错误的答案。为什么要这样做

测试用例的完整代码:

import tensorflow as tf
sess = tf.InteractiveSession()
tf.set_random_seed(1)

# Parameters
epochs = 10000
learning_rate = 0.01

# Data
train_x = [[1., 1.], [1., 2.], [2., 2.]]

# It works with this version
train_y = [2., 3., 4.]

# But converges on cost 4.0 with this version
#train_y = [[2.], [3.], [4.]]

# Number of samples
n_samples = len(train_x)

# Inputs and outputs
x = tf.placeholder(tf.float32, name='x')
y = tf.placeholder(tf.float32, name='y')

# Weights
w = tf.Variable(tf.random_normal([2]), name='weight')
b = tf.Variable(tf.random_normal([]), name='bias')

# Model
pred = tf.tensordot(x, w, 1) + b
cost = tf.reduce_sum((pred-y)**2 / n_samples)
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

# Train
tf.global_variables_initializer().run()
for epoch in range(epochs):
    # Print update at successive doublings of time
    if epoch&(epoch-1)==0 or epoch==epochs-1:
        print('{:6}'.format(epoch), end=' ')
        print('{:12.6f}'.format(cost.eval({x: train_x, y: train_y})), end=' ')
        print('    ['+', '.join('{:8.6f}'.format(z) for z in w.eval())+']', end=' ')
        print('{:12.6f}'.format(b.eval()))
    for (x1, y1) in zip(train_x, train_y):
        optimizer.run({x: x1, y: y1})
为什么? 问题是在输入不同形状的张量时计算成本函数。更具体地说,它是
pred-y
计算

为了向您展示在这个特定示例中出现的错误,同时避免混乱,我将使用与您上面提到的形状和值相同的常量:

y0 = tf.constant([2., 3., 4.])
y1 = tf.constant([[2.], [3.], [4.]])
pred = tf.constant([2., 3., 4.])
现在,让我们看看表达式
pred-y0
pred-y1
的形状:

res0 = pred - y0
res1 = pred - y1

print(res0.shape)
print(res1.shape)
输出为:

(3,)
(3, 3)
(3,3)
显示,当计算形状
(3,)
(3,1)
pred-y1
时,我们对形状
(3,3)
进行了广播这也意味着
tf.reduce_sum()
调用summed 3x3=9个元素,而不是仅调用3个元素。

对于这种情况,您可以通过使用
tf.transpose()
y1
转换为
(1,3)
来解决此问题:

现在输出为:

(1, 3)
如何修复: 现在,回到你的代码。。。只需更改以下表达式:

cost = tf.reduce_sum((pred-y)**2 / n_samples)
致:

在这两种情况下,你都会像预期的那样收敛到零

cost = tf.reduce_sum((pred-y)**2 / n_samples)
cost = tf.reduce_sum((pred-tf.transpose(y))**2 / n_samples)