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

Полтора года назад я случайно наткнулся на Python и Anaconda в качестве инструмента для Data Science (DS) во время участия в Data Hackathon. Множество библиотек Python подчеркивают универсальность Python как инструментария для науки о данных. К сожалению, тогда у меня не было необходимого набора навыков для использования Python. С тех пор я прошел онлайн-курсы по Python и SQL, и постепенно у меня появился интерес к области DS. Стремясь ускорить переход на DS, я записался на программу Data Science Immersive (DSI) от General Assembly. DSI - это трехмесячный интенсивный учебный лагерь, направленный на обучение студентов базовым знаниям и навыкам в области науки о данных посредством экспериментального обучения по серии проектов. В этой статье я, как новичок в DS, надеюсь поделиться некоторыми полезными моментами в моем проекте, посвященном классификации террористических бомбардировок, с помощью мотивирующего (информационного) текста.

  • Планирование имеет значение, но также имеет значение гибкость. В случае с Capstone мы можем сами выбрать тему по своему усмотрению. Однако, хотя мы предлагаем наш первоначальный выбор темы и постановки проблемы, то, что может быть не сразу очевидно, так это то, что тема как проект DS должна поддерживаться наличием данных . Набор данных для моего первоначального выбора будет недоступен до недели спустя (соревнование Kaggle). Прислушиваясь к указаниям своего инструктора, я исследовал UCI и репозитории данных Kaggle, прежде чем выбрать Global Terrorism Dataset (GTD) на Kaggle. Я выбрал эту тему, потому что 1) я хотел пересмотреть методы НЛП, делая что-то немного другое, и 2) исследовать потенциал скрытого распределения Дирихле (LDA); моделирование тем НЛП без учителя в качестве обучающего материала для классификации.
  • Попробуйте вести обзор рабочего процесса моделирования. Визуализация рабочего процесса моделирования помогает в организации проекта и обеспечивает согласованность в реализации проекта. Это тем более важно, когда вы пытаетесь найти баланс между осмыслением сложных тем и работой над краеугольным камнем среди других задач. Это также помогло сэкономить драгоценное время при переводе мыслительного процесса на подходы машинного обучения. в формате, удобном для общения с преподавателями и одноклассниками. Сэкономленное время было использовано при развертывании модели, которое также преподнесло много сюрпризов и возможностей для обучения. Благодаря рабочему процессу моделирования это также помогло выделить время для пересмотра предыдущих методов и опробования новых вещей (например, анимации, маскирования изображений, тематической модели, развертывания модели). Давайте углубимся в технические детали!

Набор данных и исследовательский анализ данных (EDA)

На Kaggle доступно несколько наборов данных, касающихся глобального терроризма. Для Capstone я использовал набор данных за период с 1970 по 2017 год. Из-за размера набора данных я использовал Git Large File Storage для управления отправкой файлов в Github. Набор данных закодирован в формате ISO-8859–1, который необходимо указать для чтения файла. К счастью, это одна из немногих тем, обсуждаемых на Kaggle. Однако что, если кто-то встречает другой формат, но не уверен в его кодировке? Этот подход Агнесе Пойкане-Пучок должен пригодиться. Набор данных содержит 181 691 запись и 135 переменных, описывающих детали конкретного террористического акта. Поскольку это проект НЛП, главная особенность, представляющая интерес, - это мотивный текст, который описывает контекст, преступника, цели и источник информации для любого террористического инцидента. Я использовал spaCy для визуализации распознаваемых сущностей и структуры фраз в текстах мотивов. Последовательность формулировок помогает укрепить уверенность в использовании их в качестве входных данных для классификации текста. Это также продемонстрировало важность хорошего качества данных. Тем не менее, поскольку мотивный текст - это функция, введенная после 1997 года, только 32 521 запись содержит адекватные текстовые данные для классификации текста после очистки данных.

Другие переменные, используемые в EDA, помогли понять глобальные тенденции терроризма от наиболее активных групп до наиболее предпочитаемых форм нападений и основных мотивов террористических групп. Другие визуализации и обоснование выбора переменных для EDA можно найти здесь (README: p03_dataclean_ed, Jupyter notebook: P5.0 Data Cleaning, EDA, Feature engineering.ipynb). Некоторые визуальные элементы, которые непосредственно связаны с проектированием функций для классификации текста, извлечены для иллюстрации здесь.

Вдохновленный работой Ганса Рослинга, я исследовал использование анимации как средства визуализации террористических актов как с пространственной, так и с временной точки зрения. Изначально я использовал ImageMagick для создания .gif, но не смог устранить техническую проблему (сгенерированный файл .gif самоуничтожается) и, следовательно, откатился на стороннее программное обеспечение для файла .gif. Визуализируя соотношение различных режимов атаки на протяжении многих лет, бомбардировка остается излюбленной формой атаки, составляя ~ 50% от всех режимов атаки.

Оценка модели подготовки данных и классификатора текста (часть 1)

Я бы построил модель классификатора, которая принимает мотивирующий текст в качестве входных данных и выводит двоичную классификацию (атака с применением бомбы или небомбовая атака). Я выделил спланированные бомбардировки как положительный класс, а все другие атаки как отрицательный. Класс относительно сбалансирован с бомбардировками на 48%. Данные делятся на 80–20 на данные обучения / тестирования. Затем данные поезда делятся на 80–20 на поезда и проверяют подмножества. Что касается моделей классификаторов, я исследовал модели логистической регрессии и наивного Байеса. Результаты (основанные на наборе данных проверки (удержания)) приведены ниже. Модель логистической регрессии - это более эффективная модель, основанная на чувствительности (цель состоит в том, чтобы уменьшить ложноотрицательные результаты, которые предсказываются небомбардировочными атаками, когда они являются фактическими бомбардировками) и ROC AUC.

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

Тематическое моделирование

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

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

LDA - это метод тематического моделирования. Хотя он полезен для выявления кластеров слов (тем) из документов, он не был интегрирован с моделью классификатора текста. Обзор и ручная маркировка данных для тематической классификации невозможны из-за набора данных. Кроме того, у меня нет необходимых знаний в предметной области, чтобы определить потенциальную тему, к которой может принадлежать конкретный террористический инцидент, на основе текста мотива.

Выходные данные LDA как входные данные для задачи классификации

Статья Марка Келечавы об использовании тематических моделей LDA в качестве входных данных для модели классификации послужила источником вдохновения и предоставила ценную информацию о том, как можно интегрировать тематические модели в модель классификатора текста. За каждым набором слов для темы стоит вероятностное распределение тем из каждой записи мотивированного текста. Если модель, обученная распределению тем, может обобщать невидимые данные, мы можем сделать вывод, что модель определила кластеры тем (лежащие в основе мотивы в этом контексте), которые остаются применимыми к новым невидимым данным.

Вот мои шаги:

  1. Тематическое моделирование с использованием набора данных Train.
  2. Найдите оптимальное количество тем на основе оценки когерентности.
  3. Обучите модель LDA на данных поезда. Распределения вероятностей тем (TPD) затем используются в качестве векторов признаков в модели логистической регрессии для бинарной классификации (атаки с использованием бомбы или атаки без использования бомбы) в наборе данных проверки (удержания).
  4. Используйте обученную модель LDA для получения TPD из тестовых данных.
  5. Запустите модель логистической регрессии на TPD, чтобы увидеть, обобщает ли модель.

Один из ключевых шагов заключается в извлечении векторов признаков для тем. В моем случае оптимальное количество тем - 41.

# Make train Vectors
train_vecs = []
for i in range(len(X_train)):
    top_topics = lda_train.get_document_topics(traincorpus[i], minimum_probability=0.0)
    topic_vec = [top_topics[i][1] for i in range(41)]
    train_vecs.append(topic_vec)

Модель обобщает более высокую чувствительность и ROC AUC на тестовом наборе данных! Следующим вопросом, естественно, будет: «Какова будет производительность модели, если объединить токены из CountVectorizer и TPD из LDA?»

Оценка модели текстового классификатора (Часть 2)

Поскольку вывод CountVectorizer представляет собой разреженную матрицу счетчиков токенов, необходимо выполнить некоторое преобразование, чтобы включить объединение вывода LDA. Есть много способов сделать это. Вот что я сделал:

# Convert sparse matrix to dense
X_tr_dense = X_train_cleancv.toarray()
X_ts_dense = X_test_cleancv.toarray()
# add numpy array (train and test topic model vectors to dense matrix)
X_tr_dense_tm = np.concatenate((X_tr_dense,X_tr_vec),axis=1)
X_ts_dense_tm = np.concatenate((X_ts_dense,X_ts_vec),axis=1)
from scipy.sparse import csr_matrix
# Convert back to sparse matrix for modeling
X_tr_sparse = csr_matrix(X_tr_dense_tm)
X_ts_sparse = csr_matrix(X_ts_dense_tm)

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

Развертывание модели

Прислушиваясь к советам инструкторов попробовать развернуть модель, я сразу же взялся за нее. Развертывание модели может быть одновременно увлекательным предприятием и непростым делом, особенно для такого новичка, как я. Для развертывания модели я использовал Heroku. Это платформа как услуга (PaaS), которая позволяет разработчикам создавать, запускать и управлять приложениями в облаке. Пошаговое руководство, приведенное ниже, описывает некоторые из открытий, сделанных мной в процессе обучения. Надеюсь, это пригодится тем, кто хочет развернуть свои модели. Следуйте инструкциям и адаптируйте код в соответствии с потребностями вашего собственного проекта.

Что необходимо заранее

  1. Установите Git (если у вас еще нет; скорее всего, он уже установлен)
  2. Установите Интерфейс командной строки Heroku
  3. Создайте учетную запись Heroku
  4. html для вашей модели (проектирование может занять значительное время, поэтому можно сначала сделать это заранее). Примечание. Я назвал ее index.html

Подумайте, как вы хотите, чтобы развернутая модель работала. В моем заключительном камне модель классификатора принимает список очищенного текста с удаленными настраиваемыми игнорируемыми словами. Под руководством инструктора я выбираю CountVectorizer, настраиваемые стоп-слова и производственную модель. В Jupyter:

import pickle
# save model to disk 
filename1 = 'finalized_model.sav'
pickle.dump(model_lr2, open(filename1, 'wb'))
filename2 = 'finalized_cv.sav'
pickle.dump(cv2, open(filename2, 'wb'))
filename3 = 'finalized_stopwords.sav'
pickle.dump(s_words2, open(filename3, 'wb'))

Настроить виртуальную среду

Для размещения вашего приложения (модели, которую вы хотите развернуть) вам также понадобятся flask и virtualenv. Установите их с помощью Anaconda Navigator или командной строки Anaconda. Затем настройте пространство каталога проекта для локального размещения проекта в первую очередь. В моем случае у меня уже был главный каталог для хранения различных проектов, поэтому коды немного отличаются. Для нужд своего проекта я создал виртуальную среду и назвал ее capstone. В подсказке Anaconda:

cd virtualenvs
virtualenv capstone
# activate env from Scripts folder
cd Scripts
activate.bat
# to deactivate
deactivate.bat

Установите gunicorn (для Heroku), заморозьте модули python для вашей среды следующим образом:

pip install gunicorn
pip freeze >> requirements.txt

В зависимости от потребностей проекта можно подумать о настройке списка требований. Поскольку я не использовал большинство модулей, я вручную обрезал пакеты (чтобы сократить время развертывания на последующих этапах). За подробностями обращайтесь к файлу requirements.txt на Github.

Создайте файл nltk.txt в корневой папке, заполните его используемыми модулями nltk. Это для использования Heroku-python nltk.

Скрипт Flask

Создайте папку под названием templates для хранения HTML-формы.

mkdir templates

Переместите index.html в эту папку. Скопируйте файлы pickle в корневой каталог папки virtualenv проекта (т.е. capstone), в дальнейшем называемый корневым каталогом.

Скрипт Python

Создайте скрипты Python в корневом каталоге. Эти сценарии зависят от вашей модели и функционального потока. Дополнительные сведения см. В Requiredfn.py и service.py (где я храню модель приложения) на Github. .

Локальное прототипирование

Чтобы запустить службу, в Anaconda Prompt последовательно введите следующее. URL-адрес должен отображаться, где можно получить доступ к веб-странице и настроить веб-страницу по мере необходимости в режиме реального времени.

SET FLASK_APP=service.py
SET FLASK_DEBUG=1
flask run

Heroku

Создайте Procfile в корневом каталоге (без расширений!). Procfile нужна только одна строка. filename - это имя скрипта Python, который содержит приложение flask с именем app.

# Within Procfile
web: gunicorn <filename>:<main method name>
# filename refers to the python script containing flask application with flask name app
# app = Flask(__name__)
# In this instance the line is
web: gunicorn service:app

Войдите в Heroku, создайте приложение и разверните его, используя Anaconda Prompt.

heroku login
heroku create
# two url returned will be returned, the latter is the Heroku git remote repo where the application lives # on Heroku. The former is the web url where the application will be once deployed.
git add .
git commit -m"message"
git push heroku master
# Ensure at least one instance of application is running
heroku ps:scale web=1
# Say hello to your application!
heroku open

Предостережения

Развернутая в настоящее время модель является упрощенной в том смысле, что она принимает только один ввод (текст мотива). В реальных операциях не ожидается, что классификация интеллекта полностью соответствует модели. В качестве исходных данных для развернутой модели я использовал одинаковое сочетание текстов мотивов, относящихся как к бомбовым, так и к небомбардировочным атакам. Пожалуйста, зайдите на этот сайт, чтобы попробовать. Некоторые могут задаться вопросом, почему бы не создать пространство для ввода данных пользователем? Два соображения: 1) текущая настройка модели позволяет связывать записи с фактами, и 2) учитывая чувствительность предмета, я бы хотел избежать геймификации.

Подведение итогов и дальнейшая работа

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

  • Изучите влияние дополнительных функций на производительность модели (пространственные и временные аспекты проектирования функций, такие как атаки по регионам, атаки по десятилетиям).
  • Изучите использование TFIDFVectorizer и spaCy. Подобно CountVectorizer, TFIDFVectorizer подсчитывает частоту слов, но обратно пропорционален частоте слова в корпусе (коллекции документов).
  • Разверните до мультиклассовых классификаций.

Мыслительный процесс по выбору основной темы для кода для Capstone и материалов для развертывания модели размещен на моем GitHub здесь.

Спасибо за чтение!

Afternote (5Jul2020): Я осознаю, что сгенерированный .gif немного мал и труден для чтения, и я пытаюсь найти способ сохранить размер разрешения сгенерированного .gif (анимации карты мира). Если у вас есть идея сделать это, оцените, если вы можете предложить способ сделать это. Спасибо.