一个进程跑多个深度学习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)

 

 

 

 

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