В этой статье мы сделаем шаг вперед и исследуем словарный запас и сопоставление фраз с помощью библиотеки spaCy в Python. Мы определим шаблоны, а затем посмотрим, какие фразы соответствуют определенному нами шаблону. Это похоже на определение регулярных выражений, включающих части речи.
Соответствие на основе правил
Библиотека spaCy поставляется с инструментом Matcher, который можно использовать для определения пользовательских правил для сопоставления фраз. Процесс использования инструмента Matcher довольно прост.
Первое, что вам нужно сделать, это определить шаблоны, которые вы хотите сопоставить. Затем вам нужно добавить шаблоны в инструмент сопоставления и, наконец, вы должны применить инструмент сопоставления к документу, с которым вы хотите сопоставить свои правила. Лучше всего это пояснить на примере.
Для сопоставления на основе правил вам необходимо выполнить следующие шаги.
Создание объекта соответствия
Первым шагом является создание объекта сопоставления:
import spacy
nlp = spacy.load('en_core_web_sm')
from spacy.matcher import Matcher
m_tool = Matcher(nlp.vocab)
Определение шаблонов
Следующим шагом является определение шаблонов, которые будут использоваться для фильтрации похожих фраз. Предположим, мы хотим найти фразы «quickbrownfox», «quick-brown-fox», «qucik brown fox» или «quick brownfox». Для этого нам нужно создать следующие четыре шаблона:
p1 = [{'LOWER': 'quickbrownfox'}]
p2 = [{'LOWER': 'quick'}, {'IS_PUNCT': True}, {'LOWER': 'brown'}, {'IS_PUNCT': True}, {'LOWER': 'fox'}]
p3 = [{'LOWER': 'quick'}, {'LOWER': 'brown'}, {'LOWER': 'fox'}]
p4 = [{'LOWER': 'quick'}, {'LOWER': 'brownfox'}]
В приведенном выше сценарии:
- p1 ищет фразу «quickbrownfox»;
- p2 ищет фразу «quick-brown-fox»;
- p3 пытается найти «qucik brown fox»;
- p4 ищет фразу «quick brownfox».
Атрибут токена LOWER определяет, что фраза должна быть преобразована в нижний регистр перед сопоставлением.
Как только шаблоны определены, нам нужно добавить их к объекту Matcher, который мы создали ранее.
m_tool.add('QBF', None, p1, p2, p3, p4)
Здесь QBF – это имя нашего сопоставителя. Вы можете дать ему любое имя.
Применение Matcher к документу
Следующий шаг – применить сопоставление к текстовому документу и посмотреть, сможем ли мы найти какое-нибудь совпадение. Сначала создадим простой документ:
sentence = nlp(u'The quick-brown-fox jumps over the lazy dog. The quick brown fox eats well. \
the quickbrownfox is dead. the dog misses the quick brownfox')
Чтобы применить сопоставление к документу. Его необходимо передать в качестве параметра объекту сопоставления. Результатом будут все идентификаторы фраз, сопоставленных в документе, а также их начальная и конечная позиции в документе. Выполните следующий скрипт:
phrase_matches = m_tool(sentence) print(phrase_matches )
Результат выполнения скрипта выше выглядит следующим образом:
[(12825528024649263697, 1, 6), (12825528024649263697, 13, 16), (12825528024649263697, 21, 22), (12825528024649263697, 29, 31)]
Из вывода вы можете видеть, что найдено четыре фразы. Первое длинное число в каждом выводе – это идентификатор совпавшей фразы, второе и третье числа – это начальная и конечная позиции фразы.
Чтобы на самом деле лучше просмотреть результат, мы можем перебирать каждую совпавшую фразу и отображать ее строковое значение. Выполните следующий скрипт:
for match_id, start, end in phrase_matches:
string_id = nlp.vocab.strings[match_id]
span = sentence[start:end]
print(match_id, string_id, start, end, span.text)
Вывод:
12825528024649263697 QBF 1 6 quick-brown-fox 12825528024649263697 QBF 13 16 quick brown fox 12825528024649263697 QBF 21 22 quickbrownfox 12825528024649263697 QBF 29 31 quick brownfox
На выходе вы можете увидеть все совпавшие фразы вместе с их словарными идентификаторами, а также начальной и конечной позицией.
Дополнительные параметры
Официальная документация из библиотеки sPacy содержит подробную информацию обо всех токенах и подстановочных знаках, которые могут использоваться для сопоставления фраз.
Например, атрибут «*» определен для поиска одного или нескольких экземпляров токена.
Давайте напишем простой шаблон, который может идентифицировать фразу «quick — brown — fox».
Давайте сначала удалим предыдущее сопоставление QBF.
m_tool.remove('QBF')
Далее нам нужно определить наш новый паттерн:
p1 = [{'LOWER': 'quick'}, {'IS_PUNCT': True, 'OP':'*'}, {'LOWER': 'brown'}, {'IS_PUNCT': True, 'OP':'*'}, {'LOWER': 'fox'}]
m_tool.add('QBF', None, p1)
Шаблон p1 будет соответствовать всем фразам, в которых есть одна или несколько знаков препинания во фразе quick brown fox. Теперь давайте определим наш документ для фильтрации:
sentence = nlp(u'The quick--brown--fox jumps over the quick-brown---fox')
Вы можете видеть, что в нашем документе есть две фразы quick — brown — fox и quick-brown — fox, которые должны соответствовать нашему шаблону. Применим нашу матрицу к документу и посмотрим на результат:
phrase_matches = m_tool(sentence)
for match_id, start, end in phrase_matches:
string_id = nlp.vocab.strings[match_id]
span = sentence[start:end]
print(match_id, string_id, start, end, span.text)
Результат выполнения скрипта выше выглядит следующим образом:
12825528024649263697 QBF 1 6 quick--brown--fox 12825528024649263697 QBF 10 15 quick-brown---fox
Из вывода вы можете видеть, что наш сопоставитель успешно сопоставил две фразы.
Фразовое соответствие
В последнем разделе мы увидели, как мы можем определить правила, которые можно использовать для идентификации фраз из документа. Помимо определения правил, мы можем напрямую указать фразы, которые мы ищем. Это более эффективный способ сопоставления фраз.
В этом разделе мы будем выполнять сопоставление фраз в статье Википедии об искусственном интеллекте.
import bs4 as bs
import urllib.request
import re
import nltk
scrapped_data = urllib.request.urlopen('https://en.wikipedia.org/wiki/Artificial_intelligence')
article = scrapped_data .read()
parsed_article = bs.BeautifulSoup(article,'lxml')
paragraphs = parsed_article.find_all('p')
article_text = ""
for p in paragraphs:
article_text += p.text
processed_article = article_text.lower()
processed_article = re.sub('[^a-zA-Z]', ' ', processed_article )
processed_article = re.sub(r'\s+', ' ', processed_article)
Шаги по выполнению сопоставления фраз очень похожи на сопоставление на основе правил.
Как создать объект?
В качестве первого шага вам нужно создать PhraseMatcher объект. Это делает следующий скрипт:
import spacy
nlp = spacy.load('en_core_web_sm')
from spacy.matcher import PhraseMatcher
phrase_matcher = PhraseMatcher(nlp.vocab)
Обратите внимание, что в предыдущем разделе мы создали объект Matcher. В данном случае мы создаем объект PhraseMathcer.
Как создать список фраз?
На втором этапе вам нужно создать список фраз для сопоставления, а затем преобразовать этот список в документы spaCy NLP, как показано в следующем скрипте:
phrases = ['machine learning', 'robots', 'intelligent agents'] patterns = [nlp(text) for text in phrases]
Наконец, вам нужно добавить список фраз в средство сопоставления фраз.
phrase_matcher.add('AI', None, *patterns)
Здесь имя нашего сопоставителя – AI.
Применение Matcher к документу
Как и сопоставление на основе правил, нам снова нужно применить наш сопоставитель фраз к документу. Однако наша проанализированная статья не в формате документа spaCy. Поэтому мы преобразуем нашу статью в формат документа sPacy, а затем применим к статье наш сопоставитель фраз.
sentence = nlp (processed_article) matched_phrases = phrase_matcher(sentence)
На выходе у нас будут все идентификаторы всех совпавших фраз вместе с их начальным и конечным индексами в документе, как показано ниже:
[(5530044837203964789, 37, 39), (5530044837203964789, 402, 404), (5530044837203964789, 693, 694), (5530044837203964789, 1284, 1286), (5530044837203964789, 3059, 3061), (5530044837203964789, 3218, 3220), (5530044837203964789, 3753, 3754), (5530044837203964789, 5212, 5213), (5530044837203964789, 5287, 5288), (5530044837203964789, 6769, 6771), (5530044837203964789, 6781, 6783), (5530044837203964789, 7496, 7498), (5530044837203964789, 7635, 7637), (5530044837203964789, 8002, 8004), (5530044837203964789, 9461, 9462), (5530044837203964789, 9955, 9957), (5530044837203964789, 10784, 10785), (5530044837203964789, 11250, 11251), (5530044837203964789, 12290, 12291), (5530044837203964789, 12411, 12412), (5530044837203964789, 12455, 12456)]
Чтобы увидеть строковое значение совпадающих фраз, выполните следующий скрипт:
for match_id, start, end in matched_phrases:
string_id = nlp.vocab.strings[match_id]
span = sentence[start:end]
print(match_id, string_id, start, end, span.text)
В выводе вы увидите значение strig для совпадающих фраз, как показано ниже:
5530044837203964789 AI 37 39 intelligent agents 5530044837203964789 AI 402 404 machine learning 5530044837203964789 AI 693 694 robots 5530044837203964789 AI 1284 1286 machine learning 5530044837203964789 AI 3059 3061 intelligent agents 5530044837203964789 AI 3218 3220 machine learning 5530044837203964789 AI 3753 3754 robots 5530044837203964789 AI 5212 5213 robots 5530044837203964789 AI 5287 5288 robots 5530044837203964789 AI 6769 6771 machine learning 5530044837203964789 AI 6781 6783 machine learning 5530044837203964789 AI 7496 7498 machine learning 5530044837203964789 AI 7635 7637 machine learning 5530044837203964789 AI 8002 8004 machine learning 5530044837203964789 AI 9461 9462 robots 5530044837203964789 AI 9955 9957 machine learning 5530044837203964789 AI 10784 10785 robots 5530044837203964789 AI 11250 11251 robots 5530044837203964789 AI 12290 12291 robots 5530044837203964789 AI 12411 12412 robots 5530044837203964789 AI 12455 12456 robots
В выходных данных вы можете увидеть все три фразы, которые мы пытались найти, а также их начальный и конечный индексы и идентификаторы строк.
Стоп-слова
Прежде чем мы закончим эту статью, я просто хотел коснуться концепции стоп-слов. Стоп-слова – это английские слова, такие как «the», «a», «an» и т.д., которые сами по себе не имеют никакого значения. Стоп-слова часто не очень полезны для задач НЛП, таких как классификация текста или языковое моделирование. Поэтому часто лучше удалить эти стоп-слова перед дальнейшей обработкой документа.
Библиотека spaCy содержит 305 стоп-слов. Кроме того, в зависимости от наших требований, мы также можем добавлять или удалять стоп-слова из библиотеки spaCy.
Чтобы увидеть стоп-слова spaCy по умолчанию, мы можем использовать stop_words атрибут модели spaCy, как показано ниже:
import spacy
sp = spacy.load('en_core_web_sm')
print(sp.Defaults.stop_words)
На выходе вы увидите все стоп-слова sPacy:
{'less', 'except', 'top', 'me', 'three', 'fifteen', 'a', 'is', 'those', 'all', 'then', 'everyone', 'without', 'must', 'has', 'any', 'anyhow', 'keep', 'through', 'bottom', 'get', 'indeed', 'it', 'still', 'ten', 'whatever', 'doing', 'though', 'eight', 'various', 'myself', 'across', 'wherever', 'himself', 'always', 'thus', 'am', 'after', 'should', 'perhaps', 'at', 'down', 'own', 'rather', 'regarding', 'which', 'anywhere', 'whence', 'would', 'been', 'how', 'herself', 'now', 'might', 'please', 'behind', 'every', 'seems', 'alone', 'from', 'via', 'its', 'become', 'hers', 'there', 'front', 'whose', 'before', 'against', 'whereafter', 'up', 'whither', 'two', 'five', 'eleven', 'why', 'below', 'out', 'whereas', 'serious', 'six', 'give', 'also', 'became', 'his', 'anyway', 'none', 'again', 'onto', 'else', 'have', 'few', 'thereby', 'whoever', 'yet', 'part', 'just', 'afterwards', 'mostly', 'see', 'hereby', 'not', 'can', 'once', 'therefore', 'together', 'whom', 'elsewhere', 'beforehand', 'themselves', 'with', 'seem', 'many', 'upon', 'former', 'are', 'who', 'becoming', 'formerly', 'between', 'cannot', 'him', 'that', 'first', 'more', 'although', 'whenever', 'under', 'whereby', 'my', 'whereupon', 'anyone', 'toward', 'by', 'four', 'since', 'amongst', 'move', 'each', 'forty', 'somehow', 'as', 'besides', 'used', 'if', 'name', 'when', 'ever', 'however', 'otherwise', 'hundred', 'moreover', 'your', 'sometimes', 'the', 'empty', 'another', 'where', 'her', 'enough', 'quite', 'throughout', 'anything', 'she', 'and', 'does', 'above', 'within', 'show', 'in', 'this', 'back', 'made', 'nobody', 'off', 're', 'meanwhile', 'than', 'neither', 'twenty', 'call', 'you', 'next', 'thereupon', 'therein', 'go', 'or', 'seemed', 'such', 'latterly', 'already', 'mine', 'yourself', 'an', 'amount', 'hereupon', 'namely', 'same', 'their', 'of', 'yours', 'could', 'be', 'done', 'whole', 'seeming', 'someone', 'these', 'towards', 'among', 'becomes', 'per', 'thru', 'beyond', 'beside', 'both', 'latter', 'ours', 'well', 'make', 'nowhere', 'about', 'were', 'others', 'due', 'yourselves', 'unless', 'thereafter', 'even', 'too', 'most', 'everything', 'our', 'something', 'did', 'using', 'full', 'while', 'will', 'only', 'nor', 'often', 'side', 'being', 'least', 'over', 'some', 'along', 'was', 'very', 'on', 'into', 'nine', 'noone', 'several', 'i', 'one', 'third', 'herein', 'but', 'further', 'here', 'whether', 'because', 'either', 'hereafter', 'really', 'so', 'somewhere', 'we', 'nevertheless', 'last', 'had', 'they', 'thence', 'almost', 'ca', 'everywhere', 'itself', 'no', 'ourselves', 'may', 'wherein', 'take', 'around', 'never', 'them', 'to', 'until', 'do', 'what', 'say', 'twelve', 'nothing', 'during', 'sixty', 'sometime', 'us', 'fifty', 'much', 'for', 'other', 'hence', 'he', 'put'}
Вы также можете проверить, является ли слово стоп-словом или нет. Для этого вы можете использовать is_stop атрибут, как показано ниже:
sp.vocab['wonder'].is_stop
Так как «wonder» не является стоп-словом spaCy, в выходных данных вы увидите False. Для добавления или удаления в стоп — слова Spacy, вы можете использовать sp.Defaults.stop_words.add() и sp.Defaults.stop_words.remove() методы соответственно.
sp.Defaults.stop_words.add('wonder')
Затем нам нужно установить для is_stop тега wonder значение True, как показано ниже:
sp.vocab['wonder'].is_stop = True
Заключение
Сопоставление фраз и словарного запаса – одна из важнейших задач обработки естественного языка. В этой статье мы продолжили обсуждение того, как использовать Python для выполнения сопоставления на основе правил и фраз. Кроме того, мы видели стоп-слова spaCy.