如何正确减小 tensorflow 保存模型的大小? [英] How to properly reduce the size of a tensorflow savedmodel?

查看:113
本文介绍了如何正确减小 tensorflow 保存模型的大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个检查点形式的 tensorflow 预训练模型,我打算通过将模型转换为 savedmodel 形式来部署该模型以供服务.保存模型的大小有点过大.(保存模型中的variables.data-00000-of-0001"文件超过数百MB.)我在谷歌上搜索了如何减少变量的大小,但找不到好的答案.你能帮我理解如何减少张量流保存模型中变量的大小吗?展示一个简单的例子会很棒.谢谢!

I have a tensorflow pre-trained model in a checkpoint form, and I intended to deploy the model for serving by converting the model into the savedmodel form. The size of the saved model is kind of too large. (The "variables.data-00000-of-0001" file in the savedmodel is more than hundred of MBs.) I googled how to reduce the size of variables, but I could not find a good answer. Could you help me understand how to reduce the size of variables in a tensorflow savedmodel? It will be great to show a simple example. Thanks!

推荐答案

我们可以使用下面提到的方法减小 Tensorflow 模型的大小:

We can reduce the size of a Tensorflow Model using the below mentioned methods:

  1. 冻结:将存储在 SavedModel 的检查点文件中的变量转换为直接存储在模型图中的常量.这减小了模型的整体尺寸.

  1. Freezing: Convert the variables stored in a checkpoint file of the SavedModel into constants stored directly in the model graph. This reduces the overall size of the model.

剪枝:去除预测路径中未使用的节点和图形的输出,合并重复节点,以及清理其他节点操作,如摘要、身份等.

Pruning: Strip unused nodes in the prediction path and the outputs of the graph, merging duplicate nodes, as well as cleaning other node ops like summary, identity, etc.

常量折叠:在模型中查找总是计算为常量表达式的任何子图,并用这些常量替换它们.折叠批范数:将批归一化中引入的乘法折叠成前一层的权重乘法.

Constant folding: Look for any sub-graphs within the model that always evaluate to constant expressions, and replace them with those constants. Folding batch norms: Fold the multiplications introduced in batch normalization into the weight multiplications of the previous layer.

量化:将权重从浮点数转换为较低的精度,例如 16 位或 8 位.

Quantization: Convert weights from floating point to lower precision, such as 16 or 8 bits.

冻结图形的代码如下:

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)

修剪和恒定折叠的代码如下:

Code for Pruning and Constant Folding is mentioned below:

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!')

我们通过传递所需优化的列表来调用模型上的代码,如下所示:

We call the code on our model by passing a list of the desired optimizations, like so:

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')

量化代码如下:

transforms = ['quantize_nodes', 'quantize_weights',]
optimize_graph(saved_model_dir, None, transforms, 'head/predictions/class_ids')

一旦应用了优化,我们需要将优化图转换回 GraphDef.代码如下所示:

Once the Optimizations are applied, we need to convert the Optimized Graph back to GraphDef. Code for that is shown below:

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!')

示例代码如下所示:

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)

这篇关于如何正确减小 tensorflow 保存模型的大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆