Для тех, кто пытается развернуть свои первые модели TensorFlow, это, вероятно, будет хорошей документацией по проблемам, с которыми они могут столкнуться, которые почти не упоминаются ни в одном учебнике. И я проверил. Это не предназначено для того, чтобы научить вас развертывать модели или даже создавать модели.

Вероятно, одна из наиболее важных частей машинного обучения — это когда созданные модели интегрируются с другими продуктами, услугами, веб-сайтами или приложениями, которые можно использовать. Именно это мы имеем в виду, когда говорим, что развертываем модели. Построенная модель не имеет большого значения, если она остается в виде файла или в блокнотах, в которых она была создана.

Опять же, эта статья не является вводной статьей о развертывании модели с помощью Flask или даже о построении модели. Минимальное понимание моделей машинного обучения с TensorFlow, бэкенд-разработки с Flask поможет. Я просто хотел бы задокументировать проблемы, с которыми я столкнулся, пытаясь развернуть свои модели Computer Vision, которые находились в локальном хранилище около года, в веб-приложение через Flask и Heroku.

Модели, которые я построил, были с TensorFlow. Видите ли, у меня возникла идея перенести три моих облегченных модели (каждая модель .h5 весила ~100 МБ) в одно и то же приложение Flask. Я не хотел создавать отдельное приложение для каждой модели. У меня были практические знания Flask в течение последних нескольких месяцев, поэтому было естественным воплотить в жизнь мои рабочие модели с помощью Flask, а также расширить свои знания о бэкэнд-фреймворке.

HTML-формы

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

Для этого требуется HTML-форма.

Этот фрагмент кода ниже находился в: app/templates/birds.html. Важно то, что он находился в папке с именем templates.

<form action="{{ url_for('upload_birds') }}" method="POST" enctype = "multipart/form-data">   
 <input type = "file" name = "file" />    
<br>    
<input type = "submit"/>
</form>

Часть, которая читает url_for(), представляет собой функциональность Flask, которая использует имя функции upload_bird(), чтобы определить, куда будет отправлено загруженное изображение. Сначала я написал фактический URL-адрес HTML, предоставленный сервером Flask. Выглядело это примерно так: https://127.0.0.1:5000/birds-result. Для наглядности вот как выглядит функция upload_birds()

Функция predict_bird() была просто функцией для предварительной обработки входного файла в массивы, ожидаемые моделью TensorFlow, и для возврата прогноза. Для всех целей относитесь к этому так.

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

Отображение изображений

При разработке приложения Flask я столкнулся с ситуацией, когда загруженные изображения будут отображаться на HTML-странице, но не на странице, отображаемой через Flask. Я думал, что это проблема с тем, как был написан путь, но позже я увидел из Интернета, что мне пришлось указать Flask, чтобы узнать, где находятся статические файлы.

app = Flask(__name__, static_folder="uploads")

Папка загрузок — это место, куда будут поступать загруженные изображения от пользователей. Чтобы отобразить изображения пользователю, HTML-код для них выглядел примерно так:

<img src="{{ url_for('static', filename=file_path) }}" alt="bird-picture" height="500" width="500"/>

Фрагмент выше, где находится html-страница результатов птиц, которая получает как загруженное изображение, так и прогноз для отображения.

Требования Головная боль

У меня была привычка всегда работать с моими пакетами, установленными глобально, поэтому я не работал в виртуальной среде. Чтобы загрузить свои страницы в Heroku, вам понадобится файл require.txt, который позволит серверу установить все зависимости. Пожалуйста, начните свой проект в виртуальной среде и, когда закончите, заморозьте пипс › требования.txt в корневую папку проекта. Пришлось потрудиться :(.

ПРОБЛЕМА GIT LFS

Загрузка моделей .h5 на GitHub для хостинга оказалась головной болью. Я не знал, что на GitHub есть ограничения по размеру загрузки. Все файлы размером более 100 МБ должны быть загружены через GIT LFS, что в основном перемещает ваши файлы на другой сервер и оставляет указатели на него в вашем репозитории.

Сначала вы устанавливаете GIT LFS. Напишите файл .gitattributes, который сообщает GIT, какие файлы следует загружать через GIT LFS. Теперь важно сначала добавить и зафиксировать этот файл .gitattributes, прежде чем добавлять другие файлы/папки, иначе вы снова столкнетесь с проблемой, описанной выше. Я понял это трудным путем. Мои .gitattributes выглядели так

*.h5 filter=lfs diff=lfs merge=lfs -text

Для всей папки вы сделаете что-то вроде

app/main/model_artifacts/**/* filter=lfs diff=lfs merge=lfs -text

Вскоре вы увидите, почему мне нужно было это сделать.

Снова добавьте и зафиксируйте файл .gitattributes, прежде чем переходить к добавлению других файлов/папок.

Проблема TensorFlow/проблема с путем

Я думаю, что это была самая неприятная проблема, с которой я столкнулся, поскольку она привела к множеству других проблем, пытающихся исправить ее и все такое.

Теперь мое приложение Heroku развернуто и «работает». Я хотел протестировать свои модели, но продолжал сталкиваться с ошибками внутреннего сервера. Это расстроило меня на некоторое время. Я проверил журналы страницы Heroku с помощью

heroku logs --tails

И увидел, что сервер не может найти мою модель TensorFlow. Большую часть трех часов я думал, что это ошибка TensorFlow, и я менял версию вместе с версией зависимостей, а затем развертывал снова, снова и снова. Я был неправ. Здесь я затронул несколько вопросов, которые я также обсудил бы в ближайшее время.

Я подумал, что это проблема пути, а затем заменил «\», который использует мой ноутбук, на «/», который использует Heroku. Я тоже ошибся.

Я также решил преобразовать свои модели из файла .h5 в формат TensorFlow SavedModel. Для этого мне сначала пришлось переобучить свои лучшие модели, а затем сохранить их в формате SavedModelFormat вместо .h5, но я понял, что могу работать лучше и быстрее, просто загрузив модель .h5, а затем сохранив ее в формате SavedModel. Это выглядело как

model = tensorflow.keras.models.load_model('birds.h5')
print(model.summary()) # to be sure
model.save(filepath)

Однако я тоже ошибался. Это очень расстраивало. Именно здесь я научился включать папки в файл .gitattribute, как упоминалось ранее.

Это было намного позже и на многих страницах Stackoverflow, когда я понял, что файлов моделей действительно не было в репозитории, поскольку GIT LFS взял их в другом месте! Это было описано выше. Все, что мне нужно было сделать, это сообщить Heroku, что я сделал это, и указать, где на самом деле находятся файлы. Я просто приведу ссылку на ответ StackOverflow, который помог мне, так как они объяснили это лучше. Таким образом, мне пришлось связать GIT LFS с Heroku (по умолчанию это не делается), установив для него пакет сборки и создав токен личного доступа, а также включив их в переменные конфигурации на Heroku.

Проблема с размером фрагмента

Пытаясь загрузить свои модели в Hub, и помните, что у меня их было три, я продолжал сталкиваться с проблемой, в которой я превысил лимит Heroku в 500 МБ. Это ограничение должно было содержать установку всех зависимостей и файлов. Я знал, что это огромная проблема, потому что TensorFlow весил 400 МБ+. Я перешел на более позднюю версию по этой причине и по причине, описанной выше, но это не помогло, пока я не вспомнил, что устанавливал полный пакет, который включал версию для графического процессора. Поскольку мне нужен TensorFlow для вывода, а не для обучения, я переключился на версию с процессором, и это уменьшило размер слага, но я все еще превышал квоту.

В этот момент я знал, что лучше не сдаваться. Я попробовал смесь всего вышеперечисленного и столкнулся со смесью всего, что обсуждалось. Но в конце концов я решил разделить задачу. Я создал два веб-приложения и развернул две модели в одном из них, а затем развернул третью в другом. Я отполировал переключение, поменяв местами ссылки со ссылками, предоставленными Heroku.

Я бы включил фактические журналы ошибок, которые у меня были, в эту статью, но в то время меня больше интересовала работа веб-приложения, чем документирование. Кроме того, это ошибки, которые я мог вспомнить навскидку, и я подозреваю, что у меня было больше. Я надеюсь, что это может помочь любому, кто пытается развернуть свою первую модель машинного обучения на Heroku через Flask.