Ваши проекты в портфолио могут сделать или разрушить вашу возможность трудоустройства! Это более верно для начинающих специалистов по данным, поскольку наука о данных — это не просто теоретическая тарабарщина, а скорее смесь теории и практической реализации. Когда мы говорим о проекте Data Science, мы действительно имеем в виду блокнот Jupyter, загруженный на GitHub, или мы также хотим увидеть реализацию моделей с использованием приятного графического пользовательского интерфейса (GUI)? Я полагаю, что почти все из вас согласятся, что оба утверждения верны. Когда я пытался продемонстрировать свою работу миру, я столкнулся почти со всеми препятствиями, с которыми может столкнуться новичок во время развертывания. Все учебники, которые я нашел, говорили о Heroku, но в то время, когда я пытался развернуть свой проект, он уже не был бесплатным. Поэтому я подумал о создании учебника исключительно по созданию и развертыванию веб-приложения с использованием бесплатной альтернативы Render.

Прежде чем мы даже начнем, давайте установим ожидания! Это не руководство по обучению модели машинного обучения. Скорее предположим, что вы уже обучили модель и сохранили ее с помощью pickle. В этом руководстве вы узнаете, как создать веб-приложение, которое будет использовать вашу обученную модель для прогнозирования результата/цели на основе входных данных/функций, предоставленных пользователями в графическом интерфейсе. В этом руководстве вы также узнаете, как развернуть приложение на Render.

Это простая форма развертывания с использованием Flask и Render для начинающих.

1.0 Немного теории

1.1 Что такое рендеринг

Render — это облачная платформа как услуга (PaaS), которая позволяет разработчикам создавать, запускать и управлять приложениями полностью в облаке. Он поддерживает множество языков, таких как Python, Ruby, Rust, Node.js и другие. Для нашей цели мы будем использовать Python. Раньше Heroku была популярной платформой для инженеров-любителей и студентов, которые могли бесплатно развертывать свои приложения. С 28 ноября 2022 года компания прекратила предлагать бесплатные тарифные планы. Поэтому пользователи обратились к другим бесплатным альтернативам, таким как Render. В качестве предварительного условия нам понадобится файл requirements.txt. Это файл, содержащий имена всех зависимостей проекта. Render должен установить зависимости перед запуском приложения.

1.2 Что такое фляга

Flask — это микровеб-фреймворк, написанный на Python и разработанный Армином Ронахером. Он предоставляет библиотеки для создания легковесных веб-приложений. Flask становится все более популярным из-за своей простоты и легкости, а также из-за небольшой кривой обучения. Он подходит как новичкам, так и профессионалам.

Теперь, когда у нас есть теоретическое понимание этого проекта, давайте приступим к работе!

Чтобы дать вам предварительный просмотр, структура папки нашего проекта будет выглядеть так:

├── models
│   ├── model.pkl        <- model saved after it is trained
├── requirements.txt     <- required for deploying at Render
├── static
│   ├── image       
│   │   ├── img.jpg      <- image to be used in your GUI
│   ├── style.css        <- CSS stylesheet for your GUI
├── templates
│   ├── index.html       <- HTML template for your GUI
├── app.py               <- the main file containing the Flask app

2.0 О нашем проекте

Вот веб-приложение, которое мы собираемся создать:

Вы можете проверить общедоступный репозиторий здесь:



В этом проекте мы использовали набор данных, размещенный на Kaggle компанией UCI Machine Learning. Мы создадим веб-приложение, которое будет предсказывать тип стекла на основе различных химических элементов, используемых в нем. К химическим элементам относятся:

  • РИ — Иридиум
  • NA — натрий
  • Mg — магний
  • Ал — алюминий
  • Si — кремний
  • К — калий
  • Са — Кальций
  • Ба — барий
  • Fe — железо

** Не обращайте внимания на любые другие файлы или папки в репозитории GitHub, кроме файлов, упомянутых в файловой структуре выше. Мы будем использовать только сохраненную модель и сосредоточимся на создании и развертывании приложения.

3.0 Создание приложения Flask

3.1 Виртуальная среда

Прежде всего, нам нужно создать виртуальную среду на нашей локальной машине. Давайте создадим среду, используя venv или conda

conda create --name glass-type-prediction python=3.10
conda activate glass-type-prediction

3.2 Модель

Наш model будет находиться в виде файла .pkl в папке model. Как указывалось ранее, мы предполагали, что мы обучили и сохранили модель с помощью pickle. Поэтому я намеренно исключил обучающую часть, чтобы фактический учебник был простым и понятным. Вы можете загрузить файл model.pkl с GitHub.

3.3 Установка зависимостей

requirements.txt требуется Render, чтобы мы могли развернуть на нем наш проект. Создайте новый файл в своем каталоге и назовите его requirements.txt. Вставьте в файл следующие библиотеки:

click
flask
gunicorn
itsdangerous
jinja2
markupsafe
numpy
werkzeug

Установите зависимости, используя pip, выполнив следующую команду на своем терминале:

pip install -r requirements.txt

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

** По моему опыту, лучше оставить в файле только названия библиотек. Я получил ошибку конфликта версий, когда использовал определенный номер версии для ряда библиотек.

3.4 Шаблоны и index.html

Нам нужна папка, в которой будет храниться файл HTML для нашего графического интерфейса. Эта папка должна называться templates. Если его имя отличается от templates, вам нужно указать другое имя при создании экземпляра приложения в файле app.py:

app = Flask(__name__, template_folder='something-else')

Внутри этой папки создайте файл с именем index.html, который будет содержать код HTML для внешнего интерфейса нашего проекта. Вставьте в файл следующее:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Glass Type Prediction</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="../static/style.css">
        <link rel="preconnect" href="<https://fonts.googleapis.com>">
        <link rel="preconnect" href="<https://fonts.gstatic.com>" crossorigin>
        <link href="<https://fonts.googleapis.com/css2?family=Noto+Sans:ital@0;1&family=Source+Serif+Pro:wght@600&display=swap>" rel="stylesheet">
        <script src="<https://kit.fontawesome.com/c9c493ee57.js>" crossorigin="anonymous"></script>
    </head>
    <body>
        <div class="container">
            <div class="row heading">
                <h1 class="text-center">Glass Type Prediction</h1>
                <br>
                <p class="text-center">Insert the amount of chemical elements in a glass to find out the type of it.</p>
                <br>
                <p class="text-center">For example, if you insert the values as follow:</p>
                <p class="text-center">Iridium : 1.51730, Sodium : 12.35, Magnesium : 2.72, Aluminium : 1.63, <br>Silicon : 72.87,
                Potassium : 0.70, Calcium : 9.23, Barium : 0.00 and Iron :	0.00</p>
                <br>
                <p class="text-center">It will return the type as 'build wind non-float'</p>
            </div>
            <form action="{{ url_for('predict')}}" method="post" class="form">
                <div class="row">
                    <div class="col">
                        <label class="label" for="Iridium">Iridium</label>
                        <br>
                        <input type="text" name="Iridium" id="Iridium" class="text-input"/>
                        <br>
                        <label class="label" for="Sodium">Sodium</label>
                        <br>
                        <input type="text" name="Sodium" id="Sodium" class="text-input"/>
                        <br>
                        <label class="label" for="Magnesium">Magnesium</label>
                        <br>
                        <input type="text" name="Magnesium" id="Magnesium" class="text-input"/>
                    </div>
                    <div class="col">
                        <label class="label" for="Aluminium">Aluminium</label>
                        <br>
                        <input type="text" name="Aluminium" id="Aluminium" class="text-input"/>
                        <br>
                        <label class="label" for="Silicon">Silicon</label>
                        <br>
                        <input type="text" name="Silicon" id="Silicon" class="text-input"/>
                        <br>
                        <label class="label" for="Potassium">Potassium</label>
                        <br>
                        <input type="text" name="Potassium" id="Potassium" class="text-input"/>
                    </div>
                    <div class="col">
                        <label class="label" for="Calcium">Calcium</label>
                        <br>
                        <input type="text" name="Calcium" id="Calcium" class="text-input"/>
                        <br>
                        <label class="label" for="Barium">Barium</label>
                        <br>
                        <input type="text" name="Barium" id="Barium" class="text-input"/>
                        <br>
                        <label class="label" for="Iron">Iron</label>
                        <br>
                        <input type="text" name="Iron" id="Iron" class="text-input"/>
                    </div>
                </div>
                <div class="row">{{ prediction_text }}</div>
                <div class="row">
                    <button type="submit" class="btn"><span>Predict Type</span></button>
                </div>
            </form>
            <div class="row footer">
                <p>Image Credit: <a href=": <https://www.pexels.com/photo/architect-architecture-beach-bridge-262347/>">Pixabay on pexels.com</a> </p>
            </div>
        </div>
    </body>
</html>

Этот файл может содержать гораздо более сложный и изощренный код. Мы постарались упростить этот пример.

3.5 Статическая папка

В нашем проекте нам нужна папка с именем static, внутри которой нам нужен файл с именем style.css и папка с именем image. В папке будет изображение с именем img.jpg. Вы можете скачать изображение с Pexel.

3.5.1 стиль.css

Этот файл будет содержать все наши коды CSS. Давайте создадим файл style.css и поместим в него следующее:

*  
    { 
    margin: 0; 
    padding: 0; 
    border: 0; 
}
body 
    { 
    background-color: #000000;     
    text-align:center; 
} 
.container
    {  
    width:990px;  
    text-align:left;   
    margin-left:auto;  
    margin-right:auto;  
    background-color: #1d1d1d; 
    color: #ffffff;
    height: 100%;
    overflow: hidden;
}
.row {
    width: 100%;
    float: left;
    text-align: center; 
    margin-top: 50px;
}
.col {
    width: 33%;
    float: left;
    margin-left:auto;  
    margin-right:auto; 
}
.heading {
    background: linear-gradient(242deg, rgb(104 0 243 / 88%), rgb(0 0 0 / 69%)), url("image/img.jpg");
    background-repeat: no-repeat;
    background-size: cover;
    height: auto;
    width: 100%;
    padding-top: 50px;
    padding-bottom: 50px;
    margin-top: 0px;
}
.form {
    margin: auto;
}
.label {
    line-height: 2.5;
    font-family: 'Noto Sans', sans-serif;
    font-weight: 400;
    font-size: 10pt;
}
.footer {
    margin-bottom: 20px;
}
.footer > p {
    font-family: 'Noto Sans', sans-serif;
    font-style: italic;
    font-weight: 400;
    font-size: 10pt;
    color: #ffffff;
}
.footer > p > a {
    color: #ffffff
}
h1 {
    color: #ffffff;
    font-family: 'Source Serif Pro', serif;
    font-weight: 600;
    font-size: 28pt;
}
p {
    color: #ffffff;
    font-family: 'Noto Sans', sans-serif;
    font-weight: 400;
    font-style: italic;
    font-size: 12pt;
}
.btn > span {
    font-family: 'Source Serif Pro', serif;
    font-weight: 600;
    font-size: 11pt;
    text-transform: uppercase;
}
.text-left {
    text-align: left;
}
.text-right {
    text-align: right;
}
.text-center {
    text-align: center;
}
.btn {
    background-color: #6f4cff;
    color: #ffffff;
    height: 50px;
    width: 250px;
    padding: 10px;
    transition: 0.3s;   
}
.btn:hover {
    background-color: #573cc2;
}
.text-input {
    height: 30px;
    margin-bottom: 30px;
    padding: 5px 10px;
}

3.6 app.py

В папке вашего проекта вам нужен файл с именем app.py, куда вам нужно вставить следующий код:

# importing all dependencies
import numpy as np
from flask import Flask, request, render_template
import pickle

# instantiating the app
app = Flask(__name__)

# loading the model from the model.pkl file
model = pickle.load(open("models/model.pkl", "rb"))

# this is the function that the app will run at http://127.0.0.1:8000
@app.route("/")
def home():
    return render_template("index.html")

# this is the function that the button will run
@app.route("/predict", methods=["POST"])
def predict():
    """
    For rendering results on HTML GUI
    """
    float_features = [float(x) for x in request.form.values()]
    final_features = [np.array(float_features)]
    prediction = model.predict(final_features)
    output = prediction[0]
    return render_template(
        "index.html", prediction_text="Glass Type: {}".format(output)
    )

if __name__ == "__main__":
    app.run(debug=True, port=8000)

Теперь запустите app.py, запустив код в своем терминале:

python app.py

и он покажет следующее в вашем терминале:

* Serving Flask app
* Running on <http://127.0.0.1:8000> (Press CTRL+C to quit)

Откройте URL-адрес в браузере или щелкните по нему, нажав ctrl/cmd, приложение загрузится в браузере, в котором запущен шаблон. index.html. Шаблон содержит форму для ввода данных пользователем. Как только мы нажимаем кнопку PREDICT TYPE, действие формы в нашем файле index.html запускает функцию predict() из нашего файла app.py, которая затем принимает пользовательский ввод через форму и возвращает прогноз для того же файла HTML.

С последним шагом наше приложение готово к развертыванию.

4.0 Развертывание

4.1 Отправьте свой проект на GitHub

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



4.2 Развертывание при рендеринге

Развертывание на Render не так сложно. Это 4-этапный процесс. Если вам нужно узнать больше, вы можете проверить документацию Render для Python: https://render.com/docs/deploy-flask

Шаг 1. Создайте учетную запись на Render и войдите в нее

Посетите https://render.com и нажмите Начать бесплатно, чтобы зарегистрировать новую учетную запись, если у вас ее еще нет. Если у вас есть учетная запись, войдите в нее.

Шаг 2. Создайте новое приложение

После входа в систему вы попадете на панель инструментов (https://dashboard.render.com). Если вы впервые используете Render, в разделе Начать через несколько минут нажмите Новая веб-служба, и вы попадете на страницу, где вы можете подключить свою учетную запись GitHub, чтобы выбрать репозиторий для проекта. Нажмите +Подключить учетную запись и выберите все репозитории или только репозиторий для этого проекта. Нажмите Установить. Вам будет предложено подтвердить пароль на GitHub.

Шаг 3. Подключите репозиторий

Вы будете перенаправлены на страницу, на которой были раньше. Но на этот раз вы увидите свои репозитории в списке с кнопкой Подключиться справа от них. Нажмите Подключиться рядом с вашим проектом, и вы попадете на страницу сведений о проекте. Страница запросит следующую информацию:

  1. Название. Укажите подходящее название для вашего проекта.
  2. Регион: попробуйте выбрать регион, ближайший к вашему местоположению.
  3. Ветвь: обычно Master, но при необходимости вы можете выбрать любую другую марку.
  4. Корневой каталог (необязательно): по умолчанию выбирается корневой каталог репозитория. Вы можете оставить это поле пустым.
  5. Среда: выберите Python 3 для этого проекта.
  6. Команда сборки: по умолчанию это pip install -r requirements.txt. Если ваш файл requirements.txt называется по-другому, вы можете отредактировать команду.
  7. Start Command: Put gunicorn app:app Render использует gunicorn для запуска сервера, а app — это имя файла вашего приложения flask.

Вы также можете выбрать тип экземпляра для рендеринга. Давайте выберем Бесплатный план.

Теперь нажмите Создать веб-службу.

Шаг 4. Разверните!

Вы попадете на новую страницу, где увидите статус своего развертывания. Render установит все зависимости, сгенерирует образ контейнера и запустит ваше веб-приложение. Если есть какая-либо проблема, статус будет failed, в противном случае будет ОК. Если развертывание завершится неудачно, исправьте ошибки и зафиксируйте изменения в репозитории GitHub. Затем нажмите Развертывание вручную и выберите Развернуть последнюю фиксацию. Когда состояние станет ОК, вы можете перейти к поддомену, предоставленному Render, в левом верхнем углу страницы, и увидеть ваше недавно развернутое веб-приложение.

Мое приложение работает по адресу https://glass-type-prediction.onrender.com.

5.0 Заключение

Надеюсь, теперь вы понимаете, как представить свой проект машинного обучения в виде веб-приложения. Если вы никогда раньше не развертывали приложение, вы освоитесь с концепциями и шагами. Как только это произойдет, вы сможете создать более сложное веб-приложение, изучив больше о Flask и Render. Если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь оставлять комментарии, чтобы я мог быстро ответить.