Первые шаги в Spark NLP: преобразование строковых данных

В прошлой статье мы говорили об установке Spark NLP на различные операционные системы, а теперь приступим уже к программированию. Сегодня затронем преобразование строковых данных в подходящий для Spark NLP тип данных. Читайте в этой статье: как преобразовать string в document и причем здесь DocumentAssembler, как очистить текст от переходов на следующую строку и табуляции.

Запускаем приложение с пакетом Spark NLP

Если вы прочитали предыдущую статью об установке Spark NLP на компьютер или Google Colab, то теперь можно спокойно заниматься написанием кода. Для запуска приложения Apache Spark необходимо вызывать функцию start:

import sparknlp

# Для обучения на GPU: sparknlp.start(gpu=True)
spark = sparknlp.start()

Данный код инициализирует приложение с установленными пакетами Spark NLP. Поскольку это обычное приложение Spark мы можем прочитать любой датасет. Для примера рассмотрим датасет c Kaggle c отзывами IMDB. Если вы работаете в Google Colab, то вот статья о том, как скачивать данные с Kaggle прямо с Колаба.

Итак, прочитаем датасет через Apache Spark:

df = spark.read.csv('IMDB Dataset.csv', header=True)
df.show()

# Первые строчки
+--------------------+--------------------+
|              review|           sentiment|
+--------------------+--------------------+
|One of the other ...|            positive|
|"A wonderful litt...| not only is it w...|
|"I thought this w...| but spirited you...|
|Basically there's...|            negative|
|"Petter Mattei's ...| power and succes...|
+--------------------+--------------------+

Взглянем теперь на схему данного датафрейма:

df.printSchema()

# Вывод:
root
 |-- review: string (nullable = true)
 |-- sentiment: string (nullable = true)

Как видим она состоит из двух столбцов строкового типа. Однако если вы планируете работать с Spark NLP, вам нужно преобразовать строковый тип, поскольку аннотаторы работают в первую очередь с собственным типом Document (есть еще другие, но этот основной). Для задачи преобразования типов понадобится Document Assembler.

Зачем нужен Document Assembler

Класс DocumentAssembler преобразует данные строкового типа в данные типа Document. Над данными этого типа мы можем производить операции Spark NLP. У класса DocumentAssembler есть основные методы:

  • setInputCol имя строкового столбца, который будет преобразован (в нашем датасете это столбец review);
  • setOutputCol (опциональный метод) имя создаваемого столбца в типе документа (по умолчанию document);
  • setCleanupMode (опциональный метод) очищает строки. Возможные значения:
    1. dissable: текст сохраняется в исходном виде. Стоит по умолчанию.
    2. inplace: удаляет переходы на следующие строки (“\n”) и табуляцию (“\t”).
    3. inplace_full: удаляет переходы на следующие строки и табуляцию, включая те, которые находятся внутри строк.
    4. shrink: удаляет переходы на следующие строки, табуляцию, а также объединяет несколько пробелов и пустые строки в один пробел.
    5. shrink_full: удаляет переходы на следующие строки, табуляцию, включая те, что внутри строк, а также объединяет несколько пробелов и пустые строки в один пробел.

Пример использования Document Assembler

Нам понадобится создать объект этого класса. В нашем датасете входящим столбцом для преобразования является столбец review. Также выберем параметр очистки shrink, т.е. удалим все '\n', '\t' и объединим идущие подряд пробелы в один. Код для преобразования строковых данных в Apache Spark выглядит следующим образом:

from sparknlp.base import DocumentAssembler

documentAssembler = DocumentAssembler() \
                   .setInputCol("review") \
                   .setCleanupMode("shrink")

doc_df = documentAssembler.transform(df)
doc_df.show(5)

# Первые пять строк:
+--------------------+--------------------+--------------------+
|              review|           sentiment|            document|
+--------------------+--------------------+--------------------+
|One of the other ...|            positive|[[document, 0, 17...|
|"A wonderful litt...| not only is it w...|[[document, 0, 43...|
|"I thought this w...| but spirited you...|[[document, 0, 72...|
|Basically there's...|            negative|[[document, 0, 74...|
|"Petter Mattei's ...| power and succes...|[[document, 0, 19...|
+--------------------+--------------------+--------------------+

Третий столбец как раз и является результатом преобразования DocumentAssembler. Взглянем на схему полученного DataFrame:

doc_df.printSchema()
root
 |-- review: string (nullable = true)
 |-- sentiment: string (nullable = true)
 |-- document: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- annotatorType: string (nullable = true)
 |    |    |-- begin: integer (nullable = false)
 |    |    |-- end: integer (nullable = false)
 |    |    |-- result: string (nullable = true)
 |    |    |-- metadata: map (nullable = true)
 |    |    |    |-- key: string
 |    |    |    |-- value: string (valueContainsNull = true)
 |    |    |-- embeddings: array (nullable = true)
 |    |    |    |-- element: float (containsNull = false)

Как вы можете заметить тип document имеет сложную структуру данных. Он является массивом, внутри которого лежат разные типы данных, в том числе и другие массивы, например, embeddings. Обращаться к каждому из элементов можно через dot-нотацию, т.е. через точку. Например, вот так выглядит обращению к элементу end (номер окончания текста):

doc_df.select('document.end').show(2)

# Результат:
+------+
|end   |
+------+
|[1760]|
|[432] |
+------+

Если требуется раскрыть документ и получить в отдельных столбцах его элементы, то используйте функцию Spark — explode. Пример разбития сложной структуры данных на отдельные столбцы в Apache Spark следующим образом:

import pyspark.sql.functions as F

doc_df.withColumn("tmp", F.explode("document")) \
    .select("tmp.*") \
    .show(5)

# Результат:
+-------------+-----+----+--------------------+---------------+----------+
|annotatorType|begin| end|              result|       metadata|embeddings|
+-------------+-----+----+--------------------+---------------+----------+
|     document|    0|1760|One of the other ...|[sentence -> 0]|        []|
|     document|    0| 432|"A wonderful litt...|[sentence -> 0]|        []|
|     document|    0| 723|"I thought this w...|[sentence -> 0]|        []|
|     document|    0| 747|Basically there's...|[sentence -> 0]|        []|
|     document|    0| 199|"Petter Mattei's ...|[sentence -> 0]|        []|
+-------------+-----+----+--------------------+---------------+----------+

Эту таблицу можете использовать только для наглядности, так как работа в Spark NLP осуществляется через тип Document.

Теперь с полученным датафреймом вы можете решать различные задачи: проводить лемматизацию, проверять на орфографию, создавать свои NLP-модели, получать векторные представления и всё, что доступно в Spark NLP. Также отметим, что если вы берете готовые конвейеры машинного обучения (Machine Learning), то проводить преобразование DocumentAssembler не нужно — они сами это сделают через метод transform.

 

О Machine Learining, подготовке данных, векторизации текстов на фреймворке Apache Spark с реальными примерами Data Science вы узнаете на специализированном курсе по «Машинное обучение в Apache Spark» в лицензированном учебном центре обучения и повышения квалификации разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве.

Записаться на курс

Смотреть раcписание

Источники
  1. https://nlp.johnsnowlabs.com/docs/en/transformers

Добавить комментарий

Поиск по сайту