一 基本流程
1.python腳本中定義自己的模型,訓練完成后將tensorflow graph定位導出為protobuf的二進制文件或者文本文件(一個僅有tensor定義但是不含有權重參數的文件);
2.python腳本訓練過程保存模型參數文件*.ckpt;
3.調用tensorflow自帶的freeze_graph.py小工具,輸入格式為*.pb活在*.pbtxt的protobuf文件和*.ckpt的參數文件,輸出為一個新的同時包含圖定義和參數的*.pb文件(這個步驟的作用是把checkpoint .ckpt文件中的參數轉化為常量const operator后和之前的tensor定義綁在一起)。
二 具體操作
1.幾個用到的python API
(1)tf.train.write_graph
write_graph( graph_or_graph_def, logdir, name, as_text=True )
The graph is written as text proto unless as_text is False.
v = tf.Variable(0, name='my_variable') sess = tf.Session() tf.train.write_graph(sess.graph_def, '/tmp/my-model', 'train.pbtxt')
or
v = tf.Variable(0, name='my_variable') sess = tf.Session() tf.train.write_graph(sess.graph, '/tmp/my-model', 'train.pbtxt')
Args:
- graph_or_graph_def: A Graph or a GraphDef protocol buffer.
- logdir:Directory where to write the graph. This can refer to remote fiesystems, such as Google Cloud Storage (GCS).
- name:Filename for the graph.
- as_text: If True ,writes the graph as an ASCII proto.
Returns:
The path of the output proto file.
(2)tf.name_scope
Aliases:
- tf.contrib.keras.backend.name_scope
- tf.name_scope
name_scope( name, default_name=None, values=None )
For example, to define a new python op called my_op:
def my_op(a, b, c, name=None): with tf.name_scope(name, "MyOp", [a, b, c]) as scope: a = tf.convert_to_tensor(a, name="a") b = tf.convert_to_tensor(b, name="b") c = tf.convert_to_tensor(c, name="c") # Define some computation that uses `a`, `b`, and `c`. return foo_op(..., name=scope)
Args:
- name: The name argument that is passed to the op function.
- default_name:The default name to use if the name argument is None.
- values: The list of Tensor arguments that are passed to the op function.
Returns:
A context manager for use in defining Python ops. Yields the name scope.
Raises:
- ValueError: if neither name nor default_name is provided but values are.
2.操作舉例
用一個簡單的腳本,來訓練一個包含1個隱含層的ANN模型來對Iris數據集分類,模型每層節點數:【5,64,3】
具體腳本參考:https://github.com/rockingdingo/tensorflow-tutorial
(1)定義Graph中輸入和輸出tensor名稱
為了方便我們在調用C++ API時,能夠准確根據Tensor的名稱取出對應的結果,在Python腳本訓練時就定義好每個tensor的tensor_name。如果tensor包含命名空間namespace的如“namespace_A/tensor_A"需要用完整的名稱。
在這個例子中,我們定義以下三個tensor的tensorname:
class TensorNameConfig(object): input_tensor = "inputs" target_tensor = "target" output_tensor = "output_node" # To Do
(2)輸出graph的定義文件*.pb和參數文件*.ckpt
我們要在訓練的腳本nn_model.py中加入兩處代碼:
第一處是將tensorflow的graph_def保存成./models/目錄下一個文件nn_model.pbtxt,里面包含由圖中各個tensor的定義名稱等信息;
第二處是在訓練代碼紅加入保存參數文件的代碼,將訓練好的ANN模型的權重Weight和Bias同時保存到./ckpt目錄下的*.ckpt,*.meta等文件。
最后執行python nn_model.py就可以完成訓練過程。
# 保存圖模型 tf.train.write_graph(session.graph_def, FLAGS.model_dir, "nn_model.pbtxt", as_text=True) # 保存 Checkpoint checkpoint_path = os.path.join(FLAGS.train_dir, "nn_model.ckpt") model.saver.save(session, checkpoint_path) # 執行命令完成訓練過程 python nn_model.py
(3)使用freeze_graph.py小工具整合模型freeze_graph
最后利用tensorflow自帶的freeze_graph.py小工具把.ckpt文件中的參數固定在graph內,輸出nn_model_frozen.pb
# 運行freeze_graph.py 小工具 # freeze the graph and the weights python freeze_graph.py --input_graph=../model/nn_model.pbtxt --input_checkpoint=../ckpt/nn_model.ckpt --output_graph=../model/nn_model_frozen.pb --output_node_names=output_node # 或者執行 sh build.sh # 成功標志: # Converted 2 variables to const ops. # 9 ops in the final graph.
Args:
- --input_graph:模型的圖的定義文件nn_model.pb(不包含權重);
- --input_checkpoint:模型的參數文件nn_model.ckpt;
- --output_graph:綁定后包含參數的圖模型文件nn_model_frozen.pb;
- --output_node_names:輸出待機算的tensor名字