Обробка природної мови (NLP) у Python з кодом (Частина 1. Аналіз тональності)

Oleh Dubetcky
3 min readMar 21, 2021

У цій частині розглянемо аналіз тональності текстів на прикладі новин

Ми будемо використовувати Google Colab тому вам не потрібно нічого встановлювати або налаштовувати на вашому комп’ютері.

Обробка природної мови (Natural Language Processing — NLP) — це технологія, яка допомагає комп’ютеру розуміти природну мову людини. Використовуючи NLP, розробники можуть систематизувати і структурувати знання для виконання таких завдань, як автоматичне реферування, переклад, розпізнавання іменованих сутностей, аналіз тональності, розпізнавання мови, тематична сегментація та інше.

NLTK (Natural Language Toolkit) — провідна платформа для створення NLP-програм на Python. У неї легкі у використанні інтерфейси для багатьох мовних корпусів, а також бібліотеки для обробки текстів для класифікації, токенізаціі, стемінгу, розмічування частин мови (POS-тегування), синтаксичного аналізу та семантичного аналізу.

У нашому прикладі ми будемо використовувати, два інструменти NLTK:

  • Інструмент «Аналіз настроїв VADER» (генерує позитивні, негативні і нейтральні оцінки настроїв для заданих вхідних даних).
  • Інструмент токенізатора «word_tokenize» (розбиває великий текст на послідовність більш дрібних одиниць, таких як речення або слова).

Щоб використовувати VADER і word_tokenize, нам спочатку потрібно завантажити і встановити додаткові данні для NLTK.

import nltk
nltk.download('stopwords')
nltk.download('punkt')
nltk.download('vader_lexicon')

VADER (Valence Aware Dictionary and sEntiment Reasoner) — це інструмент оцінки тональності, доданий в NLTK у 2014 році. На відміну від інших методів, що вимагають навчання зв’язаного тексту перед використанням, VADER готовий до аналізу без будь-якої спеціального налаштування. VADER унікальний тим, що чітко розрізняє позитивність і негативність різного ступеня.

Обчислити тональність заголовку

!pip install feedparser
import feedparser
posts = []
rss_url='https://www.pravda.com.ua/ukr/rss/view_news/'
response = feedparser.parse(rss_url)
for each in response['entries']:
if each['title'] in [x['title'] for x in posts]:
pass
else:
posts.append({
"title": each['title'],
"link": each['links'][0]['href'],
"tags": [x['term'] for x in each['tags']],
"date": time.strftime('%Y-%m-%d', each['published_parsed'])
})
for i, post in enumerate(p['title'] for p in posts):
print(i, post)

Завантажемо тональний словник української мови

import requests
import csv
url = 'https://raw.githubusercontent.com/lang-uk/tone-dict-uk/master/tone-dict-uk.tsv'
r = requests.get(url)
with open(nltk.data.path[0]+'/tone-dict-uk.tsv', 'wb') as f:
f.write(r.content)
d = {}
with open(nltk.data.path[0]+'/tone-dict-uk.tsv', 'r') as csv_file:
for row in csv.reader(csv_file, delimiter='\t'):
d[row[0]] = float(row[1])
from nltk.sentiment.vader import SentimentIntensityAnalyzer
SIA = SentimentIntensityAnalyzer()
SIA.lexicon.update(d)

Алгоритм VADER виводить оцінки настроїв для 4 класів настроїв :

neg: Негативний
neu: Нейтральний
pos: Позитивний
compound: Складний (Сукупний бал)

Давайте порахуємо оцінку настрою для наданих заголовків за допомогою VADER, щоб зрозуміти, на що здатний цей інструмент.

for i, post in enumerate(p['title'] for p in posts):
print(i, post, SIA.polarity_scores(post)["compound"])

Як видно з принту результату обробки — багато позицій визначено як нейтральна тональність (0.0), це через те, що ми не виконали попередньої підготовки тексту. Попередня обробка тексту використовується для поліпшення роботи алгоритмів. Тож, виконаємо очищення від стоп-слів та приведемо слова в нормальну форму. Т.к. у NLTK, поки немає корпусу української мови, то для мормологічного аналізу скористаємось pymorphy2

url = 'https://raw.githubusercontent.com/olegdubetcky/Ukrainian-Stopwords/main/ukrainian'
r = requests.get(url)
with open(nltk.data.path[0]+'/corpora/stopwords/ukrainian', 'wb') as f:
f.write(r.content)
# Retrieve HTTP meta-data
print(r.status_code)
print(r.headers['content-type'])
print(r.encoding)
import string
from nltk.corpus import stopwords
stopwords = stopwords.words("ukrainian")
!pip install git+https://github.com/kmike/pymorphy2.git
!pip install -U pymorphy2-dicts-uk
import pymorphy2
morph = pymorphy2.MorphAnalyzer(lang='uk')
stop_words = frozenset(stopwords+list(string.punctuation))
for i, post in enumerate(p['title'] for p in posts):
sentences = nltk.sent_tokenize(post)
for sentence in sentences:
words = nltk.word_tokenize(sentence)
without_stop_words = [word for word in words if not word in stop_words]
normal_words=[]
for token in without_stop_words:
p = morph.parse(token)[0]
normal_words.append(p.normal_form)

print(i, post, "RAW: ", SIA.polarity_scores(post)["compound"],"NORM: ", SIA.polarity_scores(' '.join(normal_words))["compound"])

Тож, результат значно краще.

Повний приклад у Colab

Джерела:
1. Natural Language Toolkit
2. Проекти групи lang-uk

Якщо вам сподобалася стаття, внизу можна підтримати автора плесканням 👏🏻 Дякую за прочитання!

--

--

Oleh Dubetcky

I am an management consultant with a unique focus on delivering comprehensive solutions in both human resources (HR) and information technology (IT).