<jupyter_start><jupyter_text>Optimize Trained Models for Inference  [Graph Transform Tool](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/graph_transforms)Great [Blog Post](https://petewarden.com/2016/12/30/rewriting-tensorflow-graphs-with-the-gtt/) by [<NAME>](https://www.linkedin.com/in/petewarden) from Google  Types of Optimizations* Remove training-only operations (checkpoint saving, drop out)* Strip out unused nodes* Remove debug operations* Fold batch normalization ops into weights (super cool)* Round weights* Quantize weights  Original Model (CPU)  File SizeWARNING:  If this directory doesn't exist, you need to train the model in an earlier notebook!!<jupyter_code>%%bash

ls -l /root/models/optimize_me/linear/cpu/<jupyter_output><empty_output><jupyter_text>Graph<jupyter_code>%%bash

summarize_graph --in_graph=/root/models/optimize_me/linear/cpu/unoptimized_cpu.pb
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import re
from google.protobuf import text_format
from tensorflow.core.framework import graph_pb2

def convert_graph_to_dot(input_graph, output_dot, is_input_graph_binary):
    graph = graph_pb2.GraphDef()
    with open(input_graph, "rb") as fh:
        if is_input_graph_binary:
            graph.ParseFromString(fh.read())
        else:
            text_format.Merge(fh.read(), graph)
    with open(output_dot, "wt") as fh:
        print("digraph graphname {", file=fh)
        for node in graph.node:
            output_name = node.name
            print("  \"" + output_name + "\" [label=\"" + node.op + "\"];", file=fh)
            for input_full_name in node.input:
                parts = input_full_name.split(":")
                input_name = re.sub(r"^\^", "", parts[0])
                print("  \"" + input_name + "\" -> \"" + output_name + "\";", file=fh)
        print("}", file=fh)
        print("Created dot file '%s' for graph '%s'." % (output_dot, input_graph))
        
input_graph='/root/models/optimize_me/linear/cpu/unoptimized_cpu.pb'
output_dot='/root/notebooks/unoptimized_cpu.dot'
convert_graph_to_dot(input_graph=input_graph, output_dot=output_dot, is_input_graph_binary=True)
%%bash

dot -T png /root/notebooks/unoptimized_cpu.dot \
    -o /root/notebooks/unoptimized_cpu.png > /tmp/a.out
from IPython.display import Image

Image('/root/notebooks/unoptimized_cpu.png', width=1024, height=768)<jupyter_output><empty_output><jupyter_text>Strip Unused Nodes<jupyter_code>%%bash

transform_graph \
    --in_graph=/root/models/optimize_me/linear/cpu/unoptimized_cpu.pb \
    --out_graph=/root/models/optimize_me/linear/cpu/strip_unused_optimized_cpu.pb \
    --inputs='x_observed' \
    --outputs='add' \
    --transforms='
strip_unused_nodes'
%%bash

ls -l /root/models/optimize_me/linear/cpu<jupyter_output><empty_output><jupyter_text>Graph<jupyter_code>%%bash

summarize_graph --in_graph=/root/models/optimize_me/linear/cpu/strip_unused_optimized_cpu.pb
input_graph='/root/models/optimize_me/linear/cpu/strip_unused_optimized_cpu.pb'
output_dot='/root/notebooks/strip_unused_optimized_cpu.dot'
convert_graph_to_dot(input_graph=input_graph, output_dot=output_dot, is_input_graph_binary=True)
%%bash

dot -T png /root/notebooks/strip_unused_optimized_cpu.dot \
    -o /root/notebooks/strip_unused_optimized_cpu.png > /tmp/a.out
from IPython.display import Image

Image('/root/notebooks/strip_unused_optimized_cpu.png')<jupyter_output><empty_output><jupyter_text>Remove NodesRemove pesky `Identity` and `CheckNumerics`<jupyter_code>%%bash

transform_graph \
    --in_graph=/root/models/optimize_me/linear/cpu/strip_unused_optimized_cpu.pb \
    --out_graph=/root/models/optimize_me/linear/cpu/remove_nodes_optimized_cpu.pb \
    --inputs='x_observed' \
    --outputs='add' \
    --transforms='
strip_unused_nodes
remove_nodes(op=Identity, op=CheckNumerics)'
%%bash

ls -l /root/models/optimize_me/linear/cpu<jupyter_output><empty_output><jupyter_text>Graph<jupyter_code>%%bash

summarize_graph --in_graph=/root/models/optimize_me/linear/cpu/remove_nodes_optimized_cpu.pb
input_graph='/root/models/optimize_me/linear/cpu/remove_nodes_optimized_cpu.pb'
output_dot='/root/notebooks/remove_nodes_optimized_cpu.dot'
convert_graph_to_dot(input_graph=input_graph, output_dot=output_dot, is_input_graph_binary=True)
%%bash

dot -T png /root/notebooks/remove_nodes_optimized_cpu.dot \
    -o /root/notebooks/remove_nodes_optimized_cpu.png > /tmp/a.out
from IPython.display import Image

Image('/root/notebooks/remove_nodes_optimized_cpu.png')<jupyter_output><empty_output><jupyter_text>Fold Constants<jupyter_code>%%bash

transform_graph \
--in_graph=/root/models/optimize_me/linear/cpu/unoptimized_cpu.pb \
--out_graph=/root/models/optimize_me/linear/cpu/fold_constants_optimized_cpu.pb \
--inputs='x_observed' \
--outputs='add' \
--transforms='
strip_unused_nodes
remove_nodes(op=Identity, op=CheckNumerics)
fold_constants(ignore_errors=true)'<jupyter_output><empty_output><jupyter_text>File Size<jupyter_code>%%bash

ls -l /root/models/optimize_me/linear/cpu<jupyter_output><empty_output><jupyter_text>Graph<jupyter_code>%%bash

summarize_graph --in_graph=/root/models/optimize_me/linear/cpu/fold_constants_optimized_cpu.pb
input_graph='/root/models/optimize_me/linear/cpu/fold_constants_optimized_cpu.pb'
output_dot='/root/notebooks/fold_constants_optimized_cpu.dot'
convert_graph_to_dot(input_graph=input_graph, output_dot=output_dot, is_input_graph_binary=True)
%%bash

dot -T png /root/notebooks/fold_constants_optimized_cpu.dot \
    -o /root/notebooks/fold_constants_optimized_cpu.png > /tmp/a.out
from IPython.display import Image

Image('/root/notebooks/fold_constants_optimized_cpu.png')<jupyter_output><empty_output><jupyter_text>Fold Batch NormalizationsPrereq: `fold_constants`<jupyter_code>%%bash

transform_graph \
--in_graph=/root/models/optimize_me/linear/cpu/unoptimized_cpu.pb \
--out_graph=/root/models/optimize_me/linear/cpu/fold_batch_norms_optimized_cpu.pb \
--inputs='x_observed' \
--outputs='add' \
--transforms='
strip_unused_nodes
remove_nodes(op=Identity, op=CheckNumerics)
fold_constants(ignore_errors=true)
fold_batch_norms
fold_old_batch_norms'<jupyter_output><empty_output><jupyter_text>File Size<jupyter_code>%%bash

ls -l /root/models/optimize_me/linear/cpu<jupyter_output><empty_output><jupyter_text>Graph<jupyter_code>%%bash

summarize_graph --in_graph=/root/models/optimize_me/linear/cpu/fold_batch_norms_optimized_cpu.pb
input_graph='/root/models/optimize_me/linear/cpu/fold_batch_norms_optimized_cpu.pb'
output_dot='/root/notebooks/fold_batch_norms_optimized_cpu.dot'
convert_graph_to_dot(input_graph=input_graph, output_dot=output_dot, is_input_graph_binary=True)
%%bash

dot -T png /root/notebooks/fold_batch_norms_optimized_cpu.dot \
    -o /root/notebooks/fold_batch_norms_optimized_cpu.png > /tmp/a.out
from IPython.display import Image

Image('/root/notebooks/fold_batch_norms_optimized_cpu.png')<jupyter_output><empty_output><jupyter_text>Quantize WeightsPrereq: `fold_batch_norms`<jupyter_code>%%bash

transform_graph \
--in_graph=/root/models/optimize_me/linear/cpu/unoptimized_cpu.pb \
--out_graph=/root/models/optimize_me/linear/cpu/quantize_weights_optimized_cpu.pb \
--inputs='x_observed' \
--outputs='add' \
--transforms='
strip_unused_nodes
remove_nodes(op=Identity, op=CheckNumerics)
fold_constants(ignore_errors=true)
fold_batch_norms
fold_old_batch_norms
quantize_weights'<jupyter_output><empty_output><jupyter_text>File Size<jupyter_code>%%bash

ls -l /root/models/optimize_me/linear/cpu/<jupyter_output><empty_output><jupyter_text>Graph<jupyter_code>%%bash

summarize_graph --in_graph=/root/models/optimize_me/linear/cpu/quantize_weights_optimized_cpu.pb
input_graph='/root/models/optimize_me/linear/cpu/quantize_weights_optimized_cpu.pb'
output_dot='/root/notebooks/quantize_weights_optimized_cpu.dot'
convert_graph_to_dot(input_graph=input_graph, output_dot=output_dot, is_input_graph_binary=True)
%%bash

dot -T png /root/notebooks/quantize_weights_optimized_cpu.dot \
    -o /root/notebooks/quantize_weights_optimized_cpu.png > /tmp/a.out
from IPython.display import Image

Image('/root/notebooks/quantize_weights_optimized_cpu.png')<jupyter_output><empty_output><jupyter_text>Combine All Optimizations<jupyter_code>%%bash

transform_graph \
--in_graph=/root/models/optimize_me/linear/cpu/unoptimized_cpu.pb \
--out_graph=/root/models/optimize_me/linear/cpu/fully_optimized_cpu.pb \
--inputs='x_observed' \
--outputs='add' \
--transforms='
strip_unused_nodes
remove_nodes(op=Identity, op=CheckNumerics)
fold_constants(ignore_errors=true)
fold_batch_norms
fold_old_batch_norms
quantize_weights'<jupyter_output><empty_output><jupyter_text>File Size<jupyter_code>%%bash

ls -l /root/models/optimize_me/linear/cpu/<jupyter_output><empty_output><jupyter_text>Graph<jupyter_code>%%bash

summarize_graph --in_graph=/root/models/optimize_me/linear/cpu/fully_optimized_cpu.pb
input_graph='/root/models/optimize_me/linear/cpu/fully_optimized_cpu.pb'
output_dot='/root/notebooks/fully_optimized_cpu.dot'
convert_graph_to_dot(input_graph=input_graph, output_dot=output_dot, is_input_graph_binary=True)
%%bash

dot -T png /root/notebooks/fully_optimized_cpu.dot \
    -o /root/notebooks/fully_optimized_cpu.png > /tmp/a.out
from IPython.display import Image

Image('/root/notebooks/fully_optimized_cpu.png')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1226505256451099, 'fraction_numerical': 0.001911436763300414, 'mean_word_length': 6.278207109737249, 'pattern_counts': {'":': 1, '<': 74, '<?xml version=': 0, '>': 82, 'https://': 3, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '158806', 'license': 'Apache-2.0', 'n_tokens_mistral': 3538, 'n_tokens_neox': 3465, 'n_words': 393, 'path': 'jupyterhub/notebooks/zz_under_construction/tensorflow/optimize/07_Optimize_Model.ipynb', 'repo_name': 'just4jc/pipeline', 'size': '9422'}