Обработка естественного языка (Natural Language Processing, NLP) является перспективным направлением Data Science и Big Data. Сегодня мы расскажем вам о применении методов NLP в PySpark. В этой статье вы узнаете об обычной токенизации и на основе регулярных выражений, стоп-словах русского и английского языков, а также о N-граммах в PySpark.
Токенизация в PySpark
Токенизация — это процесс разбиения текста на текстовые единицы (чаще всего слова). В PySpark за это отвечают Tokenizer и RegexTokenizer. Создадим DataFrame, который состоит из простых предложений, а также определим функцию (udf), которая будет считать количество слов в списке.
from pyspark.ml.feature import Tokenizer, RegexTokenizer
from pyspark.sql.functions import col, udf
from pyspark.sql.types import IntegerType
sentenceDataFrame = spark.createDataFrame([
(0, "Привет я слышал о NLP PySpark"),
(1, "Как же хочется попасть на Big Data курсы"),
(2, "Модели,линейной,регрессии,очень,хороши")
], ["id", "sentence"])
countTokens = udf(lambda words: len(words), IntegerType())
Tokenizer разбивает текст на слова, разделённые пробелом. Ниже код на Python это демонстрирует. Как видим, последнюю строку он посчитал за один токен, потому что в этом тексте нет пробелов.
tokenizer = Tokenizer(inputCol="sentence", outputCol="words")
tokenized = tokenizer.transform(sentenceDataFrame)
tokenized.select("sentence", "words")\
.withColumn("tokens", countTokens(col("words"))).show(truncate=False)
+-------------------------------------------------+------+
|words |tokens|
+-------------------------------------------------+------+
|[привет, я, слышал, о, nlp, pyspark] |6 |
|[как, же, хочется, попасть, на, big, data, курсы]|8 |
|[модели,линейной,регрессии,очень,хороши] |1 |
+-------------------------------------------------+------+
На практике лучше применять RegexTokenizer, который позволяет проводить токенизацию на основе регулярных выражений. Параметр pattern используется в качестве разделителя. По умолчанию pattern имеет значение "\\s+" (пробел), т.е. ничем не отличается от обычного Tokenizer. Но мы можем разбить текст на слова с учётом запятых:
regexTokenizer = RegexTokenizer(inputCol="sentence", outputCol="words", pattern=r"[,\s]")
regexTokenized = regexTokenizer.transform(sentenceDataFrame)
regexTokenized.select("sentence", "words") \
.withColumn("tokens", countTokens(col("words"))).show(truncate=False)
+-------------------------------------------------+------+
|words |tokens|
+-------------------------------------------------+------+
|[привет, я, слышал, о, nlp, pyspark] |6 |
|[как, же, хочется, попасть, на, big, data, курсы]|8 |
|[модели, линейной, регрессии, очень, хороши] |5 |
+-------------------------------------------------+------+
Следует, однако, быть острожным с регулярными выражениями, если работаете с кириллицей. Например, \W (не слово) найдёт не только знаки препинания и цифры, но и кириллические буквы.
Удаление стоп-слов
Многие алгоритмы Machine Learning очень чувствительны к шумам. В NLP к таким шумам относятся стоп-слова. Чаще всего это слова, которые не несут большой информативной нагрузки. В PySpark для удаления стоп-слов используется класс StopWordsRemover.
StopWordsRemover принимает список слов, а не строку (str), поэтому предварительно следует токенизировать текст, как это было описано выше. Вот так в Python выглядит удаление стоп-слов для английского языка:
from pyspark.ml.feature import StopWordsRemover
sentenceData = spark.createDataFrame([
(0, ["I", "saw", "the", "red", "balloon"]),
(1, ["Mary", "had", "a", "little", "lamb"])
], ["id", "raw"])
remover = StopWordsRemover(inputCol="raw", outputCol="filtered")
remover.transform(sentenceData).show()
+---+----------------------------+--------------------+
|id |raw |filtered |
+---+----------------------------+--------------------+
|0 |[I, saw, the, red, balloon] |[saw, red, balloon] |
|1 |[Mary, had, a, little, lamb]|[Mary, little, lamb]|
+---+----------------------------+--------------------+
Для русского языка в PySpark есть специальный список стоп-слов, доступный через loadDefaultStopWords(language). Например, для токенизированного выше текста на русском (regexTokenized) удаление стоп-слов выглядит следующим образом:
rus_stopwords = StopWordsRemover.loadDefaultStopWords("russian")
remover = StopWordsRemover(inputCol="words",
outputCol="filtered",
stopWords=rus_stopwords)
remover.transform(regexTokenized).show()
+-------------------------------------------------+--------------------------------------------+
|words |filtered |
+-------------------------------------------------+--------------------------------------------+
|[привет, я, слышал, о, nlp, pyspark] |[привет, слышал, nlp, pyspark] |
|[как, же, хочется, попасть, на, big, data, курсы]|[хочется, попасть, big, data, курсы] |
|[модели, линейной, регрессии, очень, хороши] |[модели, линейной, регрессии, очень, хороши]|
+-------------------------------------------------+--------------------------------------------+
Разбиение на N-граммы
Ещё один полезным инструментом NLP является разбиение слов на N-граммы — группы последовательных слов, которые можно извлечь из текстов. N-граммы позволяют сохранить контекст, поскольку становится известно, какое слово идёт следующим.
Для этого в PySpark используется Ngram, который принимает список слов, поэтому текст следует также предварительно следует токенизировать. Ngram не зависит от языка. Вот так в Python выглядит извлечение биграмм (би = 2):
from pyspark.ml.feature import NGram
wordDataFrame = spark.createDataFrame([
(0, ["Привет", "Я", "слышал", "о", "Spark"]),
(1, ["PySpark", "NLP", "это", "очень", "просто", "если", "подумать"]),
(2, ["Модели", "линейной", "регрессии", "просты"])
], ["id", "words"])
ngram = NGram(n=2, inputCol="words", outputCol="ngrams")
ngramDataFrame = ngram.transform(wordDataFrame)
ngramDataFrame.select("ngrams").show()
+---------------------------------------------------------------------------+
|ngrams |
+---------------------------------------------------------------------------+
|[Привет Я, Я слышал, слышал о, о Spark] |
|[PySpark NLP, NLP это, это очень, очень просто, просто если, если подумать]|
|[Модели линейной, линейной регрессии, регрессии просты] |
+---------------------------------------------------------------------------+
На этом примере видно, что «регрессия» теперь ассоциируется со словом «линейная».
О предобработке текстов в рамках NLP с помощью PySpark вы узнаете на специализированном курсе «NLP – обработка естественного языка с Python» в нашем лицензированном учебном центре обучения и повышения квалификации разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве.
Источники


