[Перевод] Python и разработка простого веб-приложения, использующего технологии машинного обучения

Тот, кто занимается машинным обучением (Machine Learning, ML), обычно, реализуя различные проекты, выполняет следующие действия: сбор данных, их очистка, разведочный анализ данных, разработка модели, публикация модели в локальной сети или в интернете. Вот хорошее видео, в котором можно узнать подробности об этом.

648baf2ca8562a09d7f4d942bbb0f2d7.jpg


Жизненный цикл проекта в сфере машинного обучения

Этап публикации модели завершает жизненный цикл ML-проектов. Он так же важен для дата-сайентистов и специалистов по машинному обучению, как и другие этапы. Обычные подходы к публикации моделей предусматривают использование универсальных фреймворков, таких, как Django или Flask. Главные проблемы тут заключаются в том, что для применения подобных инструментов требуются особые знания и навыки, и в том, что работа с ними может потребовать немалых затрат времени.

Автор статьи, перевод которой мы сегодня публикуем, хочет рассказать о том, как, используя Python-библиотеки streamlit, pandas и scikit-learn, создать простое веб-приложение, в котором применяются технологии машинного обучения. Он говорит, что размер этого приложения не превышает 50 строк. Статья основана на этом видео, которое можно смотреть параллельно с чтением. Инструменты, которые будут здесь рассмотрены, кроме прочего, позволяют ускорить и упростить развёртывание ML-проектов. 

Обзор модели, определяющей вид цветка ириса


Сегодня мы создадим простое веб-приложение, использующее технологии машинного обучения. Оно будет классифицировать цветки ириса из выборки Фишера, относя их к одному из четырёх видов: ирис щетинистый (iris setosa), ирис версиколор (iris versicolor), ирис виргинский (iris virginica). Возможно, вы уже видели множество ML-примеров, построенных на основе этого знаменитого набора данных. Но, надеюсь, то, что я тут буду рассматривать ещё один такой пример, вам не помешает. Ведь этот набор — он как «lorem ipsum» — классический бессмысленный текст-заполнитель, который вставляют в макеты страниц.

Нам, чтобы построить модель и опубликовать её где-нибудь, понадобятся библиотеки streamlit, pandas и scikit-learn. Взглянем на общую схему проекта. Он будет состоять из двух больших частей: фронтенд и бэкенд.

Во фронтенд-части приложения, а именно, на веб-странице, будет боковая панель, находящаяся слева, в которой можно будет вводить входные параметры модели, которые связаны с характеристиками цветков ириса: длина лепестка (petal length), ширина лепестка (petal width), длина чашелистика (sepal length), ширина чашелистика (sepal width). Эти данные будут передаваться бэкенду, где предварительно обученная модель будет классифицировать цветки, используя заданные характеристики. Фактически, речь идёт о функции, которая, получая характеристики цветка, возвращает его вид. Результаты классификации отправляются фронтенду.

В бэкенд-части приложения то, что ввёл пользователей, сохраняется в датафрейме, который будет использоваться в виде тестовых данных для модели. Потом будет построена модель для обработки данных. В ней будет применяться алгоритм «случайный лес» из библиотеки scikit-learn. И наконец, модель будет применена для классификации данных, введённых пользователем, то есть — для определения вида цветка. Кроме того, вместе со сведениями о виде цветка, будут возвращаться и данные о прогностической вероятности. Это позволит нам определить степень достоверности результатов классификации.

Установка библиотек


Как уже было сказано, здесь мы будем пользоваться тремя библиотеками: streamlit, pandas и scikit-learn. Установить их можно, пользуясь pip install:

pip install streamlit
pip install pandas
pip install -U scikit-learn


Разработка веб-приложения


Теперь напишем код приложения. Проект у нас довольно скромный. Он состоит из менее чем 50 строк кода. А если точнее — то их тут всего 48. Если же этот код «уплотнить», избавившись от комментариев и пустых строк, то размер текста программы сократится до 36 строк.

import streamlit as st
import pandas as pd
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier

st.write("""
# Simple Iris Flower Prediction App
This app predicts the **Iris flower** type!
""")

st.sidebar.header('User Input Parameters')

def user_input_features():
    sepal_length = st.sidebar.slider('Sepal length', 4.3, 7.9, 5.4)
    sepal_width = st.sidebar.slider('Sepal width', 2.0, 4.4, 3.4)
    petal_length = st.sidebar.slider('Petal length', 1.0, 6.9, 1.3)
    petal_width = st.sidebar.slider('Petal width', 0.1, 2.5, 0.2)
    data = {'sepal_length': sepal_length,
            'sepal_width': sepal_width,
            'petal_length': petal_length,
            'petal_width': petal_width}
    features = pd.DataFrame(data, index=[0])
    return features

df = user_input_features()

st.subheader('User Input parameters')
st.write(df)

iris = datasets.load_iris()
X = iris.data
Y = iris.target

clf = RandomForestClassifier()
clf.fit(X, Y)

prediction = clf.predict(df)
prediction_proba = clf.predict_proba(df)

st.subheader('Class labels and their corresponding index number')
st.write(iris.target_names)

st.subheader('Prediction')
st.write(iris.target_names[prediction])
#st.write(prediction)

st.subheader('Prediction Probability')
st.write(prediction_proba)


Разбор кода


Теперь разберём этот код.

▍Импорт библиотек

import streamlit as st
import pandas as pd
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier


В этих строках мы импортируем библиотеки streamlit и pandas, назначая им, соответственно, псевдонимы st и pd. Мы, кроме того, импортируем пакет datasets из библиотеки scikit-learn (sklearn). Мы воспользуемся этим пакетом ниже, в команде iris = datasets.load_iris(), для загрузки интересующего нас набора данных. И наконец, тут мы импортируем функцию RandomForestClassifier() из пакета sklearn.ensemble.

▍Формирование боковой панели

st.sidebar.header('User Input Parameters')


В этой строке мы описываем заголовок боковой панели, используя функцию st.sidebar.header(). Обратите внимание на то, что тут sidebar стоит между stи header(), что и даёт полное имя функции st.sidebar.header(). Эта функция сообщает библиотеке streamlit о том, что мы хотим поместить заголовок в боковую панель.

def user_input_features():
    sepal_length = st.sidebar.slider('Sepal length', 4.3, 7.9, 5.4)
    sepal_width = st.sidebar.slider('Sepal width', 2.0, 4.4, 3.4)
    petal_length = st.sidebar.slider('Petal length', 1.0, 6.9, 1.3)
    petal_width = st.sidebar.slider('Petal width', 0.1, 2.5, 0.2)
    data = {'sepal_length': sepal_length,
            'sepal_width': sepal_width,
            'petal_length': petal_length,
            'petal_width': petal_width}
    features = pd.DataFrame(data, index=[0])
    return features


Здесь мы объявляем функцию user_input_features(), которая берёт данные, введённые пользователем (то есть — четыре характеристики цветка, которые вводятся с использованием ползунков), и возвращает результат в виде датафрейма. Стоит отметить, что каждый входной параметр вводится в систему с помощью ползунка. Например, ползунок для ввода длины чашелистика (sepal length) описывается так: st.sidebar.slider(‘Sepal length’, 4.3, 7.9, 5.4). Первый из четырёх входных аргументов этой функции задаёт подпись ползунка, выводимую выше него. Это, в данном случае, текст Sepal length. Два следующих аргумента задают минимальное и максимальное значения, которые можно задавать с помощью ползунка. Последний аргумент задаёт значение, выставляемое на ползунке по умолчанию, при загрузке страницы. Здесь это — 5.4.

▍Создание модели

df = user_input_features()


Здесь датафрейм, сформированный функцией user_input_features(), которую мы только что обсудили, записывается в переменную df.

iris = datasets.load_iris()


Загрузка набора данных Iris из пакета sklearn.datasets и запись его в переменную iris.

X = iris.data


Создание переменной Х, содержащей сведения о 4 характеристиках цветка, которые имеются в iris.data.

Y = iris.target


Создание переменной Y, которая содержит сведения о виде цветка. Эти сведения хранятся в iris.target.

clf = RandomForestClassifier()


Здесь мы, пользуясь функцией RandomForestClassifier(), назначаем классификатор, основанный на алгоритме «случайный лес», переменной clf.

clf.fit(X, Y)


Тут мы обучаем модель, пользуясь функцией clf.fit(), передавая ей в качестве аргументов переменные X и Y. Суть происходящего заключается в том, что модель будет обучена определению вида цветка (Y) на основе его характеристик (X).

prediction = clf.predict(df)


Получение сведений о виде цветка с помощью обученной модели.

prediction_proba = clf.predict_proba(df)


Получение сведений о прогностической вероятности.

▍Формирование основной панели

st.write("""
# Simple Iris Flower Prediction App
This app predicts the **Iris flower** type!
""")


Здесь мы, пользуясь функцией st.write(), выводим текст. А именно, речь идёт о заголовке, выводимом в главной панели приложения, текст которого задан в формате Markdown. Символ # используется для указания того, что текст является заголовком. За строкой заголовка идёт строка обычного текста.

st.subheader('User Input parameters')


В этой строке, пользуясь функцией st.subheader(), мы указываем подзаголовок, выводимый в основной панели. Этот подзаголовок используется для оформления раздела страницы, в котором будет выведено содержимое датафрейма, то есть того, что было введено пользователем с помощью ползунков.

st.write(df)


Этой командой мы выводим на основную панель содержимое датафрейма df.

st.subheader('Class labels and their corresponding index number')


Данный код описывает второй подзаголовок основной панели. В этом разделе будут выведены данные о видах цветков.

st.write(iris.target_names)


Здесь, во второй раздел основной панели, выводятся названия видов цветков (setosa, versicolor и virginica) и соответствующие им номера (0, 1, 2).

st.subheader('Prediction')


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

st.write(iris.target_names[prediction])


Вывод результата классификации. Стоит отметить, что содержимое переменной prediction — это номер вида цветка, выданный моделью на основе входных данных, введённых пользователем. Для того чтобы вывести название вида, используется конструкция iris.target_names[prediction].

st.subheader('Prediction Probability')


Выводим заголовок четвёртого (и последнего) раздела основной панели. Здесь будут представлены данные о прогностической вероятности.

st.write(prediction_proba)


Вывод данных о прогностической вероятности.

Запуск веб-приложения


Код приложения сохранён в файле iris-ml-app.py. Мы готовы к тому, чтобы его запустить. Сделать это можно, выполнив следующую команду в терминале:

streamlit run iris-ml-app.py


Если всё идёт как надо, через некоторое время вы должны увидеть следующее:

> streamlit run iris-ml-app.py
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://10.0.0.11:8501


Через несколько секунд должно появиться окно браузера, в котором будет открыт адрес http://localhost:8501.

То, что вы увидите, будет похоже на следующий рисунок.

fca91974baea819bb9741060ed889021.png


Скриншот веб-приложения для классификации цветков ириса. Если щёлкнуть по стрелке, находящейся в левом верхнем углу окна, расположенного в верхней части рисунка, будет открыта боковая панель

Итоги


Можете себя поздравить: только что вы создали веб-приложение, в котором используются технологии машинного обучения. Вы вполне можете упомянуть подобное приложение в своём портфолио ML-проектов, а если хотите, можете опубликовать его на своём веб-сайте (правда, вы, вполне возможно, решите построить собственную модель, используя другие данные). 

Пользуетесь ли вы библиотекой streamlit?

guabcgmwuqoopx1ar80sjpz6keq.png

de0yl-6ppopvisr_a80b4yuhjj8.png

© Habrahabr.ru