为什么我的tensorflow代码运行得如此之慢?批量大小为1

时间:2018-02-01 20:47:31

标签: python tensorflow

所以我有以下目标函数。它一次仅适用于一个训练示例(我有我避免批量的原因)。正如你所看到它非常轻巧,所以我希望它能够快速运行。

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,没有小批量)?

编辑:我应该补充一点,如果我不为每批次提供一个项目(目标函数必须改变),它的速度相当快,但这并不像我所说的那样......

2 个答案:

答案 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是数组,但您使用的是单个元素。尝试准确喂养你需要的东西。
  • 尝试在CPU上运行
  • 尝试查看效果时间表:https://towardsdatascience.com/howto-profile-tensorflow-1a49fb18073d
  • 如果这些步骤没有显示任何简单的修复,请使用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上运行整个数据集,然后只检索最后的值。