张量不是该图的元素;部署Keras模型

时间:2018-07-01 22:07:19

标签: python tensorflow flask keras

我正在部署一个keras模型,并通过flask API将测试数据发送到该模型。我有两个文件:

首先:我的Flask应用:

# Let's startup the Flask application
app = Flask(__name__)

# Model reload from jSON:
print('Load model...')
json_file = open('models/model_temp.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
keras_model_loaded = model_from_json(loaded_model_json)
print('Model loaded...')

# Weights reloaded from .h5 inside the model
print('Load weights...')
keras_model_loaded.load_weights("models/Model_temp.h5")
print('Weights loaded...')

# URL that we'll use to make predictions using get and post
@app.route('/predict',methods=['GET','POST'])
def predict():
    data = request.get_json(force=True)
    predict_request = [data["month"],data["day"],data["hour"]] 
    predict_request = np.array(predict_request)
    predict_request = predict_request.reshape(1,-1)
    y_hat = keras_model_loaded.predict(predict_request, batch_size=1, verbose=1)
    return jsonify({'prediction': str(y_hat)}) 

if __name__ == "__main__":
    # Choose the port
    port = int(os.environ.get('PORT', 9000))
    # Run locally
    app.run(host='127.0.0.1', port=port)

第二:文件Im用于将json数据发送到api端点:

response = rq.get('api url has been removed')
data=response.json()
currentDT = datetime.datetime.now()
Month = currentDT.month
Day = currentDT.day
Hour = currentDT.hour

url= "http://127.0.0.1:9000/predict"
post_data = json.dumps({'month': month, 'day': day, 'hour': hour,})
r = rq.post(url,post_data)

我从Flask得到有关Tensorflow的回复:

ValueError:Tensor Tensor(“ dense_6 / BiasAdd:0”,shape =(?, 1),dtype = float32)不是此图的元素。

我的keras模型是一个简单的6密层模型,并且训练没有错误。

有什么想法吗?

7 个答案:

答案 0 :(得分:16)

Flask使用多个线程。您遇到的问题是因为tensorflow模型未在同一线程中加载和使用。一种解决方法是强制tensorflow使用gloabl默认图。

在加载模型后添加它

global graph
graph = tf.get_default_graph() 

在您的预测之内

with graph.as_default():
    y_hat = keras_model_loaded.predict(predict_request, batch_size=1, verbose=1)

答案 1 :(得分:4)

将您的keras模型包装到一个类中要简单得多,并且该类可以跟踪自己的图和会话。这样可以避免具有多个线程/进程/模型可能导致的问题,而这几乎可以肯定是导致问题的原因。尽管其他解决方案也可以使用,但这是目前为止最通用,可扩展并涵盖所有方面的解决方案。使用这个:

import os
from keras.models import model_from_json
from keras import backend as K
import tensorflow as tf
import logging

logger = logging.getLogger('root')


class NeuralNetwork:
    def __init__(self):
        self.session = tf.Session()
        self.graph = tf.get_default_graph()
        # the folder in which the model and weights are stored
        self.model_folder = os.path.join(os.path.abspath("src"), "static")
        self.model = None
        # for some reason in a flask app the graph/session needs to be used in the init else it hangs on other threads
        with self.graph.as_default():
            with self.session.as_default():
                logging.info("neural network initialised")

    def load(self, file_name=None):
        """
        :param file_name: [model_file_name, weights_file_name]
        :return:
        """
        with self.graph.as_default():
            with self.session.as_default():
                try:
                    model_name = file_name[0]
                    weights_name = file_name[1]

                    if model_name is not None:
                        # load the model
                        json_file_path = os.path.join(self.model_folder, model_name)
                        json_file = open(json_file_path, 'r')
                        loaded_model_json = json_file.read()
                        json_file.close()
                        self.model = model_from_json(loaded_model_json)
                    if weights_name is not None:
                        # load the weights
                        weights_path = os.path.join(self.model_folder, weights_name)
                        self.model.load_weights(weights_path)
                    logging.info("Neural Network loaded: ")
                    logging.info('\t' + "Neural Network model: " + model_name)
                    logging.info('\t' + "Neural Network weights: " + weights_name)
                    return True
                except Exception as e:
                    logging.exception(e)
                    return False

    def predict(self, x):
        with self.graph.as_default():
            with self.session.as_default():
                y = self.model.predict(x)
        return y

答案 2 :(得分:1)

仅在加载模型后添加model._make_predict_function() `

# Model reload from jSON:
print('Load model...')
json_file = open('models/model_temp.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
keras_model_loaded = model_from_json(loaded_model_json)
print('Model loaded...')

# Weights reloaded from .h5 inside the model
print('Load weights...')
keras_model_loaded.load_weights("models/Model_temp.h5")
print('Weights loaded...')
keras_model_loaded._make_predict_function()

答案 3 :(得分:1)

事实证明,这种方式不需要clear_session调用,并且在配置友好的同时,使用来自已配置会话session = tf.Session(config=_config); self.graph = session.graph的图形对象并将创建的图形的预测作为默认with self.graph.as_default():提供干净的方法

from keras.backend.tensorflow_backend import set_session
...
def __init__(self):
    config = self.keras_resource()
    self.init_model(config)

def init_model(self, _config, *args):
    session = tf.Session(config=_config)
    self.graph = session.graph
    #set configured session 
    set_session(session)
    self.model = load_model(file_path)

def keras_resource(self):
    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    return config

def predict_target(self, to_predict):
    with self.graph.as_default():
        predict = self.model.predict(to_predict)
    return predict

答案 4 :(得分:1)

我有同样的问题。通过将TensorFlow-1版本更改为TensorFlow-2来解决。 只需卸载ver-1并安装ver-2。

答案 5 :(得分:0)

是的,当您从带有keras的模型进行预测时,它们是一个错误。由于某些错误,Keras将无法构建图形。尝试借助张量流从模型预测图像。只需替换此行代码

Keras代码:

var list_of_details = new List<OrderInfo> {...};
var orderInfoIds = list_of_details.Select(d => d.ProductId);
context
.Orders
.Where(o => o.OrdersProducts.Any(p => orderInfoIds.Contains(p.ProductId)));

tensorflow代码:

features = model_places.predict( img )

将此库导入您的代码中并替换。

import tensorflow as tf

graph = tf.get_default_graph()

如果问题仍未解决:

如果仍然没有解决问题,请尝试刷新图表。

由于您的代码很好,因此在干净的环境中运行应该可以解决它。

清除〜/ .keras /

中的keras缓存

使用正确的软件包在新环境中运行(可以使用anaconda轻松完成)

确保您参加的是全新的会话, with graph.as_default(): features = model_places.predict( img ).tolist() 应该删除所有现有的tf图。

Keras代码:

keras.backend.clear_session()

TensorFlow代码:

keras.backend.clear_session()
features = model_places.predict( img )

答案 6 :(得分:0)

最简单的解决方案是使用 tensorflow 2.0。在 Tensorflow 2.0 环境中运行您的代码,它会起作用。

我在通过 REST 服务器公开预训练模型时遇到了同样的问题。我在服务器启动时加载模型,然后使用加载的模型通过 POST/GET 请求进行预测。虽然预测它会产生错误,因为在预测调用之间没有保存会话。虽然当我每次进行预测时加载模型时它都运行良好。

然后为了避免会话出现这个问题,我只是在 TF=2.0 环境中运行代码并且运行良好。