所以我有以下目标函数。它一次仅适用于一个训练示例(我有我避免批量的原因)。正如你所看到它非常轻巧,所以我希望它能够快速运行。
def objective(data, lam, item_biases, latent_items, latent_users):
user = data[0]
rated_item = data[1]
unrated_item = data[2]
rated_item_bias = item_biases[rated_item]
unrated_item_bias = item_biases[unrated_item]
rated_latent_item = latent_items[rated_item]
unrated_latent_item = latent_items[unrated_item]
latent_user = latent_users[user]
rated_pred = rated_item_bias + tf.reduce_sum(tf.multiply(rated_latent_item, latent_user))
unrated_pred = unrated_item_bias + tf.reduce_sum(tf.multiply(unrated_latent_item, latent_user))
difference = rated_pred - unrated_pred
obj = tf.sigmoid(difference)
obj += lam * tf.reduce_sum(rated_item_bias**2)
obj += lam * tf.reduce_sum(unrated_item_bias**2)
obj += lam * tf.reduce_sum(rated_latent_item**2)
obj += lam * tf.reduce_sum(unrated_latent_item**2)
obj += lam * tf.reduce_sum(latent_user**2)
return obj
然而,当我训练它时:
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for iteration in range(5):
samples = sample_triple(data, valid, 100000)
for sample in tqdm(samples):
cvalues = sess.run([trainer, obj], feed_dict={input_data:sample})
它非常缓慢地运行。我有一个vanilla Python SGD实现(例如手工衍生的渐变),它以80K迭代/秒运行。该张量流实现以大约30次迭代/秒运行。这显然是不合理的。显然,批量大小为1会降低速度。但到30次迭代/秒?
这是sess.run()
电话的开销吗?有没有更好的方法来确保我一次只采取一个样本( 是SGD,没有小批量)?
编辑:我应该补充一点,如果我不为每批次提供一个项目(目标函数必须改变),它的速度相当快,但这并不像我所说的那样......
答案 0 :(得分:1)
无法在评论中填写回复。 session.run
确实有一些开销。当您在GPU上运行琐碎计算并提供大值时,开销最明显。馈送始终从CPU内存中获取值并将其复制到GPU(如果您的计算在GPU上运行)。虽然基地不是那么高。例如,这段代码在我的机器上花了一秒钟:
with tf.device('cpu'):
a = tf.placeholder(dtype=tf.float32, shape=())
b = a + 1
with tf.Session() as sess:
s = time.time()
c = 0
for x in xrange(8000):
c += sess.run(b, feed_dict={a: x})
print "Computed in ", c, "in", time.time() - s
为了进一步调试,我建议:
sess.run()
item_biases, latent_items, latent_users
是数组,但您使用的是单个元素。尝试准确喂养你需要的东西。tf.while_loop
在图表中进行小批量循环。答案 1 :(得分:0)
正如iga所指出的,开销是由于sess.run()
调用将内存从GPU复制回CPU的事实。这是一项昂贵的操作。
因此,最好将您的训练操作设计为没有返回值,然后只是不定期地查询成本函数或优化变量的值。例如,
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for iteration in range(5):
samples = sample_triple(data, valid, 100000)
for sample in tqdm(samples):
sess.run( trainer, feed_dict={input_data:sample})
cvalues = sess.run( obj, feed_dict={input_data:sample})
这样,训练师就可以在GPU上运行整个数据集,然后只检索最后的值。