我有一个简单的目标,即在tensorflow保存中训练模型并在以后恢复它,以便继续训练或使用某些功能/操作。
以下是模型的简单示例
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)
在恢复的操作中,您甚至无法从原始代码中找到predict
或train_step
。我需要在保存之前命名此操作吗?如何让predict
返回并运行类似
sess=tf.Session()
sess.run([predict], feed_dict = {x:X})
P.S。我在tensorflow中阅读了许多关于保存和恢复的教程,但仍然不太了解它是如何工作的。
答案 0 :(得分:2)
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”,对应于你总结的内容。为了清楚起见,我不确定只是这个操作对应于给定的代码行,因为打印中存在具有相同类型输入的其他添加,但这是可能的。
所以总结到现在为止:你的操作在那里,你在打印时看到它们。但为什么你不看“预测”这个词?好吧,因为这不是Tensorflow图中张量或操作的名称,它只是代码中变量的名称。
前进,你怎么能访问这个“预测”?答案是通过它的名称,如图中所示。在上面的例子中,预测的名称可以是“添加”,如果我对我的猜测是正确的,那么让我们将其命名为“预测”,这样您就可以轻松控制哪个操作对应于它。
为了命名“预测”,我们在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”访问你的“预测”,2)我们可以确认你的“预测”实际上是名为“add_1”的操作 - 只需检查操作的“输入”属性上方“here_i_put_a_name”。
完成后,让我们访问“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”之间的区别。第一个是操作,最后一个是张量。