Урок 9: Патерни, тренди та кластеризація

Навігація курсу: Хаб: Уроки

Попередній: Урок-08-Воркшоп | Наступний: Урок-10-Моніторинг-реального-часу


Слайди (Презентаційний текст)

Слайд 1 — Заголовок

Патерни, тренди та кластеризація
Від окремих фактів до системного розуміння


Слайд 2 — Навіщо аналіз патернів?

Один факт = одна точка.
Патерн = смисл.

OSINT-аналітик не тільки збирає — він виявляє структуру:

  • Чи є цикл у поведінці суб’єкта?
  • Які теми домінують у спільноті?
  • Куди рухається тренд?
  • Хто схожий на кого?

AI-підхід 2025-2026: ML-алгоритми знаходять патерни у даних де людина бачить хаос


Слайд 3 — Типи патернів у OSINT

Тип патернуПрикладІнструменти
ЧасовийПублікації щовівторка о 9:00 → часовий поясPandas, матриці активності
МовнийПерехід з UK на RU у пості → аудиторія зміниласьNLP, topic modeling
МережевийТой самий набір акаунтів репостить завжди разом → ботофермаGephi, Betweenness
КонтентнийТематичні кластери публікаційTF-IDF, BERTopic
ПоведінковийРізка зміна частоти публікацій → щось сталосьAnomaly detection

Слайд 4 — Аналіз тимчасових патернів

Матриця активності (теплова карта):

import pandas as pd
import matplotlib.pyplot as plt
 
# posts_df має колонки: timestamp, platform
posts_df['hour'] = posts_df['timestamp'].dt.hour
posts_df['weekday'] = posts_df['timestamp'].dt.day_name()
 
# Матриця: день тижня × година дня
pivot = posts_df.pivot_table(
    index='weekday', columns='hour',
    values='id', aggfunc='count'
)
 
plt.figure(figsize=(14, 5))
plt.imshow(pivot, aspect='auto', cmap='YlOrRd')
plt.colorbar(label='Кількість постів')
plt.title('Матриця активності')

Що виявляємо:

  • Часовий пояс (пік активності)
  • Робочий vs особистий час
  • Аномальна активність (ніч, вихідні)

Слайд 5 — Кластеризація тексту

Мета: знайти тематичні групи без попередніх міток

Алгоритми:

  • K-Means — потрібно вказати кількість кластерів
  • DBSCAN — сам знаходить кількість, виявляє шум
  • BERTopic — сучасний підхід на трансформерах, 2025-2026 стандарт
from bertopic import BERTopic
 
model = BERTopic(language="multilingual")
topics, probs = model.fit_transform(documents)
 
# Переглянути топ-теми
print(model.get_topic_info())

Слайд 6 — BERTopic для OSINT (2025-2026)

BERTopic — виявлення тем у корпусі документів:

  1. Векторизація документів (BERT ембедінги)
  2. Зменшення розмірності (UMAP)
  3. Кластеризація (HDBSCAN)
  4. Видалення стоп-слів (c-TF-IDF)

Практика OSINT:

  • Аналіз 1000+ Telegram-постів → виявлення тематичних кластерів
  • Аналіз новинного потоку → визначення домінантних наративів
  • Аналіз коментарів → розуміння настроїв спільноти

Слайд 7 — Аналіз трендів

TF-IDF для виявлення ключових термінів:

from sklearn.feature_extraction.text import TfidfVectorizer
 
# Порівняти два часових проміжки
vectorizer = TfidfVectorizer(max_features=100, ngram_range=(1,2))
period_1 = vectorizer.fit_transform(docs_jan)
period_2 = vectorizer.transform(docs_apr)
 
# Слова що зросли у вазі → новий тренд

Для OSINT: відстеження зміни наративів у часі, виявлення нових тем


Слайд 8 — Виявлення аномалій

Anomaly Detection для моніторингу:

from sklearn.ensemble import IsolationForest
 
# Ознаки: кількість постів на день, uniq авторів, engagement
X = df[['daily_posts', 'unique_authors', 'avg_engagement']].values
 
model = IsolationForest(contamination=0.05)
df['anomaly'] = model.fit_predict(X)
 
# anomaly = -1 → аномальний день (атака, кампанія, подія)
anomalies = df[df['anomaly'] == -1]

Застосування: виявлення координованих інформаційних кампаній, раптового зростання уваги до суб’єкта


Слайд 9 — Поведінкові патерни особи

Що аналізуємо:

СигналІнтерпретація
Час постів щодня о 7-9Особа в UTC+2 або UTC+3
Різкий стоп публікаційПодорож, проблеми, зміна ролі
Зміна мовиНова аудиторія, переїзд
Новий тип контентуЗміна стратегії або аудиторії
Видалення старих постівOpSec, юридичні проблеми, переформатування

Слайд 10 — Практичний інструментарій (2025-2026)

ЗавданняІнструментМова
Тематична кластеризаціяBERTopicPython
Часові рядиProphet (Meta), statsmodelsPython
Мережевий аналізGephi, NetworkXGUI / Python
АномаліїIsolation Forest, LSTMPython
Sentiment trendsVADER, HuggingFace pipelinesPython
ВізуалізаціяMatplotlib, Plotly, TableauPython / GUI

Слайд 11 — Кейс: аналіз дезінформаційної кампанії

Крок 1: Зібрати 5000+ постів за темою (Telegram + Twitter/X)
Крок 2: BERTopic → виявити 8 кластерів наративів
Крок 3: Часовий аналіз → коли кожен наратив з’явився
Крок 4: Мережевий аналіз → хто першим поширював кожний наратив
Крок 5: Anomaly detection → виявити дні координованих публікацій

Результат: карта наративів + часова шкала + мережа поширення


Слайд 12 — Обмеження алгоритмів

  • K-Means: погано на нерівних кластерах, потребує k
  • BERTopic: повільний на дуже великих даних (>1M документів)
  • Isolation Forest: чутливий до параметра contamination
  • Все алгоритмічне: виявляє кореляції, не причинно-наслідкові зв’язки

Правило: алгоритм вказує де дивитись, людина вирішує що це означає


Нотатки доповідача

До слайду 4 — Матриця активності

Демонстрація: візьміть публічний Telegram-канал, зберіть метадані 200+ постів (тільки timestamp, без контенту), побудуйте теплову карту. Часовий пояс автора часто видний одразу. Цей аналіз займає 15-20 хвилин у Jupyter і дає чіткий результат.

До слайду 6 — BERTopic

BERTopic — справжній прорив 2022-2023 який став стандартом до 2025-2026. Він не потребує попереднього визначення кількості тем і чудово справляється з багатомовними корпусами. Підкресліть: для аналітика без ML-бекграунду достатньо знати як запустити і як інтерпретувати результат.

До слайду 11 — Кейс

Розберіть реальний або гіпотетичний кейс детально. Ідеально якщо є реальний приклад дезінформаційної кампанії яку студенти пам’ятають. Пройдіть кроки вголос, показуючи як кожен інструмент додає до загальної картини.


Домашнє завдання

Завдання 1 — Матриця активності (обов’язкове)

Знайдіть будь-який публічний Telegram-канал (мінімум 500 постів).

  1. Зберіть metadata останніх 200+ постів (timestamp, views)
  2. Побудуйте матрицю активності (день × година)
  3. Зробіть висновки: часовий пояс, ритм роботи, аномалії
  4. Здайте: Jupyter notebook + скріншот матриці + висновки

Завдання 2 — Тематична кластеризація (обов’язкове)

Зберіть 100+ текстових постів на одну тему з Telegram або Twitter.

  1. Встановіть BERTopic: pip install bertopic
  2. Запустіть кластеризацію
  3. Опишіть знайдені кластери: як би ви їх назвали?
  4. Чи є кластер що виглядає аномально?

Завдання 3 — Trend аналіз (бажане)

Оберіть ключове слово або особу. Зберіть кількість згадок по тижнях за останні 3 місяці.
Побудуйте часовий ряд. Знайдіть піки і поясніть їх (яка подія викликала ріст?).


Матеріали для студентів

Ресурси

Кластеризація і ML для OSINT:

Стартовий код: матриця активності

"""
Аналіз матриці активності Telegram-каналу
Для курсу AI for OSINT 2026
"""
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
 
# Припускаємо що у вас є CSV з колонкою 'timestamp'
# (зібраний через Telegram API або ручно)
 
def build_activity_matrix(csv_path, tz_offset=0):
    df = pd.read_csv(csv_path)
    df['timestamp'] = pd.to_datetime(df['timestamp'], utc=True)
    
    # Корекція часового поясу
    df['local_time'] = df['timestamp'] + pd.Timedelta(hours=tz_offset)
    df['hour'] = df['local_time'].dt.hour
    df['weekday'] = df['local_time'].dt.day_name()
    
    # Порядок днів тижня
    day_order = ['Monday', 'Tuesday', 'Wednesday',
                 'Thursday', 'Friday', 'Saturday', 'Sunday']
    
    # Побудова pivot-таблиці
    pivot = df.pivot_table(
        index='weekday', columns='hour',
        values='message_id' if 'message_id' in df.columns else df.columns[0],
        aggfunc='count',
        fill_value=0
    ).reindex(day_order)
    
    # Теплова карта
    plt.figure(figsize=(16, 6))
    sns.heatmap(pivot, cmap='YlOrRd', linewidths=0.5,
                annot=True, fmt='d', cbar_kws={'label': 'Кількість постів'})
    plt.title('Матриця активності')
    plt.xlabel('Година дня (UTC+{})'.format(tz_offset))
    plt.ylabel('День тижня')
    plt.tight_layout()
    plt.savefig('activity_matrix.png', dpi=150)
    plt.show()
    
    # Висновки
    peak_hour = pivot.values.sum(axis=0).argmax()
    peak_day = pivot.sum(axis=1).idxmax()
    print(f"Пік активності: {peak_day}, {peak_hour}:00")
    print(f"Орієнтовний часовий пояс: UTC+{tz_offset}")
    
    return pivot
 
# Використання:
# matrix = build_activity_matrix('telegram_posts.csv', tz_offset=2)

← Урок-08-Воркшоп | Наступний урок: Урок-10-Моніторинг-реального-часу →