Расширенное руководство по анализу НЛП с использованием Python и NLTK.
Узнайте глубже основополагающие концепции обработки естественного языка.
В своей предыдущей статье я представил обработку естественного языка (НЛП) и набор инструментов естественного языка (NLTK), набор инструментов НЛП, созданный в Пенсильванском университете. Я продемонстрировал, как анализировать текст и определять стоп-слова в Python, а также представил концепцию корпуса — набора текстовых данных, который помогает обрабатывать текст с готовыми данными. В этой статье я продолжу использовать наборы данных для сравнения и анализа естественного языка.
Основными строительными блоками, рассматриваемыми в этой статье, являются:
- WordNet и синсеты
- Сравнение сходства
- Дерево и древесный берег
- Распознавание названного объекта
WordNet и синсеты
WordNet — это большой корпус лексических баз данных в NLTK. WordNet поддерживает когнитивные синонимы (обычно называемые синсетами) слов, коррелирующих с существительными, глаголами, прилагательными, наречиями, синонимами, антонимами и многим другим.
WordNet — очень полезный инструмент для анализа текста. Он доступен на многих языках (китайском, английском, японском, русском, испанском и других) по множеству лицензий (от с открытым исходным кодом до коммерческих). Первый WordNet был создан Принстонским университетом для английского языка по лицензии MIT.
Слово обычно ассоциируется с несколькими синсетами в зависимости от его значения и частей речи. Каждый синсет обычно предоставляет следующие атрибуты:
Attribute | Definition | Example |
---|---|---|
Name | Name of the synset | Example: The word "code" has five synsets with names code.n.01 , code.n.02 , code.n.03 , code.v.01 , code.v.02 |
POS | Part of speech of the word for this synset | The word "code" has three synsets in noun form and two in verb form |
Definition | Definition of the word (in POS) | One of the definitions of "code" in verb form is: "(computer science) the symbolic arrangement of data or instructions in a computer program" |
Examples | Examples of word's use | One of the examples of "code": "We should encode the message for security reasons" |
Lemmas | Other word synsets this word+POC is related to (not strictly synonyms, but can be considered so); lemmas are related to other lemmas, not to words directly | Lemmas of code.v.02 (as in "convert ordinary language into code") are code.v.02.encipher , code.v.02.cipher , code.v.02.cypher , code.v.02.encrypt , code.v.02.inscribe , code.v.02.write_in_code |
Antonyms | Opposites | Antonym of lemma encode.v.01.encode is decode.v.01.decode |
Hypernym | A broad category that other words fall under | A hypernym of code.v.01 (as in "Code the pieces with numbers so that you can identify them later") is tag.v.01 |
Meronym | A word that is part of (or subordinate to) a broad category | A meronym of "computer" is "chip" |
Holonym | The relationship between a parent word and its subordinate parts | A hyponym of "window" is "computer screen" |
Существует несколько других атрибутов, которые вы можете найти в исходном файле nltk/corpus/reader/wordnet.py
в
.
Некоторый код может помочь этому иметь больше смысла.
Эта вспомогательная функция:
def synset_info(synset):
print("Name", synset.name())
print("POS:", synset.pos())
print("Definition:", synset.definition())
print("Examples:", synset.examples())
print("Lemmas:", synset.lemmas())
print("Antonyms:", [lemma.antonyms() for lemma in synset.lemmas() if len(lemma.antonyms()) > 0])
print("Hypernyms:", synset.hypernyms())
print("Instance Hypernyms:", synset.instance_hypernyms())
print("Part Holonyms:", synset.part_holonyms())
print("Part Meronyms:", synset.part_meronyms())
print()
synsets = wordnet.synsets('code')
показывает это:
5 synsets:
Name code.n.01
POS: n
Definition: a set of rules or principles or laws (especially written ones)
Examples: []
Lemmas: [Lemma('code.n.01.code'), Lemma('code.n.01.codification')]
Antonyms: []
Hypernyms: [Synset('written_communication.n.01')]
Instance Hpernyms: []
Part Holonyms: []
Part Meronyms: []
...
Name code.n.03
POS: n
Definition: (computer science) the symbolic arrangement of data or instructions in a computer program or the set of such instructions
Examples: []
Lemmas: [Lemma('code.n.03.code'), Lemma('code.n.03.computer_code')]
Antonyms: []
Hypernyms: [Synset('coding_system.n.01')]
Instance Hpernyms: []
Part Holonyms: []
Part Meronyms: []
...
Name code.v.02
POS: v
Definition: convert ordinary language into code
Examples: ['We should encode the message for security reasons']
Lemmas: [Lemma('code.v.02.code'), Lemma('code.v.02.encipher'), Lemma('code.v.02.cipher'), Lemma('code.v.02.cypher'), Lemma('code.v.02.encrypt'), Lemma('code.v.02.inscribe'), Lemma('code.v.02.write_in_code')]
Antonyms: []
Hypernyms: [Synset('encode.v.01')]
Instance Hpernyms: []
Part Holonyms: []
Part Meronyms: []
Синсеты и леммы имеют древовидную структуру, которую вы можете визуализировать:
def hypernyms(synset):
return synset.hypernyms()
synsets = wordnet.synsets('soccer')
for synset in synsets:
print(synset.name() + " tree:")
pprint(synset.tree(rel=hypernyms))
print()
code.n.01 tree:
[Synset('code.n.01'),
[Synset('written_communication.n.01'),
...
code.n.02 tree:
[Synset('code.n.02'),
[Synset('coding_system.n.01'),
...
code.n.03 tree:
[Synset('code.n.03'),
...
code.v.01 tree:
[Synset('code.v.01'),
[Synset('tag.v.01'),
...
code.v.02 tree:
[Synset('code.v.02'),
[Synset('encode.v.01'),
...
WordNet не охватывает все слова и информацию о них (сегодня в английском языке около 170 000 слов и около 155 000 в последней версии WordNet), но это хорошая отправная точка. Если после изучения концепций этого строительного блока вы обнаружите, что он не соответствует вашим потребностям, вы можете перейти на другой. Или вы можете создать свою собственную WordNet!
Попробуй сам
Используя библиотеки Python, загрузите страницу Википедии с открытым исходным кодом и перечислите синсеты и леммы всех слов.
Сравнение сходства
Сравнение сходства — это строительный блок, который определяет сходство между двумя частями текста. Он имеет множество приложений в поисковых системах, чат-ботах и т. д.
Например, связаны ли слова «футбол» и «футбол»?
syn1 = wordnet.synsets('football')
syn2 = wordnet.synsets('soccer')
# A word may have multiple synsets, so need to compare each synset of word1 with synset of word2
for s1 in syn1:
for s2 in syn2:
print("Path similarity of: ")
print(s1, '(', s1.pos(), ')', '[', s1.definition(), ']')
print(s2, '(', s2.pos(), ')', '[', s2.definition(), ']')
print(" is", s1.path_similarity(s2))
print()
Path similarity of:
Synset('football.n.01') ( n ) [ any of various games played with a ball (round or oval) in which two teams try to kick or carry or propel the ball into each other's goal ]
Synset('soccer.n.01') ( n ) [ a football game in which two teams of 11 players try to kick or head a ball into the opponents' goal ]
is 0.5
Path similarity of:
Synset('football.n.02') ( n ) [ the inflated oblong ball used in playing American football ]
Synset('soccer.n.01') ( n ) [ a football game in which two teams of 11 players try to kick or head a ball into the opponents' goal ]
is 0.05
Самый высокий показатель сходства слов составляет 0,5, что указывает на их тесное родство.
А как насчет «кода» и «ошибки»? Оценки сходства этих слов, используемых в информатике, составляют:
Path similarity of:
Synset('code.n.01') ( n ) [ a set of rules or principles or laws (especially written ones) ]
Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]
is 0.1111111111111111
...
Path similarity of:
Synset('code.n.02') ( n ) [ a coding system used for transmitting messages requiring brevity or secrecy ]
Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]
is 0.09090909090909091
...
Path similarity of:
Synset('code.n.03') ( n ) [ (computer science) the symbolic arrangement of data or instructions in a computer program or the set of such instructions ]
Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]
is 0.09090909090909091
Это самые высокие оценки сходства, что указывает на их родство.
NLTK предоставляет несколько показателей сходства, таких как:
- путь_сходство
- lch_similarity
- wup_similarity
- res_similarity
- jcn_similarity
- lin_similarity
См. раздел «Сходство» на странице «Интерфейс WordNet», чтобы определить подходящий для вашего приложения.
Попробуй сам
Используя библиотеки Python, начните со страницы «Категория Википедии: Списки компьютерных терминов» и подготовьте список терминологии, а затем посмотрите, как слова соотносятся.
Дерево и древесный берег
С помощью NLTK вы можете представить структуру текста в виде дерева, чтобы облегчить анализ текста.
Вот пример:
Простой текст, предварительно обработанный и помеченный частью речи (POS):
import nltk
text = "I love open source"
# Tokenize to words
words = nltk.tokenize.word_tokenize(text)
# POS tag the words
words_tagged = nltk.pos_tag(words)
Вы должны определить грамматику для преобразования текста в древовидную структуру. В этом примере используется простая грамматика, основанная на тегах Penn Treebank.
# A simple grammar to create tree
grammar = "NP: {<JJ><NN>}"
Далее используйте грамматику для создания дерева:
# Create tree
parser = nltk.RegexpParser(grammar)
tree = parser.parse(words_tagged)
pprint(tree)
Это производит:
Tree('S', [('I', 'PRP'), ('love', 'VBP'), Tree('NP', [('open', 'JJ'), ('source', 'NN')])])
Вы можете увидеть это лучше графически.
tree.draw()
(Гириш Манаголи, CC BY-SA 4.0)
Такая структура помогает правильно объяснить смысл текста. В качестве примера определите тему в этом тексте:
subject_tags = ["NN", "NNS", "NP", "NNP", "NNPS", "PRP", "PRP$"]
def subject(sentence_tree):
for tagged_word in sentence_tree:
# A crude logic for this case - first word with these tags is considered subject
if tagged_word[1] in subject_tags:
return tagged_word[0]
print("Subject:", subject(tree))
Это показывает, что «Я» является субъектом:
Subject: I
Это базовый строительный блок анализа текста, который применим к более крупным приложениям. Например, когда пользователь говорит: «Забронируйте рейс для моей мамы Джейн в Нью-Йорк из Лондона 1 января», чат-бот, использующий этот блок, может интерпретировать запрос как:
Действие: забронировать
Что: полет
Путешественник: Джейн
Из: Лондон
Куда: Нью-Йорк
Дата: 1 января (следующего года)
Банк деревьев относится к корпусу с предварительно размеченными деревьями. Для многих языков доступны открытые, условно бесплатные и коммерческие древовидные банки. Наиболее часто используемым для английского языка является Penn Treebank, взятый из Wall Street Journal, часть которого включена в NLTK. Некоторые способы использования древовидного банка:
words = nltk.corpus.treebank.words()
print(len(words), "words:")
print(words)
tagged_sents = nltk.corpus.treebank.tagged_sents()
print(len(tagged_sents), "sentences:")
print(tagged_sents)
100676 words:
['Pierre', 'Vinken', ',', '61', 'years', 'old', ',', ...]
3914 sentences:
[[('Pierre', 'NNP'), ('Vinken', 'NNP'), (',', ','), ('61', 'CD'), ('years', 'NNS'), ('old', 'JJ'), (',', ','), ('will', 'MD'), ('join', 'VB'), ('the', 'DT'), ('board', 'NN'), ('as', 'IN'), ('a', 'DT'), ('nonexecutive', 'JJ'), ('director', 'NN'), ...]
Смотрите теги в предложении:
sent0 = tagged_sents[0]
pprint(sent0)
[('Pierre', 'NNP'),
('Vinken', 'NNP'),
(',', ','),
('61', 'CD'),
('years', 'NNS'),
...
Создайте грамматику, чтобы преобразовать это в дерево:
grammar = '''
Subject: {<NNP><NNP>}
SubjectInfo: {<CD><NNS><JJ>}
Action: {<MD><VB>}
Object: {<DT><NN>}
Stopwords: {<IN><DT>}
ObjectInfo: {<JJ><NN>}
When: {<NNP><CD>}
'''
parser = nltk.RegexpParser(grammar)
tree = parser.parse(sent0)
print(tree)
(S
(Subject Pierre/NNP Vinken/NNP)
,/,
(SubjectInfo 61/CD years/NNS old/JJ)
,/,
(Action will/MD join/VB)
(Object the/DT board/NN)
as/IN
a/DT
(ObjectInfo nonexecutive/JJ director/NN)
(Subject Nov./NNP)
29/CD
./.)
Посмотрите это графически:
tree.draw()
(Гириш Манаголи, CC BY-SA 4.0)
Концепция деревьев и деревьев является мощным строительным блоком для анализа текста.
Попробуй сам
Используя библиотеки Python, скачайте страницу Википедии с открытым исходным кодом и представьте текст в презентабельном виде.
Распознавание названного объекта
Текст, устный или письменный, содержит важные данные. Одной из основных целей обработки текста является извлечение этих ключевых данных. Это необходимо практически во всех приложениях, таких как чат-бот авиакомпании, который бронирует билеты, или бот, отвечающий на вопросы. NLTK предоставляет для этого функцию распознавания именованных объектов.
Вот пример кода:
sentence = 'Peterson first suggested the name "open source" at Palo Alto, California'
Посмотрите, распознаются ли в этом предложении имя и место. Предварительная обработка как обычно:
import nltk
words = nltk.word_tokenize(sentence)
pos_tagged = nltk.pos_tag(words)
Запустите тегировщик именованных объектов:
ne_tagged = nltk.ne_chunk(pos_tagged)
print("NE tagged text:")
print(ne_tagged)
print()
NE tagged text:
(S
(PERSON Peterson/NNP)
first/RB
suggested/VBD
the/DT
name/NN
``/``
open/JJ
source/NN
''/''
at/IN
(FACILITY Palo/NNP Alto/NNP)
,/,
(GPE California/NNP))
Добавлены теги имен; извлеките из этого дерева только именованные объекты:
print("Recognized named entities:")
for ne in ne_tagged:
if hasattr(ne, "label"):
print(ne.label(), ne[0:])
Recognized named entities:
PERSON [('Peterson', 'NNP')]
FACILITY [('Palo', 'NNP'), ('Alto', 'NNP')]
GPE [('California', 'NNP')]
Посмотрите это графически:
ne_tagged.draw()
(Гириш Манаголи, CC BY-SA 4.0)
Встроенный тегировщик именованных объектов NLTK, используя программу автоматического извлечения контента (ACE) PENN, обнаруживает общие объекты, такие как ОРГАНИЗАЦИЯ, ЧЕЛОВЕК, МЕСТОПОЛОЖЕНИЕ, ОБЪЕКТ и GPE (геополитический объект).
NLTK может использовать другие теги, такие как Стэнфордский распознаватель именованных объектов. Этот обученный тегировщик построен на Java, но NLTK предоставляет интерфейс для работы с ним (см. nltk.parse.stanford или nltk.tag.stanford).
Попробуй сам
Используя библиотеки Python, загрузите страницу Википедии с открытым исходным кодом и определите людей, которые оказали влияние на открытый исходный код, а также где и когда они внесли свой вклад.
Продвинутое упражнение
Если вы к этому готовы, попробуйте построить эту надстройку, используя строительные блоки, обсуждаемые в этих статьях.
Используя библиотеки Python, загрузите страницу «Категория: Информатика» в Википедии и:
- Определите наиболее распространенные униграммы, биграммы и триграммы и опубликуйте их в виде списка ключевых слов или технологий, о которых студенты и инженеры должны знать в этой области.
- Графически покажите имена, технологии, даты и места, имеющие значение в этой области. Это может быть хорошая инфографика.
- Создайте поисковую систему. Ваша поисковая система работает лучше, чем поиск в Википедии?
Что дальше?
НЛП является квинтэссенцией создания приложений. NLTK — это классический, богатый и мощный набор, который предоставляет все необходимое для создания практически привлекательных и целенаправленных приложений для реального мира.
В этой серии статей я объяснил, что делает возможным НЛП, на примере НЛТК. НЛП и НЛТК могут предложить гораздо больше. Эта серия — отправная точка, которая поможет вам начать работу.
Если ваши потребности выходят за рамки возможностей NLTK, вы можете обучить новые модели или добавить к ним возможности. Появляются новые библиотеки НЛП, основанные на NLTK, а машинное обучение широко используется в языковой обработке.