$ ls *.pb
inception_v3.optimize.pb inception_v3.pb
```
+
+## Transform a TensorFlow graph
+
+### TensorFlow
+
+The trained TensorFlow model can be trasformed by some variants to deploy it in production. This [Graph Transform Tool](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/graph_transforms#graph-transform-tool) provides to support this behavior. There are so many transform options in this tool. For more information on transform options, please see [this page](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tools/graph_transforms#transform-reference). The input and output file of this tool is a TensorFlow GraphDef file.
+
+### with tflkit
+
+The [transform_graph.sh](transform_graph.sh) file supports to transform a TensorFlow GraphDef using various transform options. This tool requires a transform information file as a parameter and the transform options are described in the information file. There is an [example file](info/transform.template) for this tool. The information file needs `INPUT` and `OUTPUT` array names. The [summarize_pb.sh](summarize_pb.sh) file will help you to define the `INPUT` and `OUTPUT` array names. The `--tensorflow_path` can change the TensorFlow location. By default, it uses `externals/tensorflow` directory.
+
+Transform information:
+ * GRAPHDEF_PATH : Full filepath of file containing frozen TensorFlow GraphDef.
+ * TRANSFORM_PATH : Full filepath of the output TensorFlow GraphDef.
+ * INPUT : Names of the input arrays, comma-separated.
+ * OUTPUT : Names of the output arrays, comma-seperated.
+ * TRANSFORM_OPTIONS : Names of transform option, space-separated.
+ By default, it includes the following options.
+ * strip_unused_nodes : Removes all nodes not used in calculated the layer given in `OUTPUT` array, fed by `INPUT` array.
+ * remove_nodes : Removes the given name nodes from the graph.
+ * `Identity` is not necessary in inference graph. But if it needs in inference graph, this tool does not remove this node.
+ * `CheckNumerics` is useful during training but it is not necessary in inference graph.
+ * fold_constants : Replaces the sub-graps that always evaluate to constant expressions with those constants. This optimization is always executed at run-time after the graph is loaded, so it does'nt help latency, but it can simplify the graph and so make futher processing easier.
+ * fold_batch_norms : Scans the graph for any channel-wise multiplies immediately after convolutions, and multiplies the convolution's weights with the Mul instead so this can be omitted at inference time. It should be run after `fold_constants`.
+
+Usage (for example, [InceptionV3](https://storage.googleapis.com/download.tensorflow.org/models/tflite/model_zoo/upload_20180427/inception_v3_2018_04_27.tgz)):
+```
+$ wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/model_zoo/upload_20180427/inception_v3_2018_04_27.tgz
+$ tar xzvf inception_v3_2018_04_27.tgz ./inception_v3.pb
+$ cat > transform.info << END
+GRAPHDEF_PATH="${PWD}/inception_v3.pb"
+TRANSFORM_PATH="${PWD}/inception_v3.transform.pb"
+INPUT="input"
+OUTPUT="InceptionV3/Predictions/Reshape_1"
+TRANSFORM_OPTIONS="strip_unused_nodes(type=float, shape=\"1,299,299,3\") remove_nodes(op=Identity, op=CheckNumerics) fold_constants(ignore_errors=true) fold_batch_norms"
+END
+$ ./transform_graph.sh --info=./transform.info
+$ ls *.pb
+inception_v3.pb inception_v3.transform.pb
+```
--- /dev/null
+#!/bin/bash
+
+usage()
+{
+ echo "usage : $0"
+ echo " --info=Information file"
+ echo " --tensorflow_path=TensorFlow path (Use externals/tensorflow by default)"
+}
+
+SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+TF_DIR="${SCRIPT_PATH}/../../externals/tensorflow"
+
+for i in "$@"
+do
+ case $i in
+ --info=*)
+ INFO=${i#*=}
+ ;;
+ --tensorflow_path=*)
+ TF_DIR=${i#*=}
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+if [ -z "$INFO" ]; then
+ echo "INFO is unset or set to the empty string"
+ usage
+ exit 1
+fi
+if [ -z "$TF_DIR" ]; then
+ echo "tensorflow_path is unset or set to the empty string"
+ usage
+ exit 1
+fi
+
+if [ ! -x "$(command -v bazel)" ]; then
+ echo "Cannot find bazel. Please install bazel."
+ exit 1
+fi
+
+source $INFO
+
+if [ -z "$GRAPHDEF_PATH" ]; then
+ echo "GRAPHDEF_PATH is unset or set to the empty string"
+ echo "Update the $INFO file"
+ exit 1
+fi
+if [ -z "$TRANSFORM_PATH" ]; then
+ echo "TRANSFORM_PATH is unset or set to the empty string"
+ echo "Update the $INFO file"
+ exit 1
+fi
+if [ -z "$INPUT" ]; then
+ echo "INPUT is unset or set to the empty string"
+ echo "Update the $INFO file"
+ exit 1
+fi
+if [ -z "$OUTPUT" ]; then
+ echo "OUTPUT is unset or set to the empty string"
+ echo "Update the $INFO file"
+ exit 1
+fi
+if [ -z "$TRANSFORM_OPTIONS" ]; then
+ echo "TRANSFORM_OPTIONS is unset or set to the empty string"
+ echo "Update the $INFO file"
+ exit 1
+fi
+
+CUR_DIR=$(pwd)
+{
+ echo "Enter $TF_DIR"
+ pushd $TF_DIR > /dev/null
+
+ bazel run tensorflow/tools/graph_transforms/transform_graph -- \
+ --in_graph="$GRAPHDEF_PATH" \
+ --out_graph="$TRANSFORM_PATH" \
+ --inputs="$INPUT" \
+ --outputs="$OUTPUT" \
+ --transforms="$TRANSFORM_OPTIONS"
+
+ popd
+
+ echo "OUTPUT FILE : $TRANSFORM_PATH"
+}