1

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

好的,这让我完全难过。

我有一个参数向量,我们称之为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

这是一些样板代码,用于实际最小化该功能。在两点上,我sess.run调用了tf.Variables 来查看值是如何变化的。

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]
4

2 回答 2

0

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

于 2018-03-21T19:32:07.823 回答
0

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

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]

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

于 2018-03-21T08:57:15.823 回答