242 lines
14 KiB
Markdown
242 lines
14 KiB
Markdown
# Стилометрия реплик 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`.
|
||
- **`TUNING.md`** — где менять параметры классификаторов, признаки, LSA и веса
|
||
блоков; рекомендуемый порядок улучшения результатов.
|
||
- **`RESULTS_ANALYSIS.md`** — независимый анализ follow-up результатов:
|
||
ранжирование моделей, статистические сравнения, ошибки, ограничения и
|
||
выводы.
|
||
- **`FINAL_REPORT.md`** — итоговый отчёт по всей работе: методика, все серии
|
||
экспериментов, результаты, обсуждение и выводы.
|
||
- **`FINAL_RESULTS.csv`** — сводная таблица ключевых результатов.
|
||
- **`FOLLOWUP_EXPERIMENTS.md`** — протокол и результаты follow-up серии,
|
||
подготовленные коллегой.
|
||
- **`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,
|
||
дельту, метрики и кросс-валидацию.
|