天天看點

tensorflow儲存模型和加載模型的方法(Python和Android)

tensorflow儲存模型和加載模型的方法(Python和Android)

一、tensorflow儲存模型的幾種方法:

(1) tf.train.saver()儲存模型

     使用 tf.train.saver()儲存模型,該方法儲存模型檔案的時候會産生多個檔案,會把計算圖的結構和圖上參數取值分成了不同的檔案存儲。這種方法是在TensorFlow中是最常用的儲存方式。

    例如:

import tensorflow as tf
# 聲明兩個變量
v1 = tf.Variable(tf.random_normal([1, 2]), name="v1")
v2 = tf.Variable(tf.random_normal([2, 3]), name="v2")
init_op = tf.global_variables_initializer() # 初始化全部變量
saver = tf.train.Saver() # 聲明tf.train.Saver類用于儲存模型
with tf.Session() as sess:
    sess.run(init_op)
    print("v1:", sess.run(v1)) # 列印v1、v2的值一會讀取之後對比
    print("v2:", sess.run(v2))
    saver_path = saver.save(sess, "save/model.ckpt")  # 将模型儲存到save/model.ckpt檔案
    print("Model saved in file:", saver_path)      

    運作後,會在save目錄下儲存了四個檔案:

tensorflow儲存模型和加載模型的方法(Python和Android)

    其中

  • checkpoint是檢查點檔案,檔案儲存了一個目錄下所有的模型檔案清單;
  • model.ckpt.meta檔案儲存了TensorFlow計算圖的結構,可以了解為神經網絡的網絡結構,該檔案可以被 tf.train.import_meta_graph 加載到目前預設的圖來使用。
  • ckpt.data : 儲存模型中每個變量的取值

(2)tf.train.write_graph()

    使用 tf.train.write_graph()儲存模型,該方法隻是儲存了模型的結構,并不儲存訓練完畢的參數值。

(3)convert_variables_to_constants固化模型結構

    很多時候,我們需要将TensorFlow的模型導出為單個檔案(同時包含模型結構的定義與權重),友善在其他地方使用(如在Android中部署網絡)。利用tf.train.write_graph()預設情況下隻導出了網絡的定義(沒有權重),而利用tf.train.Saver().save()導出的檔案graph_def與權重是分離的,是以需要采用别的方法。 我們知道,graph_def檔案中沒有包含網絡中的Variable值(通常情況存儲了權重),但是卻包含了constant值,是以如果我們能把Variable轉換為constant,即可達到使用一個檔案同時存儲網絡架構與權重的目标。

    TensoFlow為我們提供了convert_variables_to_constants()方法,該方法可以固化模型結構,将計算圖中的變量取值以常量的形式儲存。而且儲存的模型可以移植到Android平台。

    參考資料:

    【2】這裡主要實作第三種方法,因為該方法儲存的模型可以移植到Android平台運作。以下Python代碼,都共享在

    ​​  Github​​​:​​https://github.com/PanJinquan/tensorflow-learning-tutorials/tree/master/MNIST-Demo​​;

    【3】移植Android的詳細過程可參考本人的另一篇部落格資料《​​将tensorflow MNIST訓練模型移植到Android​​》:

       javascript:void(0)

二、訓練和儲存模型

    以MNIST手寫數字識别為例,這裡首先使用Python版的TensorFlow實作SoftMax Regression分類器,并将訓練好的模型的網絡拓撲結構和參數儲存為pb檔案,其中convert_variables_to_constants函數,會将計算圖中的變量取值以常量的形式儲存

#coding=utf-8
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
from tensorflow.python.framework import graph_util
print('tensortflow:{0}'.format(tf.__version__))

mnist = input_data.read_data_sets("Mnist_data/", one_hot=True)

#create model
with tf.name_scope('input'):
    x = tf.placeholder(tf.float32,[None,784],name='x_input')#輸入節點名:x_input
    y_ = tf.placeholder(tf.float32,[None,10],name='y_input')
with tf.name_scope('layer'):
    with tf.name_scope('W'):
        #tf.zeros([3, 4], tf.int32) ==> [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
        W = tf.Variable(tf.zeros([784,10]),name='Weights')
    with tf.name_scope('b'):
        b = tf.Variable(tf.zeros([10]),name='biases')
    with tf.name_scope('W_p_b'):
        Wx_plus_b = tf.add(tf.matmul(x, W), b, name='Wx_plus_b')

    y = tf.nn.softmax(Wx_plus_b, name='final_result')

# 定義損失函數和優化方法
with tf.name_scope('loss'):
    loss = -tf.reduce_sum(y_ * tf.log(y))
with tf.name_scope('train_step'):
    train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
    print(train_step)
# 初始化
sess = tf.InteractiveSession()
init = tf.global_variables_initializer()
sess.run(init)
# 訓練
for step in range(100):
    batch_xs,batch_ys =mnist.train.next_batch(100)
    train_step.run({x:batch_xs,y_:batch_ys})
    # variables = tf.all_variables()
    # print(len(variables))
    # print(sess.run(b))

# 測試模型準确率
pre_num=tf.argmax(y,1,output_type='int32',name="output")#輸出節點名:output
correct_prediction = tf.equal(pre_num,tf.argmax(y_,1,output_type='int32'))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
a = accuracy.eval({x:mnist.test.images,y_:mnist.test.labels})
print('測試正确率:{0}'.format(a))

# 儲存訓練好的模型
#形參output_node_names用于指定輸出的節點名稱,output_node_names=['output']對應pre_num=tf.argmax(y,1,name="output"),
output_graph_def = graph_util.convert_variables_to_constants(sess, sess.graph_def,output_node_names=['output'])
with tf.gfile.FastGFile('model/mnist.pb', mode='wb') as f:#’wb’中w代表寫檔案,b代表将資料以二進制方式寫入檔案。
    f.write(output_graph_def.SerializeToString())
sess.close()

# 注:
# convert_variables_to_constants函數,會将計算圖中的變量取值以常量的形式儲存:      

三、加載和測試

批量測試:

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
from PIL import Image
import matplotlib
import matplotlib.pyplot as plt

#模型路徑
model_path = 'model/mnist.pb'
#測試資料
mnist = input_data.read_data_sets("Mnist_data/", one_hot=True)
x_test = mnist.test.images
x_labels = mnist.test.labels;

with tf.Graph().as_default():
    output_graph_def = tf.GraphDef()
    with open(model_path, "rb") as f:
        output_graph_def.ParseFromString(f.read())
        tf.import_graph_def(output_graph_def, name="")

    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        # x_test = x_test.reshape(1, 28 * 28)
        input_x = sess.graph.get_tensor_by_name("input/x_input:0")
        output = sess.graph.get_tensor_by_name("output:0")

        # 【1】下面是進行批量測試----------------------------------------------------------
        pre_num = sess.run(output, feed_dict={input_x: x_test})#利用訓練好的模型預測結果
        #結果批量測試的準确率
        correct_prediction = tf.equal(pre_num, tf.argmax(x_labels, 1,output_type='int32'))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        acc = sess.run(accuracy, feed_dict={input_x: x_test})
        # a = accuracy.eval({x: mnist.test.images, y_: mnist.test.labels})
        print('測試正确率:{0}'.format(acc))

        #【2】下面是進行單張圖檔的測試-----------------------------------------------------
        testImage=x_test[0];
        test_input = testImage.reshape(1, 28 * 28)

        pre_num = sess.run(output, feed_dict={input_x: test_input})#利用訓練好的模型預測結果
        print('模型預測結果為:',pre_num)
        #顯示測試的圖檔
        testImage = testImage.reshape(28, 28)
        testImage=np.array(testImage * 255, dtype="int32")
        fig = plt.figure(), plt.imshow(testImage, cmap='binary')  # 顯示圖檔
        plt.title("prediction result:"+str(pre_num))
        plt.show()
        #儲存測定的圖檔
        testImage = Image.fromarray(testImage)
        testImage = testImage.convert('L')
        testImage.save("data/test_image.jpg")
        # matplotlib.image.imsave('data/name.jpg', im)
        sess.close()      

單個樣本測試:

import tensorflow as tf
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

#模型路徑
model_path = 'model/mnist.pb'
#測試圖檔
testImage = Image.open("data/test_image.jpg");

with tf.Graph().as_default():
    output_graph_def = tf.GraphDef()
    with open(model_path, "rb") as f:
        output_graph_def.ParseFromString(f.read())
        tf.import_graph_def(output_graph_def, name="")

    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        # x_test = x_test.reshape(1, 28 * 28)
        input_x = sess.graph.get_tensor_by_name("input/x_input:0")
        output = sess.graph.get_tensor_by_name("output:0")

        #對圖檔進行測試
        testImage=testImage.convert('L')
        testImage = testImage.resize((28, 28))
        test_input=np.array(testImage)
        test_input = test_input.reshape(1, 28 * 28)
        pre_num = sess.run(output, feed_dict={input_x: test_input})#利用訓練好的模型預測結果
        print('模型預測結果為:',pre_num)
        #顯示測試的圖檔
        # testImage = test_x.reshape(28, 28)
        fig = plt.figure(), plt.imshow(testImage,cmap='binary')  # 顯示圖檔
        plt.title("prediction result:"+str(pre_num))
        plt.show()      

讀取圖檔進行測試:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
#模型路徑
model_path = 'model/mnist.pb'
#測試圖檔
testImage = cv.imread("data/test_image.jpg");

with tf.Graph().as_default():
    output_graph_def = tf.GraphDef()
    with open(model_path, "rb") as f:
        output_graph_def.ParseFromString(f.read())
        tf.import_graph_def(output_graph_def, name="")

    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        # x_test = x_test.reshape(1, 28 * 28)
        input_x = sess.graph.get_tensor_by_name("input/x_input:0")
        output = sess.graph.get_tensor_by_name("output:0")

        #對圖檔進行測試
        testImage=cv.cvtColor(testImage, cv.COLOR_BGR2GRAY)
        testImage=cv.resize(testImage,dsize=(28, 28))
        test_input=np.array(testImage)
        test_input = test_input.reshape(1, 28 * 28)
        pre_num = sess.run(output, feed_dict={input_x: test_input})#利用訓練好的模型預測結果
        print('模型預測結果為:',pre_num)
        # cv.imshow("image",testImage)
        # cv.waitKey(0)
        #顯示測試的圖檔
        fig = plt.figure(), plt.imshow(testImage,cmap='binary')  # 顯示圖檔
        plt.title("prediction result:"+str(pre_num))
        plt.show()      

​​源碼Github​​:https://github.com/PanJinquan/MNIST-TensorFlow-Python

繼續閱讀