質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

IIS

IIS(Internet Information Services)はマイクロソフト社によって開発されたwebサーバーです。Windows上で動作します。

Azure

Azureは、マイクロソフトのクラウド プラットフォームで、旧称は Windows Azureです。PaaSとIaaSを組み合わせることで、 コンピューティング・ストレージ・データ・ネットワーキング・アプリケーションなど多くの機能を持ちます。

Q&A

解決済

2回答

781閲覧

Azure WebApps にデプロイしたPython機械学習プログラムがタイムアウトする

ShikaTech

総合スコア468

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

IIS

IIS(Internet Information Services)はマイクロソフト社によって開発されたwebサーバーです。Windows上で動作します。

Azure

Azureは、マイクロソフトのクラウド プラットフォームで、旧称は Windows Azureです。PaaSとIaaSを組み合わせることで、 コンピューティング・ストレージ・データ・ネットワーキング・アプリケーションなど多くの機能を持ちます。

1グッド

0クリップ

投稿2018/03/13 09:17

前提

Keras+Tensorflowで画像のカテゴリ分類を行なうモデルを作成しました。
これをPythonのFlaskライブラリを使って公開したAPIで読み込み、APIにPOSTされた画像のカテゴリを判定する、というプログラムを作り、AzureのWebAppsに配置します。

発生している問題

モデルが1つの時はデプロイ後正しいURLを叩くことでWEBアプリが起動できていたんですが、モデルが多くなるにつれてタイムアウトエラーが発生してしまうようになりました。

HTTP Error 500.0 - Internal Server Error D:\home\python364x64\python.exe - The FastCGI process exceeded configured activity timeout

これを解決する案、設定、そのほか何かお知恵はありませんでしょうか?

サンプルコード(main.py)

Python

1import base64 2import io 3import json 4import time 5from datetime import datetime 6from platform import python_version 7 8import keras 9import numpy as np 10from flask import Flask, jsonify, make_response, request 11from keras import metrics 12from keras.layers import Conv2D, Dense, Dropout, Flatten, MaxPooling2D 13from keras.models import Sequential, load_model 14from keras.preprocessing.image import array_to_img, img_to_array, load_img 15from keras.utils import np_utils 16from PIL import Image 17 18start = time.time() 19print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":App start.") 20 21 22app = Flask(__name__) 23app.config['JSON_AS_ASCII'] = False 24 25print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":1st model load start.") 26s1model = load_model("./models/category1.hdf5") 27print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":1st model loaded. Next 2.") 28s2model = load_model("./models/category2.hdf5") 29print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":2nd model loaded. Next 3.") 30s3model = load_model("./models/category3.hdf5") 31print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":3rd model loaded. Next 4.") 32s4model = load_model("./models/category4.hdf5") 33print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":4th model loaded. Next 5.") 34s5_P1model = load_model("./models/category5_P1.hdf5") 35print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":5th model loaded. Next 6.") 36s6_P1model = load_model("./models/category6_P1.hdf5") 37print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":6th model loaded. Next 7.") 38s7_P1model = load_model("./models/category7_P1.hdf5") 39print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":7th model loaded. Next 8.") 40s5_P2model = load_model("./models/category5_P2.hdf5") 41print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":8th model loaded. Next 9.") 42s6_P2model = load_model("./models/category6_P2.hdf5") 43print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":9th model loaded. Next 10.") 44s7_P2model = load_model("./models/category7_P2.hdf5") 45print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":10th model loaded. Next 11.") 46s5_P3model = load_model("./models/category5_P3.hdf5") 47print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":11th model loaded. Next 12.") 48s6_P3model = load_model("./models/category6_P3.hdf5") 49print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":12th model loaded. Next 13.") 50s7_P3model = load_model("./models/category7_P3.hdf5") 51print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":13th model loaded. Next 14.") 52s5_P4model = load_model("./models/category5_P4.hdf5") 53print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":14th model loaded. Next 15.") 54s6_P4model = load_model("./models/category6_P4.hdf5") 55print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":15th model loaded. Next 16.") 56s7_P4model = load_model("./models/category7_P4.hdf5") 57print(time.strftime("%H:%M:%S", time.gmtime(time.time()-start)) + ":16th model loaded. All model are loaded.") 58 59@app.route('/api/judge', methods=['POST']) 60def scoring(): 61 try: 62 if request.method == "POST": 63 content_type = request.headers["Content-Type"] 64 if content_type == None or \ 65 not content_type.startswith("application/json") or \ 66 "img" not in request.json or \ 67 "pattern" not in request.json: 68 return make_response(jsonify({'status': 'failure'}), 405) 69 70 base64str = request.json["img"] 71 # POSTで渡ってきたbase64文字列は「+」が「 」(スペース)に変換されてしまっているため、元に戻してやってからDecode。 72 dec_image = base64.b64decode(base64str.replace(" ", "+")) 73 img = Image.open(io.BytesIO(dec_image)) 74 img = img.convert("RGB") 75 img = img.resize((100, 100)) 76 data = np.asarray(img) 77 data = data.astype("float") / 255 78 79 img = data 80 81 pred1 = s1model.predict(np.array([img])) 82 pred2 = s2model.predict(np.array([img])) 83 pred3 = s3model.predict(np.array([img])) 84 pred4 = s4model.predict(np.array([img])) 85 pred5 = "" 86 pred6 = "" 87 pred7 = "" 88 pattern = request.json["pattern"] 89 if pattern == "P1": 90 pred5 = s5_P1model.predict(np.array([img])) 91 pred6 = s6_P1model.predict(np.array([img])) 92 pred7 = s7_P1model.predict(np.array([img])) 93 elif pattern == "P2": 94 pred5 = s5_P2model.predict(np.array([img])) 95 pred6 = s6_P2model.predict(np.array([img])) 96 pred7 = s7_P2model.predict(np.array([img])) 97 elif pattern == "P3": 98 pred5 = s5_P3model.predict(np.array([img])) 99 pred6 = s6_P3model.predict(np.array([img])) 100 pred7 = s7_P3model.predict(np.array([img])) 101 elif pattern == "P4": 102 pred5 = s5_P4model.predict(np.array([img])) 103 pred6 = s6_P4model.predict(np.array([img])) 104 pred7 = s7_P4model.predict(np.array([img])) 105 106 category = { 107 "1": {"category": np.argmax(pred1, axis=1).item(), "pred": pred1.tolist()[0]}, 108 "2": {"category": np.argmax(pred2, axis=1).item(), "pred": pred2.tolist()[0]}, 109 "3": {"category": np.argmax(pred3, axis=1).item(), "pred": pred3.tolist()[0]}, 110 "4": {"category": np.argmax(pred4, axis=1).item(), "pred": pred4.tolist()[0]}, 111 "5": {"category": np.argmax(pred5, axis=1).item(), "pred": pred5.tolist()[0]}, 112 "6": {"category": np.argmax(pred6, axis=1).item(), "pred": pred6.tolist()[0]}, 113 "7": {"category": np.argmax(pred7, axis=1).item(), "pred": pred7.tolist()[0]} 114 } 115 116 result = jsonify({ 117 "status": "OK", 118 "category": category 119 }) 120 121 return make_response(result, 200) 122 else: 123 return make_response(jsonify({'status': 'failure'}), 405) 124 except: 125 import traceback 126 traceback.print_exc() 127 return make_response(jsonify({"status": "failure", "message": "Internal server error"}), 500) 128 129 130if __name__ == '__main__': 131 app.run()

開発環境:ローカル

  • Python 3.6.4 :: Anaconda
  • Windows 10
  • keras 2.1.4
  • tensorflow 1.2.1

※ちなみにローカルマシン(SurfacePro4)で上記コードを実行すると読み込み完了までおおよそ7分前後かかります

実行環境:Azure Web Apps

  • 拡張機能によりPython 3.6.4をインストール
  • その他はAzurePortalから作成したまま
退会済みユーザー👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ウェブアプリの初期化に時間がかかりすぎてタイムアウトしているのであれば、以下のように別スレッドを立てて遅延ロードをしてあげれば良い気がします。

python

1from collections import defaultdict 2from threading import Thread 3 4from flask import Flask 5 6 7app = Flask(__name__) 8models = defaultdict(lambda: 'Still loading') 9keys = ('M1', 'M2', 'M3') 10 11 12@app.route('/status', methods=['GET']) 13def status(): 14 return '<br/>'.join(key + '=' + models[key] for key in keys) 15 16 17def loader(): 18 from time import sleep 19 for key in keys: 20 sleep(30) 21 models[key] = 'Ready' 22 23 24Thread(target=loader, daemon=True).start() 25if __name__ == '__main__': 26 app.run()

投稿2018/03/13 10:18

YouheiSakurai

総合スコア6142

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShikaTech

2018/03/13 11:00

頂いたコードで概ね想定通りの実装ができそうです!ありがとうございました!! ところで1点気になったので教えていただきたく。。 質問を投げた後に自分なりの別解で、モデルのloadを起動時ではなく別立てしたInit用APIに寄せ、モデル数分だけInitを呼んでから本当に叩きたいAPIを叩く形で、一応起動させることは叶っておりました。 このとき、起動時に用意したモデル用の空変数「s1model」に別のAPIから値をセットするためには「global s1model」のおまじないが必要だったわけですが、頂いたコードでは直で「models」を書き換えているように見受けられます。 若葉マーク付け忘れたんですがPython初心者のため、この辺りのカラクリがまだつかめていません。 ご教示いただければ。。 (いわゆる参照型と値型の違いとか?「s1model」は空文字初期化してるから値型で、「models」はdefaultdictで初期化してるから参照型の配列で、参照型配列の中身だから操作可能、、、みたいな?)
YouheiSakurai

2018/03/13 11:07

modelsはloaderの中でmodels[xxx]として参照してるのでglobalが不要なんです。これがもし参照ではなく代入をするのであればglobalをつけたほうが良いですね。
ShikaTech

2018/03/13 11:10

なるほど私の想像通り、参照変数の中身の操作だからOKってことですね。 重ねてご回答ありがとうございました!
ShikaTech

2018/03/13 13:09

締めた後に申し訳ないのですが、頂いたエッセンスを組み込んだコードがどうにも意図した動きになりません。 https://teratail.com/questions/117352 こちら何かアドバイスがあればご教示いただきたく。。
guest

0

単なる速度不足ではないでしょうか。

コンパイラ系の言語で組み直すほうがいいかと思われます

投稿2018/03/13 09:45

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問