我已经看到了这个问题的变化,但我还没有找到满意的答案。基本上,我想从keras model.to_json()
,model.get_weights()
,model.from_json()
,model.set_weights()
到tensorflow等效。我想我已经接近那里了,但我正处于被困的地步。如果我可以在同一个字符串中获得权重和图形,我更愿意,但我知道这是不可能的。
目前,我所拥有的是:
g = optimizer.minimize(loss_op,
global_step=tf.train.get_global_step())
de = g.graph.as_graph_def()
json_string = json_format.MessageToJson(de)
gd = tf.GraphDef()
gd = json_format.Parse(json_string, gd)
这似乎创建了图表,但显然元图不包含在变量,权重等中。还有元图,但我唯一看到的是export_meta_graph,它似乎没有序列化以同样的方式。我看到MetaGraph有一个proto函数,但我不知道如何序列化这些变量。
简而言之,您如何采用张量流模型(模型如权重,图形等),将其序列化为字符串(最好是json),然后对其进行反序列化并继续训练或提供预测。
以下是让我接近并且我已经尝试过的东西,但是大多数情况下需要写入磁盘有限制,在这种情况下我无法做到:
This is the closest one I found, but the link to serializing a metagraph doesn't exist.
答案 0 :(得分:3)
请注意,@ Maxim的解决方案每次运行时都会在图中创建新操作。
如果您频繁运行该函数,这将导致您的代码越来越慢。
两种解决此问题的方法:
与图的其余部分同时创建分配操作并重用它们:
assign_ops = []
for var_name in tf.trainable_variables():
assign_placeholder = tf.placeholder(var.dtype, shape=value.shape)
assign_op = var.assign(assign_placeholder)
assign_ops.append(assign_op)
在变量上使用load函数,我更喜欢此函数,因为它消除了对上面代码的需要:
self.params = tf.trainable_variables()
def get_weights(self):
values = tf.get_default_session().run(self.params)
return values
def set_weights(self, weights):
for i, value in enumerate(weights):
value = np.asarray(value)
self.params[i].load(value, self.sess)
(我无法发表评论,因此我将其作为答案)
答案 1 :(得分:2)
您可以使用freeze_graph
此脚本包含在Tensorflow中,允许您获取GraphDef原型,SaverDef原型以及存储在检查点文件中的一组变量值。
通过这种方式,您可以输出一个GraphDef,其中所有变量操作都转换为包含变量值的const操作。
要恢复冻结模型,您必须重新初始化图形并重新映射冻结模型中的输入,请参阅this example
答案 2 :(得分:2)
如果您想要等同于keras Model.get_weights()
和Model.set_weights()
,则这些方法与keras内部结构无关,可以轻松提取。
以下是keras源代码中的外观:
def get_weights(self):
weights = []
for layer in self.layers:
weights += layer.weights
return K.batch_get_value(weights) # this is just `get_session().run(weights)`
def set_weights(self, weights):
tuples = []
for layer in self.layers:
num_param = len(layer.weights)
layer_weights = weights[:num_param]
for sw, w in zip(layer.weights, layer_weights):
tuples.append((sw, w))
weights = weights[num_param:]
K.batch_set_value(tuples) # another wrapper over `get_session().run(...)`
Keras的weights
是numpy数组(不是json)的列表。如您所见,它使用模型体系结构已知(self.layers
)这一事实,它允许它重建从变量到值的正确映射。在K.batch_set_value
中完成了一些看似非平凡的工作,但实际上它只是准备分配操作并在会话中运行它们。
def tensorflow_get_weights():
vars = tf.trainable_variables()
values = tf.get_default_session().run(vars)
return zip([var.name for var in vars], values)
def tensorflow_set_weights(weights):
assign_ops = []
feed_dict = {}
for var_name, value in weights:
var = tf.get_default_session().graph.get_tensor_by_name(var_name)
value = np.asarray(value)
assign_placeholder = tf.placeholder(var.dtype, shape=value.shape)
assign_op = tf.assign(var, assign_placeholder)
assign_ops.append(assign_op)
feed_dict[assign_placeholder] = value
tf.get_default_session().run(assign_ops, feed_dict=feed_dict)
这里我假设您要序列化/反序列化整个模型(即所有可训练变量)和默认会话。如果不是这种情况,上面的功能很容易定制。
x = tf.placeholder(shape=[None, 5], dtype=tf.float32, name='x')
W = tf.Variable(np.zeros([5, 5]), dtype=tf.float32, name='W')
b = tf.Variable(np.zeros([5]), dtype=tf.float32, name='b')
y = tf.add(tf.matmul(x, W), b)
with tf.Session() as session:
session.run(tf.global_variables_initializer())
# Save the weights
w = tensorflow_get_weights()
print(W.eval(), b.eval())
# Update the model
session.run([tf.assign(W, np.ones([5, 5])), tf.assign(b, np.ones([5]) * 2)])
print(W.eval(), b.eval())
# Restore the weights
tensorflow_set_weights(w)
print(W.eval(), b.eval())
如果你运行这个测试,你应该看到模型被零冻结,然后得到更新,然后恢复为零。
答案 3 :(得分:0)
感谢Maxim帮我解决问题。我想发布一个答案,图表和权重转换为json,适合遇到此问题的人。为了序列化图形而不是权重,我创建了一个要点,其中包含Maxim在此处写的内容:Tensorflow graph with non json serialized weights
现在要序列化/反序列化图形和权重,我在这里创建了一个单独的要点:Tensorflow graph with json serialized weights and graph。
为了完成解释,我首先通过不返回获取权重中的变量来稍微调整权重函数,并在设置权重中抓取当前变量。这是一个重要的警告,特别是如果图表与当前的可训练变量略有不同:
import tensorflow as tf
import numpy as np
from google.protobuf import json_format
import json
def tensorflow_get_weights():
vs = tf.trainable_variables()
values = tf.get_default_session().run(vs)
return values
def tensorflow_set_weights(weights):
assign_ops = []
feed_dict = {}
vs = tf.trainable_variables()
zipped_values = zip(vs, weights)
for var, value in zipped_values:
value = np.asarray(value)
assign_placeholder = tf.placeholder(var.dtype, shape=value.shape)
assign_op = var.assign(assign_placeholder)
assign_ops.append(assign_op)
feed_dict[assign_placeholder] = value
tf.get_default_session().run(assign_ops, feed_dict=feed_dict)
接下来,我创建了两个实用程序函数,用于将权重转换为json:
def convert_weights_to_json(weights):
weights = [w.tolist() for w in weights]
weights_list = json.dumps(weights)
return weights_list
def convert_json_to_weights(json_weights):
loaded_weights = json.loads(json_weights)
loaded_weights = [np.asarray(x) for x in loaded_weights]
return loaded_weights
我有一种最初开始训练的方法。此方法将初始化变量,运行优化,获取权重和图形,并将它们转换为json。它看起来像:
def run_initial_with_json_weights(opti, feed_dict):
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(0, 250):
sess.run(opti, feed_dict=feed_dict)
first_weights = tensorflow_get_weights()
g = tf.get_default_graph().as_graph_def()
json_string = json_format.MessageToJson(g)
return json_string, convert_weights_to_json(first_weights)
现在我们有序列化的权重和图表,如果我们想继续训练和/或做出预测,我们可以做到以下几点。此方法反序列化graphdef和权重,运行优化,然后进行预测。
def run_serialized(json_graph, json_weights, feed_dict):
gd = tf.GraphDef()
gd = json_format.Parse(json_graph, gd)
weights = convert_json_to_weights(json_weights)
with tf.Session() as sess:
tf.import_graph_def(gd)
sess.run(tf.global_variables_initializer())
nu_out = tf.get_default_graph().get_tensor_by_name('outer/Sigmoid:0')
mini = tf.get_default_graph().get_tensor_by_name('mini:0')
tensorflow_set_weights(weights)
for i in range(0, 50):
sess.run(mini, feed_dict=feed_dict)
predicted = sess.run(nu_out, feed_dict=feed_dict)
return predicted
完整的xor示例在上面的要点中。