【问题标题】:simple linear regression failed to converge in tensorflow简单的线性回归未能在张量流中收敛
【发布时间】:2017-07-03 13:25:01
【问题描述】:

我是机器学习和 Tensorflow 的新手。目前我正在尝试按照教程的逻辑创建一个简单的线性回归模型,形式为 y = a*x(这里没有偏差项)。但是,由于某种原因,模型未能收敛到正确的值“a”。数据集是我在excel中创建的。如下图:

这是我的代码,它试图在我生成的这个虚拟数据集上运行 tensorflow。

import tensorflow as tf
import pandas as pd

w = tf.Variable([[5]],dtype=tf.float32)
b = tf.Variable([-5],dtype=tf.float32)
x = tf.placeholder(shape=(None,1),dtype=tf.float32)
y = tf.add(tf.matmul(x,w),b)

label = tf.placeholder(dtype=tf.float32)
loss = tf.reduce_mean(tf.squared_difference(y,label))

data = pd.read_csv("D:\\dat2.csv")
xs = data.iloc[:,:1].as_matrix()
ys = data.iloc[:,1].as_matrix()
optimizer = tf.train.GradientDescentOptimizer(0.000001).minimize(loss)
sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())

for i in range(10000):
    sess.run(optimizer,{x:xs,label:ys})
    if i%100 == 0:  print(i,sess.run(w))
print(sess.run(w))

下面是 ipython 控制台中的打印输出,正如您在第 10000 次迭代后看到的那样,w 的值约为 4.53,而不是正确的值 6。 如果有人能阐明这里出了什么问题,我将不胜感激。我玩过从 0.01 到 0.0000001 的不同学习率,没有一个设置能够让 w 收敛到 6。我读过一些建议将特征标准化为标准正态分布,我想知道这种标准化是否是必须的?没有归一化,梯度下降无法找到解决方案?非常感谢!

【问题讨论】:

  • 如果 randbetween 传递的是 0 和 0.1 而不是 -2、2 怎么办?
  • 你的学习率太小了。你有多少不同的价值观? (你的 excel 中有多少行?)。如果这个数字太小,这可能是个问题......如果你有足够的数据(并且范围足够大),你应该能够在没有任何归一化的情况下收敛
  • @gdelab 数据集包含大约 160 个数据点。我玩过更大的学习率,比如 0.1 甚至 1,但无济于事。我认为通过迭代 10000 次,模型应该仍然能够收敛
  • 经过更多测试,问题出在损失函数上(即使在较小的数据集上,它也没有给出应有的值),我仍然不知道确切的位置。然后优化确实通过减少 w 和增加 b 来最小化损失。可能是 y 或标签的塑造问题导致广播或类似的事情......

标签: python machine-learning tensorflow linear-regression gradient-descent


【解决方案1】:

这是一个整形问题:y 和 label 的形状不同([batch_size, 1] vs [batch_size])。在loss = tf.reduce_mean(tf.squared_difference(y, label)) 中,它会导致 tensorflow 对事物的解释与您想要的不同,可能是通过使用一些广播...无论如何,结果是您的损失根本不是您想要的。

要纠正这个问题,只需替换

y = tf.add(tf.matmul(x, w), b)

通过

y = tf.add(tf.matmul(x, w), b)
y = tf.reshape(y, shape=[-1])

我的完整工作代码如下:

import tensorflow as tf
import pandas as pd

w = tf.Variable([[4]], dtype=tf.float64)
b = tf.Variable([10.0], dtype=tf.float64, trainable=True)
x = tf.placeholder(shape=(None, 1), dtype=tf.float64)
y = tf.add(tf.matmul(x, w), b)
y = tf.reshape(y, shape=[-1])
label = tf.placeholder(shape=(None), dtype=tf.float64)
loss = tf.reduce_mean(tf.squared_difference(y, label))

my_path = "/media/sf_ShareVM/data2.csv"
data = pd.read_csv(my_path, sep=";")
max_n_samples_to_use = 50
xs = data.iloc[:max_n_samples_to_use, :1].as_matrix()
ys = data.iloc[:max_n_samples_to_use, 1].as_matrix()
lr = 0.000001
optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(loss)
sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())

for i in range(100000):
    _, loss_value, w_value, b_value, y_val, lab_val = sess.run([optimizer, loss, w, b, y, label], {x: xs, label: ys})
    if i % 100 == 0:  print(i, loss_value, w_value, b_value)
    if (i%2000 == 0 and 0< i < 10000):  # We use a smaller LR at first to avoid exploding gradient. It would be MUCH cleaner to use gradient clipping (by global norm)
        lr*=2
        optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(loss)

print(sess.run(w))

【讨论】:

  • 您会看到,在最初的几个非常好的步骤之后,它的收敛速度非常慢(尤其是偏差)。为了解决这个问题,我们需要更大的学习率。不幸的是,我们在这里处于爆炸梯度的边界,特别是如果您保留数据中的所有值,这就是我们需要小学习率的原因。理想情况下,您应该剪裁梯度并使用更大的学习率。
  • 感谢@gdelab,确实是整形问题。一旦固定,模型会很快收敛到正确的值。谢谢
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 2017-09-11
相关资源
最近更新 更多