对于.pb模型优化总共有两条线:
一、删除多余节点后+发布手机程序时的大幅压缩能力,主要针对手机需要两步连用:optimize_for_inference.py +quantize_graph.py(python文件见网盘:https://pan.baidu.com/s/1hdODQTUb7rqHirlUV4zpxA)

1.前者位于tensorflow1.13.1/tensorflow/python/tools中,作用删除删除输入和输出节点之间所有不需要的节点。
调用optimize_for_inference脚本会删除输入和输出节点之间所有不需要的节点。同时该脚本还做了一些其他优化以提高运行速度。例如它把显式批处理标准化运算跟卷积权重进行了合并,从而降低了计算量。
使用方法:

python3 -m optimize_for_inference.py 
 –input=/tf_files/CTNModel.pb 
 –output=/tf_files/optimized_graph.pb 
 –input_names=inputs/X 
 –output_names=output/predict

首先用bazel build出我们的optimize_for_inference脚本,再调用这个脚本,提供几个参数:输入的PB文件路径,输出的PB文件路径,输入节点名以及输出节点名。经过这一次的优化,文件变小,但大小差别不大。

2.后者位于tensorflow1.13.1/tensorflow/contrib/quantize/python中(我时用bazel build过的源码),经过这个脚本的PB文件原本的大小不会改变,但会有更多的可利用的重复性,压缩成zip包会缩小大约3~4倍的大小。说白了,就是模型大小不变,但是有了打包apk时变小的能力,打包成安卓程序时,它会变成原来的约1/4,使得apk文件不会很大。对于树莓派毫无用处。
使用方式很简单:

python3 -m quantize_graph.py 
 –input=optimized_graph.pb 
 –output=rounded_graph.pb 
 –output_node_names=final_result 
 –mode=weights_rounded


输入的参数依然是:输入的PB文件路径,输出的PB文件路径,输出节点名,这里还有个特别的参数mode,这个参数是告诉脚本我们选择哪种压缩方式,这里我们选择了对权重进行四舍五入。mode 有很多可选值:quantize, eightbit, weights, weights_rounded等,需要自己查吧。

二、graph_transforms (用 bazel 工具构建,python文件见网盘:https://pan.baidu.com/s/1hdODQTUb7rqHirlUV4zpxA) 在2017年的Google I/O大会上,曾提到过的graph_transforms是一整套优化工具,基本上所有的优化方案都能在这里找到,包括之前的那两种优化方式。
示例代码(要在有bazel-bin快捷方式的文件目录下运行,具体见我的上篇博文 跟以下代码参数有所不同):

bazel-bin/tensorflow/tools/graph_transforms/transform_graph 
 –in_graph=CTNModel.pb 
 –out_graph=optimized_graph.pb 
 –inputs=‘inputs/X’ 
 –outputs=‘output/predict’ 
 –transforms=’
 strip_unused_nodes(type=float, shape=“256*64”)
 remove_nodes(op=Identity, op=CheckNumerics)
 fold_constants(ignore_errors=true)
 fold_batch_norms
 fold_old_batch_norms’

transforms的参数代表着想要做的操作,这里主要就是删除未调用的节点,以及优化BN算法,而且必须先运行fold_constants。

还有另外两种不同功能模式:
1)Eight-bit(我上篇用的这个)

bazel-bin/tensorflow/tools/graph_transforms/transform_graph 
 –in_graph=CTNModel.pb 
 –out_graph=eight_bit_graph.pb 
 –inputs=‘inputs/X’ 
 –outputs=‘output/predict’ 
 –transforms=’
 strip_unused_nodes(type=float, shape=“25664")
 fold_constants(ignore_errors=true)
 fold_batch_norms
 fold_old_batch_norms
 quantize_weights’


把权重的数据类型由32位的float 32转成8位的int,在数据类型层面为模型减少3~4倍的占用大小。成效还是挺明显的,不过缺点就是损失精度较大,非必要情况,建议别使用。
2)round_weights 权重进行四舍五入,跟quantize_graph.py功能相同

bazel-bin/tensorflow/tools/graph_transforms/transform_graph 
 –in_graph=CTNModel.pb 
 –out_graph=rounded_grapg.pb 
 –inputs=‘inputs/X’ 
 –outputs=‘output/predict’ 
 –transforms=’
 strip_unused_nodes(type=float, shape="25664”)
 fold_constants(ignore_errors=true)
 fold_batch_norms
 fold_old_batch_norms
 round_weights(num_steps=256)’