Files
NLP/lab1/RUNBOOK.md

687 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Инструкция по запуску экспериментов
Документ предназначен для коллеги, который будет запускать серию
экспериментов на своей машине. Все команды выполняются из каталога `lab1`.
Результаты нужно упаковать и передать обратно одним архивом.
Если вы впервые открыли проект, начните с разделов 1–4. Если окружение уже
готово, переходите к разделу 5.
---
## 1. Что это за проект
Исследуется, можно ли стилометрически различить 34 персонажа Stardew Valley
по отдельным репликам, если все реплики написаны одним автором. Это
многоклассовая классификация речевых масок персонажей, а не авторская
атрибуция.
Основные характеристики:
- 2005 реплик;
- 34 класса;
- около 38 тыс. словоупотреблений;
- средняя длина реплики около 19 слов;
- классы неравномерны: от 15 до 139 реплик;
- основная метрика — macro-F1;
- схема валидации — повторная стратифицированная перекрёстная проверка.
Полный протокол: `EXPERIMENTS.md`.
Описание признаков: `FEATURES.md`.
Описание метрик и классификаторов: `METRICS_AND_CLASSIFIERS.md`.
Структура презентации: `PRESENTATION_OUTLINE.md`.
---
## 2. Требования к окружению
- Python 3.11 или новее (проверено на 3.14).
- Linux, macOS или Windows с WSL.
- Свободное место: около 1 ГБ с учётом виртуального окружения и ресурсов
NLTK.
- Интернет — только для установки зависимостей и скачивания ресурсов NLTK.
После этого эксперименты выполняются локально.
Проверьте версию:
```bash
python --version
```
Если версия ниже 3.11, обновите Python: в коде используется стандартный
модуль `tomllib`.
---
## 3. Первичная установка
### 3.1. Перейти в каталог лабораторной
```bash
cd nlp/lab1
```
Все дальнейшие команды выполняются из этого каталога.
### 3.2. Создать виртуальное окружение
Можно создать отдельное окружение внутри `lab1`:
```bash
python -m venv .venv
source .venv/bin/activate
```
На Windows:
```powershell
python -m venv .venv
.venv\Scripts\activate
```
Если в корне проекта уже есть окружение `.venv`, можно использовать его:
```bash
source ../.venv/bin/activate
```
### 3.3. Установить зависимости
```bash
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```
Проверьте, что установились основные библиотеки:
```bash
python -c "import numpy, pandas, scipy, sklearn, nltk, matplotlib; print('ok')"
```
### 3.4. Скачать ресурсы NLTK
```bash
python scripts/download_nltk_data.py
```
Ресурсы сохраняются в `lab1/nltk_data`:
- `punkt`, `punkt_tab` — токенизация и разбиение на предложения;
- `averaged_perceptron_tagger`, `averaged_perceptron_tagger_eng` —
частеречная разметка;
- `stopwords` — стоп-слова для content-LSA.
Без этих ресурсов POS-признаки отключатся, и результаты будут неполными.
### 3.5. Проверить окружение
```bash
python scripts/check_environment.py
```
Скрипт печатает версии библиотек, SHA-256 корпуса, число реплик и классов,
проверяет токенизатор и POS-теггер. В конце должно быть:
```text
Окружение готово.
```
Если POS-теггер недоступен, повторите шаг 3.4.
---
## 4. Проверка перед полной серией
### 4.1. Тесты
```bash
python -m pytest -q
```
Ожидается:
```text
33 passed
```
Если тесты не проходят, не запускайте полную серию: сначала пришлите текст
ошибки.
### 4.2. Быстрый smoke-test
```bash
python -m stylometry.cli audit
python -m stylometry.cli features
python -m stylometry.cli run --preset length --model logreg --folds 3 --repeats 1
```
Проверьте, что появились:
- `data/processed/audit.md`;
- `data/processed/lines.csv`;
- `features/stylometric.csv`;
- `features/feature_dictionary.csv`;
- каталог `results/length_logreg_<timestamp>/` с `summary.md`.
Если всё создалось, окружение готово.
---
## 5. Полная серия экспериментов
### 5.1. Основной запуск
Из каталога `lab1`:
```bash
bash scripts/run_all_experiments.sh
```
Если используется окружение в корне проекта:
```bash
PYTHON=../.venv/bin/python bash scripts/run_all_experiments.sh
```
Скрипт последовательно запускает все стадии, пишет общий лог в
`results/logs/run_all_<timestamp>.log` и останавливается при первой ошибке.
### 5.2. Быстрый режим
Для проверки, что всё работает, но без финальных чисел:
```bash
QUICK=1 bash scripts/run_all_experiments.sh
```
В быстром режиме:
- все повторы равны 1;
- вложенная кросс-валидация пропускается;
- полная серия занимает меньше времени.
Результаты быстрого режима **нельзя** использовать в отчёте как финальные.
### 5.3. Настройка повторов
По умолчанию:
| Переменная | Значение | Что регулирует |
|---|---:|---|
| `REPEATS_MAIN` | 5 | основные модели |
| `REPEATS_FAST` | 3 | baseline, benchmark, delta |
| `REPEATS_LSA` | 3 | отдельные варианты LSA |
| `REPEATS_ABLATE` | 3 | поочерёдное исключение групп |
| `REPEATS_DELTA` | 2 | дельта Барроуза |
| `SKIP_NESTED` | 0 | 1 — пропустить вложенную CV |
Пример:
```bash
REPEATS_MAIN=5 REPEATS_FAST=3 SKIP_NESTED=1 \
bash scripts/run_all_experiments.sh
```
### 5.4. Долгий запуск через tmux или nohup
Полная серия может занимать несколько часов. Если подключение к машине
может прерваться, используйте `tmux`:
```bash
tmux new -s nlp
PYTHON=../.venv/bin/python bash scripts/run_all_experiments.sh
# Ctrl+B, затем D — выйти из tmux, процесс продолжит работу
```
Вернуться:
```bash
tmux attach -t nlp
```
Или `nohup`:
```bash
nohup env PYTHON=../.venv/bin/python \
bash scripts/run_all_experiments.sh >/dev/null 2>&1 &
```
Следить за логом:
```bash
tail -f results/logs/run_all_*.log
```
### 5.5. Ориентировочное время
Время зависит от процессора, числа потоков и версии библиотек. Ориентиры для
обычного ноутбука:
| Стадия | Время |
|---|---:|
| Проверка окружения и тесты | 1–2 мин |
| Аудит и ручные признаки | 1–2 мин |
| Нижние границы | 5–10 мин |
| Классическая стилометрия | 3–6 мин |
| Ручные признаки + n-граммы | 4–8 мин |
| Основной объединённый набор | 5–10 мин |
| Варианты LSA | 10–20 мин |
| Перебор числа компонент LSA | 5–10 мин |
| Сравнение классификаторов | 15–30 мин |
| Поочерёдное исключение групп | 20–40 мин |
| Дельта Барроуза | 3–5 мин |
| Верификация и кластеризация | 3–5 мин |
| Вложенная кросс-валидация | 15–40 мин |
| Анализ длины и подгрупп | 1–2 мин |
Итого: ориентировочно **1,5–3 часа**, в зависимости от машины. Если
включены все повторы и вложенная CV, может быть дольше.
---
## 6. Что делает каждая стадия
### 6.1. Аудит корпуса (E0)
```bash
python -m stylometry.cli audit
```
Создаёт:
- `data/processed/audit.md` — отчёт по корпусу;
- `data/processed/lines.csv` — нормализованные реплики;
- `data/processed/figures/class_distribution.png`.
Проверьте: 2005 реплик, 34 персонажа, нет точных дублей, распределение
классов совпадает с `stats_per_character.xlsx`.
### 6.2. Ручные признаки
```bash
python -m stylometry.cli features
```
Создаёт:
- `features/stylometric.csv` — матрица 2005 × 454;
- `features/feature_dictionary.csv` — описание признаков.
### 6.3. Нижние границы (E1)
Запускаются:
- `length` + Dummy — частотная базовая модель;
- `length` + логистическая регрессия;
- `char` + MultinomialNB;
- `pos` + MultinomialNB;
- `fw` + логистическая регрессия.
Смысл: понять, сколько сигнала даёт только длина, только символьные
n-граммы, только POS и только функциональные слова.
### 6.4. Классическая стилометрия (E2)
```bash
python -m stylometry.cli run --preset stylometry --model logreg --repeats 5
python -m stylometry.cli run --preset stylometry --model linear_svc --repeats 5
```
Проверяет гипотезу H1 на ручных признаках без n-грамм и LSA.
### 6.5. Ручные признаки + n-граммы (E4)
```bash
python -m stylometry.cli run --preset stylometry_pos --model logreg --repeats 5
```
Показывает вклад символьных и частеречных n-грамм.
### 6.6. Основной объединённый набор (E8)
```bash
python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --repeats 5
```
Основной результат: ручные признаки + char/POS n-граммы + LSA по словам и
POS.
### 6.7. Варианты LSA (E5, E7)
Запускаются отдельно:
```bash
python -m stylometry.cli run --preset lsa_word --model logreg --repeats 3
python -m stylometry.cli run --preset lsa_word2 --model logreg --repeats 3
python -m stylometry.cli run --preset lsa_content --model logreg --repeats 3
python -m stylometry.cli run --preset lsa_fw --model logreg --repeats 3
python -m stylometry.cli run --preset lsa_char --model logreg --repeats 3
python -m stylometry.cli run --preset lsa_pos --model logreg --repeats 3
```
Сравнение `lsa_word`/`lsa_content` с `lsa_pos`/`lsa_fw`/`lsa_char` — это
основной эксперимент «стиль или тема».
### 6.8. Перебор числа компонент LSA (E5)
```bash
python -m stylometry.cli lsa-sweep \
--variants word,content,fw,char,pos \
--components 50,100,200 \
--model logreg --repeats 1
```
Результат: `results/lsa_sweep_<timestamp>/lsa_sweep.csv` с macro-F1 для
каждой пары «вариант — число компонент».
### 6.9. Сравнение классификаторов (E6)
```bash
python -m stylometry.cli benchmark \
--preset stylometry_pos_lsa \
--models logreg,linear_svc,random_forest,multinomial_nb,knn \
--repeats 3
```
Результат: `results/benchmark_<preset>_<timestamp>/summary.csv` и отдельные
каталоги по моделям.
### 6.10. Поочерёдное исключение групп признаков (E3)
```bash
python -m stylometry.cli ablate \
--preset stylometry_pos_lsa --model logreg --repeats 3
```
Результат: `results/ablation_<preset>_<timestamp>/ablation.csv` с колонкой
`delta_macro_f1`. Отрицательное значение означает, что удаление группы
ухудшило качество.
### 6.11. Дельта Барроуза (E11)
```bash
python -m stylometry.cli delta \
--features 100,200,500 --metrics manhattan,cosine --repeats 2
```
Классическая стилометрическая базовая модель; результат —
`results/delta_<timestamp>/delta_sweep.csv`.
### 6.12. Верификация «свой/чужой» (E12)
```bash
python -m stylometry.cli verify --preset stylometry_pos_lsa
```
Результат: `results/verification_<preset>_<timestamp>/summary.json` с
ROC-AUC, EER, TAR@FAR=1% и top-1.
### 6.13. Кластеризация (E13)
```bash
python -m stylometry.cli cluster --preset stylometry_pos_lsa
```
Результат: `results/clustering_<preset>_<timestamp>/clustering_metrics.csv`
и `character_centroids.csv`.
### 6.14. Вложенная кросс-валидация (E16)
```bash
python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --nested
python -m stylometry.cli run --preset stylometry_pos_lsa --model linear_svc --nested
```
Внешние блоки — оценка качества, внутренние — настройка гиперпараметров.
Сохраняются `best_params.json` и метрики внешних блоков.
### 6.15. Анализ длины и подгрупп (E9, E14, E15)
После основного запуска:
```bash
python -m stylometry.cli length-report \
--run-dir results/<каталог_основного_запуска>
python -m stylometry.cli subgroup-report \
--run-dir results/<каталог_основного_запуска> --group gender
python -m stylometry.cli subgroup-report \
--run-dir results/<каталог_основного_запуска> --group age_group
python -m stylometry.cli subgroup-report \
--run-dir results/<каталог_основного_запуска> --group species
python -m stylometry.cli compare \
--run-a results/<каталог_основного_запуска> \
--run-b results/<каталог_stylometry_pos> \
--out results/<каталог_основного_запуска>/comparison_main_vs_pos.json
```
`compare` корректно работает, если запуски сделаны с одинаковыми `--folds` и
`--seed`.
---
## 7. Если серия прервалась
Скрипт останавливается при первой ошибке. Уже созданные каталоги результатов
не удаляются. Порядок действий:
1. Посмотрите конец лога:
```bash
tail -n 100 results/logs/run_all_*.log
```
2. Исправьте причину (см. раздел 10).
3. Запустите пропущенные команды вручную из раздела 6. Можно продолжить с
нужной стадии, не повторяя всю серию.
4. Новые результаты появятся в отдельных каталогах с новыми метками времени.
Не удаляйте старые каталоги: по ним можно сравнить, что изменилось.
---
## 8. Упаковка результатов
После завершения серии:
```bash
bash scripts/collect_results.sh
```
Скрипт создаёт:
```text
exports/
├── nlp_lab1_results_<timestamp>.tar.gz
├── nlp_lab1_results_<timestamp>.tar.gz.sha256
└── nlp_lab1_results_<timestamp>_manifest.txt
```
В архив входят:
- `results/` — все запуски, метрики, предсказания, матрицы ошибок, графики,
логи;
- `features/` — матрицы признаков и LSA;
- `data/processed/` — очищенные реплики и аудит;
- `data/metadata/` — метаданные персонажей;
- манифест с версиями библиотек, SHA-256 корпуса и списком файлов.
Передайте коллеге **архив** и **файл `.sha256`**. Если архив большой,
можно передать его через файлообменник, но контрольную сумму нужно сохранить.
Проверка архива на стороне получателя:
```bash
sha256sum -c nlp_lab1_results_<timestamp>.tar.gz.sha256
tar -xzf nlp_lab1_results_<timestamp>.tar.gz
```
---
## 9. Что проверить перед отправкой
- [ ] `python scripts/check_environment.py` завершился без ошибок.
- [ ] `python -m pytest -q` — все тесты пройдены.
- [ ] В логе нет строк `ERROR`, `Traceback`, `FAILED`.
- [ ] Основной запуск `stylometry_pos_lsa` содержит `summary.md`,
`pooled_metrics.csv`, `per_class_report.csv`, `confusion_matrix.csv`.
- [ ] Есть запуски `stylometry`, `stylometry_pos`, `stylometry_pos_lsa`.
- [ ] Есть `results/benchmark_*`, `results/ablation_*`, `results/lsa_sweep_*`.
- [ ] Есть `results/verification_*` и `results/clustering_*`.
- [ ] Есть `results/logs/run_all_*.log`.
- [ ] `collect_results.sh` создал архив и `.sha256`.
---
## 10. Типичные проблемы
### 10.1. `ModuleNotFoundError`
Не установлены зависимости или выбран другой интерпретатор.
```bash
python -m pip install -r requirements.txt
python scripts/check_environment.py
```
Если используете PyCharm, проверьте, что выбран интерпретатор
`nlp/.venv/bin/python` или `lab1/.venv/bin/python`.
### 10.2. Ошибка NLTK: `Resource punkt_tab not found`
```bash
python scripts/download_nltk_data.py
```
Если интернет недоступен, скопируйте каталог `nltk_data` с другой машины в
`lab1/nltk_data`.
### 10.3. `UnicodeDecodeError` при чтении корпуса
Корпус хранится в cp1251. Код сам пробует cp1251, UTF-8 и koi8-r. Если вы
пересохранили CSV в другой кодировке, верните cp1251 или используйте
`dialogues.xlsx`.
### 10.4. `ValueError: empty vocabulary`
Обычно означает, что в обучающем блоке не осталось признаков. Проверьте:
- не пустой ли корпус;
- не отключены ли все блоки признаков;
- не выбран ли `multinomial_nb` с одним LSA без char/POS.
Для стандартных пресетов этой ошибки быть не должно.
### 10.5. Не хватает памяти
Уменьшите размерности:
```bash
python -m stylometry.cli run --preset stylometry_pos --model logreg --repeats 3
```
Или закройте другие приложения. Основной объединённый набор с LSA требует
больше памяти, чем `stylometry_pos`.
### 10.6. Серия идёт слишком долго
- Используйте `QUICK=1` для проверки.
- Уменьшите `REPEATS_FAST`, `REPEATS_ABLATE`, `REPEATS_LSA`.
- Пропустите вложенную CV: `SKIP_NESTED=1`.
- Для финального отчёта всё равно нужны основные повторы; не заменяйте их
быстрым режимом.
### 10.7. `tomllib` не найден
Нужен Python 3.11+. Обновите интерпретатор или создайте окружение на 3.11+.
---
## 11. Полная матрица экспериментов
| ID | Команда | Что проверяет |
|---|---|---|
| E0 | `audit` | Корпус, классы, длины, дубли |
| E1 | `run --preset length/char/pos/fw` | Нижние границы |
| E2 | `run --preset stylometry` | Ручная стилометрия |
| E3 | `ablate --preset stylometry_pos_lsa` | Вклад групп признаков |
| E4 | `run --preset stylometry_pos` | Вклад char/POS n-грамм |
| E5 | `lsa-sweep` и `run --preset lsa_*` | Варианты и число компонент LSA |
| E6 | `benchmark --preset stylometry_pos_lsa` | Сравнение классификаторов |
| E7 | `lsa-sweep` | Стиль или тема |
| E8 | `run --preset stylometry_pos_lsa` | Объединение блоков |
| E9 | `length-report` | Влияние длины |
| E10 | `benchmark` + per-class отчёт | Дисбаланс классов |
| E11 | `delta` | Дельта Барроуза |
| E12 | `verify` | Верификация «свой/чужой» |
| E13 | `cluster` | Кластеризация персонажей |
| E14 | `subgroup-report` | Пол, возраст, вид |
| E15 | `compare` | Мак-Немар и бутстрэп-разница |
| E16 | `run --nested` | Вложенная кросс-валидация |
| E17 | не реализовано | Агрегация в псевдодокументы по 30 предложений |
Подробные команды и интерпретация — в `EXPERIMENTS.md`.
---
## 12. Что именно отправлять обратно
Минимальный комплект:
1. `exports/nlp_lab1_results_<timestamp>.tar.gz`;
2. `exports/nlp_lab1_results_<timestamp>.tar.gz.sha256`;
3. краткий ответ: на какой машине запускали, сколько времени заняла серия,
какие стадии завершились, какие ошибки были.
Если серия не завершилась, отправьте:
- лог `results/logs/run_all_*.log`;
- архив с уже готовыми результатами;
- текст ошибки и команду, на которой она возникла.
---
## 13. Что нельзя менять без согласования
Чтобы результаты оставались сопоставимыми:
- не меняйте корпус и разметку классов;
- не удаляйте реплики и не переименовывайте персонажей;
- не меняйте `--folds`, `--seed` и схему стратификации в основных запусках;
- не меняйте определения метрик;
- не настраивайте гиперпараметры на тестовых блоках;
- не выбирайте признаки по тестовой выборке;
- не заменяйте macro-F1 на долю правильных ответов как основную метрику.
Если хотите добавить новый эксперимент, создайте отдельный сценарий и
сохраните его в `experiments/`, не изменяя основные модули.
---
## 14. Краткая шпаргалка
```bash
cd nlp/lab1
source ../.venv/bin/activate
python scripts/check_environment.py
python -m pytest -q
# быстрая проверка
QUICK=1 bash scripts/run_all_experiments.sh
# полная серия
bash scripts/run_all_experiments.sh
# упаковка результатов
bash scripts/collect_results.sh
# посмотреть лог
tail -f results/logs/run_all_*.log
```
Если что-то пошло не так, сначала пришлите лог и текст ошибки, а не только
вывод последней команды.