【问题标题】:Slightly different shape converges to wrong number - why?稍微不同的形状会收敛到错误的数字 - 为什么?
【发布时间】:2017-11-21 16:13:12
【问题描述】:

我试图弄清楚为什么 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})

【问题讨论】:

    标签: tensorflow


    【解决方案1】:

    为什么?

    问题是当您输入不同形状的张量时的成本函数计算。更具体地说,是pred - y 计算。

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

    y0 = tf.constant([2., 3., 4.])
    y1 = tf.constant([[2.], [3.], [4.]])
    pred = tf.constant([2., 3., 4.])
    

    现在,让我们看看表达式pred - y0pred - y1 的形状:

    res0 = pred - y0
    res1 = pred - y1
    
    print(res0.shape)
    print(res1.shape)
    

    输出是:

    (3,)
    (3, 3)
    

    (3, 3) 显示在计算 pred - y1 形状 (3,)(3, 1) 时,我们有一个广播来塑造 (3, 3)这也意味着tf.reduce_sum() 调用汇总了 3x3 = 9 个元素,而不仅仅是 3 个。

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

    res1_fixed = pred - tf.transpose(y1)
    print(res1_fixed.shape)
    

    现在的输出是:

    (1, 3)
    

    如何解决:

    现在,回到您的代码...只需更改以下表达式:

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

    收件人:

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

    在这两种情况下,您都将按预期将收敛到零。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多