| ML主要分為訓練和預測兩個階段,此教程就是將訓練好的模型freeze并保存下來.freeze的含義就是將該模型的圖結(jié)構(gòu)和該模型的權(quán)重固化到一起了.也即加載freeze的模型之后,立刻能夠使用了。 下面使用一個簡單的demo來詳細解釋該過程, 一、首先運行腳本tiny_model.py 說明:saver.save必須在session里面,因為在session里面,整個圖才是激活的,才能夠?qū)?shù)存進來,使用save之后能夠得到如下的文件:#-*- coding:utf-8 -*-  import tensorflow as tf  import numpy as np      with tf.variable_scope('Placeholder'):      inputs_placeholder = tf.placeholder(tf.float32, name='inputs_placeholder', shape=[None, 10])      labels_placeholder = tf.placeholder(tf.float32, name='labels_placeholder', shape=[None, 1])    with tf.variable_scope('NN'):      W1 = tf.get_variable('W1', shape=[10, 1], initializer=tf.random_normal_initializer(stddev=1e-1))      b1 = tf.get_variable('b1', shape=[1], initializer=tf.constant_initializer(0.1))      W2 = tf.get_variable('W2', shape=[10, 1], initializer=tf.random_normal_initializer(stddev=1e-1))      b2 = tf.get_variable('b2', shape=[1], initializer=tf.constant_initializer(0.1))        a = tf.nn.relu(tf.matmul(inputs_placeholder, W1) + b1)      a2 = tf.nn.relu(tf.matmul(inputs_placeholder, W2) + b2)        y = tf.div(tf.add(a, a2), 2)    with tf.variable_scope('Loss'):      loss = tf.reduce_sum(tf.square(y - labels_placeholder) / 2)    with tf.variable_scope('Accuracy'):      predictions = tf.greater(y, 0.5, name="predictions")      correct_predictions = tf.equal(predictions, tf.cast(labels_placeholder, tf.bool), name="correct_predictions")      accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))      adam = tf.train.AdamOptimizer(learning_rate=1e-3)  train_op = adam.minimize(loss)    # generate_data  inputs = np.random.choice(10, size=[10000, 10])  labels = (np.sum(inputs, axis=1) > 45).reshape(-1, 1).astype(np.float32)  print('inputs.shape:', inputs.shape)  print('labels.shape:', labels.shape)      test_inputs = np.random.choice(10, size=[100, 10])  test_labels = (np.sum(test_inputs, axis=1) > 45).reshape(-1, 1).astype(np.float32)  print('test_inputs.shape:', test_inputs.shape)  print('test_labels.shape:', test_labels.shape)    batch_size = 32  epochs = 10    batches = []  print("%d items in batch of %d gives us %d full batches and %d batches of %d items" % (      len(inputs),      batch_size,      len(inputs) // batch_size,      batch_size - len(inputs) // batch_size,      len(inputs) - (len(inputs) // batch_size) * 32)  )  for i in range(len(inputs) // batch_size):      batch = [ inputs[batch_size*i:batch_size*i+batch_size], labels[batch_size*i:batch_size*i+batch_size] ]      batches.append(list(batch))  if (i + 1) * batch_size < len(inputs):      batch = [ inputs[batch_size*(i + 1):],labels[batch_size*(i + 1):] ]      batches.append(list(batch))  print("Number of batches: %d" % len(batches))  print("Size of full batch: %d" % len(batches[0]))  print("Size if final batch: %d" % len(batches[-1]))    global_count = 0    with tf.Session() as sess:  #sv = tf.train.Supervisor()  #with sv.managed_session() as sess:      sess.run(tf.initialize_all_variables())      for i in range(epochs):          for batch in batches:              # print(batch[0].shape, batch[1].shape)              train_loss , _= sess.run([loss, train_op], feed_dict={                  inputs_placeholder: batch[0],                  labels_placeholder: batch[1]              })              # print('train_loss: %d' % train_loss)                if global_count % 100 == 0:                  acc = sess.run(accuracy, feed_dict={                      inputs_placeholder: test_inputs,                      labels_placeholder: test_labels                  })                  print('accuracy: %f' % acc)              global_count += 1        acc = sess.run(accuracy, feed_dict={          inputs_placeholder: test_inputs,          labels_placeholder: test_labels      })      print("final accuracy: %f" % acc)      #在session當中就要將模型進行保存      saver = tf.train.Saver()      last_chkp = saver.save(sess, 'results/graph.chkp')      #sv.saver.save(sess, 'results/graph.chkp')    for op in tf.get_default_graph().get_operations():      print(op.name)  
  
 
 說明: .data:存放的是權(quán)重參數(shù) .meta:存放的是圖和metadata,metadata是其他配置的數(shù)據(jù) 如果想將我們的模型固化,讓別人能夠使用,我們僅僅需要的是圖和參數(shù),metadata是不需要的 
 二、綜合上述幾個文件,生成可以使用的模型的步驟如下: 1、恢復我們保存的圖 2、開啟一個Session,然后載入該圖要求的權(quán)重 3、刪除對預測無關(guān)的metadata 4、將處理好的模型序列化之后保存運行freeze.py 
 #-*- coding:utf-8 -*-  import os, argparse  import tensorflow as tf  from tensorflow.python.framework import graph_util    dir = os.path.dirname(os.path.realpath(__file__))    def freeze_graph(model_folder):      # We retrieve our checkpoint fullpath      checkpoint = tf.train.get_checkpoint_state(model_folder)      input_checkpoint = checkpoint.model_checkpoint_path            # We precise the file fullname of our freezed graph      absolute_model_folder = "/".join(input_checkpoint.split('/')[:-1])      output_graph = absolute_model_folder + "/frozen_model.pb"        # Before exporting our graph, we need to precise what is our output node      # this variables is plural, because you can have multiple output nodes      #freeze之前必須明確哪個是輸出結(jié)點,也就是我們要得到推論結(jié)果的結(jié)點      #輸出結(jié)點可以看我們模型的定義      #只有定義了輸出結(jié)點,freeze才會把得到輸出結(jié)點所必要的結(jié)點都保存下來,或者哪些結(jié)點可以丟棄      #所以,output_node_names必須根據(jù)不同的網(wǎng)絡(luò)進行修改      output_node_names = "Accuracy/predictions"        # We clear the devices, to allow TensorFlow to control on the loading where it wants operations to be calculated      clear_devices = True            # We import the meta graph and retrive a Saver      saver = tf.train.import_meta_graph(input_checkpoint + '.meta', clear_devices=clear_devices)        # We retrieve the protobuf graph definition      graph = tf.get_default_graph()      input_graph_def = graph.as_graph_def()        #We start a session and restore the graph weights      #這邊已經(jīng)將訓練好的參數(shù)加載進來,也即最后保存的模型是有圖,并且圖里面已經(jīng)有參數(shù)了,所以才叫做是frozen      #相當于將參數(shù)已經(jīng)固化在了圖當中       with tf.Session() as sess:          saver.restore(sess, input_checkpoint)            # We use a built-in TF helper to export variables to constant          output_graph_def = graph_util.convert_variables_to_constants(              sess,               input_graph_def,               output_node_names.split(",") # We split on comma for convenience          )             # Finally we serialize and dump the output graph to the filesystem          with tf.gfile.GFile(output_graph, "wb") as f:              f.write(output_graph_def.SerializeToString())          print("%d ops in the final graph." % len(output_graph_def.node))      if __name__ == '__main__':      parser = argparse.ArgumentParser()      parser.add_argument("--model_folder", type=str, help="Model folder to export")      args = parser.parse_args()        freeze_graph(args.model_folder)  
說明:對于freeze操作,我們需要定義輸出結(jié)點的名字.因為網(wǎng)絡(luò)其實是比較復雜的,定義了輸出結(jié)點的名字,那么freeze的時候就只把輸出該結(jié)點所需要的子圖都固化下來,其他無關(guān)的就舍棄掉.因為我們freeze模型的目的是接下來做預測.所以,一般情況下,output_node_names就是我們預測的目標.
 
 三、加載freeze后的模型,注意該模型已經(jīng)是包含圖和相應(yīng)的參數(shù)了.所以,我們不需要再加載參數(shù)進來.也即該模型加載進來已經(jīng)是可以使用了. 說明:#-*- coding:utf-8 -*-  import argparse   import tensorflow as tf    def load_graph(frozen_graph_filename):      # We parse the graph_def file      with tf.gfile.GFile(frozen_graph_filename, "rb") as f:          graph_def = tf.GraphDef()          graph_def.ParseFromString(f.read())        # We load the graph_def in the default graph      with tf.Graph().as_default() as graph:          tf.import_graph_def(              graph_def,               input_map=None,               return_elements=None,               name="prefix",               op_dict=None,               producer_op_list=None          )      return graph    if __name__ == '__main__':      parser = argparse.ArgumentParser()      parser.add_argument("--frozen_model_filename", default="results/frozen_model.pb", type=str, help="Frozen model file to import")      args = parser.parse_args()      #加載已經(jīng)將參數(shù)固化后的圖      graph = load_graph(args.frozen_model_filename)        # We can list operations      #op.values() gives you a list of tensors it produces      #op.name gives you the name      #輸入,輸出結(jié)點也是operation,所以,我們可以得到operation的名字      for op in graph.get_operations():          print(op.name,op.values())          # prefix/Placeholder/inputs_placeholder          # ...          # prefix/Accuracy/predictions      #操作有:prefix/Placeholder/inputs_placeholder      #操作有:prefix/Accuracy/predictions      #為了預測,我們需要找到我們需要feed的tensor,那么就需要該tensor的名字      #注意prefix/Placeholder/inputs_placeholder僅僅是操作的名字,prefix/Placeholder/inputs_placeholder:0才是tensor的名字      x = graph.get_tensor_by_name('prefix/Placeholder/inputs_placeholder:0')      y = graph.get_tensor_by_name('prefix/Accuracy/predictions:0')                with tf.Session(graph=graph) as sess:          y_out = sess.run(y, feed_dict={              x: [[3, 5, 7, 4, 5, 1, 1, 1, 1, 1]] # < 45          })          print(y_out) # [[ 0.]] Yay!      print ("finish")  
 1、在預測的過程中,當把freeze后的模型加載進來后,我們只需要定義好輸入的tensor和目標tensor即可 2、在這里要注意一下tensor_name和ops_name, 注意prefix/Placeholder/inputs_placeholder僅僅是操作的名字,prefix/Placeholder/inputs_placeholder:0才是tensor的名字 x = graph.get_tensor_by_name('prefix/Placeholder/inputs_placeholder:0')一定要使用tensor的名字 3、要獲取圖中ops的名字和對應(yīng)的tensor的名字,可用如下的代碼: # We can list operations  #op.values() gives you a list of tensors it produces  #op.name gives you the name  #輸入,輸出結(jié)點也是operation,所以,我們可以得到operation的名字  for op in graph.get_operations():      print(op.name,op.values())  
=============================================================================================================================
 
 上面是使用了Saver()來保存模型,也可以使用sv = tf.train.Supervisor()來保存模型 #-*- coding:utf-8 -*-  import tensorflow as tf  import numpy as np      with tf.variable_scope('Placeholder'):      inputs_placeholder = tf.placeholder(tf.float32, name='inputs_placeholder', shape=[None, 10])      labels_placeholder = tf.placeholder(tf.float32, name='labels_placeholder', shape=[None, 1])    with tf.variable_scope('NN'):      W1 = tf.get_variable('W1', shape=[10, 1], initializer=tf.random_normal_initializer(stddev=1e-1))      b1 = tf.get_variable('b1', shape=[1], initializer=tf.constant_initializer(0.1))      W2 = tf.get_variable('W2', shape=[10, 1], initializer=tf.random_normal_initializer(stddev=1e-1))      b2 = tf.get_variable('b2', shape=[1], initializer=tf.constant_initializer(0.1))        a = tf.nn.relu(tf.matmul(inputs_placeholder, W1) + b1)      a2 = tf.nn.relu(tf.matmul(inputs_placeholder, W2) + b2)        y = tf.div(tf.add(a, a2), 2)    with tf.variable_scope('Loss'):      loss = tf.reduce_sum(tf.square(y - labels_placeholder) / 2)    with tf.variable_scope('Accuracy'):      predictions = tf.greater(y, 0.5, name="predictions")      correct_predictions = tf.equal(predictions, tf.cast(labels_placeholder, tf.bool), name="correct_predictions")      accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))      adam = tf.train.AdamOptimizer(learning_rate=1e-3)  train_op = adam.minimize(loss)    # generate_data  inputs = np.random.choice(10, size=[10000, 10])  labels = (np.sum(inputs, axis=1) > 45).reshape(-1, 1).astype(np.float32)  print('inputs.shape:', inputs.shape)  print('labels.shape:', labels.shape)      test_inputs = np.random.choice(10, size=[100, 10])  test_labels = (np.sum(test_inputs, axis=1) > 45).reshape(-1, 1).astype(np.float32)  print('test_inputs.shape:', test_inputs.shape)  print('test_labels.shape:', test_labels.shape)    batch_size = 32  epochs = 10    batches = []  print("%d items in batch of %d gives us %d full batches and %d batches of %d items" % (      len(inputs),      batch_size,      len(inputs) // batch_size,      batch_size - len(inputs) // batch_size,      len(inputs) - (len(inputs) // batch_size) * 32)  )  for i in range(len(inputs) // batch_size):      batch = [ inputs[batch_size*i:batch_size*i+batch_size], labels[batch_size*i:batch_size*i+batch_size] ]      batches.append(list(batch))  if (i + 1) * batch_size < len(inputs):      batch = [ inputs[batch_size*(i + 1):],labels[batch_size*(i + 1):] ]      batches.append(list(batch))  print("Number of batches: %d" % len(batches))  print("Size of full batch: %d" % len(batches[0]))  print("Size if final batch: %d" % len(batches[-1]))    global_count = 0    #with tf.Session() as sess:  sv = tf.train.Supervisor()  with sv.managed_session() as sess:      #sess.run(tf.initialize_all_variables())      for i in range(epochs):          for batch in batches:              # print(batch[0].shape, batch[1].shape)              train_loss , _= sess.run([loss, train_op], feed_dict={                  inputs_placeholder: batch[0],                  labels_placeholder: batch[1]              })              # print('train_loss: %d' % train_loss)                if global_count % 100 == 0:                  acc = sess.run(accuracy, feed_dict={                      inputs_placeholder: test_inputs,                      labels_placeholder: test_labels                  })                  print('accuracy: %f' % acc)              global_count += 1        acc = sess.run(accuracy, feed_dict={          inputs_placeholder: test_inputs,          labels_placeholder: test_labels      })      print("final accuracy: %f" % acc)      #在session當中就要將模型進行保存      #saver = tf.train.Saver()      #last_chkp = saver.save(sess, 'results/graph.chkp')      sv.saver.save(sess, 'results/graph.chkp')    for op in tf.get_default_graph().get_operations():      print(op.name)  
注意:使用了sv = tf.train.Supervisor(),就不需要再初始化了,將sess.run(tf.initialize_all_variables())注釋掉,否則會報錯.
 
 
 
 
 
 |