2017-09-03 23 views
0

我有一個工作的Keras模型,它使repl中的預測非常好,但無法加載到Flask應用程序中。這是一個Keras錯誤還是我錯過了一些基本的Python變量範圍理解?Keras load_model()僅在Flask請求上下文中失敗

燒瓶應用:

# app.py 

import os 
import sys 
from train import train_model 
from predict import predict_image 
import requests 
from flask import Flask, request, jsonify 

sys.dont_write_bytecode = True 

app = Flask(__name__) 

@app.route('/') 
def hello(): 
    return jsonify({'status': 'Service available.'}), 200 

@app.route('/predict') # ?company=<company_id>&image_url=<image_url> 
def predict_route(): 
    company_id = request.args.get('company') 
    image_url = str(request.args.get('image_url')) 
    result = predict_image(company_id, url=image_url) 
    return jsonify(result), 200 

而且我預測模塊:

# predict.py 

import os 
import random 
import re 
import pickle 
import utils 
import shutil 
import requests 
import keras 
from keras.models import load_model 
from keras import backend as K 


def load_classification_model(company_id): 
    model_dir = os.path.realpath('./models/company_' + str(company_id)) 
    model_dir += '/' + os.listdir(model_dir)[-1] 
    model_path = model_dir + '/model.h5' 
    labels_path = model_dir + '/labels.pickle' 
    print 'Loading model ' + model_path + ' ...' 
    model = load_model(model_path) 
    graph = K.function([model.layers[0].input, K.learning_phase()], [model.layers[-1].output]) 
    class_names = pickle.load(open(labels_path, 'rb')) 
    return graph, class_names 


def predict_image(company_id, url = None, part = None, inspection = None):  
    model_graph, class_names = load_classification_model(company_id) 
    # ...etc... 

它通過REPL WORKS:

import predict 
predict.predict_image(...) 
# model loads and returns expected result 

但是,如果我通過瓶的應用程序,我得到嘗試

# curl ml:5000/predict?company=1&image_url=<image_url> 

[top of traceback omitted for brevity] 
    File "/code/app.py", line 22, in predict_route 
    result = predict_image(company_id, url=image_url) 
    File "/code/predict.py", line 34, in predict_image 
    model_graph, class_names = load_classification_model(company_id) 
    File "/code/predict.py", line 21, in load_classification_model 
    model = load_model(model_path) 
    File "/usr/local/lib/python2.7/site-packages/keras/models.py", line 242, in load_model 
    topology.load_weights_from_hdf5_group(f['model_weights'], model.layers) 
    File "/usr/local/lib/python2.7/site-packages/keras/engine/topology.py", line 3095, in load_weights_from_hdf5_group 
    K.batch_set_value(weight_value_tuples) 
    File "/usr/local/lib/python2.7/site-packages/keras/backend/tensorflow_backend.py", line 2193, in batch_set_value 
    get_session().run(assign_ops, feed_dict=feed_dict) 
    File "/usr/local/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 895, in run 
    run_metadata_ptr) 
    File "/usr/local/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 1071, in _run 
    + e.args[0]) 
TypeError: Cannot interpret feed_dict key as Tensor: Tensor Tensor("Placeholder:0", shape=(2048, 64), dtype=float32) is not an element of this graph. 
+0

你這是什麼傳遞給REPL中的'predict.predict_image(...)'? –

+0

與Flask一起傳入的相同參數,我打印它們來檢查。錯誤追溯也表明了不同類型的問題,所以我認爲這不太可能。 – brittohalloran

回答

0

在使用張量流圖交叉線程時,似乎在Keras中存在一個錯誤。修復它:

# Right after loading or constructing your model, save the TensorFlow graph: 
    import tensorflow as tf 
    graph = tf.get_default_graph() 

    # In the other thread (or perhaps in an asynchronous event handler), do: 
    global graph 
    with graph.as_default(): 
     (... 
     do 
     inference 
     here...) 
+0

欣賞您的輸入。在Flask中,我甚至無法加載圖形,所以加載後我無法從tf獲取默認圖形。這看起來似乎有道理,可能在正確的軌道上,但我覺得它與Keras從它保存的模型格式中加載模型更相關,Flask中的發生與REPL不同。 – brittohalloran

+1

我想你應該在初始化Flask'app'時更好地加載Keras模型,而不是在調用API時反覆加載模型,這將非常緩慢。如果以這種方式加載模型,則可以獲取圖形,並且在調用API時,只需使用初始化模型預測並使用'with graph.as_default()將其包裝「: ' –