tensorflow serving 之minist_saved_model.py解讀


    最近在學習tensorflow serving,但是就這樣平淡看代碼可能覺得不能真正思考,就想着寫個文章看看,自己寫給自己的,就像自己對着鏡子演講一樣,寫個文章也像自己給自己講課,這樣思考的比較深,學到的也比較多,有錯歡迎揪出,

    minist_saved_model.py 是tensorflow的第一個例子,里面有很多serving的知識,還不了解,現在看。下面是它的入口函數,然后直接跳轉到main

if __name__ == '__main__':
tf.app.run()

在main函數里:

首先,是對一些參數取值等的合理性校驗:

def main(_):
if len(sys.argv) < 2 or sys.argv[-1].startswith('-'):
print('Usage: mnist_export.py [--training_iteration=x] '
'[--model_version=y] export_dir')
sys.exit(-1)
if FLAGS.training_iteration <= 0:
print 'Please specify a positive value for training iteration.'
sys.exit(-1)
if FLAGS.model_version <= 0:
print 'Please specify a positive value for version number.'
sys.exit(-1)

  然后,就開始train model,既然是代碼解讀加上自己能力還比較弱,簡單的我得解讀呀,牛人繞道。。。

# Train model
print 'Training model...'
#輸入minist數據,這個常見的,里面的源碼就是查看有沒有數據,沒有就在網上
下載下來,然后封裝成一個個batch
mnist = mnist_input_data.read_data_sets(FLAGS.work_dir, one_hot=True)

#這是創建一個session,Session是Graph和執行者之間的媒介,Session.run()實際
上將graph、fetches、feed_dict序列化到字節數組中進行計算
sess = tf.InteractiveSession()

#定義一個占位符,為以后數據等輸入留好接口
serialized_tf_example = tf.placeholder(tf.string, name='tf_example')

#feature_configs 顧名思義,是特征配置,從形式上看這是一個字典,字典中
初始化key為‘x’,value 是 tf.FixedLenFeature(shape=[784], dtype=tf.float32)的返
回值,而該函數的作用是解析定長的輸入特征feature相關配置
feature_configs = {'x': tf.FixedLenFeature(shape=[784], dtype=tf.float32),}

#parse_example 常用於稀疏輸入數據
tf_example = tf.parse_example(serialized_tf_example, feature_configs)

#
x = tf.identity(tf_example['x'], name='x') # use tf.identity() to assign name

#因為輸出是10類,所以y_設置成None×10
y_ = tf.placeholder('float', shape=[None, 10])

#定義權重變量
w = tf.Variable(tf.zeros([784, 10]))

#定義偏置變量
b = tf.Variable(tf.zeros([10]))

#對定義的變量進行參數初始化
sess.run(tf.global_variables_initializer())

#對輸入的x和權重w,偏置b進行處理
y = tf.nn.softmax(tf.matmul(x, w) + b, name='y')

#計算交叉熵
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))

#配置優化函數
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

#這個函數的作用是返回 input 中每行最大的 k 個數,並且返回它們所在位置的索引
values, indices = tf.nn.top_k(y, 10)

#這函數返回一個將索引的Tensor映射到字符串的查找表
table = tf.contrib.lookup.index_to_string_table_from_tensor(
tf.constant([str(i) for i in xrange(10)]))

#在tabel中查找索引
prediction_classes = table.lookup(tf.to_int64(indices))

#然后開始訓練迭代啦
for _ in range(FLAGS.training_iteration):
#獲取一個batch數據
batch = mnist.train.next_batch(50)
#計算train_step運算,train_step是優化函數的,這個執行帶來的作用就是
根據學習率,最小化cross_entropy,執行一次,就調整參數權重w一次
train_step.run(feed_dict={x: batch[0], y_: batch[1]})

#將得到的y和y_進行對比
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))

#對比結果計算准確率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float'))

#運行sess,並使用更新后的最終權重,去做預測,並返回預測結果
print 'training accuracy %g' % sess.run(
accuracy, feed_dict={x: mnist.test.images,
y_: mnist.test.labels})
print 'Done training!'

上面就是訓練的過程,就和普通情況下train模型是一樣的道理,現在,我們看后面的model export

 

# Export model
# WARNING(break-tutorial-inline-code): The following code snippet is
# in-lined in tutorials, please update tutorial documents accordingly
# whenever code changes.
#export_path_base基本路徑代表你要將model export到哪一個路徑下面,
#它的值的獲取是傳入參數的最后一個,訓練命令為:
bazel-bin/tensorflow_serving/example/mnist_saved_model /tmp/mnist_model
那輸出的路徑就是/tmp/mnist_model
export_path_base = sys.argv[-1]

#export_path 真正輸出的路徑是在基本路徑的基礎上加上版本號,默認是version=1
export_path = os.path.join(
tf.compat.as_bytes(export_path_base),
tf.compat.as_bytes(str(FLAGS.model_version)))
print 'Exporting trained model to', export_path

#官網解釋:Builds the SavedModel protocol buffer and saves variables and assets.
builder = tf.saved_model.builder.SavedModelBuilder(export_path)

# Build the signature_def_map.
# serialized_tf_example是上面提到的占位的輸入,
#其當時定義為tf.placeholder(tf.string, name='tf_example')

#tf.saved_model.utils.build_tensor_info 的作用是構建一個TensorInfo proto
#輸入參數是張量的名稱,類型,大小,這里是string,想應該是名稱吧,畢竟
#代碼還沒全部看完,先暫時這么猜測。輸出是,基於提供參數的a tensor protocol
# buffer
classification_inputs = tf.saved_model.utils.build_tensor_info(
serialized_tf_example)

#函數功能介紹同上,這里不同的是輸入參數是prediction_classes,
#其定義,prediction_classes = table.lookup(tf.to_int64(indices)),是一個查找表
#為查找表構建a tensor protocol buffer
classification_outputs_classes = tf.saved_model.utils.build_tensor_info(
prediction_classes)

#函數功能介紹同上,這里不同的是輸入參數是values,
#其定義,values, indices = tf.nn.top_k(y, 10),是返回的預測值
#為預測值構建a tensor protocol buffer
classification_outputs_scores = tf.saved_model.utils.build_tensor_info(values)

#然后,繼續看,下面那么多行都是一個語句,一個個結構慢慢解析
#下面可以直觀地看到有三個參數,分別是inputs ,ouputs和method_name
#inputs ,是一個字典,其key是tensorflow serving 固定定義的接口,
#為: tf.saved_model.signature_constants.CLASSIFY_INPUTS,value的話
#就是之前build的a tensor protocol buffer 之 classification_inputs
#同樣的,output 和method_name 也是一個意思,好吧,這部分就
#了解完啦。
classification_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={
tf.saved_model.signature_constants.CLASSIFY_INPUTS:
classification_inputs
},
outputs={
tf.saved_model.signature_constants.CLASSIFY_OUTPUT_CLASSES:
classification_outputs_classes,
tf.saved_model.signature_constants.CLASSIFY_OUTPUT_SCORES:
classification_outputs_scores
},
method_name=tf.saved_model.signature_constants.CLASSIFY_METHOD_NAME))

#這兩句話都和上面一樣,都是構建a tensor protocol buffer
tensor_info_x = tf.saved_model.utils.build_tensor_info(x)
tensor_info_y = tf.saved_model.utils.build_tensor_info(y)

這個和上面很多行的classification_signature,一樣的
prediction_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={'images': tensor_info_x},
outputs={'scores': tensor_info_y},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))

#這個不一樣了,tf.group的官網解釋挺簡潔的
#Create an op that groups multiple operations.
#When this op finishes, all ops in input have finished. This op has no output.
#Returns:An Operation that executes all its inputs.
#我們看下另一個tf.tables_initializer():
#Returns:An Op that initializes all tables. Note that if there are not tables the returned Op is a NoOp
legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')

#下面是重點啦,怎么看出來的?因為上面都是定義什么的,下面是最后的操作啦
#就一個函數:builder.add_meta_graph_and_variables,
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
signature_def_map={
'predict_images':
prediction_signature,
tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
classification_signature,
},
legacy_init_op=legacy_init_op)

builder.save()


print 'Done exporting!'

 

 

這里要從 tf.saved_model.builder.SavedModelBuilder 創建build開始,下面是看官網的,
可以直接參考:https://www.tensorflow.org/api_docs/python/tf/saved_model/builder/SavedModelBuilder

創建builder的是class SaveModelBuilder的功能是用來創建SaverModel

protocol buffer 並保存變量和資源,SaverModelBuilder類提供了創建

SaverModel protocol buffer 的函數方法

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM