【问题标题】:Failed to find zero weight by GradientDescentOptimizerGradientDescentOptimizer 未能找到零权重
【发布时间】:2018-04-22 15:43:56
【问题描述】:

我尝试构建一个回归模型来通过 TensorFlow 训练我的数据集。 W1*x^2 + W2*x + b时,显示nan; W2*x + b 时,可输出数字。为什么找不到 W1=0?我的模型构建逻辑有什么问题吗?

import tensorflow as tf
import csv
import re
import datetime
import numpy
import matplotlib.pyplot as plt

# Parameters
learning_rate = 0.01
training_epochs = 2000

# Training Data
data_X = [  0.,   2.,   5.,   6.,   7.,   8.,   9.,  12.,  13.,  14.]
data_Y = [ 2568.300049,  2540.100098,  2552.399902,  2583.899902,  2607.100098,
  2603.300049,  2561.699951,  2614.899902,  2590.800049,  2578.199951]
train_X = numpy.asarray(data_X)
train_Y = numpy.asarray(data_Y)
n_samples = train_X.shape[0]

# Model parameters
rng = numpy.random
W1 = tf.Variable([rng.randn()], dtype=tf.float32, name="weight1")
# OK when W1 = tf.constant(0.)
W2 = tf.Variable([rng.randn()], dtype=tf.float32, name="weight2")
b = tf.Variable([rng.randn()], dtype=tf.float32, name="bias")
# Model input and output
x = tf.placeholder(tf.float32)
y = tf.placeholder(tf.float32)
linear_model = W1*tf.square(x) + W2*x + b

# loss
loss = tf.reduce_sum(tf.square(linear_model - y))/(2*n_samples)
# optimizer
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
train = optimizer.minimize(loss)

# training loop
init = tf.global_variables_initializer()
# Start training
with tf.Session() as sess:
    sess.run(init) # reset values to wrong
    for i in range(training_epochs):
        sess.run(train, {x: train_X, y: train_Y})
    # evaluate training accuracy
    curr_W1, curr_W2, curr_b, curr_loss = sess.run([W1, W2, b, loss], {x: train_X, y: train_Y})
    print("W1: %s W2: %s b: %s loss: %s"%(curr_W1, curr_W2, curr_b, curr_loss))

    # Graphic display
    plt.plot(train_X, train_Y, 'ro', label='Original data')
    plt.plot(train_X, sess.run(W1) * numpy.square(train_X) + sess.run(W2) * train_X + sess.run(b), label='Fitted line')
    plt.legend()
    plt.show()

【问题讨论】:

    标签: python machine-learning tensorflow regression


    【解决方案1】:

    简短回答:您的学习率太大。使用更小的东西(~0.0001)并使用更多的时期(~2000000)。

    长答案:W1 是 NaN,因为在训练期间它的幅度越来越大,直到我们遇到导致 NaN 的数值问题。您可以通过将 W1 添加到您传递给 sess.run() 的获取列表中来观察它。

    此外,您可以看到它的符号不断变化,这是超调的标志(不是双关语)。实际上,如果您将错误linear_model - y 添加到获取列表中,您的符号也会不断变化。当您的学习率太大时,可能会发生这种情况。

    在尝试了不同的学习率(并补偿了更多的 epoch)之后,我得到了以下结果:

    当 W1 固定为 0 时: W1:0.0 W2:[4.70993948] b:[2539.71435547] 损失:237.369 这将是我们的基线。

    学习率 = 0.001:
    仍然是 NaN。

    学习率 = 0.0001
    training_epochs = 200000
    W1:[-2.63166738] W2:[50.53411484] b:[2375.20996094] 损失:2317.36

    学习率 = 0.0001
    training_epochs = 2000000
    W1:[-0.3543286] W2:[8.49937725] b:[2541.46655273] 损失:189.766

    所以最后一个可能是你想要的,因为它的损失与基线相当。但是,您应该对其进行试验并找到最佳值。

    【讨论】:

    • 感谢您的回复。您的解决方案可以运行,但需要很长时间才能运行。
    【解决方案2】:

    Yoel Zeldes 是正确的。但是,这样一个简单的问题不应该需要 2000000 个训练步骤。之所以在这里这样做,首先是因为二次模型不能很好地匹配明显的线性数据,其次是因为最佳解决方案需要一个巨大的偏差值,这需要很长时间才能学习,因为b 的更改的影响对W1 的更改的影响相形见绌。

    解决这个问题的一个好方法是重新调整数据。如果你包含这些行

    train_X = (train_X - numpy.mean(train_X)) / (numpy.amax(train_X) - numpy.amin(train_X))
    train_Y = (train_Y - numpy.mean(train_Y)) / (numpy.amax(train_Y) - numpy.amin(train_Y))`
    

    那么您的数据将具有 0 的平均值和 1 的范围,并且使用任一模型进行训练都会容易得多。请注意,如果您想在新数据点上测试经过训练的模型,您需要将它们缩放相同的数量。

    【讨论】:

    • 感谢您的回复。您的解决方案可以快速运行。问题:由于 X 是基于时间的序列,之后的值会递增; Y 应该(但不一定)具有比训练数据更大的值。如何调整缩放比例?
    • 如果我理解你的要求,那么你不需要做任何事情。您的模型正在学习应该适用于未来数据的参数。您的训练数据确实非常少,因此您的模型对于未来的数据可能不会非常准确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多