Пошаговое руководство по созданию веб-приложения для прогнозирования от определения проблемы до развертывания модели.

Что мы рассмотрим в этой статье

  • Сбор данных и постановка проблемы
  • Исследовательский анализ данных с помощью Pandas и NumPy
  • Предварительная обработка данных и разработка функций
  • Выбор и обучение нескольких моделей машинного обучения с помощью Sklearn
  • Оценка модели
  • Развертывание окончательно обученной модели на Heroku через приложение Flask

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

Обзор проекта

Простое веб-приложение на основе машинного обучения и NLP, которое классифицирует данные сообщения как спам или хам (не спам), построенное с использованием Flask и развернутое на Heroku.

Чтобы просмотреть развернутое приложение, щелкните ссылку ниже : https: // sms-spam- predictor-nlp.herokuapp.com/

Демонстрация развернутого веб-приложения

Приступим…

Шаг 1. Сбор данных и описание проблемы

Самый первый шаг каждого проекта машинного обучения - это сосредоточение внимания на данных. Очень важная задача решить, что, как и откуда брать необходимые данные для решения данной Задачи. Необходимые данные могут быть собраны из внутренней базы данных клиентов, сторонних API, сайтов онлайн-данных или с помощью веб-скрапинга. Итак, для этого проекта мы собираемся использовать данные о сборе SMS-спама UCI-ML из Kaggle.

Вот ссылка на набор данных:
https://www.kaggle.com/uciml/sms-spam-collection-dataset

Постановка проблемы: Классифицировать данное текстовое сообщение как спам или хам.

Шаг 2. Загрузка набора данных

Сначала импортируйте необходимые библиотеки для загрузки данных и выполнения EDA.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

Затем прочтите и загрузите файл в фрейм данных, используя метод read_csv, и давайте взглянем на основную информацию о данных с помощью метода info().

#reading and checking the basic structure of the data
sms_data = pd.read_csv("spam.csv",encoding='latin-1')
sms_data.info()

Примечание. Кодировка символов этого набора данных - latin-1 (ISO / IEC 8859–1).

Набор данных содержит 5 столбцов. Столбец v1 - это метка набора данных («ветчина» или «спам»), а столбец v2 содержит текст SMS-сообщения. Столбцы «Безымянный: 2», «Безымянный: 3» и «Безымянный: 4» содержат «NaN» (не число), обозначающее пропущенные значения. Они не нужны, поэтому их можно отбросить, поскольку они не будут полезны при построении модели.

Следующий фрагмент кода отбросит и переименует столбцы, чтобы облегчить понимание набора данных:

# creating a copy of the dataset so that the changes will not affect the original dataset.
sms_df = sms_data. Copy() 
# Dropping the redundant looking columns (for this project)
to_drop = ["Unnamed: 2","Unnamed: 3","Unnamed: 4"]
sms_df = sms_df. Drop(sms_df[to_drop], axis=1)
# Renaming the columns for better understanding 
sms_df.rename(columns = {"v1":"Target", "v2":"Message"}, inplace = True)
sms_df.head()

Теперь набор данных выглядит более четким и понятным.

Шаг 3. Исследовательский анализ данных

Выполнит исследование данных в несколько этапов, указанных ниже:

  • Чтобы проверить основную информацию о таких данных, как количество строк и столбцов, типы данных и нулевые значения, мы можем использовать прямую функцию pandas, называемую info ().
# using info method
sms_df.info()

Набор данных состоит из 5 572 сообщений на английском языке. Данные обозначены как любительские или спам. Фрейм данных состоит из двух столбцов. Первый столбец - это «Цель», указывающий на класс сообщения как «ветчина» или «спам», а второй столбец «Сообщение» - это строка текста. В наборе данных нет нулевых значений.

  • Мы также можем получить статистическую информацию о данных с помощью метода describe ().
# statistical info of dataset
sms_df.describe()

Перед изучением распределения набора данных и дальнейшим анализом сначала сопоставим значения (каждой категории) целевой переменной с 0 и 1. (0-Ham, 1-Spam)

# Mapping Values for labels  
sms_df['Target'] = sms_df['Target'].map({'ham': 0, 'spam': 1}) sms_df.head()
  • Теперь посмотрим на распределение этикеток
#Palette
cols= ["#E1F16A", "salmon"] 
plt.figure(figsize=(8,8))
fg = sns.countplot(x= sms_df["Target"], palette= cols)
fg.set_title("Countplot for spam Vs ham")
fg.set_xlabel("Classes(0:ham,1:spam)", color="#58508d")
fg.set_ylabel("Number of Data points")

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

Шаг 4. Разработка функций

Обработка несбалансированного набора данных с помощью передискретизации

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

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

# Handling imbalanced dataset using Oversampling 
only_spam = sms_df[sms_df['Target']==1] print('Number of Spam records: {}'.format(only_spam.shape[0])) print('Number of Ham records: {}'.format(sms_df.shape[0]-only_spam.shape[0]))
count = int((sms_df.shape[0]-only_spam.shape[0])/only_spam.shape[0])
for i in range(0, count-1):
    sms_df = pd.concat([sms_df, only_spam])

sms_df.shape

Сейчас снова проверю раздачу

Теперь из приведенного выше графика мы можем ясно сказать, что наши данные почти сбалансированы.

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

  • word_count: количество слов в текстовом сообщении
  • contains_number: содержит ли текстовое сообщение числа
  • contains_currency_symbol: символы, такие как ‘€’, ‘$’, ‘¥’, ‘£’, ‘₹’ в текстовом сообщении.

Распределение количества слов для любительских и спам-сообщений

# creating new feautre word_count
sms_df['word_count'] = sms_df['Message'].apply(lambda x: len(x.split()))
plt.figure(figsize=(12, 6))

# 1-row, 2-column, go to the first subplot
plt.subplot(1, 2, 1)
g = sns.distplot(a=sms_df[sms_df['Target']==0].word_count,color='#E1F16A')
p = plt.title('Distribution of word_count for Ham messages')

# 1-row, 2-column, go to the second subplot
plt.subplot(1, 2, 2)
g = sns.distplot(a=sms_df[sms_df['Target']==1].word_count, color='salmon')
p = plt.title('Distribution of word_count for Spam messages')

plt.tight_layout()
plt.show()

Можно видеть, что в большинстве случаев любительские сообщения короче, чем спам-сообщения, поскольку распределение слов в спам-сообщениях находится в диапазоне от 15 до 30 слов, тогда как большинство любительских сообщений попадают в диапазон менее 25 слов.

Давайте посмотрим, как сообщения связаны с символами валюты.

# Creating feature contains_currency_symbol
def currency(x):
    currency_symbols = ['€', '$', '¥', '£', '₹']
    for i in currency_symbols:
        if i in x:
            return 1
    return 0

sms_df['contains_currency_symbol']=sms_df['Message'].apply(currency)

Видно, что почти 1/3 спам-сообщений содержит символы валюты, а символы валюты редко используются в радиолюбительских сообщениях, что вполне приемлемо, поскольку большинство спам-сообщений предназначены для денег.

Теперь давайте проверим текстовые сообщения, содержащие номер

# Creating feature contains_number 
def numbers(x):     
    for i in x:         
        if ord(i)>=48 and ord(i)<=57:             
            return 1     
     return 0  
sms_df['contains_number'] = sms_df['Message'].apply(numbers)

Из приведенного выше графика мы можем сказать, что (по крайней мере, для этого набора данных) большинство спам-сообщений содержат числа, а большинство сообщений Ham не содержат чисел.

Шаг 5. Предварительная обработка данных

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

Давайте посмотрим на образец текстов перед предварительной обработкой.

print("The First 5 Texts:\0",*sms_df["Message"][:5], sep = "\n")

Ниже приведены шаги, используемые для предварительной обработки данных для НЛП:

Очистка текста:

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

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

Удаление стоп-слов : стоп-слова - это часто встречающиеся слова (например, несколько, есть, an и т. д.). Эти слова содержат значение в структуре предложения, но не вносят большой вклад в языковую обработку в НЛП. Мы удаляем их с целью устранения избыточности в нашей обработке. В библиотеке NLTK есть набор стоп-слов по умолчанию, которые мы будем удалять.

Лемматизация слов : стемминг и лемматизация - это методы нормализации текста (или иногда называемые нормализацией слов) в области НЛП.

Лемматизация - это процесс получения леммы слова. Что же тогда такое лемма? Лемма - это корень, из которого образовано слово. Например, учитывая слово «пошел», леммой будет «идти», поскольку «пошел» - это прошедшая форма слова «го».

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

Для начала нам нужно импортировать следующие библиотеки:

# libraries for performing NLP 
import nltk
import re
nltk.download('stopwords')
nltk.download('wordnet')
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from sklearn.feature_extraction.text import TfidfVectorizer

Следующий фрагмент кода выполнит предварительную обработку текста.

# Cleaning the messages
corpus = []
wnl = WordNetLemmatizer()

for sms_string in list(sms_df.Message):

  # Cleaning special character from the sms
  message = re.sub(pattern='[^a-zA-Z]', repl=' ', string=sms_string)

  # Converting the entire sms into lower case
  message = message.lower()

  # Tokenizing the sms by words
  words = message.split()

  # Removing the stop words
  filtered_words = [word for word in words if word not in set(stopwords.words('english'))]

  # Lemmatizing the words
  lemmatized_words = [wnl.lemmatize(word) for word in filtered_words]

  # Joining the lemmatized words
  message = ' '.join(lemmatized_words)

  # Building a corpus of messages
  corpus.append(message)

Посмотрим на тексты после чистки

Шаг 6. Векторизация

В НЛП очищенные данные необходимо преобразовать в числовой формат, в котором каждое слово представлено матрицей. Это также известно как встраивание слов или векторизация Word. мы будем использовать TfidfVectorizer () для векторизации предварительно обработанных данных.

#Changing text data in to numbers and Creating the Bag of Words model
tfidf = TfidfVectorizer(max_features=500)
vectors = tfidf.fit_transform(corpus).toarray()
feature_names = tfidf.get_feature_names()

#Let's have a look at our feature 
vectors.dtype

Теперь наш следующий шаг - начать обучение наших моделей машинного обучения.

Библиотеки, необходимые для построения и оценки моделей:

from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline    
from sklearn.naive_bayes import Multinomial
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
from sklearn.metrics import precision score, recall_score, plot_confusion_matrix, classification_report, accuracy_score, f1_score
from sklearn import metrics

Шаг 7. Построение и обучение моделей

мы собираемся использовать следующие шаги при построении модели:

  • Настройка функций и цели как X и Y
# Extracting independent and dependent variables from the dataset
X = pd.DataFrame(vectors, columns=feature_names)
y = sms_df['Target']
  • Разделение наборов для тестирования и обучения
# Splitting the testing and training sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
  • Постройте конвейер модели для четырех разных классификаторов.

Мы используем Наивный байесовский, RandomForestClassifier, DecisionTreeClassifier, Support Vector Machines

#Testing on the following classifiers
classifiers = [MultinomialNB(), 
               RandomForestClassifier(),
               DecisionTreeClassifier(), 
               SVC()]
for cls in classifiers:
    cls.fit(X_train, y_train)

# Dictionary of pipelines and model types for ease of reference
pipe_dict = {0: "NaiveBayes", 1: "RandomForest", 2: "DecisionTree",3: "SVC"}
  • Выполните перекрестную проверку обучающего набора для всех моделей на точность
# Cross-validation 
for i, model in enumerate(classifiers):
    cv_score = cross_val_score(model, X_train,y_train,scoring="accuracy", cv=10)
    print("%s: %f " % (pipe_dict[i], cv_score.mean()))

Итак, мы обучили модель, теперь мы будем оценивать производительность модели на данном тестовом наборе.

Шаг 8. Оценка модели

Теперь на этом этапе будет показано, как работает вся модель и какая модель хорошо работает с заданными данными. мы используем отчет о точности и матрицу неточностей для оценки модели

Давайте сначала взглянем на Отчет о точности

Отчет о точности показывает, что случайный лес и классификатор SVC получили почти одинаковые оценки.

Матрица путаницы

С помощью матрицы неточностей мы можем сказать, что SVC работает немного лучше, чем классификатор Random Forest по предоставленным данным.

Шаг 9. Развертывание модели на Heroku с помощью Flask

Развертывание модели машинного обучения означает предоставление доступа к модели конечным пользователям. Для развертывания любой обученной модели нам понадобится следующее:

  • Обученная модель: сохраните модель в файл для дальнейшей загрузки и использования веб-службой.
  • Веб-сервис: который дает цель для использования вашей модели на практике. Для нашей модели классификатора SMS-спама мы будем использовать Flask для разработки этой службы.
  • Поставщик облачных услуг: для этого проекта будет использоваться Heroku для развертывания.

Поскольку модель будет развернута, она сохраняется в файле pickle (model.pkl), созданном pickle, и этот файл будет отражен в папке вашего проекта.

Pickle - это модуль Python, который позволяет записывать объекты Python в файлы на диске и считывать их обратно в среду выполнения программы Python.

# Creating a pickle file for the CountVectorizer
pickle.dump(cv, open('cv-transform.pkl', 'wb'))
# Creating a pickle file 
filename = 'spam-sms-mnb-model.pkl'
pickle.dump(classifier, open(filename, 'wb'))
# loading
classifier = pickle.load(open(filename, 'rb'))
cv = pickle.load(open('cv-transform.pkl','rb'))

Создайте веб-страницу

Сначала создаст веб-страницу с использованием HTML и CSS, которая принимает ввод от пользователей (в данном случае текстовые сообщения) и показывает вывод (предсказывает сообщения как спам или любительские).

Вы можете найти код здесь.

Flask упрощает написание приложений, а также предоставляет множество вариантов для разработки веб-приложений.

Сначала нам нужно установить фреймворк.

pip install flask 

Создаст два файла, один с именем «app.py». Этот файл используется для запуска приложения и является движком этого приложения. Он содержит API, который получает ввод от пользователя и вычисляет прогнозируемое значение на основе модели.

И еще один файл с именем «sms_classifier_model.py», который содержит код для создания и обучения модели машинного обучения.

# Importing essential libraries
from flask import Flask, render_template, request
import pickle

Затем создадим приложение Flask.

app = Flask(__name__)

Загрузите рассол

classifier = pickle.load(open(filename, 'rb'))
cv = pickle.load(open('cv-transform.pkl','rb'))

Создайте маршрут приложения для рендеринга HTML-шаблона в качестве домашней страницы.

@app.route('/')
def home(): 
    return render_template('main.html')

Создайте API, который получает ввод от пользователя и вычисляет прогнозируемое значение на основе модели.

@app.route('/predict',methods=['POST'])
def predict():    
    if request.method == 'POST':     
        message = request.form['message']    
        data = [message]     
        vect = cv.transform(data).toarray()     
        my_prediction = classifier.predict(vect)     
    return render_template('result.html', prediction=my_prediction)

Теперь вызовите функцию запуска, чтобы запустить сервер Flask.

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

Это должно вернуть вывод, который показывает, что ваше приложение запущено. Просто скопируйте URL-адрес и вставьте его в свой браузер, чтобы протестировать приложение.

Шаг 10: Развертывание на Heroku

Heroku - это многоязычная платформа приложений, которая позволяет разработчикам развертывать свои приложения и управлять ими. Он гибкий и простой в использовании, предлагая разработчикам самый простой способ вывести свои приложения на рынок.

Сначала установите Heroku CLI, так как это упрощает создание приложений Heroku и управление ими прямо из терминала. Вы можете скачать его здесь.

Зарегистрируйтесь и войдите в Heroku. Создайте файл «Procfile» и «require.txt», который обрабатывает часть конфигурации для развертывания модели на сервере Heroku.

Следуйте приведенной ниже команде, чтобы создать Procfile:

web: gunicorn app:app

Файл требований состоит из зависимостей проекта, и для установки используйте команду, указанную ниже:

pip install -r requirements.txt

Затем зафиксируйте свой код на GitHub и подключите GitHub к Heroku.

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

Как только модель будет успешно развернута на сервере, ваше приложение будет создано, и вы получите URL-адрес.

Это ссылка на мое веб-приложение : https://sms-spam-predictor-nlp.herokuapp.com/

Заключение

Итак, мы успешно создали веб-приложение классификатора SMS-спама.

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

Для этого проекта вы можете обратиться к моему репозиторию GitHub.

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

Надеюсь, кому-то это пригодится.

Спасибо!