Azure WebApps にデプロイしたPython機械学習プログラムがタイムアウトする からの派生です。
経緯は上記URLをご参照いただきたいのですが、
- Python+Flaskで作ったAPIの起動に時間がかかっていたためAzureのWebAppsで実行開始できなかった
- 時間がかかっていたのはTensorflowの起動&多数のモデルを起動時にloadしていたため
- アドバイスの通りモデルのLoadを別スレッド化したことでAPIの起動をスムーズにすることに成功
…したんですが、今度はその読み込んだモデルが使用できない事象に見舞われてしまっています。
なにやらtensorflowのセッションが開始されていない旨のエラーが?
Using TensorFlow backend. Exception in thread Thread-1: Traceback (most recent call last): File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\tensorflow\python\client\session.py", line 942, in _run allow_operation=False) File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\tensorflow\python\framework\ops.py", line 2584, in as_graph_element return self._as_graph_element_locked(obj, allow_tensor, allow_operation) File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\tensorflow\python\framework\ops.py", line 2663, in _as_graph_element_locked raise ValueError("Tensor %s is not an element of this graph." % obj) ValueError: Tensor Tensor("Placeholder:0", shape=(3, 3, 3, 32), dtype=float32) is not an element of this graph. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\ProgramData\Miniconda3\envs\mykeras\lib\threading.py", line 916, in _bootstrap_inner self.run() File "C:\ProgramData\Miniconda3\envs\mykeras\lib\threading.py", line 864, in run self._target(*self._args, **self._kwargs) File "c:\Users\shikatech\main.py", line 113, in model_loader models[key] = load_model("./models/"+ key + ".hdf5") File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\keras\models.py", line 246, in load_model topology.load_weights_from_hdf5_group(f['model_weights'], model.layers) File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\keras\engine\topology.py", line 3189, in load_weights_from_hdf5_group K.batch_set_value(weight_value_tuples) File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\keras\backend\tensorflow_backend.py", line 2370, in batch_set_value get_session().run(assign_ops, feed_dict=feed_dict) File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\tensorflow\python\client\session.py", line 789, in run run_metadata_ptr) File "C:\ProgramData\Miniconda3\envs\mykeras\lib\site-packages\tensorflow\python\client\session.py", line 945, in _run + e.args[0]) TypeError: Cannot interpret feed_dict key as Tensor: Tensor Tensor("Placeholder:0", shape=(3, 3, 3, 32), dtype=float32) is not an element of this graph. * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
探してみるとこんな記事を見つけたわけですが、結局何が悪くてどうすればいいかが検討もつかず…
Python
import base64 import io import json from datetime import datetime from platform import python_version import keras import numpy as np from flask import Flask, jsonify, make_response, request from keras import metrics from keras.layers import Conv2D, Dense, Dropout, Flatten, MaxPooling2D from keras.models import Sequential, load_model from keras.preprocessing.image import array_to_img, img_to_array, load_img from keras.utils import np_utils from PIL import Image from collections import defaultdict from threading import Thread app = Flask(__name__) app.config['JSON_AS_ASCII'] = False model = load_model("./models/model1.hdf5") models = defaultdict(lambda: '') statuses = defaultdict(lambda: 'Still loading') keys = ("model1","model2") @app.route('/status') def status_check(): return '\n<br />'.join(key + ' -> ' + statuses[key] for key in keys) + '\n<br />' @app.route('/api/judge', methods=['GET', 'POST']) def judge(): try: for key in keys: if statuses[key] == "Still loading": return make_response(jsonify({"status": "failure", "message": "The api server is in preparation."}), 503) if request.method == "POST": content_type = request.headers["Content-Type"] if content_type == None or \ not content_type.startswith("application/json") or \ "img" not in request.json or \ "clock" not in request.json: return make_response(jsonify({'status': 'failure'}), 405) base64str = request.json["img"] # POSTで渡ってきたbase64文字列は「+」が「 」(スペース)に変換されてしまっているため、元に戻してやってからDecode。 dec_image = base64.b64decode(base64str.replace(" ", "+")) img = Image.open(io.BytesIO(dec_image)) img = img.convert("RGB") # カラーモードの変更 img = img.resize((100, 100)) # 画像サイズの変更 data = np.asarray(img) data = data.astype("float") / 255 img = data pred1 = models["model1"].predict(np.array([img])) pred2 = models["model2"].predict(np.array([img])) return make_response(jsonify({"status": "OK"}), 200) else: return make_response(jsonify({'status': 'failure'}), 405) except: import traceback traceback.print_exc() return make_response(jsonify({"status": "failure", "message": "Internal server error"}), 500) def model_loader(): for key in keys: models[key] = load_model("./models/"+ key + ".hdf5") statuses[key] = 'Ready' Thread(target=model_loader, daemon=True).start() if __name__ == '__main__': app.run()
どなたか思い当たるフシはありませんでしょうか?
追記(解決)
コメントで頂いた内容を踏まえ、次のコードでちゃんと動くようになりました。
Python
import tensorflow as tf graph = tf.get_default_graph() ~中略~ def model_loader(): global graph with graph.as_default(): for key in keys: models[key] = load_model("./models/"+ key + ".hdf5") statuses[key] = 'Ready'
まだ回答がついていません
会員登録して回答してみよう