Первичная версия: стилометрия реплик, LSA и протокол экспериментов

This commit is contained in:
2026-10-24 01:17:36 +03:00
commit c390224500
52 changed files with 10099 additions and 0 deletions

231
lab1/README.md Normal file
View File

@@ -0,0 +1,231 @@
# Стилометрия реплик Stardew Valley
Проект для лабораторной работы по автоматическому анализу текстов. Задача —
проверить, можно ли стилометрически различить персонажей игры, если все реплики
написаны одним автором. Это не авторская атрибуция, а классификация
**речевых масок персонажей** (character idiolect): автор намеренно наделяет
героев разной лексикой, синтаксисом, междометиями и пунктуацией.
Основная единица анализа — **одна реплика**. В текущем корпусе 2005 реплик,
34 персонажа. Классы неравномерны: от 15 реплик у Mister Qi до 139 у Abigail.
Поэтому основная метрика — macro-F1, а не доля правильных ответов.
## Быстрый старт
```bash
cd lab1
# 1. Установить зависимости (удобно в виртуальном окружении)
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# 2. Скачать ресурсы NLTK в локальный каталог lab1/nltk_data
python scripts/download_nltk_data.py
# 3. Проверить корпус
python -m stylometry.cli audit
# 4. Построить ручные стилометрические признаки
python -m stylometry.cli features
# 5. Запустить кросс-валидацию
python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --repeats 5
```
Если виртуальное окружение уже создано в корне проекта
(`/home/mermutef/PycharmProjects/nlp/.venv`), команды можно запускать так:
```bash
cd lab1
../.venv/bin/python -m stylometry.cli audit
```
Вместо `python -m stylometry.cli` можно использовать `python main.py`:
```bash
python main.py audit
python main.py run --preset stylometry_pos_lsa --model logreg --repeats 5
```
## Что уже реализовано
| Компонент | Модуль | Назначение |
|---|---|---|
| Чтение корпуса | `stylometry/io.py` | CSV в cp1251, XLSX, проверка колонок, SHA-256 |
| Нормализация | `stylometry/cleaning.py` | Unicode, плейсхолдеры, пробелы |
| Токенизация и POS | `stylometry/tokenization.py` | NLTK: `word_tokenize`, `sent_tokenize`, `pos_tag`; резервный режим |
| Ручные признаки | `stylometry/features/` | длина, лексика, словарное богатство, символы, пунктуация, функциональные слова, местоимения, POS, синтаксис, читаемость, разговорные маркеры |
| LSA | `stylometry/lsa.py` | TF-IDF + `TruncatedSVD` для word/content/fw/char/pos |
| Конвейеры | `stylometry/pipelines.py` | объединение блоков признаков, классификаторы, сетки гиперпараметров |
| Кросс-валидация | `stylometry/cv.py` | повторная стратифицированная и вложенная CV |
| Метрики | `stylometry/evaluation.py` | macro-F1, сбалансированная доля правильных ответов, MCC, каппа, top-k, логарифмическая потеря, оценка Брайера, бутстрэп |
| Статистика | `stylometry/stats.py` | Мак-Немар, Уилкоксон, Фридман, Холм |
| Дельта Барроуза | `stylometry/delta.py` | MFW, z-нормирование, манхэттенское и косинусное расстояние |
| Верификация | `stylometry/verification.py` | «тот же персонаж / другой персонаж», ROC-AUC, EER, TAR@FAR |
| Кластеризация | `stylometry/clustering.py` | иерархическая и k-means, ARI, NMI, силуэт |
| Визуализация | `stylometry/plotting.py` | распределение классов, scree, матрица ошибок, PCA, t-SNE |
## Команды
Все команды выполняются из каталога `lab1`.
```bash
# Аудит: отчёт data/processed/audit.md и таблица lines.csv
python -m stylometry.cli audit
# Матрица ручных признаков: features/stylometric.csv и словарь признаков
python -m stylometry.cli features
# LSA одного варианта
python -m stylometry.cli lsa --variant word --components 100
python -m stylometry.cli lsa --variant pos --components 50
python -m stylometry.cli lsa --variant char --components 50
# Одна модель
python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --repeats 5
python -m stylometry.cli run --preset stylometry_pos --model linear_svc --repeats 5
python -m stylometry.cli run --preset stylometry --model random_forest --repeats 3
# Сравнение классификаторов
python -m stylometry.cli benchmark --preset stylometry_pos_lsa \
--models logreg,linear_svc,random_forest,multinomial_nb,knn --repeats 3
# Вложенная кросс-валидация с настройкой гиперпараметров
python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --nested
# Поочерёдное исключение групп ручных признаков
python -m stylometry.cli ablate --preset stylometry_pos_lsa --model logreg --repeats 3
# Перебор вариантов LSA и числа компонент
python -m stylometry.cli lsa-sweep --variants word,pos,char --components 50,100,200
# Дельта Барроуза
python -m stylometry.cli delta --features 100,200,500 --metrics manhattan,cosine
# Верификация «свой/чужой»
python -m stylometry.cli verify --preset stylometry_pos_lsa
# Кластеризация персонажей
python -m stylometry.cli cluster --preset stylometry_pos_lsa
# Метрики по группам длины реплик (по сохранённому запуску)
python -m stylometry.cli length-report --run-dir results/<каталог_запуска>
# Парное сравнение двух запусков: Мак-Немар и бутстрэп-разница macro-F1
python -m stylometry.cli compare \
--run-a results/<каталог_запуска_A> \
--run-b results/<каталог_запуска_B>
# Метрики по полу, возрасту и виду персонажей
python -m stylometry.cli subgroup-report \
--run-dir results/<каталог_запуска> --group gender
```
Основные готовые наборы признаков (`--preset`):
| Набор | Содержимое |
|---|---|
| `stylometry` | только ручные стилометрические признаки |
| `stylometry_pos` | ручные признаки + символьные и POS n-граммы |
| `stylometry_pos_lsa` | то же + LSA по словам и POS (основной набор) |
| `all` | все блоки, включая все варианты LSA |
| `char` | только символьные n-граммы |
| `pos` | только POS n-граммы |
| `fw` | функциональные слова и местоимения |
| `lsa_word`, `lsa_pos` | только соответствующий вариант LSA |
| `length` | только признаки длины (нижняя граница) |
## Конфигурация
Файл `configs/default.toml` задаёт параметры по умолчанию:
- `[cv]` — число блоков, повторов и seed;
- `[experiment]` — набор признаков и классификатор;
- `[features]` — диапазоны n-грамм, число компонент LSA, `min_df`,
масштабирование.
Параметры командной строки имеют приоритет над конфигурацией. Например:
```bash
python -m stylometry.cli run --config configs/default.toml \
--preset stylometry_pos_lsa --model logreg --repeats 3
```
## Основные документы
- **`RUNBOOK.md`** — пошаговая инструкция для запуска полной серии
экспериментов: установка, проверка окружения, все команды, упаковка
результатов и типичные ошибки.
- **`EXPERIMENTS.md`** — подробный протокол экспериментов: гипотезы, признаки,
схема валидации, матрица экспериментов, команды запуска, анализ ошибок,
ограничения и чек-лист для следующего исследователя.
- **`FEATURES.md`** — состав стилометрических признаков, формулы и обоснование
выбора; дополняет машинно-читаемый `features/feature_dictionary.csv`.
- **`METRICS_AND_CLASSIFIERS.md`** — методическое описание метрик и
классификаторов: что показывает каждая метрика, как она считается, как
интерпретировать значения, чем отличаются модели и как объяснять это на
защите.
- **`PRESENTATION_OUTLINE.md`** — рекомендуемая структура презентации на
14 слайдов с ключевыми тезисами и предложениями по визуализации.
## Структура проекта
```text
lab1/
├── data/
│ ├── dialogues.csv
│ ├── dialogues.xlsx
│ ├── stats_per_character.xlsx
│ ├── metadata/characters.csv # пол, возраст, вид, роль
│ └── processed/ # lines.csv, audit.md, tokenized.pkl
├── features/ # матрицы признаков и LSA
├── stylometry/ # основной пакет
├── experiments/ # место для отдельных сценариев
├── configs/default.toml
├── results/ # результаты запусков
├── tests/ # pytest
├── scripts/download_nltk_data.py
├── requirements.txt
├── README.md
├── EXPERIMENTS.md
└── METRICS_AND_CLASSIFIERS.md
```
## Воспроизводимость
- Корпус читается из `data/dialogues.csv` в кодировке cp1251. SHA-256 файла
сохраняется в отчёте и метаданных запуска.
- Кэш токенизации `data/processed/tokenized.pkl` проверяется по SHA-256
исходного файла; при изменении корпуса пересобирается.
- Все обучаемые преобразования (TF-IDF, SVD, масштабирование, отбор признаков)
настраиваются только на обучающем блоке кросс-валидации. Ручные признаки и
POS-теги не используют метки, поэтому могут считаться заранее.
- Для каждого запуска сохраняются конфигурация, метрики по блокам, pooled
out-of-fold предсказания, матрица ошибок, отчёт по классам и графики.
- Случайность фиксируется параметром `--seed` (по умолчанию 42).
## Ограничения
- Реплики короткие: в среднем около 19 слов. Признаки словарного богатства и
читаемости на таких текстах нестабильны; они помечены как предварительные.
- Все тексты написаны одним автором; результат характеризует различимость
персонажей, а не авторский стиль.
- Корпус прошёл ручную фильтрацию: короткие и общие фразы удалены. Точные
правила очистки не воспроизводимы, это ограничение зафиксировано в отчёте.
- Классы неравномерны (15–139 реплик). Основная метрика — macro-F1; по редким
классам доверительные интервалы широкие.
- NLTK-теггер обучен на внешнем корпусе и может ошибаться на разговорных
конструкциях и коротких фрагментах.
- LSA по всем словам может отражать тему, а не стиль. Поэтому в протоколе
предусмотрено сравнение `lsa_word` с `lsa_pos`, `lsa_fw` и `lsa_char`.
## Тесты
```bash
cd lab1
python -m pytest -q
```
Тесты проверяют чтение корпуса, нормализацию, NLTK-разметку, признаки, LSA,
дельту, метрики и кросс-валидацию.