web-dev-qa-db-fra.com

Le tenseur n'est pas un élément de ce graphique; déploiement du modèle Keras

Je déploie un modèle keras et envoie les données de test au modèle via une API de flacon. J'ai deux fichiers:

Tout d'abord: Mon application 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 __== "__main__":
    # Choose the port
    port = int(os.environ.get('PORT', 9000))
    # Run locally
    app.run(Host='127.0.0.1', port=port)

Deuxièmement: le fichier que j'utilise pour envoyer les données JSON envoyées au point de terminaison 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)

Je reçois cette réponse de Flask concernant Tensorflow:

ValueError: Tenseur Tenseur ("dense_6/BiasAdd: 0", shape = (?, 1), dtype = float32) n'est pas un élément de ce graphique.

Mon modèle keras est un modèle simple à 6 couches denses et s'entraîne sans erreur.

Des idées?

5
DataGuy

Flask utilise plusieurs threads. Le problème que vous rencontrez est dû au fait que le modèle tensorflow n'est pas chargé et utilisé dans le même thread. Une solution de contournement consiste à forcer tensorflow à utiliser le graphe par défaut global.

Ajoutez ceci après avoir chargé votre modèle

global graph
graph = tf.get_default_graph() 

Et à l'intérieur de votre prédiction

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

Il s'avère que cette manière n'a pas besoin d'un appel clear_session et est en même temps conviviale pour la configuration, en utilisant l'objet graphique de la session configurée session = tf.Session(config=_config); self.graph = session.graph et la prédiction par le graphique créé en tant que valeur par défaut with self.graph.as_default(): offre une approche propre

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
0
Ari Gold

Juste après le chargement du modèle, ajoutez 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()
0
Prateek Gulati

C'est tellement plus simple d'envelopper votre modèle keras dans une classe et cette classe peut garder une trace de son propre graphique et de sa session. Cela évite les problèmes pouvant être causés par plusieurs threads/processus/modèles, ce qui est très certainement la cause de votre problème. Tandis que d’autres solutions fonctionneront, c’est de loin la solution la plus générale, la plus évolutive et la plus complète. Utilisez celui-ci:

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
0
Andrew Louw