Tensorflow 是如何管理图的?
How does Tensorflow manage graphs?
我意识到 Tensorflow 管理图表的方式似乎有些奇怪。
由于构建(和重建)模型非常繁琐,我决定将我的自定义模型包装在 class 中,以便我可以轻松地在其他地方重新实例化它。
当我训练和测试代码(在原来的地方)时它会工作正常,但是在我加载图形变量的代码中我会遇到各种奇怪的错误 - 变量重新定义和其他一切。这(来自我关于类似事情的上一个问题)暗示所有内容都被调用了两次。
进行大量跟踪后,归结为我使用加载代码的方式。它是在 class 中使用的,其结构类似于
class MyModelUser(object):
def forecast(self):
# .. build the model in the same way as in the training code
# load the model checkpoint
# call the "predict" function on the model
# manipulate the prediction and return it
然后在一些使用MyModelUser
的代码中我有
def test_the_model(self):
model_user = MyModelUser()
print(model_user.forecast()) # 1
print(model_user.forecast()) # 2
我(显然)希望在调用时看到两个预测。相反,第一次预测被调用并按预期工作,但第二次调用抛出了 TON 变量重用 ValueError 其中一个例子是:
ValueError: Variable weight_def/weights already exists, disallowed. Did you mean to set reuse=True in VarScope?
我设法通过添加一系列使用 get_variable
创建变量的 try/except 块来平息错误,然后在异常情况下,在范围上调用 reuse_variables
然后get_variable
除了名字什么都没有。这带来了一组新的严重错误,其中之一是:
tensorflow.python.framework.errors.NotFoundError: Tensor name "weight_def/weights/Adam_1" not found in checkpoint files
一时兴起说"what if I move the modeling building code to __init__
so its only built once?"
我的新模特用户:
class MyModelUser(object):
def __init__(self):
# ... build the model in the same way as in the training code
# load the model checkpoint
def forecast(self):
# call the "predict" function on the model
# manipulate the prediction and return it
现在:
def test_the_model(self):
model_user = MyModelUser()
print(model_user.forecast()) # 1
print(model_user.forecast()) # 2
按预期工作,打印了两个没有错误的预测。这让我相信我也可以摆脱变量重用的东西。
我的问题是:
为什么要修复它?从理论上讲,应该在原始预测方法中每次都重新实例化该图,因此它不应该创建多个图。即使在函数完成后,Tensorflow 是否会保留图形?这就是将创建代码移至 __init__
的原因吗?这让我感到非常困惑。
TF 有一个默认图表,可以添加新操作等。当您两次调用您的函数时,您会将相同的东西添加到同一个图形中两次。因此,要么构建图形一次并对其进行多次评估(正如您所做的那样,这也是 "normal" 方法),或者,如果您想更改内容,可以使用 reset_default_graph https://www.tensorflow.org/versions/r0.11/api_docs/python/framework.html#reset_default_graph 重置图形以获得新状态。
默认情况下,TensorFlow 使用在您首次调用 TensorFlow API 时创建的单个全局 tf.Graph
实例。如果您没有显式创建 tf.Graph
,所有操作、张量和变量都将在该默认实例中创建。这意味着代码中对 model_user.forecast()
的每次调用都将向同一个全局图添加操作,这有点浪费。
这里(至少)有两种可能的行动方案:
理想的做法是重组您的代码,以便 MyModelUser.__init__()
构建一个完整的 tf.Graph
,其中包含执行预测所需的所有操作,并且 MyModelUser.forecast()
只需对现有图执行 sess.run()
调用。理想情况下,您也只创建一个 tf.Session
,因为 TensorFlow 会在会话中缓存有关图形的信息,并且执行效率会更高。
侵入性较小但效率可能较低的更改是为每次调用 MyModelUser.forecast()
创建一个新的 tf.Graph
。从问题中不清楚在 MyModelUser.__init__()
方法中创建了多少状态,但您可以执行类似以下的操作以将两个调用放在不同的图中:
def test_the_model(self):
with tf.Graph(): # Create a local graph
model_user_1 = MyModelUser()
print(model_user_1.forecast())
with tf.Graph(): # Create another local graph
model_user_2 = MyModelUser()
print(model_user_2.forecast())
我意识到 Tensorflow 管理图表的方式似乎有些奇怪。
由于构建(和重建)模型非常繁琐,我决定将我的自定义模型包装在 class 中,以便我可以轻松地在其他地方重新实例化它。
当我训练和测试代码(在原来的地方)时它会工作正常,但是在我加载图形变量的代码中我会遇到各种奇怪的错误 - 变量重新定义和其他一切。这(来自我关于类似事情的上一个问题)暗示所有内容都被调用了两次。
进行大量跟踪后,归结为我使用加载代码的方式。它是在 class 中使用的,其结构类似于
class MyModelUser(object):
def forecast(self):
# .. build the model in the same way as in the training code
# load the model checkpoint
# call the "predict" function on the model
# manipulate the prediction and return it
然后在一些使用MyModelUser
的代码中我有
def test_the_model(self):
model_user = MyModelUser()
print(model_user.forecast()) # 1
print(model_user.forecast()) # 2
我(显然)希望在调用时看到两个预测。相反,第一次预测被调用并按预期工作,但第二次调用抛出了 TON 变量重用 ValueError 其中一个例子是:
ValueError: Variable weight_def/weights already exists, disallowed. Did you mean to set reuse=True in VarScope?
我设法通过添加一系列使用 get_variable
创建变量的 try/except 块来平息错误,然后在异常情况下,在范围上调用 reuse_variables
然后get_variable
除了名字什么都没有。这带来了一组新的严重错误,其中之一是:
tensorflow.python.framework.errors.NotFoundError: Tensor name "weight_def/weights/Adam_1" not found in checkpoint files
一时兴起说"what if I move the modeling building code to __init__
so its only built once?"
我的新模特用户:
class MyModelUser(object):
def __init__(self):
# ... build the model in the same way as in the training code
# load the model checkpoint
def forecast(self):
# call the "predict" function on the model
# manipulate the prediction and return it
现在:
def test_the_model(self):
model_user = MyModelUser()
print(model_user.forecast()) # 1
print(model_user.forecast()) # 2
按预期工作,打印了两个没有错误的预测。这让我相信我也可以摆脱变量重用的东西。
我的问题是:
为什么要修复它?从理论上讲,应该在原始预测方法中每次都重新实例化该图,因此它不应该创建多个图。即使在函数完成后,Tensorflow 是否会保留图形?这就是将创建代码移至 __init__
的原因吗?这让我感到非常困惑。
TF 有一个默认图表,可以添加新操作等。当您两次调用您的函数时,您会将相同的东西添加到同一个图形中两次。因此,要么构建图形一次并对其进行多次评估(正如您所做的那样,这也是 "normal" 方法),或者,如果您想更改内容,可以使用 reset_default_graph https://www.tensorflow.org/versions/r0.11/api_docs/python/framework.html#reset_default_graph 重置图形以获得新状态。
默认情况下,TensorFlow 使用在您首次调用 TensorFlow API 时创建的单个全局 tf.Graph
实例。如果您没有显式创建 tf.Graph
,所有操作、张量和变量都将在该默认实例中创建。这意味着代码中对 model_user.forecast()
的每次调用都将向同一个全局图添加操作,这有点浪费。
这里(至少)有两种可能的行动方案:
理想的做法是重组您的代码,以便
MyModelUser.__init__()
构建一个完整的tf.Graph
,其中包含执行预测所需的所有操作,并且MyModelUser.forecast()
只需对现有图执行sess.run()
调用。理想情况下,您也只创建一个tf.Session
,因为 TensorFlow 会在会话中缓存有关图形的信息,并且执行效率会更高。侵入性较小但效率可能较低的更改是为每次调用
MyModelUser.forecast()
创建一个新的tf.Graph
。从问题中不清楚在MyModelUser.__init__()
方法中创建了多少状态,但您可以执行类似以下的操作以将两个调用放在不同的图中:def test_the_model(self): with tf.Graph(): # Create a local graph model_user_1 = MyModelUser() print(model_user_1.forecast()) with tf.Graph(): # Create another local graph model_user_2 = MyModelUser() print(model_user_2.forecast())