gob*_*s14 13 python tensorflow tensorflow-serving tensorflow-estimator
背景:
我有一个基于tf.estimator.DNNClassifier的简单分类器,它通过intent标签获取文本和输出概率.我能够训练将模型输出到可服务的以及使用tensorflow服务服务于服务.问题是这个可服务性太大(大约1GB),因此我想尝试一些张量流图变换来尝试减少所服务文件的大小.
问题:
我理解如何saved_model.pb
使用和使用freeze_model.py来创建一个.pb
可用于调用转换的新文件.这些转换的结果(.pb
文件也是如此)不可用,不能与tensorflow服务一起使用.
开发者如何来自:
saved model -> graph transforms -> back to a servable
Run Code Online (Sandbox Code Playgroud)
有文档表明这肯定是可能的,但从文档到关于如何做到这一点并不直观.
我试过的:
import tensorflow as tf
from tensorflow.saved_model import simple_save
from tensorflow.saved_model import signature_constants
from tensorflow.saved_model import tag_constants
from tensorflow.tools.graph_transforms import TransformGraph
with tf.Session(graph=tf.Graph()) as sess_meta:
meta_graph_def = tf.saved_model.loader.load(
sess_meta,
[tag_constants.SERVING],
"/model/path")
graph_def = meta_graph_def.graph_def
other_graph_def = TransformGraph(
graph_def,
["Placeholder"],
["dnn/head/predictions/probabilities"],
["quantize_weights"])
with tf.Graph().as_default():
graph = tf.get_default_graph()
tf.import_graph_def(other_graph_def)
in_tensor = graph.get_tensor_by_name(
"import/Placeholder:0")
out_tensor = graph.get_tensor_by_name(
"import/dnn/head/predictions/probabilities:0")
inputs = {"inputs": in_tensor}
outputs = {"outputs": out_tensor}
simple_save(sess_meta, "./new", inputs, outputs)
Run Code Online (Sandbox Code Playgroud)
我的想法是加载servable,从meta_graph_def中提取graph_def,转换graph_def,然后尝试重新创建servable.这似乎是不正确的方法.
有没有办法从导出的servable成功执行图形转换(减少推理时的文件大小),然后用转换后的图形重新创建一个servable?
谢谢.
更新(2018-08-28):
发现contrib.meta_graph_transform()看起来很有希望.
更新(2018-12-03):
我打开的一个相关的github问题似乎是在一个详细的博客文章中解决的,该帖子列在故障单的末尾.
我们可以使用以下提到的方法优化或减小 Tensorflow 模型的大小:
冻结:将保存在 SavedModel 的检查点文件中的变量转换为直接保存在模型图中的常量。这减小了模型的整体尺寸。
修剪:去除预测路径中未使用的节点和图的输出,合并重复节点,以及清理其他节点操作,如摘要、身份等。
常量折叠:在模型中查找总是计算为常量表达式的任何子图,并将它们替换为这些常量。折叠批规范:将批归一化中引入的乘法折叠到前一层的权重乘法中。
量化:将权重从浮点数转换为较低的精度,例如 16 位或 8 位。
下面提到了冻结图形的代码:
from tensorflow.python.tools import freeze_graph
output_graph_filename = os.path.join(saved_model_dir, output_filename)
initializer_nodes = ''
freeze_graph.freeze_graph(input_saved_model_dir=saved_model_dir,
output_graph=output_graph_filename,
saved_model_tags = tag_constants.SERVING,
output_node_names=output_node_names,initializer_nodes=initializer_nodes,
input_graph=None, input_saver=False, input_binary=False,
input_checkpoint=None, restore_op_name=None, filename_tensor_name=None,
clear_devices=False, input_meta_graph=False)
Run Code Online (Sandbox Code Playgroud)
下面提到了修剪和恒定折叠的代码:
from tensorflow.tools.graph_transforms import TransformGraph
def get_graph_def_from_file(graph_filepath):
with ops.Graph().as_default():
with tf.gfile.GFile(graph_filepath, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
return graph_def
def optimize_graph(model_dir, graph_filename, transforms, output_node):
input_names = []
output_names = [output_node]
if graph_filename is None:
graph_def = get_graph_def_from_saved_model(model_dir)
else:
graph_def = get_graph_def_from_file(os.path.join(model_dir,
graph_filename))
optimized_graph_def = TransformGraph(graph_def, input_names,
output_names, transforms)
tf.train.write_graph(optimized_graph_def, logdir=model_dir, as_text=False,
name='optimized_model.pb')
print('Graph optimized!')
Run Code Online (Sandbox Code Playgroud)
我们通过传递所需优化的列表来调用模型上的代码,如下所示:
transforms = ['remove_nodes(op=Identity)', 'merge_duplicate_nodes',
'strip_unused_nodes','fold_constants(ignore_errors=true)',
'fold_batch_norms']
optimize_graph(saved_model_dir, "frozen_model.pb" , transforms, 'head/predictions/class_ids')
Run Code Online (Sandbox Code Playgroud)
量化代码如下:
transforms = ['quantize_nodes', 'quantize_weights',]
optimize_graph(saved_model_dir, None, transforms, 'head/predictions/class_ids')
Run Code Online (Sandbox Code Playgroud)
应用优化后,我们需要将优化图转换回 GraphDef。代码如下所示:
def convert_graph_def_to_saved_model(export_dir, graph_filepath):
if tf.gfile.Exists(export_dir):
tf.gfile.DeleteRecursively(export_dir)
graph_def = get_graph_def_from_file(graph_filepath)
with tf.Session(graph=tf.Graph()) as session:
tf.import_graph_def(graph_def, name='')
tf.saved_model.simple_save(
session,
export_dir,
inputs={
node.name: session.graph.get_tensor_by_name(
'{}:0'.format(node.name))
for node in graph_def.node if node.op=='Placeholder'},
outputs={'class_ids': session.graph.get_tensor_by_name(
'head/predictions/class_ids:0')}
)
print('Optimized graph converted to SavedModel!')
Run Code Online (Sandbox Code Playgroud)
示例代码如下所示:
optimized_export_dir = os.path.join(export_dir, 'optimized')
optimized_filepath = os.path.join(saved_model_dir, 'optimized_model.pb')
convert_graph_def_to_saved_model(optimized_export_dir, optimized_filepath)
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅@gobrewers14 提到的以下链接:
https://medium.com/google-cloud/optimizing-tensorflow-models-for-serving-959080e9ddbf
小智 0
运行张量流图转换后从 SavedModel 转换为可服务的方法是使用 SavedModel Builder API。
首先,您需要创建一个 SavedModel Builder 对象,然后使用 SavedModel Builder API 重建刚刚转换的图形。
接下来,您需要将资产、签名和其他元数据添加回模型中。最后,您需要调用 SavedModel Builder API 的 save() 方法,该方法会将模型保存为可服务。
然后,该 Servable 可以与 Tensorflow 服务一起使用。
归档时间: |
|
查看次数: |
727 次 |
最近记录: |