一個進程跑多個深度學習tensorflow 和keras混合模型,多實例。

一、背景:

      我們建立了10個CNN模型,然後我們又寫了一個預測類Predict,這個類會從已經保存好的模型restore恢復相應的圖結構以及模型參數。然後我們會創建10個Predict的對象Instance,每個Instance負責一個模型的預測。

      再者,我們有個NLP服務,比如要加keras訓練的句子分類,還有深度相似度模型。那麼有兩個模型同時在該進程裏。

這樣會出錯。類似於出現ValueError: Tensor Tensor("Pooler-Dense", shape=(?, 768), dtype=float32) is not an element of this graph

 

二、原因

主要是因爲不同對象裏面的不同sess使用了同一進程空間下的相同的默認圖graph

tf.get_default_graph()獲取默認圖,

import tensorflow as tf

a=tf.constant([1.0,2.0],name="a")
b=tf.constant([3.0,4.0],name="b")
c=a+b

print(c.graph)
print(tf.get_default_graph())

#結果:
#tensorflow.python.framework.ops.Graph object at 0x000001E4F528CB70
#tensorflow.python.framework.ops.Graph object at 0x000001E4F528CB70

上面因爲只有一個模型(圖)實例,那麼就一樣,如果兩個模型(圖)實例,那就會出錯了。

 

三、解決辦法

每一個實例生成一個圖調用tf.Graph(),解決模板

class MyModel():
    def __init__(self):
        self.gragh = tf.Graph()
        with self.gragh.as_default():
            self.sess = tf.Session()
            with self.sess.as_default():
                # 建立加載模型
                bert = build_transformer_model()
                self.model = keras.models.Model(bert.model.inputs, bert.model.outputs[0])

    def predict(self, s):
        with self.gragh.as_default():
            with self.sess.as_default():
                self.model.predict(s)

其次如果用bert預訓練的模型,截取其中的圖的模型,那麼可以先保存爲keras的model,然後用load_model函數加載

 

# 1 保存h5模型
# 建立加載模型
bert = build_transformer_model()

model = keras.models.Model(bert.model.inputs, bert.model.outputs[0])

model.save("model.h5")

# 2.load_model h5模型
class MyModel():
    def __init__(self):
        self.graph=  tf.Graph()
        with self.graph.as_default():
            self.session = Session()
            with self.session.as_default():
                self.model = load_model(model_path)

    def predict(self,s):
        with self.session.as_default():   # 注意這裏不需要with self.gragh.as_default(),包含了圖
            self.model.predit(s)

 

四、實際例子

tensorflow加載訓練的模型。來自於58的 qa_match開源項目模型加載

class MyModel():
    def __init__(self):
        self.model_file = tf.train.latest_checkpoint(model_path)
        self.graph = tf.Graph()  # 爲每個類(實例)單獨創建一個graph
        with self.graph.as_default():
            self.model_file = tf.train.latest_checkpoint(model_path)
            self.saver = tf.train.import_meta_graph("{}.meta".format(self.model_file))  # 創建恢復器

            # 注意!恢復器必須要在新創建的圖裏面生成,否則會出錯。
            self.sess = tf.Session()
            with self.sess.as_default():
                self.saver.restore(self.sess, self.model_file) 

    def predict(self,input_y_value,length_y_value):
            with self.graph.as_default():  # 看清這裏有兩個with 這一句特別重要,因爲要在該圖下執行tensor獲取和session
                with self.sess.as_default():
                    input_x = self.graph.get_tensor_by_name("input_x:0")
                    length_x = self.graph.get_tensor_by_name("length_x:0")
                    input_y = self.graph.get_tensor_by_name("input_y:0")
                    length_y = self.graph.get_tensor_by_name("length_y:0")
                    keep_prob = self.graph.get_tensor_by_name("keep_prob:0")
                    q_y_raw = self.graph.get_tensor_by_name("representation/q_y_raw:0")
                    qs_y_raw = self.graph.get_tensor_by_name("representation/qs_y_raw:0")

                    qs_y_raw_out = self.sess.run(qs_y_raw, feed_dict={input_y:np.array(input_y_value, dtype=np.int32),length_y: np.array(length_y_value, dtype=np.int32), keep_prob: 1.0})

小彩蛋:向量相似度

a_vecs = a_vecs / (a_vecs**2).sum(axis=1, keepdims=True)**0.5
b_vecs = b_vecs / (b_vecs**2).sum(axis=1, keepdims=True)**0.5


sims = (a_vecs * b_vecs).sum(axis=1)

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章