tensorflow - 保存和恢复操作

tensorflow - saving and restoring operations

我有一个简单的目标,即在 tensorflow 中训练模型保存并在以后恢复它,以便继续训练或使用一些 functions/operations。

这是模型的简单示例

import tensorflow as tf
import numpy as np

BATCH_SIZE = 3
VECTOR_SIZE = 1
LEARNING_RATE = 0.1

x = tf.placeholder(tf.float32, [BATCH_SIZE, VECTOR_SIZE],
                   name='input_placeholder')
y = tf.placeholder(tf.float32, [BATCH_SIZE, VECTOR_SIZE],
                   name='labels_placeholder')

W = tf.get_variable('W', [VECTOR_SIZE, BATCH_SIZE])
b = tf.get_variable('b', [VECTOR_SIZE], initializer=tf.constant_initializer(0.0))

y_hat = tf.matmul(W, x) + b
predict = tf.matmul(W, x) + b
total_loss = tf.reduce_mean(y-y_hat)
train_step = tf.train.AdagradOptimizer(LEARNING_RATE).minimize(total_loss)
X = np.ones([BATCH_SIZE, VECTOR_SIZE])
Y = np.ones([BATCH_SIZE, VECTOR_SIZE])
all_saver = tf.train.Saver() 

sess= tf.Session()
sess.run(tf.global_variables_initializer())
sess.run([train_step], feed_dict = {x: X, y:Y}))
save_path =  r'C:\some_path\save\'
all_saver.save(sess,save_path)

现在我们在这里恢复它:

meta_path = r'C:\some_path\save\.meta'
new_all_saver = tf.train.import_meta_graph(meta_path)

graph = tf.get_default_graph()
all_ops = graph.get_operations()
for el in all_ops:
    print(el)

在恢复操作中,甚至无法从原始代码中找到 predicttrain_step。我需要在保存之前命名这个操作吗?我怎样才能得到 predict 和 运行 这样的东西

sess=tf.Session()
sess.run([predict], feed_dict = {x:X})

P.S。我看了很多关于tensorflow中保存和恢复的教程,但对它是如何工作的仍然知之甚少。

1) 你的操作在恢复后的模型中,但由于你没有命名它们,它们将根据一些默认规则命名。例如,因为您有:

predict = tf.matmul(W, x) + b

那么表示 predict 的操作可能如下所示:

name: "add"
op: "Add"
input: "MatMul"
input: "b/read"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}

在这个例子中,当你执行 for el in all_ops: 并打印结果时,你会看到操作的名称是 "add",这是自动分配的;操作类型("op")为"Add",对应代码行最后执行的操作(+);并且输入是 "MatMul" 和 "b/read",对应于您求和的内容。明确地说,我不确定这个操作是否对应于给定的代码行,因为打印中存在其他具有相同输入类型的添加,但这是可能的。

所以总结到现在:你的操作就在那里,你在打印时看到它们。但是为什么没有看到"predict"这个词呢?好吧,因为这不是 Tensorflow Graph 中张量或操作的名称,它只是您代码中变量的名称。

展望未来,您如何才能访问此 "predict"?答案是通过图中所示的名称。在上面的例子中,predict 的名称可以是 "add",如果我的猜测是正确的,但让我们将你的名称命名为 "predict",这样你就可以轻松地控制与之对应的操作。

为了命名您的 "predict",让我们在 predict = tf.matmul(W, x) + b 下面添加以下代码行:

predict_named = tf.identity(predict, "here_i_put_a_name")

这一行所做的是创建一个新操作,它接收 "predict" 中定义的操作作为输入,并产生等于输入结果的输出。这个操作本身并没有做太多——只是重复一个值——但通过这个操作我可以给它添加一个名字。现在,如果您在印刷品中搜索,您将能够找到:

name: "add_1"
op: "Add"
input: "MatMul_1"
input: "b/read"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}

name: "here_i_put_a_name"
op: "Identity"
input: "add_1"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}

不错!现在你 1) 可以使用名称 "here_i_put_a_name" 访问你的 "predict" 和 2) 我们可以确认你的 "predict" 实际上是名称为 "add_1" 的操作 - 只需检查上面操作 "here_i_put_a_name".

的 "input" 属性

完成后,让我们访问操作 "here_i_put_a_name" 并完成一些预测。首先,改变你的 save_path 和 meta_path,在最后加上一个可能的文件名,例如:

save_path =  r'C:\some_path\save\my_model_name'
meta_path = r'C:\some_path\save\my_model_name.meta'

然后,在恢复代码的末尾添加:

with tf.Session(graph=graph) as sess:

    new_all_saver.restore(sess,save_path)
    my_prediction = sess.run(["here_i_put_a_name:0"], feed_dict={"input_placeholder:0": [[1],[2],[3]]})
    print(my_prediction)

使用此块,您将创建一个新的 Tensorflow 会话并使用存储在变量 "graph" 中的图形。在此上下文中,您正在将会话从 save_path 恢复到当前会话。然后,你是 运行 一个预测,或者更准确地说,你是 运行 操作 "here_i_put_a_name" 并获得这个操作的第一个输出(为什么我们在它后面有“:0”) . feed dict 将值 [[1],[2],[3]] 赋给张量 "input_placeholder:0"(同样,“:0”向我们表明这是张量,而不是运算)。

综上所述以及问题(希望)得到回答,我有一些评论:

1)根据我的经验,使用库 tf.saved_model 来保存和恢复模块会很好。但这是我个人的建议。

2)我仅限于回答你关于命名和调用操作的问题,所以我忽略了训练和预测例程。但是我认为当你将变量 X 设置为 BATCH_SIZE 作为大小时,你处理的问题是错误的。

3) 注意 "blabla" 和 "blabla:0" 之间的区别。第一个是运算,最后一个是张量。