Обработка естественного языка (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 в Москве.
Источники