Tensorflow 稍微不同的形状收敛到错误的数字-为什么?
我想弄明白为什么TensorFlow做了一些令人惊讶的事情。我已经把它归结为一个测试用例,尝试对一个简单的问题进行线性回归,只需将两个输入相加。权重会收敛到1.0,偏差也会收敛到0.0 对于此版本的培训输出:Tensorflow 稍微不同的形状收敛到错误的数字-为什么?,tensorflow,Tensorflow,我想弄明白为什么TensorFlow做了一些令人惊讶的事情。我已经把它归结为一个测试用例,尝试对一个简单的问题进行线性回归,只需将两个输入相加。权重会收敛到1.0,偏差也会收敛到0.0 对于此版本的培训输出: train_y = [2., 3., 4.] 成本应收敛到0.0,但使用此版本: train_y = [[2.], [3.], [4.]] 成本收敛到4.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)