【问题标题】:Stochastic gradient descent in Tensorflow seems conceptually wrongTensorflow 中的随机梯度下降在概念上似乎是错误的
【发布时间】:2018-12-22 07:16:59
【问题描述】:

我正在使用 Tensorflow 探索线性回归。这是我来自this notebook的代码。

import tensorflow as tf
import numpy as np
learning_rate = 0.01

x_train = np.linspace(-1,1,101)
y_train = 2*x_train + np.random.randn(*x_train.shape) * 0.33

X = tf.placeholder("float")
Y = tf.placeholder("float")
def model(X, w):
    return tf.multiply(X,w)
w = tf.Variable(0.0, name = "weights")

training_epochs = 100
y_model = model(X,w)
cost = tf.reduce_mean(tf.square(Y-y_model))
train_op = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost)
with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run(init)
    for epoch in range(training_epochs):
        for (x,y) in zip(x_train,y_train):
            sess.run(train_op, feed_dict = {X:x, Y: y})
        print(sess.run(w))

它试图最小化成本函数。根据这个问题的answers,我认为tf.reduce_mean() 会像np.mean() 一样工作。

但是,每次将一对(x,y) 馈送到train_op 时,w 的权重似乎不是根据 THE 对而是根据之前的所有对更新。

对此有何解释?这是否与与优化器一起工作有关?

【问题讨论】:

  • However, every time a pair of (x,y) is fed to the train_op, the weight w seems to update not according to THE pair but to all previous pairs.是什么意思
  • @UmangGupta 嗨!对我来说,代码的直觉是每次 sess.run(train_op, feed_dict = {X:x, Y: y}) 运行时, w 都会更新为关于那对 x,yx_train[i], y_train[i] ,所以基本上我们应该得到斜率,y/x 代表 w 的值。跨度>
  • 是的,你的理解还可以。但有一些警告。斜率 = dloss/dx,通常与 y/x 不同,它应该等于 w 的变化,而不是 w 的变化。
  • 根据model(),最小化square(y-y_model)w应该是 y/x,对吧?所以只是连接点 (x,y) 和 (0,0) 的线的斜率。
  • 不,你对优化过程和梯度的理解是完全错误的。

标签: python tensorflow


【解决方案1】:

我想回答我自己的问题。如果您认为这完全线性回归,这不是一个微不足道的问题。

  1. 我误解了 tf.train.GradientDescentOptimizer 的性能。它只运行一步来最小化损失函数,而不是最小化值。如果是这样,@UmangGupta 是正确的,我们得到了斜坡。

  2. 在每个 epoch 中,优化器都会尝试针对每个数据点“一点点”优化损失函数。因此,将数据提供给优化器的顺序很重要。所以下面的代码会给出不同的答案。

    for (x,y) in list(zip(x_train,y_train))[::-1]: sess.run(train_op, feed_dict = {X:x, Y: y})

总之,这段代码运行的不是严格的线性回归,而是它的近似值。

【讨论】:

  • 我想你也误解了线性回归。通常线性回归不是对批次进行的,而是将数据视为一个整体并使用一些求解技术(伪逆/ GD等)。上面的代码完全是带有“批量”随机梯度下降的线性回归。
  • 另外,如果您将线性回归视为拟合单个点并在所有点上进行迭代。你真的应该重新审视回归
  • @UmangGupta 我明白你的意思。毕竟没有“严谨”的。谢谢。
【解决方案2】:

如果您更改这段代码

for epoch in range(training_epochs):
    for (x,y) in zip(x_train,y_train):
        sess.run(train_op, feed_dict = {X:x, Y: y})

通过这个

for (x,y) in zip(x_train,y_train):
    for epoch in range(training_epochs):
        sess.run(train_op, feed_dict = {X:x, Y: y})

你得到你所期望的吗?

在您的原始代码中,第一个循环是指迭代,因此您要修复梯度下降的第一次迭代,然后将其应用于所有先前的对(因为您的第二个循环是指所有先前的对),然后您'正在修复第二次迭代,然后您再次对所有先前的对应用梯度下降,依此类推。

如果您如上所述交换循环,那么您正在修复一对,然后将梯度下降的所有迭代应用于该一对。我不确定这是否是你想要的。

【讨论】:

  • 这就像在最后一个数据点上运行线性回归一样好。这是完全错误的
  • @Umang Gupta 问这个问题的人似乎对为什么代码是针对所有对而不是单个对进行更新感到困惑,我建议这是由于他使用循环的方式。我不明白为什么将优化器应用于最后一个数据点是好是坏。
  • 请告诉我用户在问题中的哪个位置询问适合数据的最佳预测模型。这只是关于为什么要更新所有对而不是单个。
  • 它并没有在单次迭代中将 w.r.t 更新到所有对,这是 OP 所要求的。虽然公平点,但问题的发布方式令人困惑
  • 在一次操作中更新所有对!这条线很清楚:for epoch in range(training_epochs): 正在修复迭代,然后 for (x,y) in zip(x_train,y_train): sess.run(train_op, feed_dict = {X:x, Y: y}) 正在针对该固定迭代对所有对运行优化器!
猜你喜欢
  • 1970-01-01
  • 2016-09-25
  • 2016-06-13
  • 2021-12-18
  • 2012-05-15
  • 2016-11-09
  • 2018-12-10
  • 2019-06-19
  • 2021-02-20
相关资源
最近更新 更多