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

Предварительные требования (помимо концепций ML)

  1. Основы веб-приложения
  2. Основы HTML

Темы охватывали

  1. Создание модели
  2. Создание веб-приложения Flask
  3. Создание HTML-форм
  4. Развертывание в Интернете с помощью Heroku

Развертывание модели в основном представляет собой обмен данными, то есть мы принимаем входные данные в той или иной форме (JSON/XML и т. д.), обрабатываем их через нашу модель и, в свою очередь, выдаем результат, который по сути является данными. Ниже приведены шаги по созданию, построению и развертыванию модели.

ШАГ 1: Создайте базовую модель

Чтобы построить простую модель, я использую набор данных Iris (очень распространенный). Это набор данных бинарной классификации с 4 функциями и 1 целевой переменной. Помните, что этот пост больше посвящен развертыванию модели, а не самой модели. Вот ссылка Kaggle на набор данных

#Import basic libraries
import numpy as np
import pandas as pd
#Load the data
df = pd.read_csv('Iris.csv')
#Separate the features from labels
X = df.drop(['Id','Species'],axis=1)
y = df['Species']
#Since model cannot take in text data, we encode the y variable
from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
y = encoder.fit_transform(y)
#Split the dataset
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.25,random_state=42)
#Scale the dataset (Remember to only fit it on the train set so that we don't acquire any prior knowledge about the test set)
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
sc_X_train = scaler.fit_transform(X_train)
sc_X_test = scaler.transform(X_test)
#Create the model (Here a deep learning model is created. Any ML model will work just fine)
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

model = Sequential()
model.add(Dense(4,activation='relu', input_shape=[4,]))
model.add(Dense(3,activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy',metrics=['accuracy'])
#Train and fit the model
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss', patience=5)
model.fit(sc_X_train, y_train, epochs=400,validation_data=(sc_X_test,y_test), callbacks =[es])

ШАГ 2. Оцените модель

Проверьте, удовлетворяют ли модель и ее показатели. Измените предыдущие шаги, если это не так. Если все в порядке, доработайте модель для развертывания. В продакшене не существует концепции разделения тестов на поезда. Мы использовали его, чтобы определить лучшую рабочую модель. Когда модель будет готова к производству, лучше всего провести повторное обучение на ВСЕХ ДАННЫХ.

epochs = len(metrics) #No of epochs set to the metrics variable length
sc_X = scaler.fit_transform(X) #Scaling the entire data
model = Sequential()
model.add(Dense(4,activation='relu', input_shape=[4,]))
model.add(Dense(3,activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(sc_X, y, epochs=epochs,validation_data=(sc_X_test,y_test), callbacks =[es]) #Now the model is fit on the entire dataset

ШАГ 3: Сохраните модель и масштабатор

Помимо сохранения модели, необходимо сохранить и масштабатор. В производственной среде у нас нет инструмента или средства для масштабирования новых входящих данных.

model.save('FinalModel.h5')
import joblib
joblib.dump(scaler, 'iris_scaler.pkl') #saving the scaler object

ШАГ 4: Определите функцию для прогнозирования

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

#Creating a function to predict the output. This takes in the original model, the scaler and the json data as input parameters
def return_prediction(model,scaler,json): 
    s_len = example_input["sepal_length"]
    s_wid = example_input["sepal_width"]
    p_len = example_input["petal_length"]
    p_wid = example_input["petal_width"]
    new_flower = [[s_len,s_wid,p_len,p_wid]]
    new_flower = scaler.transform(new_flower)[0]
    #Predicting the classes based on the input. However, this will return either 0,1 or 2 and not the actual class names. So setting up the actual class names and indexing it.
    class_index = model.predict_classes(new_flower) 
    classes = np.array(['setosa','versicolor','virginica'])
    return classes[class_index]

Шаг 5. Разверните с помощью веб-приложения Flask и подключите его к интерфейсной HTML-форме.

Flask — это фреймворк для веб-приложений на основе Python. Он использует python для обработки серверной части веб-приложения (наша модель). Мы можем подключить его к внешним компонентам (HTML, JS и т. д.). Этот шаг фокусируется на объединении Flask API и модели в интерфейсную HTML-форму. Этот шаг гарантирует, что любой, кто не разбирается в технических вопросах, может просто перейти на этот веб-сайт и заполнить форму, чтобы увидеть результаты. Ниже план действий -

  • Создайте веб-приложение Flask
  • Создайте необходимые файлы HTML
  • Используйте Flask для создания HTML-формы и вставки в home.html (принимайте ввод пользователя и отправляйте в приложение flask).
  • Используйте Flask, чтобы принять отправленные данные формы
  • Используйте Flask, чтобы вернуть прогноз в prediction.html (возвращает прогноз после завершения работы функции прогнозирования)

ПРИМЕЧАНИЕ:

  • Чтобы запустить приложение flask, нам нужно написать скрипт Python (.py). Я не запускаю скрипт непосредственно на блокноте Jupyter, потому что он работает в веб-браузере и может конфликтовать с возможностями фляги. Рекомендую писать скрипт отдельно в текстовом редакторе.
  • Все файлы HTML должны находиться в папке с названием «шаблон» (все ниже). Flask автоматически обнаружит файлы только в этой папке.

Вот скрипт фляжного веб-приложения

#modelflask.py
from flask import Flask, render_template, session, redirect, url_for
import numpy as np
from flask_wtf import FlaskForm
from wtforms import TextField, SubmitField
from tensorflow.keras.models import load_model
import joblib
#Define the prediction function (copy paste from step 4)
def return_prediction(model,scaler,json): 
    s_len = example_input["sepal_length"]
    s_wid = example_input["sepal_width"]
    p_len = example_input["petal_length"]
    p_wid = example_input["petal_width"]
    new_flower = [[s_len,s_wid,p_len,p_wid]]
    new_flower = scaler.transform(new_flower)[0]
    class_index = model.predict_classes(new_flower)
    classes = np.array(['setosa','versicolor','virginica'])
    return classes[class_index]
#Initialize the flask app
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'

#Creating a form class and inheriting the FlaskForm which is an inbuilt class
class MyForm(FlaskForm):
    sep_len = TextField("Sepal Length")
    sep_wid = TextField("Sepal Width")
    pet_len = TextField("Petal Length")
    pet_wid = TextField("Petal Width")

    submit = SubmitField("Predict Result")


#Create a basic route for a home page
@app.route("/", methods=['GET','POST'])
def index():
    form = MyForm()
    if form.validate_on_submit():
        session['sep_len'] = form.sep_len.data
        session['sep_wid'] = form.sep_wid.data
        session['pet_len'] = form.pet_len.data
        session['pet_wid'] = form.pet_wid.data

        return redirect(url_for('prediction')) #Upon validation, redirect it to the prediction function ('/prediction')
    return render_template('home.html',form=form) #Returning an html form

#Load the model and the scaler
load_model = load_model('FinalModel.h5')
load_scaler = joblib.load('iris_scaler.pkl')

#Create a routing view for prediction
@app.route("/prediction")
def prediction():
    contents = {}
    contents['sepal_length'] = float(session['sep_len'])
    contents['sepal_width'] = float(session['pet_wid'])
    contents['petal_length'] = float(session['sep_len'])
    contents['petal_width'] = float(session['pet_wid'])

    results = return_prediction(load_model, load_scaler, contents) #Store the results from the return_prediction function 

    return render_template('prediction.html',results=results) #Returning an html form


if __name__ == '__main__':
    app.run()

Вот код HTML для обоих файлов

<!--home.html-->
<h2>Enter the flower measurements below</h2>
<form method='POST'>
    {# This hidden_tag is a CSRF security feature. #}
    {{ form.hidden_tag() }}
    {{form.sep_len.label }} {{form.sep_len}}
    <br>
    {{form.sep_wid.label }} {{form.sep_wid}}
    <br>
    {{form.pet_len.label }} {{form.pet_len}}
    <br>
    {{form.pet_wid.label }} {{form.pet_wid}}
    <br>
    {{form.submit()}}
</form>
<!--prediction.html-->
<h1>Based on the information given, here's the result</h1>
<ul>
    <li>Sepal Length: {{session['sep_len']}}</li>
    <li>Sepal Width: {{session['sep_wid']}}</li>
    <li>Petal Length: {{session['pet_len']}}</li>
    <li>Petal Width: {{session['pet_wid']}}</li>
</ul>
<h2>The predicted flower class is: {{results}}</h2>

Шаг 6. Развертывание в Интернете

Теперь мы подошли к последнему шагу. Теперь мы протестировали и поняли, что локально все работает нормально, и пришло время перенести его в Интернет. Существует множество различных сервисов для развертывания и размещения веб-приложений. Хотя поставщики облачных услуг, такие как MS Azure, AWS, GCP, могут предоставлять бесплатные услуги в ограниченном количестве, на этот раз мы используем полностью бесплатную услугу от Heroku. (Однако более тяжелые приложения могут не подпадать под категорию бесплатного пользования). Вот план действий

  • Создайте новую папку на рабочем столе и скопируйте папку шаблонов, сценарий фляги, сохраненную модель и файлы масштабирования. Не забудьте переименовать скрипт фляги в app.py.
  • Перейдите на signup.heroku.com и зарегистрируйтесь.
  • Установите интерфейс командной строки Heroku со страницы devcenter.heroku.com/categories/command-line. CLI Heroku требует, чтобы GIT был установлен в системе. Убедитесь, что он у вас есть.
  • Откройте приглашение anaconda и перейдите во вновь созданную папку. Создайте среду специально для этого развертывания
conda create --name envname
  • Активировать среду
conda activate envname
  • Установите необходимые библиотеки (flask, Flask-WTF, tensorflow, scikit-learn, gunicorn)
  • Создайте эти библиотеки в файле требований, чтобы загрузить его на сервер.
pip freeze > requirements.txt
  • Создайте файл процесса в любом текстовом редакторе и сохраните его как Procfile. Содержимое файла -
web: gunicorn app:app
  • Вернитесь в Heroku и нажмите «Создать новое приложение».
  • Дайте уникальное имя приложения
  • Выберите метод развертывания как Heroku Git
  • Следуйте всем инструкциям командной строки, предоставленным как таковые
  $ heroku login (browser opens. Login using Heroku creds)
  $ git init
  $ heroku git:remote -a nameoftheapp
  $ git add .
  $ git commit -am "Enter commit message"
  $ git push heroku master

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

ЗАКЛЮЧИТЕЛЬНЫЕ ПРИМЕЧАНИЯ:

Рассматривайте этот пост как шаблон для создания и развертывания собственной модели и веб-приложения. Выход за рамки прогнозов и развертывание модели — это как завершение полного круга. Хотя этот метод требует фундаментальных знаний HTML и веб-приложений, это отличное оружие в арсенале. У меня есть ссылка на GitHub, которая показывает полную версию, которую я рекомендую вам посмотреть. Спасибо!

Подпишитесь на меня в LinkedIn по адресу https://www.linkedin.com/in/bharathwajmurali/