Эта статья состоит из трех частей

Модель НЛП, развертывание с флягой, развертывание в Интернете (Heroku)

Вы можете проверить работающую развернутую модель здесь: http://www.nltkbot.com/

Прежде чем перейти к статье, вам необходимо правильно установить Python в вашей системе, и вам необходимо иметь базовое представление о моделях машинного обучения.

В этой статье рассматривается только часть развертывания модели с помощью flask, а не подробное построение модели. Поэтому, если у вас уже есть рабочая модель, вы можете использовать эту модель для развертывания и можете сразу перейти к части развертывания, или же вы можете использовать приведенный ниже пример модели.

ЧАСТЬ 1) — Модель НЛП

Поскольку построение модели выходит за рамки этой статьи, я просто объясню модель и то, что она делает. Если кому-то нужны наборы данных для дальнейшего улучшения модели, ссылки на github приведены в конце статьи в разделах «Ссылки».

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

Процесс очистки данных включал удаление всех URL-адресов, знаков препинания, а библиотека NLTK использовалась для токенизации, лемметизации и удаления стоп-слов. Убедитесь, что у вас уже установлена ​​библиотека NLTK, иначе она выдаст ошибки.

import pandas as pd
import numpy as np
import nltk
import string
import re
import pickle

nltk.download('stopwords')
nltk.download('wordnet')

train_data = pd.read_csv('train.csv')
test_data = pd.read_csv('test.csv')

data = pd.concat([train_data, test_data], axis=0)

df = data.copy()

df['label'].value_counts()


# Removing URLs
def remove_url(text):
    return re.sub(r"http\S+", "", text)

#Removing Punctuations
def remove_punct(text):
    new_text = []
    for t in text:
        if t not in string.punctuation:
            new_text.append(t)
    return ''.join(new_text)


#Tokenizer
from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'\w+')



#Removing Stop words
from nltk.corpus import stopwords
def remove_sw(text):
    new_text = []
    for t in text:
        if t not in stopwords.words('english'):
            new_text.append(t)
    return new_text

#Lemmatizaion
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()

def word_lemmatizer(text):
    new_text = []
    for t in text:
        lem_text = lemmatizer.lemmatize(t)
        new_text.append(lem_text)
    return new_text

df['tweet'] = df['tweet'].apply(lambda t: remove_url(t))

df['tweet'] = df['tweet'].apply(lambda t: remove_punct(t))

df['tweet'] = df['tweet'].apply(lambda t: tokenizer.tokenize(t.lower()))

df['tweet'] = df['tweet'].apply(lambda t: remove_sw(t))

df['tweet'] = df['tweet'].apply(lambda t: word_lemmatizer(t))

Позже текст был векторизован с помощью TfidVectorizer перед отправкой в ​​модель для прогнозирования. Модель LightGbm использовалась для прогнозирования без какой-либо настройки гиперпараметров, как я уже упоминал ранее, построение модели выходит за рамки этой статьи. Наконец, модель и векторизатор должны быть сохранены с помощью pickle, чтобы мы могли позже загрузить эти модели в наше приложение, чтобы предсказать результаты пользовательского ввода.

features_set = df.copy()

train_set = features_set.iloc[:len(train_data), :]

test_set = features_set.iloc[len(train_data):, :]

X = train_set['tweet']


for i in range(0, len(X)):
    X.iloc[i] = ' '.join(X.iloc[i])


Y = train_set['label']


from sklearn.feature_extraction.text import TfidfVectorizer

TfidV = TfidfVectorizer()

X = TfidV.fit_transform(X)



from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size = 0.1, random_state = 1234)


from lightgbm import LGBMClassifier

lgb = LGBMClassifier(scale_pos_weight=3)

lgb.fit(X, Y)

#lgb.fit(x_train, y_train)

y_predict_lgb = lgb.predict(x_test)

from sklearn.metrics import confusion_matrix, f1_score

cm_lgb = confusion_matrix(y_test, y_predict_lgb)

f1_lgb = f1_score(y_test, y_predict_lgb)

score_lgb = lgb.score(x_test, y_test)


with open('twitter_predictions.pkl', 'wb') as file:
    pickle.dump(lgb, file)
    
with open('vectorizer.pkl', 'wb') as file:
    pickle.dump(TfidV, file)

ЧАСТЬ 2) — Развертывание с использованием Flask

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

Flask — это микрофреймворк для Python, его легко настроить. Перед установкой flask создайте каталог (я назвал его flask_app), в котором вы собираетесь установить приложение flask, и создайте виртуальную среду (я назвал его nlp_env) в этом каталоге и активируйте его, и он должен выглядеть примерно так:

C:\Users\Surya\Documents\flask_app>py -m venv nlp_env
C:\Users\Surya\Documents\flask_app>nlp_env\Scripts\activate
(nlp_env) C:\Users\Surya\Documents\flask_app>

Теперь мы можем установить flask, для установки flask мы используем pip установщика пакетов python.

(nlp_env) C:\Users\Surya\Documents\flask_app>pip install flask

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

(nlp_env) C:\Users\Surya\Documents\flask_app>set FLASK_APP=app.py

Теперь мы проверим работу знаменитого «Hello World» с нашим фляжным приложением. Откройте текстовый редактор и напишите приведенный ниже код.

import flask

app = flask.Flask(__name__)

@app.route('/')
def index():
 return "<h1>Hello World</h1>"

Код довольно прост, мы просто импортировали библиотеку flask и создали экземпляр класса Flask, а __name__ ссылается на имя текущего модуля, в котором мы работаем (здесь это app.py). В следующей строке мы создаем маршрут, за которым следует функция, которая возвращает прямо в браузер.

Пришло время увидеть, как наше приложение flask запущено и работает в браузере, просто введите flask run, и вы должны увидеть приложение, работающее по адресу локального хоста (что-то вроде этого, работающее на http://127.0.0.1:5000/)

(nlp_env) C:\Users\Surya\Documents\flask_app>flask run

Написание html непосредственно в app.py не рекомендуется, и это также выглядит не очень хорошо, поэтому мы создадим отдельную папку в нашем непосредственно и будем ссылаться на нее в нашем app.py. Мы также должны создать отдельную папку для хранения наших сохраненных моделей, которые позже мы будем использовать для прогнозирования. После создания папок ваша структура папок должна выглядеть так, как показано ниже.

Мы обновим наш app.py, чтобы отразить эти изменения. Сначала мы загрузим файлы нашей модели, а затем обновим наш класс Flask с помощью папки с шаблонами. В дополнение к этому мы также обновим нашу маршрутизацию, чтобы принимать запросы GET и POST.

import flask

#Use pickle to load in the pre-trained model.

with open(f'model/twitter_predictions.pkl', 'rb') as f:
    model = pickle.load(f)

with open(f'model/vectorizer.pkl', 'rb') as f:
    vectorizer = pickle.load(f)

app = flask.Flask(__name__, template_folder='templates')

@app.route('/', methods=['GET', 'POST'])
def index():
    return "<h1>Hello World</h1>"

Наше приложение по-прежнему возвращает «Hello World» с запросом GET. Итак, нам нужно, чтобы наше приложение возвращало правильный html, и для этого мы создадим html-файл (index.html) в папке с нашими шаблонами. Я собираюсь добавить простую html-форму в index.html, которая позволит пользователю ввести текст и отправить его.

<!doctype html>
<html>

<head>
    <title>Enter Text</title>
</head>
<form action="{{ url_for('index') }}" method="POST">
    <fieldset>
        <legend>Enter Review:</legend>
        <textarea name="tweet" rows="10" cols="80" required></textarea>
        <br>
        <br>
        <input type="submit">
    </fieldset>
</form>

Когда пользователь вводит текст и отправляет его, наше приложение получает запрос POST с текстом, прикрепленным к «твиту». Нам нужно обновить наш app.py, чтобы обрабатывать этот запрос POST и отображать результат соответствующим образом.

import flask

#Use pickle to load in the pre-trained model.
with open(f'model/twitter_predictions.pkl', 'rb') as f:
    model = pickle.load(f)

with open(f'model/vectorizer.pkl', 'rb') as f:
    vectorizer = pickle.load(f)

app = flask.Flask(__name__, template_folder='templates')

@app.route('/', methods=['GET', 'POST'])
def index():
    
    if flask.request.method == 'GET':
        return(flask.render_template('index.html'))
    
    if flask.request.method == 'POST':
        
        tweet = flask.request.form['tweet']

Мы получили пользовательский ввод, который нам нужно предсказать из запроса POST, поэтому мы будем использовать нашу ранее загруженную модель для предсказания результатов. Поскольку пользовательский ввод все еще находится в необработанном виде, нам нужно преобразовать его в машиночитаемый вид так же, как мы делали это при построении модели в первой части. Сначала мы преобразуем его в фрейм данных с теми же именами столбцов, которые понимает наша сохраненная модель, а позже все шаги, которые мы использовали при построении модели, будут выполняться в том же порядке. Итак, наш окончательный файл app.py должен выглядеть так, как показано ниже.

import flask
import pickle
import pandas as pd
import numpy as np
import nltk
import string
import re


# Use pickle to load in the pre-trained model.
with open(f'model/twitter_predictions.pkl', 'rb') as f:
    model = pickle.load(f)


with open(f'model/vectorizer.pkl', 'rb') as f:
    vectorizer = pickle.load(f)



# Removing URLs
def remove_url(text):
    return re.sub(r"http\S+", "", text)

#Removing Punctuations
def remove_punct(text):
    new_text = []
    for t in text:
        if t not in string.punctuation:
            new_text.append(t)
    return ''.join(new_text)


#Tokenizer
from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'\w+')



#Removing Stop words
from nltk.corpus import stopwords

def remove_sw(text):
    new_text = []
    for t in text:
        if t not in stopwords.words('english'):
            new_text.append(t)
    return new_text

#Lemmatizaion
from nltk.stem import WordNetLemmatizer

lemmatizer = WordNetLemmatizer()

def word_lemmatizer(text):
    new_text = []
    for t in text:
        lem_text = lemmatizer.lemmatize(t)
        new_text.append(lem_text)
    return new_text



app = flask.Flask(__name__, template_folder='templates')

@app.route('/', methods=['GET', 'POST'])

def index():
    
    if flask.request.method == 'GET':
        return(flask.render_template('index.html'))
    
    if flask.request.method == 'POST':
        
        tweet = flask.request.form['tweet']

        df = pd.DataFrame([tweet], columns=['tweet'])



        df['tweet'] = df['tweet'].apply(lambda t: remove_url(t))

        df['tweet'] = df['tweet'].apply(lambda t: remove_punct(t))

        df['tweet'] = df['tweet'].apply(lambda t: tokenizer.tokenize(t.lower()))

        df['tweet'] = df['tweet'].apply(lambda t: remove_sw(t))

        df['tweet'] = df['tweet'].apply(lambda t: word_lemmatizer(t))




        final_text = df['tweet']

        final_text.iloc[0] = ' '.join(final_text.iloc[0])

        final_text = vectorizer.transform(final_text)



        prediction = model.predict(final_text)
        
        return flask.render_template('index.html', result=prediction, original_input={'Mobile Review':tweet})




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

Прогнозируемый результат в app.py сохраняется в переменной результата, которая будет отображать результат в index.html. Мы создадим новый элемент div для отображения результата вместе с пользовательским вводом, когда запрос POST отображает index.html. Элемент div имеет простой оператор if else для проверки типа результата и добавления цвета к результату. Я добавил некоторые стили к html-странице, чтобы она выглядела красиво. Таким образом, наш окончательный HTML-файл будет выглядеть следующим образом:

<!doctype html>
<html>
<style>
form {
    margin: auto;
    width: 35%;
}
.result {
    margin: auto;
    width: 35%;
    border: 1px solid #ccc;
}
</style>
<head>
    <title>Enter Text</title>
</head>
<form action="{{ url_for('index') }}" method="POST">
    <fieldset>
        <legend>Enter Mobile Review:</legend>
        <textarea name="tweet" rows="10" cols="80" required></textarea>
        <br>
        <br>
        <input type="submit">
    </fieldset>
</form>
<br>
<div class="result" align="center">
    {% if result == 0 %}
        {% for variable, value in original_input.items() %}
            <b>{{ variable }}</b> : {{ value }}
        {% endfor %}
        <br>
        <br> 
           <p style="font-size:30px">The Review is:</p>
           <p style="font-size:40px; color: green;">{{ result }}</p>
    {% elif result == 1 %}
        {% for variable, value in original_input.items() %}
            <b>{{ variable }}</b> : {{ value }}
        {% endfor %}
        <br>
        <br> 
           <p style="font-size:30px">The Review is:</p>
           <p style="font-size:40px; color: red;">{{ result }}</p>
    {% endif %}
</div>
</html>

Теперь введите, запустите flask и посмотрите, как модель ML в браузере запущена и работает и готова предсказывать некоторые твиты. Ура !! вы успешно развернули модель НЛП с флягой на своем локальном компьютере. Вы можете дополнительно добавить стиль и фон в приложение, чтобы оно выглядело более ярким, или вы можете проверить мое приложение на наличие полного шаблона https://github.com/vijjeswarapusuryateja/mobile-review-rating.

ЧАСТЬ 3) — Развертывание в Интернете (Heroku)

Здесь я рассказываю только о развертывании модели НЛП на Heroku, если у вас уже есть учетная запись в Heroku. Если вы не знакомы с Heroku, в Интернете доступно множество источников богатой информации о Heroku. Объяснение процесса регистрации в Heroku не входит в задачу этой статьи. Поэтому вам нужно установить git, Heroku CLI, прежде чем переходить к следующему шагу.

Первый шаг — создать репозиторий git для нашего веб-приложения.

(nlp_env) C:\Users\Surya\Documents\flask_app>git init

Аутентифицируйтесь с помощью Heroku и создайте новое приложение heroku

(nlp_env) C:\Users\Surya\Documents\flask_app>heroku login
(nlp_env) C:\Users\Surya\Documents\flask_app>heroku create flask-app-nlp

Чтобы наше приложение успешно работало на Heroku, нам нужно добавить три дополнительных файла.

Создайте файл requirements.txt в каталоге flask_app, и он должен иметь следующее

flask
pandas
numpy
gunicorn
lightgbm
nltk

Аналогичным образом создайте файл nltk.txt и добавьте следующее

stopwords
wordnet
pros_cons
reuters
omw-1.4

Наконец, создайте Procfile в каталоге flask_app и добавьте следующую строку.

web: gunicorn app:app

Ваша окончательная папка flask_app теперь должна выглядеть так:

Добавьте все эти файлы в репозиторий, используя команды git, как показано ниже.

(nlp_env) C:\Users\Surya\Documents\flask_app>git add .
(nlp_env) C:\Users\Surya\Documents\flask_app>git commit -m "First commit!"

Установите удаленный пункт назначения для нажатия с git на heroku

(nlp_env) C:\Users\Surya\Documents\flask_app>heroku git:remote -a flask-app-nlp

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

(nlp_env) C:\Users\Surya\Documents\flask_app>git push heroku master

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

После завершения загрузки вы можете ввести heroku open и увидеть приложение, работающее в веб-браузере. В качестве альтернативы вы можете посмотреть свое приложение с созданным вами именем http://flask-app-nlp.herokuapp.com. Я уже создал приложение с таким именем в Heroku, поэтому вместо этого используйте другое имя.

(nlp_env) C:\Users\Surya\Documents\flask_app>heroku open

Возможные ошибки!

Если у вас возникнут проблемы с развертыванием heroku, всегда рекомендуется проверять журналы heroku, чтобы устранить проблему. Одно из решений наиболее распространенной проблемы, возникающей при развертывании NLP, связано с библиотекой NLTK, и ее можно исправить, указав соответствующий корпус в файле nltk.txt, который отображается в журналах heroku.

ПОЛЕЗНЫЕ ССЫЛКИ (набор данных, репозиторий Github, развернутая модель)

Ссылки на наборы данных, на которых обучалась модель: https://github.com/vijjeswarapusuryateja/Datasets

Ссылка на код развернутого приложения: https://github.com/vijjeswarapusuryateja/mobile-review-rating

Рабочая развернутая модель: http://www.nltkbot.com/

Портфолио: https://vijjeswarapusuryateja.github.io/