Estoy tratando de servir un modelo de aprendizaje automático a través de una API usando Flask's Blueprints, aquí está mi archivo __init__.py de Flask
from flask import Flask def create_app(test_config=None): app = Flask(__name__) @app.route("/healthcheck") def healthcheck() -> str: return "OK" # Registers the machine learning blueprint from . import ml app.register_blueprint(ml.bp) return app El archivo ml.py que contiene el modelo para el punto final /ml
import numpy as np from . import configuration as cfg import tensorflow as tf from flask import ( Blueprint, flash, request, url_for ) bp = Blueprint("ml", __name__, url_prefix="/ml") keras_model = None graph = None @bp.before_app_first_request def load_model(): print("Loading keras model") global keras_model global graph with open(cfg.config["model"]["path"], 'r') as model_file: yaml_model = model_file.read() keras_model = tf.keras.models.model_from_yaml(yaml_model) graph = tf.get_default_graph() keras_model.load_weights(cfg.config["model"]["weights"]) @bp.route('/predict', methods=['POST']) def predict() -> str: global graph features = np.array([request.get_json()['features']]) print(features, len(features), features.shape) with graph.as_default(): prediction = keras_model.predict(features) print(prediction) return "%.2f" % predictionEjecuto el servidor usando un script de línea de comando
#!/bin/bash export FLASK_APP=src export FLASK_ENV=development flask run Y si voy a localhost:5000/healthcheck obtengo la respuesta OK como debería, cuando ejecuto el siguiente curl
curl -X POST \ http://localhost:5000/ml/predict \ -H 'Cache-Control: no-cache' \ -H 'Content-Type: application/json' \ -d '{ "features" : [17.0, 0, 0, 12.0, 1, 0, 0] }' Por primera vez me sale la respuesta [[1.00]] , si vuelvo a ejecutar me sale el siguiente error
tensorflow.python.framework.errors_impl.FailedPreconditionError: Error while reading resource variable dense/kernel from Container: localhost. This could mean that the variable was uninitialized. Not found: Container localhost does not exist. (Could not find resource: localhost/dense/kernel) [[{{node dense/MatMul/ReadVariableOp}}]]Si modifico el archivo Blueprint, el servidor detectará los cambios y lo actualizará, puedo volver a llamar a la API y devolverá el resultado correcto para la primera llamada y volveré al error. ¿Por qué pasó esto? ¿Y por qué solo para las llamadas posteriores a la primera?
Puede intentar crear una referencia a la sesión que se usa para cargar los modelos y luego configurarla para que Keras la use en cada solicitud. es decir, haz lo siguiente:
from tensorflow.python.keras.backend import set_session from tensorflow.python.keras.models import load_model tf_config = some_custom_config sess = tf.Session(config=tf_config) graph = tf.get_default_graph() # IMPORTANT: models have to be loaded AFTER SETTING THE SESSION for keras! # Otherwise, their weights will be unavailable in the threads after the session there has been set set_session(sess) model = load_model(...)y luego en cada solicitud:
global sess global graph with graph.as_default(): set_session(sess) model.predict(...)