Исправление времени ожидания Flask из-за создания большой модели Keras на Heroku - PullRequest
0 голосов
/ 25 июня 2018

Итак, у меня есть простое демонстрационное приложение Flask, предназначенное для работы с моделью Keras, которую я обучал. Приложение работает нормально на моем компьютере, но часто на Heroku. В приложении модель загружается при запуске Flask. Это имеет смысл, так как тогда нам не нужно перезагружать модель при каждом запросе. Обычно это будет хорошо, так как Flask будет работать непрерывно. Однако, учитывая, что это бесплатное приложение Heroku, Heroku деактивирует мой экземпляр через 30 минут. Это означает, что каждый раз, когда приложению приходится перезагружать модель с нуля, что вызывает ошибку тайм-аута из-за создания экземпляра модели (что часто занимает более 20 секунд) (иногда оно также имеет ошибку нехватки памяти). Я хотел бы уменьшить время загрузки модели, если это возможно. Запрет на поиск другого способа избежать тайм-аута в Heroku без обновления (т. Е., Возможно, многопоточности). Я понимаю, что могу разместить свою модель на графическом процессоре в AWS или как-нибудь еще, а затем назвать ее, но я бы хотел сделать ее максимально простой и экономически эффективной. Он не предназначен для обслуживания тысяч запросов, а просто работает, когда 1 или 2 человека нажимают на ссылку из моей статьи.

Код ниже.

import os
from flask import Flask, redirect, url_for, request, render_template, send_from_directory
from werkzeug import secure_filename
from examples2.example_keras import SimpleResNet50, ResNet2

# folder to upload pictures
UPLOAD_FOLDER = 'uploads/'
# what files can upload
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])

# start + config
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['ALLOWED_EXTENSIONS']=ALLOWED_EXTENSIONS
model = ResNet2("long_path/model_weights.h5")
# main route
@app.route('/')
def index():
    return render_template('upload.html')

Пример кода ошибки

at=error code=H12 desc="Request timeout" method=GET path="/" host=lung-r.herokuapp.com request_id=79bfba10-810e-444d-a73a-d32bcd68d603 fwd="24.198.104.217" dyno=web.1 connect=0ms service=30000ms status=503 bytes=0 protocol=https
2018-06-25T05:22:18.893433+00:00 app[web.1]: load model weights_path:

Ответы [ 4 ]

0 голосов
/ 23 августа 2018

Это что-то вроде хака, но оно должно работать.

Вместо импорта библиотеки бегемота keras, просто импортируйте нужные материалы из tensorflow.contrib.

Пример:

from tensorflow.python.keras.layers import LSTM, TimeDistributed, Dense, ...
0 голосов
/ 08 июля 2018

Создайте класс, который загружает модель при инициализации и предлагает функцию прогнозирования.

Внедрить экземпляр этого класса с помощью инжектора колбы (https://github.com/alecthomas/flask_injector) в функцию API.

0 голосов
/ 10 августа 2018

Ошибка тайм-аута часто связана с тем, что Keras должен загрузить бэкэнд TensorFlow, который вызывает тайм-аут dyno через 30 секунд, если он еще не завершил загрузку.Время загрузки модели обычно не должно быть проблемой.

Вы должны проверить, что такое логи heroku, прежде чем истечет время ожидания.Если импорт библиотеки Keras приводит к «загрузке серверной части Tensorflow», а затем время ожидания dyno истекло, попробуйте вместо этого использовать расширение TensorFlow Keras.

Я бы посмотрел документацию здесь: https://www.tensorflow.org/api_docs/python/tf/keras/models/load_model

Вы можете сохранить модель как h5, а затем импортировать ее с помощью этой функции.Он должен хорошо работать на Heroku - не уверен, что в пакете TF Keras есть предварительно обученные модели, такие как ResNet.

Надеюсь, это поможет.

0 голосов
/ 27 июня 2018

Вы ожидаете, что он будет работать только с 1-2 людьми, которые нажимают на ссылку из вашей статьи?

Рассматривали ли вы создание Jupyter Notebook, включая скомпилированный вывод в ipynb, а затем ссылку на него на вашем github?

Github имеет встроенный предварительный рендер, а затем вы можете просто включить руководство по настройке, чтобы они работали локально.


Единственное, о чем я могу думать, - это использовать работников Heroku, подпроцесс или:

model = None
# main route
@app.route('/')
def index():
    global model
    if model is None: model = ResNet2("long_path/model_weights.h5") 
    # to inform the user, load this^ in another thread/process,
    # and return 'loading' message
    return render_template('upload.html')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...