Машинное обучение, Программирование, Python

Мультиклассовая классификация текста с использованием PySpark, MLlib и Doc2Vec

Как использовать Apache Spark MLlib с PySpark для проблем NLP и как моделировать Doc2Vec в Spark MLlib

Apache Spark сегодня довольно популярен для масштабирования любого приложения для обработки данных. Для машинного обучения также имеется библиотека под названием MLlib. Это подход распределенного программирования для решения проблем машинного обучения. В этой статье мы увидим, как интегрировать MLlib с PySpark, а также методы использования Doc2Vec с PySpark для решения проблем классификации текста.

Прежде чем продолжить, нам нужно знать, что такое Doc2Vec. Это модель НЛП для описания текста или документа. Он преобразует текст в вектор числовых функций, который будет использоваться в любом алгоритме машинного обучения. По сути, это техника разработки функций. Он пытается понять контекст документов путем случайной выборки слов и обучает им нейронную сеть. Векторы скрытого слоя нейронной сети становятся векторами документов, также известными как «Doc2Vec». Существует еще один метод, называемый Word2Vec, который также работает по аналогичным принципам. Но вместо документов / текстов он работает с корпусом слов и предоставляет векторы для слов. Для получения дополнительных сведений о «Doc2Vec» и «Word2Vec» следующие ресурсы будут полезны:

Настройка PySpark

Для этой статьи требуется локальная установка PySpark. Мы будем использовать PySpark 2.4.3 и Python 2.7 по соображениям совместимости и установим достаточно памяти для этого приложения. Мы можем добиться этого, как показано ниже:

Теперь мы можем видеть этот искровой объект

spark

Исследование данных и постановка проблемы

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

Давайте сначала посмотрим, что есть в наборе данных!

Общее количество записей

total_df.count()

Отображение набора данных

total_df.show()

Как мы видим, набор данных содержит некоторые ненужные тексты, такие как «### abstract ###» и «### Introduction ###». Эти тексты - не что иное, как комментарии к этим файлам. Этот набор данных еще не разделен на отдельные столбцы «метка» и «содержание», что очень часто встречается при проблемах с классификацией. Итак, это нужно очистить и разделить на соответствующие столбцы для дальнейшей обработки.

Посмотрим, как мы можем это сделать.

input_df = input_rdd.toDF()
input_df.show()

«_1» - это ярлык, а «_2» - это фактический текст нашей проблемы. Теперь мы можем использовать этот набор данных для дальнейшей обработки и реального решения проблем.

Давайте посмотрим, сколько разных категорий существует для предложений, т.е. сколько разных значений в столбце «_1».

input_df.groupBy('_1').count().show()

Итак, всего существует 5 различных классов / категорий, и это проблема классификации текста с 5 классами.

Базовая очистка текста

Перед тем, как перейти к обработке «Doc2Vec», необходимо выполнить базовую очистку текста. Типичная очистка текста включает следующие шаги

  1. Преобразование в нижний регистр
  2. Удаление знаков препинания
  3. Удаление целых чисел, чисел
  4. Удаление лишних пробелов
  5. Удаление тегов (например, ‹html›, ‹p› и т. Д.)
  6. Удаление стоп-слов (например, "и", "к", "то" и т. Д.)
  7. Stemming (преобразование слов в корневую форму)

Мы будем использовать библиотеку Python «gensim» для очистки всего текста.

Давайте посмотрим на содержание конкретного предложения и как с ним работает функция clean_text.

input_rdd.take(1)[0][1]

clean_text(input_rdd.take(1)[0])[1]

Хотя «очищенное» предложение больше не является грамматически правильным, оно все же содержит контекст, который очень важен для обработки «Doc2Vec».

Теперь давайте посмотрим, как мы можем использовать эту функцию в PySpark для очистки всех предложений

cleaned_rdd = input_rdd.map(lambda x : clean_text(x))
cleaned_df = cleaned_rdd.toDF()
cleaned_df.show()

Конвейер машинного обучения

А теперь пора заняться реальной работой. На данный момент Apache Spark не предоставляет API для Doc2Vec. Но в нем есть трансформатор Word2Vec. Он основан на подходе Skip-Gram. Согласно документации Apache Spark:

Word2VecModel преобразует каждый документ в вектор, используя среднее значение всех слов в документе

Скажем, для нашего варианта использования одно предложение состоит из 5 слов. Затем, например, типичный Word2Vec преобразует каждое слово в вектор признаков размером 100. В этом случае представление Doc2Vec будет средним для всех этих 100 векторов длины, и его длина также будет равна 100. Это упрощенная схема «усреднения» модели «Doc2Vec». Мы будем использовать эту усредненную схему «Word2Vec» Apache Spark в качестве нашей модели «Doc2Vec».

Наш конвейер машинного обучения будет состоять из двух этапов.

  1. Токенизатор
  2. Модель Word2Vec.

Для этого воспользуемся Apache Spark Pipeline API.

Напечатаем содержимое Doc2Vec

doc2vecs_df.show()

Столбец «features» - это фактические плотные векторы «Doc2Vec». Мы использовали Doc2Vec размера 300. Обычно предпочтительный размер составляет от 100 до 300.

Модельное обучение и оценка

Следующим шагом будет включение этих функций «Doc2Vec» в модель классификатора. Мы попробуем с моделью RandomForest & LogisticRegression.

Нам нужно разделить данные на обучающий и тестовый набор и оценить точность модели.

w2v_train_df, w2v_test_df = doc2vecs_df.randomSplit([0.8, 0.2])

Модель RandomForest

Spark MLlib не понимает типичных категориальных переменных. Для этого наши метки классов (столбец _1) должны быть преобразованы в индексы. API StringIndexer делает это за нас.

Здесь также мы должны построить конвейер со следующими этапами

  1. StringIndexer (input = ‘_1’, output = ‘label’)
  2. Классификатор RandomForest (label column = «label», features column = «features». Этот «features» взят из преобразования «Doc2Vec»)
accuracy = rf_model_evaluator.evaluate(rf_predictions)
print("Accuracy = %g" % (accuracy))

Модель логистической регрессии

Для LogisticRegression также применимы те же стадии конвейера.

accuracy = lr_model_evaluator.evaluate(lr_predictions)
print("Accuracy = %g" % (accuracy))

Мы видим, что с точки зрения точности оба классификатора более или менее одинаковы. Точность можно дополнительно повысить, настроив «гиперпараметр» и изменив классификатор. Это выходит за рамки данной статьи. Читатели этой статьи могут попробовать это самостоятельно.

Это подводит нас к концу. Мы узнали, как использовать Spark MLlib с PySpark, моделировать Doc2Vec, строить конвейеры.

Jupyter Notebook с этой статьей можно найти на Github. Мы будем очень благодарны за любые отзывы.

Недавно я написал книгу по ML (https://twitter.com/bpbonline/status/1256146448346988546)