Tensorflow在切片上循环,并在急切执行模式下分配给变量

Tensorflow在切片上循环,并在急切执行模式下分配给变量,tensorflow,for-loop,variable-assignment,tensorflow2.0,eager-execution,Tensorflow,For Loop,Variable Assignment,Tensorflow2.0,Eager Execution,对于一些自定义代码,我需要运行For循环,以便在Tensorflow 2中动态创建一个变量(启用了急切执行模式)。(在我的自定义代码中,我写入变量的值需要渐变,因此我希望跟踪for循环中的计算,以便从autodiff获得渐变)。我的代码可以工作,但速度非常慢。事实上,它比在numpy中执行相同的操作慢几个数量级 我已经隔离了这个问题,并提供了一个玩具代码片段来突出这个问题。修复它将允许我修复自定义代码 import numpy as np import tensorflow as tf impo

对于一些自定义代码,我需要运行For循环,以便在Tensorflow 2中动态创建一个变量(启用了急切执行模式)。(在我的自定义代码中,我写入变量的值需要渐变,因此我希望跟踪for循环中的计算,以便从autodiff获得渐变)。我的代码可以工作,但速度非常慢。事实上,它比在numpy中执行相同的操作慢几个数量级

我已经隔离了这个问题,并提供了一个玩具代码片段来突出这个问题。修复它将允许我修复自定义代码

import numpy as np
import tensorflow as tf
import timeit

N = int(1e5)
data = np.random.randn(N)
def numpy_func(data):
    new_data = np.zeros_like(data)
    for i in range(len(data)):
        new_data[i] = data[i]
    return new_data

def tf_func(data):
    new_data = tf.Variable(tf.zeros_like(data))
    for i in range(len(data)):
        new_data[i].assign(data[i])
    return new_data    

%timeit numpy_func(data)
%timeit tf_func(data)
这段代码片段的要点是,在for循环中,我只需要更新变量的一部分。在每次迭代中,要更新的切片是不同的。用于更新的数据在每次迭代时都是不同的(在我的自定义代码中,它是依赖于变量切片的一些简单计算的结果,这里我只是使用固定数组来隔离问题。)

我使用的是Tensorflow 2,Tensorflow代码理想情况下需要在启用急切执行的情况下运行,因为部分自定义操作依赖于急切执行

我是Tensorflow的新手,如果您能帮我解决这个问题,我将不胜感激

非常感谢,,
Max

这样使用时,TensorFlow的速度永远不会很快。理想的解决方案是将计算矢量化,这样就不需要显式地循环,但这取决于您正在计算的确切内容(如果您愿意,您可以发布另一个问题)。但是,使用可以获得更好的性能。我对你的函数做了一些修改,将
new_data
作为输出参数,因为它不允许你在第一次调用后创建变量(但实际上,如果你删除
new_data
参数,它也会起作用,因为它会在全局范围内找到变量)

将numpy导入为np
导入tensorflow作为tf
导入时间信息
#输入数据
N=int(1e3)
数据=np.random.randn(N)
#努比
def numpy_func(数据、新数据):
新的_数据[:]=0
对于范围内的i(len(数据)):
新数据[i]=数据[i]
新数据=np.类零(数据)
%timeit numpy_func(数据、新数据)
#每个回路143µs±4.41µs(7次运行的平均值±标准偏差,每个10000个回路)
#张量流
def tf_func(数据、新数据):
新数据赋值(tf.zeros_like(数据))
对于范围内的i(len(数据)):
新建数据[i]。分配(数据[i])
新数据=tf.变量(类似于tf.零(数据))
%timeit tf_func(数据、新数据)
#每个回路119 ms±3.68 ms(7次运行的平均值±标准偏差,每个10个回路)
#功能
#这相当于将其用作装饰器
tf_func2=tf.函数(tf_func)
新数据=tf.变量(类似于tf.零(数据))
tf_func2(数据,新数据)#第一次调用较慢
%timeit tf_func2(数据、新数据)
#每个回路3.55 ms±40.6µs(7次运行的平均值±标准偏差,每个100个回路)

这是在CPU上运行的,结果在GPU上可能会有很大差异。在任何情况下,正如您所看到的,它仍然比NumPy慢20倍多,但也比Python函数快30倍多。

TensorFlow在这样使用时永远不会很快。理想的解决方案是将计算矢量化,这样就不需要显式地循环,但这取决于您正在计算的确切内容(如果您愿意,您可以发布另一个问题)。但是,使用可以获得更好的性能。我对你的函数做了一些修改,将
new_data
作为输出参数,因为它不允许你在第一次调用后创建变量(但实际上,如果你删除
new_data
参数,它也会起作用,因为它会在全局范围内找到变量)

将numpy导入为np
导入tensorflow作为tf
导入时间信息
#输入数据
N=int(1e3)
数据=np.random.randn(N)
#努比
def numpy_func(数据、新数据):
新的_数据[:]=0
对于范围内的i(len(数据)):
新数据[i]=数据[i]
新数据=np.类零(数据)
%timeit numpy_func(数据、新数据)
#每个回路143µs±4.41µs(7次运行的平均值±标准偏差,每个10000个回路)
#张量流
def tf_func(数据、新数据):
新数据赋值(tf.zeros_like(数据))
对于范围内的i(len(数据)):
新建数据[i]。分配(数据[i])
新数据=tf.变量(类似于tf.零(数据))
%timeit tf_func(数据、新数据)
#每个回路119 ms±3.68 ms(7次运行的平均值±标准偏差,每个10个回路)
#功能
#这相当于将其用作装饰器
tf_func2=tf.函数(tf_func)
新数据=tf.变量(类似于tf.零(数据))
tf_func2(数据,新数据)#第一次调用较慢
%timeit tf_func2(数据、新数据)
#每个回路3.55 ms±40.6µs(7次运行的平均值±标准偏差,每个100个回路)
这是在CPU上运行的,结果在GPU上可能会有很大差异。在任何情况下,正如您所看到的,它仍然比NumPy慢20倍多,但也比Python函数快30倍多