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

Практикуйтесь в анализе текста в НЛП с помощью Python


Познакомьтесь с основополагающими концепциями обработки естественного языка.

Обработка естественного языка (НЛП) — это специализированная область анализа и создания человеческих языков. Человеческие языки, которые по праву называют естественными, очень контекстно-зависимы и часто неоднозначны, что позволяет создавать отчетливое значение. (Вспомните анекдот, где жена просит мужа «возьми пакет молока, а если у них есть яйца, возьми шесть», поэтому он получает шесть пакетов молока, потому что у них были яйца.) НЛП обеспечивает способность понимать вводимые данные на естественном языке и соответствующим образом производить вывод на естественном языке.

Компьютерная лингвистика (CL) — это более обширная область лингвистического понимания и моделирования. НЛП — это разновидность CL, которая занимается инженерными аспектами понимания и генерации языка. НЛП — это междисциплинарная область, которая затрагивает множество областей, включая искусственный интеллект (ИИ), машинное обучение (МО), глубокое обучение (ГО), математику и статистику.

Некоторые из приложений, которые вы можете создать с помощью НЛП, включают:

  • Машинный перевод. Поскольку в мире существует более 6000 языков, НЛП в сочетании с нейронным машинным переводом может облегчить перевод текста с одного языка на другой.
  • Чат-боты. Персональные помощники, такие как Alexa, Siri и Mycroft с открытым исходным кодом, сегодня прочно вошли в нашу жизнь. НЛП лежит в основе этих чат-ботов, помогая машинам анализировать, изучать и понимать речь, а также обеспечивать голосовой ответ.
  • Возможность голосового управления. NLP позволяет дружественно обслуживать клиентов в сфере здравоохранения, туризма, розничной торговли и других отраслях.
  • Анализ настроений. Компании всегда хотят держать руку на пульсе клиентов и принимать упреждающие меры, когда они чувствуют недовольство. НЛП делает это возможным.
  • Продуктивность работы с персоналом. Специалистам по кадрам приходится обрабатывать огромное количество документов, и NLP может использовать автоматизацию процесса документирования, чтобы частично облегчить эту нагрузку.

Строительные блоки НЛП

Подобно тому, как небоскреб строится по кирпичикам, вы можете создавать большие приложения, подобные приведенным выше, используя фундаментальные и важные строительные блоки НЛП.

Доступно несколько библиотек НЛП с открытым исходным кодом, таких как Stanford CoreNLP, spaCy и Genism на Python, Apache OpenNLP и GateNLP на Java и других языках.

Чтобы продемонстрировать функции строительных блоков НЛП, я буду использовать Python и его основную библиотеку НЛП Natural Language Toolkit (NLTK). НЛТК был создан в Пенсильванском университете. Это широко используемая и удобная отправная точка для знакомства с НЛП. Изучив его концепции, вы можете изучить другие библиотеки для создания своих приложений НЛП «небоскреба».

Основными строительными блоками, рассматриваемыми в этой статье, являются:

  • Токенизация в предложения и слова
  • Стоп-слова
  • словосочетания
  • Идентификация частей речи
  • Стемминг и лемматизация
  • Корпус

Настраивать

В этой статье предполагается, что вы знакомы с Python. После установки Python загрузите и установите NLTK:

pip install nltk

Затем установите данные NLTK:

python -m nltk.downloader popular

Если у вас много места для хранения и хорошая пропускная способность, вы также можете использовать python -m nltk.downloader all. Дополнительную информацию см. на странице установки NLTK.

Также имеется пользовательский интерфейс для выбора данных для загрузки, который можно запустить с помощью оболочки Python:

Python 3.8.2 ...
Type "help", ...

>>> import nltk
>>> nltk.download()

(Opensource.com, CC BY-SA 4.0)

Токенизировать предложения и слова

Первым шагом в анализе и обработке текста является разделение текста на предложения и слова — процесс, называемый токенизацией. Токенизация текста упрощает дальнейший анализ. Почти все приложения для анализа текста начинаются с этого шага.

Вот несколько примеров с этой строкой текста:

text = "Computers don't speak English. So, we've to learn C, C++, ,C#, Java, Python and the like! Yay!"

Токенизация предложения:

from nltk.tokenize import sent_tokenize
sentences = sent_tokenize(text)
print(len(sentences), 'sentences:', sentences)

Токенизация слов:

from nltk.tokenize import word_tokenize
words = word_tokenize(text)
print(len(words), 'words:', words)
29 word(s): ['Computers', 'do', "n't", 'speak', 'English', '.', 'So', ',', 'we', "'ve", 'to', 'learn', 'C', ',', 'C++', ',', ',', 'C', '#', ',', 'Java', ',', 'Python', 'and', 'the', 'like', '!', 'Yay', '!']

NLTK использует регулярные выражения для внутренней токенизации. Внимательный читатель может спросить, можно ли токенизировать без использования NLTK. Да, ты можешь. Однако NLTK хорошо спроектирован, учитывая все возможные варианты; например, что-то вроде nltk.org должно оставаться одним словом ['nltk.org'], а не ['nltk', 'org']:

text = "I love nltk.org"

Если вы токенизируете с помощью приведенного выше кода, nltk.org сохраняется как одно слово:

1 sentence(s): ['I love nltk.org']
3 word(s): ['I', 'love', 'nltk.org']

NLTK не предлагает возможности заменять такие сокращения, как «не» на «не делать» и «у нас» на «у нас есть», но библиотека pycontractions может помочь.

Попробуй сам

Используя библиотеки Python, загрузите страницу Википедии с открытым исходным кодом и токенизируйте текст.

Стоп-слова

В таком языке, как английский, много «пустых» слов (технически называемых «стоп-словами»), которые необходимы в устной и письменной речи, но не имеют ценности при анализе. NLTK может идентифицировать и удалять эти стоп-слова, чтобы помочь обработке текста сосредоточиться на необходимых словах.

См. слова, которые считаются стоп-словами:

from nltk.corpus import stopwords
stop_words = stopwords.words('english')
print(len(stop_words), "stopwords:", stop_words)
179 stopwords: ['i', 'me', 'my', 'myself', 'we', ..., "wouldn't"]

Сначала токенизируйте текст, затем отфильтруйте стоп-слова:

text = "Computers don't speak English. So, we've to learn C, C++, Java, Python and the like! Yay!"

from nltk.tokenize import word_tokenize
words = word_tokenize(text)

print(len(words), "in original text:", words)
25 words in original text: ['Computers', 'do', 'not', 'speak', 'English', '.', 'So', ',', 'we', 'have', 'to', 'learn', 'C', ',', 'C++', ',', 'Java', ',', 'Python', 'and', 'the', 'like', '!', 'Yay', '!']
words = [word for word in words if word not in stop_words]
print(len(words), "without stopwords:", words)
18 words without stopwords: ['Computers', 'speak', 'English', '.', 'So', ',', 'learn', 'C', ',', 'C++', ',', 'Java', ',', 'Python', 'like', '!', 'Yay', '!']

В тексте все еще есть знаки препинания, которые добавляют шума. Чтобы удалить их, используйте строковый класс Python. Некоторые знаки препинания важны, например, вопросительный знак. Этот метод можно использовать для удаления знаков препинания (без использования NLTK).

См. символы, которые считаются знаками препинания:

import string
punctuations = list(string.punctuation)
print(punctuations)
['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']

Удалить знаки препинания:

words = [word for word in words if word not in punctuations]
print(len(words), "words without stopwords and punctuations:", words)
11 words without stopwords and punctuations: ['Computers', 'speak', 'English', 'So', 'learn', 'C', 'C++', 'Java', 'Python', 'like', 'Yay']

Попробуй сам

Используя библиотеки Python, загрузите страницу Википедии с открытым исходным кодом и удалите стоп-слова. Какой процент страницы занимают стоп-слова?

словосочетания

Коллокация относится к двум (или более) словам, которые часто встречаются вместе. Коллокации помогают понять формирование текста, а также помогают в текстовом поиске и сравнении сходства.

Для этого примера используйте более длинный текстовый файл из Project Gutenburg. (Проект Гутенберг — это инициатива по оцифровке книг.)

Скачать текст:

# coding: utf-8

import urllib.request

# Download text and decode
# Note: Set proxy if behind a proxy (https://docs.python.org/2/library/urllib.html)
url = "http://www.gutenberg.org/files/1342/1342-0.txt"
text = urllib.request.urlopen(url).read().decode()
print(text)
The Project Gutenberg EBook of Pride and Prejudice, by Jane Austen
This eBook is for the use of anyone anywhere at no cost and with
...
      Chapter 1
      It is a truth universally acknowledged, that a single man in
      possession of a good fortune
...
      bringing her into Derbyshire, had been the means of
      uniting them.

Предварительная обработка (токенизация, удаление стоп-слов и удаление пунктуации):

# Tokenize
from nltk.tokenize import word_tokenize
text = word_tokenize(text)

# Remove stopwords
from nltk.corpus import stopwords
stops = stopwords.words('english')
# print(stops)
words = [word for word in text if word not in stops]

# Remove punctuations
import string
punctuations = list(string.punctuation)
# print(punctuations)

words = [word for word in words if word not in punctuations]
print("Without punctuations:", words)
Preprocessed: ['The', 'Project', 'Gutenberg', 'EBook', 'Pride', 'Prejudice', 'Jane', 'Austen', ...

Биграммы (два слова, которые встречаются вместе):

# Bigrams
from nltk.metrics import BigramAssocMeasures
from nltk.collocations import BigramCollocationFinder
bigram_collocation = BigramCollocationFinder.from_words(words)
# Top 10 most occurring collocations
print("Bigrams:", bigram_collocation.nbest(BigramAssocMeasures.likelihood_ratio, 10))
Bigrams: [('”', '“'), ('Mr.', 'Darcy'), ('Lady', 'Catherine'), ('”', 'said'), ('Mrs.', 'Bennet'), ('Mr.', 'Collins'), ('Project', 'Gutenberg-tm'), ('“', 'I'), ('Sir', 'William'), ('Miss', 'Bingley')]

Внимательный читатель может заметить, что символы двойных кавычек — «» (код 8220) и « (код 8221) — все еще встречаются в тексте после удаления пунктуации. string.punctuation не обнаруживает их, поскольку они отличаются от стандартной двойной кавычки « (кодовая точка 34). Чтобы их обработать, добавьте символы в список пунктуации.

Триграммы (три слова, которые появляются вместе):

# Trigrams
from nltk.collocations import TrigramCollocationFinder
from nltk.metrics import TrigramAssocMeasures
trigram_collocation = TrigramCollocationFinder.from_words(text)
# Top 10 most occurring collocations
print("Trigrams:", trigram_collocation.nbest(TrigramAssocMeasures.likelihood_ratio, 10))
Trigrams: [('late', 'Mr.', 'Darcy'), ('Mr.', 'Darcy', 'returned'), ('saw', 'Mr.', 'Darcy'), ('friend', 'Mr.', 'Darcy'), ('Mr.', 'Darcy', 'walked'), ('civility', 'Mr.', 'Darcy'), ('Mr.', 'Darcy', 'looked'), ('said', 'Mr.', 'Darcy'), ('surprised', 'Mr.', 'Darcy'), ('Mr.', 'Darcy', 'smiled')]

«Мистер Дарси» есть почти везде! Можно предположить, что он главный герой романа. Это пример извлечения информации с помощью НЛП.

Попробуй сам

Используя библиотеки Python, загрузите страницу Википедии с открытым исходным кодом. Можно предположить, что «открытый исходный код» — это наиболее часто встречающаяся биграмма, а «открытый исходный код» — наиболее распространенная триграмма. Посмотрим, сможете ли вы это подтвердить.

Идентификация частей речи

НЛТК имеет возможность определять части речи слов (POS). Определение POS необходимо, поскольку слово имеет разные значения в разных контекстах. Слово «код» как существительное могло означать «систему слов для целей секретности» или «программные инструкции», а как глагол оно могло означать «преобразовать сообщение в секретную форму» или «написать инструкции для компьютера». Знание контекста необходимо для правильного понимания текста.

Вот пример использования этого текста:

text = "Computers don't speak English. So, we've to learn C, C++, Java, Python and the like! Yay!"

Предварительно обработайте текст, как вы это делали ранее:

import nltk
from nltk.tokenize import word_tokenize

words = word_tokenize(text)

Определите теги POS:

pos_tagged_text = nltk.pos_tag(words)
print(pos_tagged_text)
[('Computers', 'NNS'), ('do', 'VBP'), ("n't", 'RB'), ('speak', 'VB'), ('English', 'NNP'), ('.', '.'), ('So', 'RB'), (',', ','), ('we', 'PRP'), ("'ve", 'VBP'), ('to', 'TO'), ('learn', 'VB'), ('C', 'NNP'), (',', ','), ('C++', 'NNP'), (',', ','), ('Java', 'NNP'), (',', ','), ('Python', 'NNP'), ('and', 'CC'), ('the', 'DT'), ('like', 'JJ'), ('!', '.'), ('Yay', 'NN'), ('!', '.')]

NNS, VBP и т. д. — это POS-коды, определенные Пенсильванским университетом, их также можно просмотреть программно:

nltk.help.upenn_tagset()
NNS: noun, common, plural
    undergraduates scotches bric-a-brac products bodyguards facets coasts
    divestitures storehouses designs clubs fragrances averages
    subjectivists apprehensions muses factory-jobs ...
VBP: verb, present tense, not 3rd person singular
    predominate wrap resort sue twist spill cure lengthen brush terminate
    appear tend stray glisten obtain comprise detest tease attract
    emphasize mold postpone sever return wag ...
...

Вы можете увидеть определение POS каждого слова в предложении:

for pos_tag_word in pos_tagged_text:
    print(pos_tag_word[0], ":")
    nltk.help.upenn_tagset(pos_tag_word[1])
Computers :
NNS: noun, common, plural
	...
do :
VBP: verb, present tense, not 3rd person singular
	...
n't :
RB: adverb
	...
speak :
VB: verb, base form
	...
English :
NNP: noun, proper, singular
	...
. :
.: sentence terminator

Попробуй сам

Используя библиотеки Python, загрузите страницу Википедии с открытым исходным кодом и определите POS всех слов в тексте.

Стемминг и лемматизация

Слова обычно изменяются (например, буквы с суффиксом, аффиксом и т. д.) для выражения их формы (например, множественного числа, времени и т. д.). Dog -> Dogs — пример флексии. Обычно слова необходимо сравнивать в их исходной форме для эффективного сопоставления текста.

Стемминг и лемматизация — это два метода преобразования слова в неизменяемую форму. Суть и стемминга, и лемматизации одна: привести слово к его наиболее естественной форме. Но они различаются тем, как они это делают.

  • Стемминг использует простой механизм, который удаляет или изменяет флексии для формирования корневого слова, однако корневое слово может не быть допустимым словом в языке.
  • Лемматизация также удаляет или изменяет флексии для формирования корневого слова, но корневое слово является допустимым словом в языке.

Лемматизация использует набор словных данных (называемый корпусом, обсуждаемый в следующем разделе) для получения корневых слов; следовательно, это медленнее, чем стеблевание. В некоторых случаях достаточно стемминга, а в других случаях требуется лемматизация.

В NLTK имеется несколько стеммеров и лемматизаторов (например, RegexpStemmer, LancasterStemmer, PorterStemmer, WordNetLemmatizer, RSLPStemmer и другие). Существует также множество встроенных стеммеров и лемматизаторов, которые вы можете выбрать (см. пакет nltk.stem).

Чтобы сравнить их, попробуйте PorterStemmer и WordNetLemmatizer.

Создайте экземпляр PorterStemmer:

import nltk
stemmer = nltk.stem.PorterStemmer()

Определите слово «здание»:

word = "building"
print("Stem of", word, stemmer.stem(word))
Stem of building : build

Стемминг не знает POS, поэтому слово «строительство» в форме существительного или глагола происходит от слова «строить».

Это не относится к лемматизации с использованием WordNetLemmatizer:

lemmatizer = nltk.stem.WordNetLemmatizer()
word = "building"
pos = 'n';
print("Lemmatization of", word, "(" , pos, "):", lemmatizer.lemmatize(word, pos))
pos = 'v';
print("Lemmatization of", word, "(" , pos, "):", lemmatizer.lemmatize(word, pos))
Lemmatization of building ( n ): building
Lemmatization of building ( v ): build

Лемматизация занимает больше времени (в данном примере немного, но заметно), чем стемминг.

Попробуй сам

Используя библиотеки Python, загрузите страницу Википедии с открытым исходным кодом, предварительно обработайте и преобразуйте текст в его исходные формы. Попробуйте это с различными модулями стемминга и лемматизации. Используйте модуль таймера Python для измерения их производительности.

Корпус

Корпус в NLTK — это набор текстовых данных. НЛТК предоставляет несколько корпусов. Corpora помогает в обработке текста с готовыми данными. Например, подборка инаугурационных обращений президентов США может помочь в анализе и подготовке речей.

В NLTK доступны несколько читателей корпуса. В зависимости от обрабатываемого текста вы можете выбрать наиболее подходящий. Необходимый корпус должен быть установлен вместе с Data (см. раздел Настройка выше).

Существует несколько типов корпусов, которые указывают на структуру и тип данных, которые предоставляет корпус. Доступный список корпусов можно найти в пользовательском интерфейсе nltk_data (см. раздел «Настройка»).

(Opensource.com, CC BY-SA 4.0)

Доступ к корпусу осуществляется через считыватель. Читатель, который будет использоваться для корпуса, зависит от типа корпуса. Например, корпус Гутенберга хранит текст в обычном текстовом формате, и доступ к нему осуществляется с помощью PlaintextCorpusReader. Корпус Брауна содержит категоризированный текст с тегами, доступ к которому осуществляется с помощью CategorizedTaggedCorpusReader. Читатели следуют древовидной структуре. Вот некоторые корпуса и их читатели.

(Opensource.com, CC BY-SA 4.0)

Вот как получить доступ к корпусам.

Сначала создайте служебную функцию для отображения информации о корпусе на основе типа устройства чтения корпуса:

def corpus_info(corpus):
    print(corpus)
    print()
    print("README:", corpus.readme())
    print()
    files = corpus.fileids()
    print(len(files), "files:")
    print(files)
    print()
    file = files[0]
    text = corpus.raw(file)
    print("File", file, len(corpus.paras(file)), "paras", len(corpus.sents(file)), "sentences", len(corpus.words(file)), "words", ":")
    print(text.encode("utf-8"))
    print()
    if isinstance(corpus, nltk.corpus.TaggedCorpusReader):
        tagged_words = corpus.tagged_words()
        print(len(tagged_words), "tags:")
        print(tagged_words)
        print()
    if isinstance(corpus, nltk.corpus.CategorizedTaggedCorpusReader):
        categories = corpus.categories()
        print(len(categories), "categories:")
        print(categories)
        print()
        category = categories[-1]
        files = corpus.fileids(category)
        print(len(files), "files in category", category, ":")
        print(files)
        print()
        file = files[0]
        print("File:", file, len(corpus.paras(file)), "paras", len(corpus.sents(file)), "sentences", len(corpus.words(file)), "words")
        print()
        print("Raw text:")
        text = corpus.raw(file)
        print(text)
        print()
        print("Tagged text:")
        tagged_words = corpus.tagged_words(file)
        print(tagged_words)
        print()

Вот два примера корпусов:

  • ABC — это сборник новостей Австралийской комиссии по телерадиовещанию. Это базовый корпус обычного текста:

    corpus_info(nltk.corpus.abc)
    <PlaintextCorpusReader in '.../corpora/abc' (not loaded yet)>
        
    README: b'Australian Broadcasting Commission 2006\nhttp://www.abc.net.au/\n\nContents:\n* Rural News    http://www.abc.net.au/rural/news/\n* Science News  http://www.abc.net.au/science/news/\n\n'
        
    2 files:
    ['rural.txt', 'science.txt']
        
    File: rural.txt 2425 paras 13015 sentences 345580 words :
    'PM denies knowledge of AWB kickbacks\nThe Prime Minister has denied ...
  • Корпус Брауна содержит около миллиона слов современного американского английского языка, собранных Университетом Брауна:

    corpus_info(nltk.corpus.brown)
    <CategorizedTaggedCorpusReader in '.../corpora/brown' (not loaded yet)>
        
    README: BROWN CORPUS
    A Standard Corpus of Present-Day Edited American
    ...
        
    500 files:
    ['ca01', 'ca02', 'ca03', ...]
        
    File ca01 67 paras 98 sentences 2242 words :
    b"\n\n\tThe/at Fulton/np-tl County/nn-tl Grand/jj-tl Jury/nn-tl ...
        
    1161192 tags:
    [('The', 'AT'), ('Fulton', 'NP-TL'), ...]
        
    15 categories:
    ['adventure', 'belles_lettres', 'editorial', 'fiction', 'government', 'hobbies', 'humor', 'learned', 'lore', 'mystery', 'news', 'religion', 'reviews', 'romance', 'science_fiction']
        
    6 files in category science_fiction :
    ['cm01', 'cm02', 'cm03', 'cm04', 'cm05', 'cm06']
        
    File: cm01 57 paras 174 sentences 2486 words
        
    Raw text:
    Now/rb that/cs he/pps ...
        
    Tagged text: 
    [('Now', 'RB'), ('that', 'CS'), ('he', 'PPS'), ...]

Представьте, что вы могли бы сделать, имея в своем распоряжении такой корпус! С помощью корпуса Брауна вы можете научить модель классифицировать и помечать тексты, чтобы чат-бот, например, мог лучше понимать намерения человека. Вы также можете создать свой собственный корпус.

Следующие шаги

В моей следующей статье я расширю ваши знания о строительных блоках НЛП, показав, как сравнивать проанализированные данные, реализовывать распознавание сущностей и многое другое с помощью NLP и NLTK.

А пока попробуйте обучить модель машинного обучения с использованием корпуса Брауна для категоризации текста и тегирования слов. Примените это к части книги П.Г. Вудхауса и посмотрите, какую категорию она определяет.