Tensorflow TF中批处理时的回溯

Tensorflow TF中批处理时的回溯,tensorflow,tensorflow2.0,tensorflow-xla,Tensorflow,Tensorflow2.0,Tensorflow Xla,我有一个模型,我想计算它的梯度w.r.t.输入。计算需要内存,因此我想将其分为若干批 由于我关心计算时间,所以我希望将所有内容都封装在tf.function中 这是我将要做的一个例子: import tensorflow as tf import tensorflow_probability as tfp def model(sample): # Just a trivial example. This function in reality takes more arguments

我有一个模型,我想计算它的梯度w.r.t.输入。计算需要内存,因此我想将其分为若干批

由于我关心计算时间,所以我希望将所有内容都封装在
tf.function

这是我将要做的一个例子:

import tensorflow as tf
import tensorflow_probability as tfp

def model(sample):
    # Just a trivial example. This function in reality takes more arguments and creates
    # a large computational graph
    return tf.reduce_logsumexp(tfp.distributions.Normal(0., 1.).log_prob(sample), axis=1)

input_ = tf.random.uniform(maxval=1., shape=(100,10000000))

compiled_model = tf.function(model)

def get_batches(vars_, batch_size=10):
    current_beginning = 0
    all_elems = vars_[0].shape[0]
    while current_beginning < all_elems:
        yield tf.Variable(vars_[current_beginning:current_beginning+batch_size])
        current_beginning += batch_size

res = []        

for batch in get_batches(input_, batch_size=1):
    with tf.GradientTape() as tape_logprob:
        tape_logprob.watch(batch)
        log_prob = compiled_model(batch)
    
    res.append(tape_logprob.gradient(log_prob, batch))
    
将tensorflow导入为tf
导入tensorflow_概率作为tfp
def型号(示例):
#这只是一个微不足道的例子。实际上,此函数接受更多参数并创建
#大型计算图
返回tf.reduce_logsumexp(tfp.distributions.Normal(0,1.).log_prob(示例),轴=1)
输入=tf.random.uniform(maxval=1,shape=(10010000000))
编译的_model=tf.函数(model)
def get_批次(变量,批次大小=10):
当前\u开始=0
所有元素=变量[0]。形状[0]
当前元素开始<所有元素:
产量tf.变量(变量[当前开始:当前开始+批量大小])
当前\u开始+=批次大小
res=[]
对于get_批次中的批次(输入_,批次大小=1):
使用tf.GradientTape()作为磁带_logprob:
磁带/日志探测表(批量)
log_prob=编译的_模型(批处理)
res.append(磁带对数概率梯度(对数概率,批次))

如果你运行这个代码,你会发现它在XLA编译过程中引起了重写,并且严重影响了性能:

警告:tensorflow:最近5次调用中有5次调用触发了tf.function Retracting。跟踪代价高昂,跟踪次数过多可能是由于(1)在循环中重复创建@tf.function,(2)传递不同形状的张量,(3)传递Python对象而不是张量。对于(1),请在循环之外定义@tf.function。对于(2),@tf.function具有实验性的_relax_shapes=True选项,该选项可以松弛参数形状,从而避免不必要的回溯。有关(3),请参阅和了解更多详细信息

我不明白为什么这里会发生回溯。以下是警告中提到的要点: 1). 我不在循环中定义
tf.function
(尽管我在循环中运行它)。 2). 输入张量的形状总是相同的,因此我认为编译应该只发生一次。 3). 我不使用普通Python对象

我在这里遗漏了什么细微差别?如何让这个例子起作用

在进行实验时,我注意到,我可以通过将
log\u prob=compiled\u model(batch)
包装成一个简单的
tf.map\u fn
来消除警告消息,但与非批处理版本的计算相比,我仍然观察到了很大的性能下降