如何在 Django 的多个同时进行的 Keras 分类器会话中进行预测?

How to predict in multiple and simultanous Keras classifier sessions in Django?

我知道以前有人问过类似的问题,我已经阅读了所有这些问题,但是 none 解决了我的问题。

我有一个 Django 项目,我在其中使用 sequence_classifiers 中的 CNNSequenceClassifier,这是一个 Keras 模型。模型文件之前已经过拟合并保存到特定的目的地,我从中再次加载它们并预测我想要什么。

clf = CNNSequenceClassifier(epochs=2)

当我加载模型时我这样做,由于我在搜索中找到的建议,它在加载模型之前使用全局模型,然后是其他两行:

global clf
clf = pickle.load(open(modelfilenameandpath, "rb"))
global graph
graph = tf.get_default_graph()

在预测之前我使用 graph.as_default()

with graph.as_default():
    probs = clf.predict_proba(the_new_vecs)
K.clear_session()

我放 K.clear_session() 是因为我在 for 循环中进行预测,有时 for 循环预测的下一项与最后一项混淆并引发张量流错误。但显然 K.clear_session() 清除了会话并使新项目的预测很容易正常工作。

问题出在我的 views.py 我有两个触发预测的函数。有时我需要同时使用两者。但是由于该项目使用的是 Tensorflow 后端,因此只定义了一个会话,这两个函数的预测会混淆在一起。 K.clear_session() 在这里没有帮助,因为它仅适用于该特定会话,并且不希望在同一会话中出现新内容。

我真的不知道如何让函数在开始加载模型时理解 and/or 想要预测它,开始一个新的独立会话,这样就不会混淆任何东西。 我见过这样的代码:

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

但我不知道 probs = clf.predict_proba(the_new_vecs) 放在哪里。似乎所有这些都需要将您想在会话中完成的操作作为参数传递给 sess.run(),这对我不起作用,或者至少我不知道如何让它起作用。我希望在新会话中完成预测,之后 probs 的值非常重要。 global_variables_initializer() 似乎也改变了我所有变量的值。

我也试过 K.set_session()K.get_session() 但没有成功。

总而言之,我认为我被卡住的原因是我不知道如何使用会话来达到我的目的。不知道在哪里用什么代码?!

请帮忙!

此时您有 2 个选择,要么使用多处理库,要么在收到请求时分拆一个新进程。这里要小心用完内存。

另一个(推荐)是导出您的 TensorFlow 模型以在 tensorflow 服务中提供服务,因为您可以选择加载同一模型的多个实例,这样您就可以同时提供服务而不必担心事情比如内存管理或者加载和卸载内存。

我对 tensorflow 图表和会话的理解是:

A tensorflow 图托管操作,placeholders 和 Variables。 tensorflow 图存在于 tensorflow 会话中(这就是为什么要使用 tensorflow.train.Saver 保存经过训练的模型,您需要类似 Saver.save(sess, the graph) 的东西)。

这是一个简单的例子,可以帮助您理解 keras 模型和 tensorflow 图表之间的关系:

import tensorflow as tf 
from keras.layers import Input, Dense
from keras.models import Model 

tf.reset_default_graph()
graph_1, graph_2 = tf.Graph(), tf.Graph()
with graph_1.as_default():
    x_in = Input(shape=(1, ), name='in_graph1')
    pred = Dense(5, name='dense1_graph1')(x_in)
    pred = Dense(1, name='dense2_graph1')(pred)
    model = Model(input=x_in, output=pred)
with graph_2.as_default():
    x_in = Input(shape=(1, ), name='in_graph2')
    pred = Dense(10, name='dense1_graph2')(x_in)
    pred = Dense(1, name='dense2_graph2')(pred)
    model = Model(input=x_in, output=pred)


with tf.Session() as sess:
    default_ops = sess.graph.get_operations()

with graph_1.as_default():
    with tf.Session() as sess:
        one_ops = sess.graph.get_operations()

with graph_2.as_default():
    with tf.Session() as sess:      
        two_ops = sess.graph.get_operations()

正如您在运行代码中看到的那样,default_ops是一个空列表,这意味着默认图中没有操作。 one_ops 是第一个 keras 模型的操作列表,two_ops 是第二个 keras 模型的操作列表。

因此,通过使用 with graph.as_default(),可以将 keras 模型专门嵌入到 tensorflow 图中。

考虑到这一点,在单个脚本中加载多个 keras 模型变得很容易。我认为下面的示例脚本将解决您的困惑:

import numpy as np
import tensorflow as tf 
from keras.layers import Input, Dense
from keras.models import Model
from Keras.models import model_from_json

tf.reset_default_graph()
x = np.linspace(1, 4, 4)
y = np.random.rand(4)

models = {}
graph_1, graph_2 = tf.Graph(), tf.Graph()

# graph_1 
with graph_1.as_default():
    x_in = Input(shape=(1, ), name='in_graph1')
    pred = Dense(5, name='dense1_graph1')(x_in)
    pred = Dense(1, name='dense2_graph1')(pred)
    model = Model(input=x_in, output=pred)
    models['graph_1'] = model
# graph_2
with graph_2.as_default():
    x_in = Input(shape=(1, ), name='in_graph2')
    pred = Dense(10, name='dense1_graph2')(x_in)
    pred = Dense(1, name='dense2_graph2')(pred)
    model = Model(input=x_in, output=pred)
    models['graph_2'] = model

# save the two models 
with tf.Session(graph=graph_1) as sess:
    with open("model_1.json", "w") as source:
        source.write(models['graph_1'].to_json())
    models['graph_1'].save_weights("weights_1.h5")
with tf.Session(graph=graph_2) as sess:
    with open("model_2.json", "w") as source:
        source.write(models['graph_2'].to_json())
    models['graph_2'].save_weights("weights_2.h5")

####################################################
# play with the model 
pred_one, pred_one_reloaded = [], []
pred_two, pred_two_reloaded = [], []
for _ in range(10):
    print(_)
    if _ % 2 == 0:

        with graph_1.as_default():
            with tf.Session() as sess:
                sess.run(tf.global_variables_initializer())
                pred_one.append(models['graph_1'].predict(x).ravel())
        with tf.Session() as sess:
            with open("model_1.json", "r") as f:
                model = model_from_json(f.read())
            model.load_weights("weights_1.h5")
            pred_one_reloaded.append(model.predict(x).ravel())

    else:
        with graph_2.as_default():
            with tf.Session() as sess:
                sess.run(tf.global_variables_initializer())
                pred_two.append(models['graph_2'].predict(x).ravel())
        with tf.Session() as sess:
            with open("model_2.json", "r") as f:
                model = model_from_json(f.read())
            model.load_weights("weights_2.h5")
            pred_two_reloaded.append(model.predict(x).ravel())

pred_one = np.array(pred_one)
pred_one_reloaded = np.array(pred_one_reloaded)
pred_two = np.array(pred_two)
pred_two_reloaded = np.array(pred_two_reloaded)

print(pred_one)
print(pred_one_reloaded)
print(pred_two)
print(pred_two_reloaded)