【问题标题】:tensorflow: change in parameter weights is different than it should be based on gradientstensorflow:参数权重的变化与基于梯度的变化不同
【发布时间】:2018-03-21 08:21:06
【问题描述】:

编辑:解决了——使用不同的梯度训练示例与优化器更新是愚蠢的。

好吧,这让我完全被难住了。

我有一个参数向量,我们称之为w

w = [-1.34554319, 0.86998659, 0.52366061, 2.6723526, 0.18756115, 0.16547382]

我使用compute_gradients 计算出 w 的渐变,它告诉我渐变是:

dw = [-0.0251517 , 0.88050844, 0.80362262, 0.14870925, 0.10019595, 1.33597524]

我的学习率是0.1。尔格:

w_new = w - 0.1 * dw

w_new = [-1.34302802, 0.78193575, 0.44329835, 2.65748168, 0.17754156, 0.0318763]

您可以自己检查数学,但应该检查一下。但是,如果我运行 tensorflow 代码并评估 w_new 的值,我会得到:

w_new_tf = [-1.27643258, 0.9212401, 0.09922112, 2.55617223, 0.38039282, 0.15450044]

老实说,我不知道它为什么这样做。

编辑:让我为您提供确切的代码,向您展示它为什么不起作用。如您所见,这可能是由于索引造成的。

这里是样板代码。

import numpy as np
import tensorflow as tf

max_item = 331922
max_user = 1581603
k = 6
np.random.seed(0)
_item_biases = np.random.normal(size=max_item)
np.random.seed(0)
_latent_items = np.random.normal(size=(max_item, k))
np.random.seed(0)
_latent_users = np.random.normal(size=(max_user, k))

item_biases = tf.Variable(_item_biases, name='item_biases')
latent_items = tf.Variable(_latent_items, name='latent_items')
latent_users = tf.Variable(_latent_users, name='latent_users')

input_data = tf.placeholder(tf.int64, shape=[3], name='input_data')

这是自定义目标函数。

def objective(data, lam, item_biases, latent_items, latent_users):  
    with tf.name_scope('indices'):
        user = data[0]
        rated_item = data[1]
        unrated_item = data[2]

    with tf.name_scope('input_slices'):
        rated_item_bias = tf.gather(item_biases, rated_item, name='rated_item_bias')
        unrated_item_bias = tf.gather(item_biases, unrated_item, name='unrated_item_bias')

        rated_latent_item = tf.gather(latent_items, rated_item, name='rated_latent_item')
        unrated_latent_item = tf.gather(latent_items, unrated_item, name='unrated_latent_item')

        latent_user = tf.gather(latent_users, user, name='latent_user')

    with tf.name_scope('bpr_opt'):
        difference = tf.subtract(rated_item_bias, unrated_item_bias, 'bias_difference')
        ld = tf.subtract(rated_latent_item, unrated_latent_item, 'latent_item_difference')
        latent_difference = tf.reduce_sum(tf.multiply(ld, latent_user), name='latent_difference')
        total_difference = tf.add(difference, latent_difference, name='total_difference')

    with tf.name_scope('obj'):        
        obj = tf.sigmoid(total_difference, name='activation')
    with tf.name_scope('regularization'):
        reg = lam * tf.reduce_sum(rated_item_bias**2)
        reg += lam * tf.reduce_sum(unrated_item_bias**2) 
        reg += lam * tf.reduce_sum(rated_latent_item**2) 
        reg += lam * tf.reduce_sum(unrated_latent_item**2)
        reg += lam * tf.reduce_sum(latent_user**2)

    with tf.name_scope('final'):
        final_obj = -tf.log(obj) + reg


    return final_obj

这里有一些样板代码来实际最小化该功能。在两点上,我对tf.Variables 进行了sess.run 调用,以查看值的变化情况。

obj = objective(input_data, 0.05, item_biases, latent_items, latent_users)

optimizer = tf.train.GradientDescentOptimizer(0.1)
trainer = optimizer.minimize(obj)
sess = tf.Session()
sess.run(tf.global_variables_initializer())


citem_biases, clatent_items, clatent_users = \
    sess.run([item_biases, latent_items, latent_users])

print (clatent_users[1490103]) # [-1.34554319, 0.86998659, 0.52366061, 2.6723526 , 0.18756115, 0.16547382]

cvalues = sess.run([trainer, obj], feed_dict={input_data:[1490103, 278755, 25729]})
citem_biases, clatent_items, clatent_users = \
    sess.run([item_biases, latent_items, latent_users]) 
print (clatent_users[1490103]) #[-1.27643258,  0.9212401 ,  0.09922112,  2.55617223,  0.38039282, 0.15450044]

最后,这里是一些实际获取渐变的代码。这些渐变是根据手工导出的渐变进行双重检查的,因此它们是正确的。抱歉代码的丑陋,这是另一个 SO 答案的公然复制和粘贴:

grads_and_vars = optimizer.compute_gradients(obj, tf.trainable_variables())
sess = tf.Session()
sess.run(tf.global_variables_initializer())
gradients_and_vars = sess.run(grads_and_vars, feed_dict={input_data:[1490103, 278830, 140306]})
print (gradients_and_vars[2][0]) #[-0.0251517 ,  0.88050844,  0.80362262,  0.14870925,  0.10019595, 1.33597524]

【问题讨论】:

  • 你应该提供一个可重现的例子
  • 好的,我添加了我的整个代码。这并不漂亮,但我的代码中可能有一百万个东西会导致这个问题(错误或 tensorflow 问题),所以我继续发布了整个内容。

标签: python tensorflow tensorflow-gradient


【解决方案1】:

您没有提供完整的代码,但我运行了一个类似的示例,它确实对我有用。这是我的代码:

with tf.Graph().as_default():
  ph = tf.constant([1., 2., 3.])
  v = tf.get_variable('v', (3,))
  loss = tf.square(ph-v)
  optimizer = tf.train.GradientDescentOptimizer(0.1)
  trainer = optimizer.minimize(loss)
  gradients = optimizer.compute_gradients(loss)[0][0]

  with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    grad_mat = sess.run(gradients)
    v_0 = sess.run(v)
    sess.run(trainer)
    v_1 = sess.run(v)

    print(grad_mat)
    print(v_0)
    print(v_0 - 0.1*grad_mat)
    print(v_1)

这是输出(显然每次都会有点不同,由于get_variable的随机初始化):

[-2.01746035 -5.61006117 -6.7561307 ]
[-0.00873017 -0.80503058 -0.37806535]
[ 0.19301586 -0.24402446  0.29754776]
[ 0.19301586 -0.24402446  0.29754776]

如您所料,最后两行是相同的。

【讨论】:

  • 当然。我添加了我的代码的全部内容。我怀疑这不是一个简单的梯度下降问题(当然希望不是!),但在处理稀疏切片等时可能是一个问题。尝试运行我在顶部的代码,如果遇到同样的问题,请告诉我。
【解决方案2】:

问题:我为梯度和训练器提供了不同的输入。 解决方案:提供相同的输入。

【讨论】:

    猜你喜欢
    • 2021-12-11
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多