如何有效地跟踪 TensorFlow 张量的历史记录?
How do I efficiently track the history of a tensorflow tensor?
这种使用 TensorArray
的模式是否是跟踪张量历史的有效方式?内部循环中的所有内容是否都在 GPU 上完成而不向 CPU 传输任何内容?我该如何验证?
import tensorflow as tf
with tf.device('/device:GPU:0'):
@tf.function
def f(x, y):
return y, x + y
x_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
y_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
x = tf.Variable([1.0])
y = tf.Variable([1.0])
x_array.write(0, x)
y_array.write(0, y)
for i in tf.range(10):
x = x_array.read(i)
y = y_array.read(i)
new_x, new_y = f(x, y)
x_array.write(i + 1, new_x)
y_array.write(i + 1, new_y)
print(x_array.stack())
print(y_array.stack())
这就是我真正想要做的,但它甚至没有 运行:
import tensorflow as tf
with tf.device('/device:GPU:0'):
@tf.function
def f(x, y):
return y, x + y
@tf.function
def g(n):
for i in tf.range(n):
x = x_array.read(i)
y = y_array.read(i)
new_x, new_y = f(x, y)
x_array.write(i + 1, new_x)
y_array.write(i + 1, new_y)
x_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
y_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
x = tf.Variable([1.0])
y = tf.Variable([1.0])
x_array.write(0, x)
y_array.write(0, y)
g(tf.constant(10))
print(x_array.stack())
print(y_array.stack())
这是修复第二个代码段的方法:
import tensorflow as tf
with tf.device('/device:GPU:0'):
@tf.function
def f(x, y):
return y, x + y
@tf.function
def g(x, y, n):
x_array = tf.TensorArray(tf.float32, n + 1, dynamic_size=False,
clear_after_read=True)
y_array = tf.TensorArray(tf.float32, n + 1, dynamic_size=False,
clear_after_read=True)
x_array = x_array.write(0, x)
y_array = y_array.write(0, y)
for i in range(n):
x, y = f(x, y)
x_array = x_array.write(i + 1, x)
y_array = y_array.write(i + 1, y)
return x_array.stack(), y_array.stack()
x = tf.Variable([1.0])
y = tf.Variable([1.0])
x_hist, y_hist = g(x, y, tf.constant(10))
print(x_hist)
# tf.Tensor(
# [[ 1.]
# [ 1.]
# [ 2.]
# [ 3.]
# [ 5.]
# [ 8.]
# [13.]
# [21.]
# [34.]
# [55.]
# [89.]], shape=(11, 1), dtype=float32)
print(y_hist)
# tf.Tensor(
# [[ 1.]
# [ 2.]
# [ 3.]
# [ 5.]
# [ 8.]
# [ 13.]
# [ 21.]
# [ 34.]
# [ 55.]
# [ 89.]
# [144.]], shape=(11, 1), dtype=float32)
有一些问题。 tf.function
应该将其输入作为参数,而不是来自全局范围。您可以在函数内创建张量数组,并且可以将它们设置为 fixed-size 并使用 clear-after-read,因为您之后不会使用它们。但将每个 write
操作的结果分配给数组变量很重要,因为这将使它成为 "the tensor array after writing"。您不需要在循环中使用 tf.range
。并且 "history" 数组可以通过写入每次迭代的结果来更有效地填充,而不是再次从数组中读取。
关于 GPU,因为所有东西都在 tf.device
上下文中,所以它都会被分配并 运行 在 GPU 上,如果不能 运行 就会出错,所以只要一切 运行s 就应该没问题。
这种使用 TensorArray
的模式是否是跟踪张量历史的有效方式?内部循环中的所有内容是否都在 GPU 上完成而不向 CPU 传输任何内容?我该如何验证?
import tensorflow as tf
with tf.device('/device:GPU:0'):
@tf.function
def f(x, y):
return y, x + y
x_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
y_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
x = tf.Variable([1.0])
y = tf.Variable([1.0])
x_array.write(0, x)
y_array.write(0, y)
for i in tf.range(10):
x = x_array.read(i)
y = y_array.read(i)
new_x, new_y = f(x, y)
x_array.write(i + 1, new_x)
y_array.write(i + 1, new_y)
print(x_array.stack())
print(y_array.stack())
这就是我真正想要做的,但它甚至没有 运行:
import tensorflow as tf
with tf.device('/device:GPU:0'):
@tf.function
def f(x, y):
return y, x + y
@tf.function
def g(n):
for i in tf.range(n):
x = x_array.read(i)
y = y_array.read(i)
new_x, new_y = f(x, y)
x_array.write(i + 1, new_x)
y_array.write(i + 1, new_y)
x_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
y_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
clear_after_read=False)
x = tf.Variable([1.0])
y = tf.Variable([1.0])
x_array.write(0, x)
y_array.write(0, y)
g(tf.constant(10))
print(x_array.stack())
print(y_array.stack())
这是修复第二个代码段的方法:
import tensorflow as tf
with tf.device('/device:GPU:0'):
@tf.function
def f(x, y):
return y, x + y
@tf.function
def g(x, y, n):
x_array = tf.TensorArray(tf.float32, n + 1, dynamic_size=False,
clear_after_read=True)
y_array = tf.TensorArray(tf.float32, n + 1, dynamic_size=False,
clear_after_read=True)
x_array = x_array.write(0, x)
y_array = y_array.write(0, y)
for i in range(n):
x, y = f(x, y)
x_array = x_array.write(i + 1, x)
y_array = y_array.write(i + 1, y)
return x_array.stack(), y_array.stack()
x = tf.Variable([1.0])
y = tf.Variable([1.0])
x_hist, y_hist = g(x, y, tf.constant(10))
print(x_hist)
# tf.Tensor(
# [[ 1.]
# [ 1.]
# [ 2.]
# [ 3.]
# [ 5.]
# [ 8.]
# [13.]
# [21.]
# [34.]
# [55.]
# [89.]], shape=(11, 1), dtype=float32)
print(y_hist)
# tf.Tensor(
# [[ 1.]
# [ 2.]
# [ 3.]
# [ 5.]
# [ 8.]
# [ 13.]
# [ 21.]
# [ 34.]
# [ 55.]
# [ 89.]
# [144.]], shape=(11, 1), dtype=float32)
有一些问题。 tf.function
应该将其输入作为参数,而不是来自全局范围。您可以在函数内创建张量数组,并且可以将它们设置为 fixed-size 并使用 clear-after-read,因为您之后不会使用它们。但将每个 write
操作的结果分配给数组变量很重要,因为这将使它成为 "the tensor array after writing"。您不需要在循环中使用 tf.range
。并且 "history" 数组可以通过写入每次迭代的结果来更有效地填充,而不是再次从数组中读取。
关于 GPU,因为所有东西都在 tf.device
上下文中,所以它都会被分配并 运行 在 GPU 上,如果不能 运行 就会出错,所以只要一切 运行s 就应该没问题。