Порахувати частоту слів — що обговорюється найчастіше
Класифікувати повідомлення за темами
Знайти схожі тексти
Нові терміни
NLP
Natural Language Processing — обробка природної мови. Алгоритми для роботи з текстом.
Токенізація
Розбиття тексту на окремі слова (токени). "Привіт світ" → ["Привіт", "світ"]
Стоп-слова
Часті слова без значення: і, в, на, що. Зазвичай фільтруються.
Лематизація
Зведення слова до базової форми: "позиції" → "позиція".
N-грами
Послідовності з N слів. Біграми: "вогневий контакт", "точка збору".
Частина 1: Базова обробка тексту
Очищення тексту
import re
text = "Група на позиції 48.4567, 35.0234! Зв'язок встановлено..."
# Нижній регістр
text_lower = text.lower()
# Видалення пунктуації
text_clean = re.sub(r'[^\w\s]', '', text_lower)
# Видалення чисел
text_no_nums = re.sub(r'\d+', '', text_clean)
# Видалення зайвих пробілів
text_final = ' '.join(text_no_nums.split())
print(f"Оригінал: {text}")
print(f"Очищено: {text_final}")
Токенізація
# Простий спосіб — split()
text = "група на позиції зв'язок встановлено"
tokens = text.split()
print(f"Токени: {tokens}")
# Результат: ['група', 'на', 'позиції', "зв'язок", 'встановлено']
Фільтрація стоп-слів
# Українські стоп-слова (базовий набір)
STOP_WORDS = {
'і', 'в', 'на', 'що', 'це', 'до', 'з', 'не', 'та', 'як',
'від', 'за', 'по', 'для', 'але', 'або', 'ще', 'вже', 'так',
'був', 'буде', 'є', 'їх', 'його', 'її', 'ми', 'ви', 'вони'
}
text = "група на позиції і зв'язок вже встановлено"
tokens = text.lower().split()
# Фільтруємо
filtered = [word for word in tokens if word not in STOP_WORDS]
print(f"Без стоп-слів: {filtered}")
# Результат: ['група', 'позиції', "зв'язок", 'встановлено']
Частина 2: Частота слів
from collections import Counter
import re
# Тестові повідомлення
messages = [
"Група на позиції, зв'язок встановлено",
"Переміщення до нової позиції",
"Вогневий контакт на позиції",
"Зв'язок втрачено, потрібна підтримка",
"Група вийшла на позицію спостереження",
"Підтримка надана, зв'язок відновлено"
]
# Об'єднуємо та очищаємо
all_text = ' '.join(messages).lower()
all_text = re.sub(r'[^\w\s]', '', all_text)
tokens = all_text.split()
# Фільтруємо стоп-слова
STOP_WORDS = {'на', 'до', 'і', 'в', 'з'}
tokens = [t for t in tokens if t not in STOP_WORDS]
# Підраховуємо
word_counts = Counter(tokens)
print("Найчастіші слова:")
for word, count in word_counts.most_common(10):
print(f" {word}: {count}")
N-грами (біграми)
from collections import Counter
def get_ngrams(tokens, n=2):
"""Генерує n-грами зі списку токенів"""
return [' '.join(tokens[i:i+n]) for i in range(len(tokens)-n+1)]
text = "вогневий контакт на позиції спостереження"
tokens = text.split()
bigrams = get_ngrams(tokens, 2)
print(f"Біграми: {bigrams}")
# ['вогневий контакт', 'контакт на', 'на позиції', 'позиції спостереження']
trigrams = get_ngrams(tokens, 3)
print(f"Триграми: {trigrams}")
# ['вогневий контакт на', 'контакт на позиції', 'на позиції спостереження']
Частина 3: Пошук патернів
Пошук ключових слів
import re
# Словник категорій
CATEGORIES = {
'рух': ['переміщення', 'рух', 'вийшл', 'прибу', 'відбу'],
'контакт': ['вогневий', 'контакт', 'обстріл', 'бій'],
'зв\'язок': ['зв\'язок', 'радіо', 'сигнал', 'частот'],
'техніка': ['танк', 'бтр', 'бмп', 'гармат', 'машин']
}
def categorize(text):
"""Визначає категорії повідомлення"""
text_lower = text.lower()
found = []
for category, keywords in CATEGORIES.items():
for keyword in keywords:
if keyword in text_lower:
found.append(category)
break
return found if found else ['інше']
# Тест
messages = [
"Група здійснює переміщення",
"Вогневий контакт, потрібна підтримка",
"Зв'язок втрачено",
"Виявлено 2 танки на позиції"
]
for msg in messages:
cats = categorize(msg)
print(f"{msg[:40]}... → {cats}")
Витягування сутностей
import re
text = """
Сокіл-1 доповідає: група Орел на позиції 48.4567, 35.0234.
Контакт з Беркутом о 14:30. Підтримка від Грім-2 очікується.
"""
# Позивні (слово-число або слово з великої літери)
callsigns = re.findall(r'\b[А-ЯІЇЄҐA-Z][а-яіїєґa-z]+(?:-\d+)?\b', text)
print(f"Можливі позивні: {set(callsigns)}")
# Координати
coords = re.findall(r'\d+\.\d+,?\s*\d+\.\d+', text)
print(f"Координати: {coords}")
# Час
times = re.findall(r'\b\d{1,2}:\d{2}\b', text)
print(f"Час: {times}")
Частина 4: Схожість текстів
Знайти схожі повідомлення — корисно для виявлення дублікатів або пов'язаних подій.
from collections import Counter
import math
def text_to_vector(text):
"""Перетворює текст у вектор частот слів"""
words = text.lower().split()
return Counter(words)
def cosine_similarity(vec1, vec2):
"""Косинусна схожість між двома векторами"""
# Спільні слова
common = set(vec1.keys()) & set(vec2.keys())
# Скалярний добуток
dot_product = sum(vec1[w] * vec2[w] for w in common)
# Норми
norm1 = math.sqrt(sum(v**2 for v in vec1.values()))
norm2 = math.sqrt(sum(v**2 for v in vec2.values()))
if norm1 == 0 or norm2 == 0:
return 0
return dot_product / (norm1 * norm2)
# Тест
msg1 = "група на позиції зв'язок встановлено"
msg2 = "зв'язок з групою на позиції підтверджено"
msg3 = "вогневий контакт потрібна підтримка"
vec1 = text_to_vector(msg1)
vec2 = text_to_vector(msg2)
vec3 = text_to_vector(msg3)
print(f"Схожість 1-2: {cosine_similarity(vec1, vec2):.2f}") # Висока
print(f"Схожість 1-3: {cosine_similarity(vec1, vec3):.2f}") # Низька
💡 Косинусна схожість: 1.0 = ідентичні, 0.0 = нічого спільного. Значення > 0.5 зазвичай означає схожі тексти.
Практична задача
Аналіз перехоплених повідомлень. Створи text_analysis.py:
import re
from collections import Counter
# --- ДАНІ ---
messages = [
"[08:23] Сокіл-1: Група на позиції, зв'язок встановлено",
"[08:45] Орел-2: Переміщення до точки Альфа",
"[09:12] Сокіл-1: Вогневий контакт, потрібна підтримка",
"[09:30] Грім-3: Підтримка надана, рухаюсь до позиції",
"[10:15] Орел-2: Прибув на точку Альфа, зв'язок стабільний",
"[10:45] Сокіл-1: Контакт завершено, втрат немає",
"[11:00] Беркут-1: Спостереження з позиції, рух противника",
"[11:30] Грім-3: На позиції, готовий до підтримки",
]
# --- ОЧИЩЕННЯ ---
def clean_text(text):
# Видаляємо час та позивні на початку
text = re.sub(r'^\[.*?\]\s*\S+:\s*', '', text)
# Нижній регістр, без пунктуації
text = re.sub(r'[^\w\s]', '', text.lower())
return text
# --- АНАЛІЗ ---
STOP_WORDS = {'на', 'до', 'з', 'і', 'в', 'є', 'що'}
all_tokens = []
for msg in messages:
clean = clean_text(msg)
tokens = [t for t in clean.split() if t not in STOP_WORDS]
all_tokens.extend(tokens)
# Частота слів
word_freq = Counter(all_tokens)
print("=== ТОП-10 СЛІВ ===")
for word, count in word_freq.most_common(10):
print(f" {word}: {count}")
# --- ПОЗИВНІ ---
callsigns = []
for msg in messages:
match = re.search(r'\]\s*(\S+-\d+):', msg)
if match:
callsigns.append(match.group(1))
callsign_freq = Counter(callsigns)
print("\n=== АКТИВНІСТЬ ПОЗИВНИХ ===")
for cs, count in callsign_freq.most_common():
print(f" {cs}: {count} повідомлень")
# --- КАТЕГОРИЗАЦІЯ ---
CATEGORIES = {
'рух': ['переміщення', 'рух', 'прибув', 'рухаюсь'],
'контакт': ['вогневий', 'контакт', 'противник'],
'зв\'язок': ['зв\'язок', 'стабільний'],
'підтримка': ['підтримка', 'готовий']
}
print("\n=== КАТЕГОРІЇ ПОВІДОМЛЕНЬ ===")
for msg in messages:
text_lower = msg.lower()
cats = []
for cat, keywords in CATEGORIES.items():
if any(kw in text_lower for kw in keywords):
cats.append(cat)
if cats:
print(f" {msg[:50]}... → {cats}")
Очікуваний результат
=== ТОП-10 СЛІВ ===
позиції: 4
звязок: 3
підтримка: 3
контакт: 2
...
=== АКТИВНІСТЬ ПОЗИВНИХ ===
Сокіл-1: 3 повідомлень
Орел-2: 2 повідомлень
Грім-3: 2 повідомлень
Беркут-1: 1 повідомлень
=== КАТЕГОРІЇ ПОВІДОМЛЕНЬ ===
[08:23] Сокіл-1: Група на позиції, зв'язок встано... → ['зв'язок']
[08:45] Орел-2: Переміщення до точки Альфа... → ['рух']
...
Якщо не працює
Помилка
Рішення
UnicodeDecodeError
Проблема з кодуванням. Читай файли з encoding='utf-8'
re.error
Помилка в регулярному виразі. Перевір екранування спецсимволів
KeyError в Counter
Слово не знайдено. Використовуй .get() або перевіряй наявність
Робота з AI
Є текстовий файл з перехопленими повідомленнями. Формат:
[час] Позивний: текст повідомлення
Напиши скрипт для аналізу:
1. Витягни всі унікальні позивні та порахуй їх активність
2. Знайди найчастіші слова (без стоп-слів)
3. Витягни координати, час, назви місць
4. Категоризуй повідомлення: рух, контакт, зв'язок, інше
5. Знайди схожі повідомлення (косинусна схожість > 0.5)
6. Збережи звіт у CSV
Українська мова, коментарі українською.
Додатково: бібліотеки NLP
Для складніших задач є спеціалізовані бібліотеки:
spaCy
Швидкий NLP: токенізація, NER, залежності
NLTK
Класична бібліотека NLP, багато інструментів
pymorphy2
Морфологія для української/російської
langdetect
Визначення мови тексту
sentence-transformers
Семантична схожість (нейромережі)
pip install pymorphy2
import pymorphy2
morph = pymorphy2.MorphAnalyzer(lang='uk')
words = ['позиції', 'переміщення', 'встановлено']
for word in words:
parsed = morph.parse(word)[0]
print(f"{word} → {parsed.normal_form} ({parsed.tag})")
Чек-лист
☐
Очищення тексту працює
☐
Частота слів рахується
☐
Стоп-слова фільтруються
☐
Позивні витягуються regex
☐
Категоризація працює
☐
text_analysis.py виконується
Самостійна практика
Хмара слів. Встанови wordcloud та візуалізуй частоту
Біграми. Знайди найчастіші пари слів
Кластеризація. Згрупуй схожі повідомлення
Наступний урок
Урок 8: Автоматизація та звіти
Створення автоматичних звітів, планування задач, пайплайни обробки.