В этой серии статей мы рассмотрим, как на основе готовых моделей разрабатывать приложения, использующие машинное обучение, и развертывать их на различных платформах. Начнем с создания Web-приложения на основе Streamlit и развертывания его на облачной платформе Heroku, используя бесплатный аккаунт. В качестве примера сделаем приложение для классификации изображений.
Классификация изображений с помощью TensorFlow
Для классификации изображений мы будем использовать библиотеку TensorFlow и модель EfficientNetB0, обученную на наборе данных ImageNet. Эта модель умеет распознавать 1000 классов изображений.
EfficientNetB0 – не самая качественная предварительно обученная модель, у нее доля правильных ответов (Top-1 Accuracy) составляет 77.1%. Но зато размер у модели очень маленький – всего 29 МБ. Небольшой размер модели важен для нас, т.к. в бесплатном аккаунте Heroku есть ограничения по объему памяти для запуска приложений: не более 512 МБ. Поэтому большие модели можно развертывать только на платном аккаунте. Кроме того, EfficientNetB0 работает достаточно быстро: время распознавания 46 с.
Классифицировать изображение с использованием модели EfficientNetB0 можно с помощью слегка модифицированного кода с сайта Keras:
from tensorflow.keras.applications import EfficientNetB0 from tensorflow.keras.preprocessing import image from tensorflow.keras.applications.efficientnet import preprocess_input from tensorflow.keras.applications.efficientnet import decode_predictions import numpy as np # Загружаем предварительно обученную модель EfficientNetB0 model = EfficientNetB0(weights='imagenet') # Прописываем путь к файлу с изображением img_path = 'plane.jpg' # Загружаем изображение в память # EfficientNetB0 рассчитана на изображения размером 224х224 img = image.load_img(img_path, target_size=(224, 224)) # Выполняем предварительную обработку изображения x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) # Запускаем распознавание preds = model.predict(x) # Печатаем ТОП-3 класса с самой большой вероятностью classes = decode_predictions(preds, top=3)[0] for cl in classes: print(cl[1], cl[2])
Давайте попробуем запустить этот код для распознавания вот такого изображения с самолетом (картинку нужно предварительно сохранить в файл ‘plane.jpg‘).

После запуска получим следующий результат:
airliner 0.4786306
wing 0.0591435
warplane 0.03492508
Самая большая вероятность, что на картинке воздушный лайнер (airliner) – 47%. Это правильный ответ. На втором месте крыло (wing) – почти 6%. Крыло на изображении, действительно, есть, и даже не одно, а два. Однако основной объект – это самолет, а не отдельные крылья. Так что второй ответ будем считать неправильным, хотя и достаточно обоснованным. Третий вариант – военный самолет (warplane), вероятность всего 3,4%, что не очень много. Опять же, ответ частично правильный: на картинке самолет, но другого типа – гражданский, а не военный.
Итак, код для определения объектов на изображении работает. Но его нужно запускать из командной строки и каждый раз прописывать путь к изображению прямо в коде. Это делать очень неудобно. Давайте создадим Web-приложение, в которое пользователь может загрузить любую картинку, которую он хочет распознать.
Создание Web-приложения с помощью Streamlit
Быстро преобразовать наш скрипт на Python в Web-приложение можно с помощью бесплатной библиотеки Streamlit, созданной как раз для этих целей. Streamlit позволяет добавлять в скрипт элементы управления, например, загрузчик изображений, и запускать этот скрипт во встроенном Web-сервере.
Для начала нам нужно установить Streamlit с помощью pip:
pip install streamlit
Описание элементов управления в Streamlit выполняется в скрипте на Python. Давайте создадим простое Web-приложение, которое позволяет загрузить изображение.
import io import streamlit as st from PIL import Image def load_image(): """Создание формы для загрузки изображения""" # Форма для загрузки изображения средствами Streamlit uploaded_file = st.file_uploader( label='Выберите изображение для распознавания') if uploaded_file is not None: # Получение загруженного изображения image_data = uploaded_file.getvalue() # Показ загруженного изображения на Web-странице средствами Streamlit st.image(image_data) # Возврат изображения в формате PIL return Image.open(io.BytesIO(image_data)) else: return None # Выводим заголовок страницы средствами Streamlit st.title('Классификация изображений') # Вызываем функцию создания формы загрузки изображения img = load_image()
Запуск Web-приложения выполняется командой:
streamlit run app.py
При запуске нужно указать имя скрипта на Python с описанием Web-страницы, в нашем случае app.py. Streamlit запустит встроенный Web-сервер, а в нем – страницу на основе скрипта app.py.

Сервер Streamlit запущен по адресу http://localhost:8501. Наше приложение будет выглядеть следующим образом.

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

Web-приложение для распознавания изображений
Мы создали заготовку приложения, которое позволяет загрузить на сервер картинку. Теперь нам нужно аккуратно перенести в это приложение код, который занимается распознованием изображения. Для удобства исходный скрипт распознавания мы разделим на несколько функций. Первая функция загружает нейронную сеть.
def load_model(): model = EfficientNetB0(weights='imagenet') return model
Вторая функция выполняет предварительную обработку изображения для подготовки к распознаванию.
def preprocess_image(img): img = img.resize((224, 224)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) return x
Третья функция печатает названия и вероятность для ТОП 3 классов, выданных моделью.
def print_predictions(preds): classes = decode_predictions(preds, top=3)[0] for cl in classes: st.write(cl[1], cl[2])
Теперь мы готовы написать код, создающий Web-страницу с помощью Streamlit.
# Загружаем предварительно обученную модель model = load_model() # Выводим заголовок страницы st.title('Классификация изображений') # Выводим форму загрузки изображения и получаем изображение img = load_image() # Показывам кнопку для запуска распознавания изображения result = st.button('Распознать изображение') # Если кнопка нажата, то запускаем распознавание изображения if result: # Предварительная обработка изображения x = preprocess_image(img) # Распознавание изображения preds = model.predict(x) # Выводим заголовок результатов распознавания жирным шрифтом # используя форматирование Markdown st.write('**Результаты распознавания:**') # Выводим результаты распознавания print_predictions(preds)
Полный код приложения можно посмотреть в репозитории с исходным кодом для статьи.
Запущенное приложение будет выглядеть так.

Если нажать кнопку «Распознать изображение», то запуститься нейронная сеть и результаты ее работы будут показаны под изображением.

На первом месте по прежнему воздушный лайнер (airliner), так что распознавание происходит правильно.
Более подробно о создании Web-приложения распознавания изображений с использованием Streamlit и TensorFlow можно посмотреть в видео.
Итак, у нас получилось создать Web-приложение, в которое можно загрузить произвольную картинку для распознавания. Однако это приложение запускается только на локальном компьютере, его адрес – http://localhost:8501. Это означает, что другие пользователи не смогут подключиться к этому приложению по сети. Чтобы это стало возможным, нужно разместить приложение на каком-либо сервере в Интернет. Для этого хорошо подходят облачные платформы. Далее мы рассмотрим, как разместить наше приложение на облачной платформе Heroku.
Облачная платформа Heroku
Heroku – это облачная платформа PaaS (Platform as a Service), которая предоставляет удобные инструменты для развертывания приложения. Пользователю не нужно самому создавать виртуальную машину, устанавливать ОС, запускать и настраивать Web-сервер. Все это платформа Heroku делает автоматически.
Чтобы развернуть приложение на Heroku нужно просто сделать push в репозиторий Git Heroku. Это очень удобно.
На Heroku есть бесплатные аккаунты, в которых можно использовать 550 часов работы контейнеров (на Heroku контейнеры называются Dyno). У бесплатного аккаунта есть ограничения по ресурсам контейнера:
-
Максимальный объем оперативной памяти: 512 МБ.
-
Максимальный объем образа для контейнера (на Heroku он называется slug): 500 МБ.
Бесплатный контейнер останавливается после 30 минут бездействия. Но если к остановленному таким образом контейнеру поступает запрос, то он автоматически запускается.
Возможностей бесплатного аккаунта вполне достаточно для создания небольших прототипов, домашних и образовательных проектов. В том числе для запуска нашего Web-приложения классификации изображений.
Создание приложения на платформе Heroku
Если у вас еще нет аккаунта на Heroku, то нужно зарегистрироваться. После регистрации и входа вы попадаете в панель управления Heroku (dashboard).

Чтобы создать новое приложение, нужно в правой верхней части панели управления Heroku нажать на кнопку «New», а затем в появившемся меню выбрать пункт «Create new app». Откроется страница создания приложения, в котором нужны выполнить три действия:
-
Ввести имя приложения. Имя должно быть уникально для всех приложений Heroku. Пользователи смогут обращаться к вашему приложению по ссылке виде https://app-name.herokuapp.com. Например, если имя приложения image-classification-demo, то ссылка на приложение будет https://image-classification-demo.herokuapp.com. Heroku подсвечивает введенное имя зеленым, если оно свободно, и красным в противном случае.
-
Выбрать регион размещения приложения. Регионов доступно всего два, США и Европа. Лучше выбирать тот, который географически ближе к вам. Поэтому я выбрал Европу.
-
Нажать на кнопку «Create app».

Приложение на платформе Heroku создано, но пока в нем нет нашего кода. Чтобы этот код можно было развернуть в приложении, его нужно разместить в репозитории Git и добавить конфигурационные файлы с инструкциями по запуску приложения на облачной платформе.
Создание Git репозитория для Web-приложения
Давайте создадим репозиторий Git в том каталоге, где находится наш Python скрипт с Web-приложением. Для этого выполняем команду:
git init -b main
Теперь нужно добавит скрипт с Web-приложением в репозиторий. Пусть скрипт называется image_classification.py, тогда команды будут следующие:
git add image_classification.py git commit -m "Add image_classification.py"
Репозиторий Git создан и скрипт с Web-приложением зафиксирован в нем. Однако пока репозиторий не готов для развертывания на Heroku. Облачной платформе для успешного запуска нашего приложения требуются дополнительные сведения:
-
Какие библиотеки Python нужны для работы приложения? Heroku установит эти библиотеки в образ для запуска приложения. В Python список библиотек указывается в файле requirements.txt.
-
Как запускать наше приложение? Вручную мы запускали приложение из командной строки с помощью
streamlit run. Heroku использует файл с названиемProcfileчтобы узнать, как нужно запускать приложение. Именно в него мы и пропишем команду запуска. Также нужно будет добавить дополнительный скрипт на shell, который создает конфигурационные файлы Streamlit для работы в режиме сервера.
Мы начнем с файла requirements.txt. В него нужно записать всего две библиотеки:
streamlit tensorflow-cpu
Обратите внимание, что мы будем использовать версию TensorFlow с поддержкой только CPU. Во-первых, в контейнерах Heroku нет GPU, поэтому пытаться его применять бессмысленно. Во-вторых, версия TensorFlow с поддержкой GPU занимает значительное место, превышающее размер образа для бесплатного аккаунта на Heroku в 500МБ.
Теперь можно создать bash скрипт, создающий конфигурационные файлы Streamlit. Файл будет называться setup.sh и содержать следующее:
mkdir -p ~/.streamlit/ echo "\ [general]\n\ email = \"ваш@email.com\"\n\ " > ~/.streamlit/credentials.toml echo "\ [server]\n\ headless = true\n\ port = $PORT\n\ " > ~/.streamlit/config.toml
Первая команда в этом скрипте создает каталог .streamlit в домашнем каталоге пользователя, где и будут храниться настройки Streamlit.
Вторая команда записывает в файл credentials.toml адрес вашей почты. Не забудьте прописать этот адрес в скрипт.
Третья команда создает конфигурационный файл для сервера Streamlit config.toml, в котором две опции:
-
headless = true– при запуске Streamlit не будет открывать новое окно браузера (это поведение Streamlit по умолчанию подходит для персонального компьютера, но не для сервера) -
port = $PORT– Streamlit будет работать не на порту 8501, как он обычно делает, а на порту, который ему укажет облачная платформа Heroku в переменной окружения$PORT.
Последний файл, Procfile, содержит команду, которую платформа Heroku должна выполнить для запуска нашего приложения:
web: sh setup.sh && streamlit run image_classification.py
web в начале строки говорит Heroku о типе контейнера, в котором должно быть запущено приложение – контейнер для Web приложений. Затем идет команда запуска приложения, которая в нашем случае состоит из двух частей:
-
sh setup.sh– запуск скрипта для создания конфигурационных файлов -
streamlit run image_classification.py— запуск нашего Web-приложения в Streamlit. Эта команда выполняется только в случае успешного выполнения первой команды (символы&&).
Все три файла есть в репозитории с исходным кодом статьи.
Теперь нам нужно зафиксировать добавление новых файлов в репозитории Git:
git add requirements.txt setup.sh Procfile git commit -m "Add configs for Heroku"
Сейчас наш репозиторий готов к развертыванию на Heroku!
Развертывание приложения из Git репозитория на Heroku
Инструкция по развертыванию есть на закладке «Deploy» приложения Heroku.

-
Устанавливаем Heroku CLI. Подробная инструкция есть на сайте Heroku. Установка в Linux:
curl https://cli-assets.heroku.com/install.sh | shУстановка на macOS:
brew tap heroku/brew && brew install herokuДля Windows нужно скачать и запустить установочный файл.
-
Выполняем логин в Heroku CLI. В консоли запускаем команду:
heroku loginПосле этого откроется окно браузера, в котором нужно будет войти на платформу Heroku. В случае успешного логина появится сообщение о том, что окно браузера можно закрыть и вернуться в командную строку. В консоли также будет написано об успешном выполнении логина.

Успешная аутентификация в Heroku CLI -
Подключаем удаленный Git репозиторий Heroku.
heroku git:remote -a image-classification-demoНе забудьте заменить image-classification-demo на название вашего приложения на Heroku.
После подключения удаленного репозитория Git на платформе Heroku, развертывание можно выполнять с помощью push в этот репозиторий:
git push heroku main
В результате Heroku запустит сборку образа контейнера для вашего приложения и развернет его по ссылке вида https://application-name.herokuapp.com. В облачной платформе наше приложение выглядит следующим образом:

Пользователям можно давать ссылку на наше приложение – https://image-classification-demo.herokuapp.com. При необходимости Heroku позволяет подключить собственный домен для приложения.
Итоги
Итак, мы рассмотрели, как преобразовать Python скрипт классификации изображений в Web-приложение и развернуть его на облачной платформе Heroku. Основные действия, которые необходимо выполнить:
-
Написать скрипт классификации изображений. Мы использовали библиотеку TensorFlow, но подойдет PyToch или любая аналогичная библиотека.
-
Преобразовать скрипт в Web-приложение с помощью библиотеки Streamlit.
-
Создать приложение на облачной платформе Heroku в бесплатном аккаунте.
-
Создать репозиторий Git для развертывания приложения, добавить в него конфигурационные файлы, необходимые Heroku.
-
Подключить репозиторий Git к приложению на Heroku и выполнить развертывание командой
git push. -
Передать ссылку на развернутое приложение пользователям.
В следующей части мы рассмотрим, как развертывать созданное нами Web-приложение классификации изображений через Docker.
Магистратура Инженерия искусственного интеллекта
Если вам интересно создавать приложения, использующие модели машинного обучения, и развертывать их для продуктивного применения пользователями, приглашаем в новую магистратуру Уральского федерального университета «Инженерия искусственного интеллекта«.
В этой магистратуре мы учим создавать крупные программные системы, использующие машинное обучение. Основные курсы магистратуры в двух областях:
-
Машинное обучение: математические основы, классические алгоритмы, глубокие нейронные сети, компьютерное зрение, обработка естественного языка, анализ временных рядов.
-
Промышленная разработка программного обеспечения: Python, Linux, программная инженерия, DevOps, MLOps.
В магистратуре вы будете работать над проектами от компаний-партнеров. В случае успешного выполнения проекта есть шанс устроиться на работу прямо во время обучения в магистратуре.
Социальные сети магистратуры цифровых профессий УрФУ:
Пишем о программах магистратуры в области ИТ, кибербезопасности и радиоэлектроники: как поступить, как подготовиться к экзаменам, как перейти в ИТ с помощью магистратуры.
Полезные ссылки
ссылка на оригинал статьи https://habr.com/ru/post/664076/

Добавить комментарий