Первичная версия: стилометрия реплик, LSA и протокол экспериментов
This commit is contained in:
747
lab1/EXPERIMENTS.md
Normal file
747
lab1/EXPERIMENTS.md
Normal file
@@ -0,0 +1,747 @@
|
||||
# Протокол экспериментов
|
||||
|
||||
Документ описывает постановку, признаки, схему валидации, метрики и порядок
|
||||
запуска экспериментов. Он рассчитан на следующего исследователя, который будет
|
||||
проводить финальные серии опытов и готовить отчёт.
|
||||
|
||||
Методические пояснения к метрикам и классификаторам вынесены в
|
||||
`METRICS_AND_CLASSIFIERS.md`. Здесь — практическая часть: что запускать, в
|
||||
каком порядке и как интерпретировать результаты.
|
||||
|
||||
---
|
||||
|
||||
## 1. Исследовательский вопрос
|
||||
|
||||
**Вопрос.** Различимы ли 34 персонажа Stardew Valley по стилометрическим
|
||||
признакам отдельных реплик, если все реплики написаны одним автором?
|
||||
|
||||
Это задача **классификации речевых масок персонажей**, а не авторской
|
||||
атрибуции. Автор один, но персонажи наделены разной лексикой, синтаксисом,
|
||||
междометиями, длиной реплик и пунктуацией. Положительный результат означает,
|
||||
что созданные автором речевые маски статистически различимы; он не означает,
|
||||
что у персонажей разные авторы.
|
||||
|
||||
### Гипотезы
|
||||
|
||||
| Обозначение | Гипотеза | Как проверяем |
|
||||
|---|---|---|
|
||||
| H1 | Функциональные слова, POS-признаки и символьные n-граммы различают персонажей выше случайного уровня | E2, E3, E4 |
|
||||
| H2 | На коротких репликах POS- и char-признаки устойчивее словарного богатства и читаемости | E3, E9 |
|
||||
| H3 | LSA по всем словам отражает тему, а LSA по POS и функциональным словам — стиль | E7 |
|
||||
| H4 | Более длинные реплики классифицируются лучше | E9 |
|
||||
| H5 | Ошибки группируются вокруг персонажей со сходным возрастом, полом, ролью или «человечностью» | E14 |
|
||||
|
||||
Случайный уровень для 34 классов: доля правильных ответов около 2,9%,
|
||||
macro-F1 около 2,9%, top-3 около 8,8%. Любые результаты нужно сравнивать с
|
||||
этими значениями, а не с нулём.
|
||||
|
||||
---
|
||||
|
||||
## 2. Данные
|
||||
|
||||
### 2.1. Текущий корпус
|
||||
|
||||
| Параметр | Значение |
|
||||
|---|---|
|
||||
| Файл | `data/dialogues.csv` |
|
||||
| Кодировка | cp1251 |
|
||||
| Реплик | 2005 |
|
||||
| Персонажей | 34 |
|
||||
| Словоупотреблений | около 38,2 тыс. |
|
||||
| Средняя длина реплики | 19,1 слова |
|
||||
| Медиана | 17 слов |
|
||||
| Минимум / максимум | 3 / 78 слов |
|
||||
| Классы | 15–139 реплик |
|
||||
| Точные дубли реплик | 0 |
|
||||
|
||||
Корпус уже прошёл ручную фильтрацию: удалены короткие и общие фразы. Точные
|
||||
правила очистки не сохранились, поэтому корпус используется как есть. Это
|
||||
ограничение нужно указать в отчёте: восстановить исходное распределение
|
||||
коротких реплик нельзя.
|
||||
|
||||
Редкие классы: Mister Qi (15), Sandy (21), Dwarf (23), Wizard (24),
|
||||
Vincent (26), Krobus (28). При 5-блочной кросс-валидации у Mister Qi в каждом
|
||||
тестовом блоке около 3 реплик; метрики по нему будут иметь широкий
|
||||
доверительный интервал.
|
||||
|
||||
### 2.2. Аудит
|
||||
|
||||
```bash
|
||||
cd lab1
|
||||
python -m stylometry.cli audit
|
||||
```
|
||||
|
||||
Результаты:
|
||||
|
||||
- `data/processed/lines.csv` — нормализованные реплики;
|
||||
- `data/processed/audit.md` — отчёт с распределением классов, длин и сверкой
|
||||
с `stats_per_character.xlsx`;
|
||||
- `data/processed/figures/class_distribution.png` — график.
|
||||
|
||||
---
|
||||
|
||||
## 3. Предобработка
|
||||
|
||||
Корпус не перечищается. Выполняются только обратимые и не меняющие смысл
|
||||
операции:
|
||||
|
||||
1. Приведение Unicode: многоточие, кавычки, тире, неразрывные пробелы.
|
||||
2. Замена плейсхолдеров `<PLAYER>`, `<FARM>`, `<PET>`, `<SPOUSE>`, `<TIME>`,
|
||||
`<NOUN>`, `<NAME>` на слова `PLAYER`, `FARM` и т.д. Количество плейсхолдеров
|
||||
сохраняется отдельным признаком.
|
||||
3. Схлопывание повторных пробелов.
|
||||
4. Токенизация NLTK: `word_tokenize`.
|
||||
5. Разбиение на предложения: `sent_tokenize`.
|
||||
6. Частеречная разметка: `pos_tag`; перевод тегов Penn Treebank в Universal
|
||||
POS.
|
||||
7. Для POS-последовательностей подряд идущие знаки препинания схлопываются в
|
||||
один тег `PUNCT`.
|
||||
|
||||
Не выполняется:
|
||||
|
||||
- удаление стоп-слов (они являются стилометрическим сигналом);
|
||||
- удаление пунктуации;
|
||||
- лемматизация по умолчанию (инфлексия — тоже стиль);
|
||||
- удаление коротких реплик;
|
||||
- приведение регистра к нижнему для всех признаков.
|
||||
|
||||
### 3.1. Ресурсы NLTK
|
||||
|
||||
```bash
|
||||
cd lab1
|
||||
python scripts/download_nltk_data.py
|
||||
```
|
||||
|
||||
Скачиваются `punkt`, `punkt_tab`, `averaged_perceptron_tagger`,
|
||||
`averaged_perceptron_tagger_eng`, `stopwords` в `lab1/nltk_data`. Если ресурсы
|
||||
недоступны, токенизатор переходит в резервный режим на регулярных выражениях,
|
||||
а POS-признаки отключаются. Для финальных экспериментов нужен NLTK-режим:
|
||||
проверьте, что в метаданных запуска `pos_available=true`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Признаковое пространство
|
||||
|
||||
### 4.1. Ручные стилометрические признаки
|
||||
|
||||
Всего около 454 признаков. Они не обучаются на данных, поэтому могут быть
|
||||
посчитаны заранее.
|
||||
|
||||
| Группа | Примеры | Статус |
|
||||
|---|---|---|
|
||||
| Длина | число токенов, слов, символов, предложений; средняя длина предложения; доля длинных слов | Основная, но чувствительна к длине |
|
||||
| Лексика | распределение длин слов, доля слов с апострофом, заглавных, цифр | Основная |
|
||||
| Словарное богатство | TTR, Guiraud, Herdan, Yule's K, Simpson's D, hapax/dis, Honoré | Предварительный |
|
||||
| Символы | частоты букв a–z, доля заглавных, цифр, пунктуации, апострофов | Основная |
|
||||
| Пунктуация | запятые, точки, восклицательные, вопросительные, многоточия, повторная пунктуация | Основная |
|
||||
| Функциональные слова | около 150 закрытых слов и 12 категорий | Основная |
|
||||
| Местоимения | 1-е, 2-е, 3-е лицо, возвратные, притяжательные, отношение I/you | Основная |
|
||||
| Части речи | Universal POS, Penn Treebank, модальность, время, герундий, причастие | Основная |
|
||||
| Синтаксис-прокси | число клауз, подчинительные союзы, вопрос/восклицание, пассив-прокси | Основная |
|
||||
| Читаемость | Flesch, FK grade, Gunning Fog, SMOG, Coleman-Liau, ARI | Предварительный |
|
||||
| Разговорные маркеры | плейсхолдеры, ALL CAPS, многоточия, междометия, смех, дискурсивные маркеры, хеджи, интенсификаторы, вежливость, отрицания, сокращения | Основная |
|
||||
|
||||
Признаки `vocabulary` и `readability` помечены как предварительные: на репликах
|
||||
длиной 10–20 слов они нестабильны. Их влияние нужно проверять отдельно, а не
|
||||
включать в основной вывод без оговорок.
|
||||
|
||||
### 4.2. Символьные n-граммы
|
||||
|
||||
TF-IDF по `char_wb`, диапазон 2–5, `min_df=3`, до 5000 признаков, L2-норма.
|
||||
Хорошо отражают морфологию, пунктуацию и орфографические привычки.
|
||||
|
||||
### 4.3. POS n-граммы
|
||||
|
||||
TF-IDF по последовательностям Universal POS, диапазон 1–3, `min_df=3`, до 500
|
||||
признаков, L2-норма. Это относительно устойчивый к теме синтаксический сигнал.
|
||||
|
||||
### 4.4. Словарь признаков
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli features
|
||||
```
|
||||
|
||||
Создаёт:
|
||||
|
||||
- `features/stylometric.csv` — матрица 2005 × 454;
|
||||
- `features/feature_dictionary.csv` — название, группа, описание, статус.
|
||||
|
||||
Словарь нужно использовать в отчёте: для каждой группы указать, какие
|
||||
признаки и почему выбраны.
|
||||
|
||||
---
|
||||
|
||||
## 5. Латентно-семантический анализ
|
||||
|
||||
LSA реализован как:
|
||||
|
||||
```text
|
||||
TF-IDF -> TruncatedSVD(k) -> L2-нормализация
|
||||
```
|
||||
|
||||
Варианты:
|
||||
|
||||
| Вариант | Колонка | n-граммы | Что отражает |
|
||||
|---|---|---|---|
|
||||
| `word` | `text` | 1 | тему и стиль |
|
||||
| `word2` | `text` | 1–2 | тему и устойчивые сочетания |
|
||||
| `content` | `content_text` | 1–2 | содержание после удаления стоп-слов |
|
||||
| `fw` | `fw_text` | 1–2 | синтаксис через функциональные слова |
|
||||
| `char` | `text` | 2–5 (символы) | морфологию и пунктуацию |
|
||||
| `pos` | `pos_text` | 1–4 (POS) | синтаксический стиль |
|
||||
|
||||
Основные параметры: `sublinear_tf=true`, `min_df=3`, `max_df=0.9`,
|
||||
`max_features=2000–8000`, `n_components=50–300`. Все параметры настраиваются
|
||||
только на обучающих блоках; для интерпретационных графиков можно обучить LSA
|
||||
на всём корпусе, но это нельзя использовать для оценки качества.
|
||||
|
||||
### 5.1. Что проверять в LSA
|
||||
|
||||
1. **График объяснённой дисперсии и накопленная дисперсия.** Сколько
|
||||
компонент объясняют основную часть дисперсии.
|
||||
2. **Top-термины компонент.** Интерпретируемость осей: тема, эмоциональность,
|
||||
формальность, длина.
|
||||
3. **Внешняя оценка.** Macro-F1 классификатора при разных `k`.
|
||||
4. **Сравнение вариантов.** Если `lsa_word` и `lsa_content` значительно лучше
|
||||
`lsa_pos` и `lsa_fw`, классификация в существенной степени опирается на
|
||||
тему, а не на стиль.
|
||||
5. **Стабильность.** Bootstrap по репликам и углы между подпространствами
|
||||
(опционально; при малом числе компонент полезно).
|
||||
|
||||
### 5.2. Команды
|
||||
|
||||
```bash
|
||||
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 lsa-sweep --variants word,content,fw,char,pos \
|
||||
--components 50,100,200 --model logreg --repeats 1
|
||||
```
|
||||
|
||||
Результаты: матрицы `features/lsa_<variant>_k<k>.csv`, наиболее
|
||||
информативные термины компонент, объяснённая дисперсия, график объяснённой
|
||||
дисперсии.
|
||||
|
||||
---
|
||||
|
||||
## 6. Классификаторы
|
||||
|
||||
В основном сравнении участвуют:
|
||||
|
||||
| Модель | Краткая характеристика | Вероятности |
|
||||
|---|---|---|
|
||||
| `dummy` | предсказывает самый частый класс | да |
|
||||
| `multinomial_nb` | наивный байесовский классификатор для неотрицательных признаков | да |
|
||||
| `logreg` | логистическая регрессия с L2 и балансировкой классов | да |
|
||||
| `linear_svc` | линейный метод опорных векторов | нет, есть решающая функция |
|
||||
| `random_forest` | случайный лес | да |
|
||||
| `extra_trees` | сверхслучайные деревья | да |
|
||||
| `knn` | k ближайших соседей с косинусным расстоянием | да |
|
||||
|
||||
Для MultinomialNB автоматически исключаются LSA-блоки (компоненты могут быть
|
||||
отрицательными) и используется MinMax-масштабирование. Для остальных моделей
|
||||
ручные признаки стандартизуются и L2-нормируются, а TF-IDF- и LSA-блоки уже
|
||||
нормированы. Это нужно, чтобы блоки разной размерности не подавляли друг
|
||||
друга.
|
||||
|
||||
Подробное описание моделей, их формул, гиперпараметров и ограничений — в
|
||||
`METRICS_AND_CLASSIFIERS.md`.
|
||||
|
||||
### 6.1. Сетки гиперпараметров
|
||||
|
||||
| Модель | Параметры |
|
||||
|---|---|
|
||||
| `logreg` | `C ∈ {0.1, 1, 10}` |
|
||||
| `linear_svc` | `C ∈ {0.1, 1, 10}` |
|
||||
| `random_forest`, `extra_trees` | `max_depth ∈ {None, 30}`, `min_samples_leaf ∈ {1, 2}` |
|
||||
| `multinomial_nb` | `alpha ∈ {0.1, 1, 3}` |
|
||||
| `knn` | `n_neighbors ∈ {3, 5, 9}` |
|
||||
|
||||
Настройка выполняется внутри вложенной кросс-валидации. Для одиночного запуска
|
||||
`run` без `--nested` гиперпараметры фиксированы значениями по умолчанию; это
|
||||
быстрее, но для финального сравнения нужен `--nested`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Схема валидации
|
||||
|
||||
### 7.1. Основная схема
|
||||
|
||||
```python
|
||||
RepeatedStratifiedKFold(n_splits=5, n_repeats=5, random_state=42)
|
||||
```
|
||||
|
||||
Почему 5 блоков:
|
||||
|
||||
- минимальный класс — 15 реплик;
|
||||
- в каждом тестовом блоке около 3 реплик на класс;
|
||||
- все 34 класса присутствуют и в обучении, и в тесте;
|
||||
- 10 блоков дали бы 1–2 реплики на класс и ещё более шумные оценки.
|
||||
|
||||
Почему повторная:
|
||||
|
||||
- один прогон 5-блочной CV даёт одну оценку; повторность позволяет оценить
|
||||
разброс;
|
||||
- для финального отчёта используйте 5 повторов; для быстрых проверок — 1–3.
|
||||
|
||||
### 7.2. Вложенная кросс-валидация
|
||||
|
||||
```python
|
||||
outer = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
|
||||
inner = StratifiedKFold(n_splits=3, shuffle=True, random_state=42)
|
||||
```
|
||||
|
||||
Внешние блоки — оценка качества; внутренние — настройка гиперпараметров.
|
||||
Такой протокол уменьшает оптимистическое смещение, которое возникает, если
|
||||
настраивать гиперпараметры на тех же данных, где измеряется качество.
|
||||
|
||||
### 7.3. Контроль утечек
|
||||
|
||||
- TF-IDF, SVD, масштабирование и отбор признаков обучаются только на
|
||||
обучающем блоке.
|
||||
- Ручные признаки и POS-теги не используют метки; их можно считать заранее.
|
||||
- Точных дублей реплик в корпусе нет, поэтому одна и та же реплика не может
|
||||
попасть в обучение и тест.
|
||||
- При появлении почти одинаковых реплик нужно проверить `StratifiedGroupKFold`
|
||||
с группами по нормализованному тексту. В текущем корпусе точных дублей нет.
|
||||
- Нельзя выбирать признаки или `k` LSA по тестовым метрикам. Все решения — по
|
||||
внутренней кросс-валидации.
|
||||
|
||||
---
|
||||
|
||||
## 8. Метрики
|
||||
|
||||
Подробные определения, формулы и интерпретация — в
|
||||
`METRICS_AND_CLASSIFIERS.md`. Кратко:
|
||||
|
||||
| Метрика | Роль |
|
||||
|---|---|
|
||||
| Macro-F1 | Основная метрика: каждый из 34 классов равноправен |
|
||||
| Сбалансированная доля правильных ответов | Средняя полнота по классам; удобна для редких персонажей |
|
||||
| Доля правильных ответов | Нужна для сравнения с литературой |
|
||||
| MCC | Устойчив к дисбалансу, учитывает все клетки матрицы ошибок |
|
||||
| Cohen's kappa | Согласие с поправкой на случай |
|
||||
| Top-3, top-5 | Важны при 34 классах |
|
||||
| Log loss, Brier | Качество вероятностей и калибровка |
|
||||
| Точность, полнота и F-мера по классам | Показывают, какие персонажи проваливаются |
|
||||
| Матрица ошибок | Анализ пар перепутывания |
|
||||
|
||||
Основной отчётный результат — **pooled out-of-fold macro-F1** с 95%
|
||||
бутстрэп-интервалом и среднее ± стандартное отклонение по повторам. Среднее
|
||||
macro-F1 по отдельным блокам тоже полезно, но на класс приходится около трёх
|
||||
объектов, поэтому оно шумное.
|
||||
|
||||
### 8.1. Статистические сравнения
|
||||
|
||||
- **Мак-Немар** — парное сравнение двух моделей на одних и тех же тестовых
|
||||
репликах.
|
||||
- **Уилкоксон** — парное сравнение результатов по блокам; описательная
|
||||
проверка стабильности.
|
||||
- **Фридман** — сравнение трёх и более моделей.
|
||||
- **Поправка Холма—Бонферрони** — при множественных сравнениях.
|
||||
- **Бутстрэп-интервалы** — основной способ показать неопределённость.
|
||||
|
||||
Не сравнивайте модели только по доле правильных ответов: при дисбалансе и
|
||||
34 классах она может вводить в заблуждение. Пример: модель, предсказывающая
|
||||
только Abigail, имеет долю правильных ответов около 7%, но macro-F1 около
|
||||
0,004.
|
||||
|
||||
---
|
||||
|
||||
## 9. Матрица экспериментов
|
||||
|
||||
Все команды выполняются из `lab1`. Перед серией полезно один раз выполнить
|
||||
`audit` и `features`.
|
||||
|
||||
### E0. Аудит корпуса
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli audit
|
||||
```
|
||||
|
||||
Что проверить: число реплик и классов, распределение длин, отсутствие дублей,
|
||||
совпадение с `stats_per_character.xlsx`.
|
||||
|
||||
### E1. Базовые уровни
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli run --preset length --model logreg --repeats 5
|
||||
python -m stylometry.cli run --preset char --model multinomial_nb --repeats 3
|
||||
python -m stylometry.cli run --preset pos --model multinomial_nb --repeats 3
|
||||
python -m stylometry.cli run --preset fw --model logreg --repeats 3
|
||||
python -m stylometry.cli run --preset length --model dummy --repeats 1
|
||||
```
|
||||
|
||||
Смысл: понять, сколько сигнала даёт только длина, только символьные n-граммы,
|
||||
только POS, только функциональные слова и случайная/частотная базовая модель.
|
||||
|
||||
### 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.
|
||||
|
||||
### E3. Поочерёдное исключение групп признаков
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli ablate --preset stylometry_pos_lsa --model logreg --repeats 3
|
||||
```
|
||||
|
||||
Для каждой группы признаков строится вариант «без этой группы». Результат —
|
||||
`results/ablation_*/ablation.csv` с колонкой `delta_macro_f1`. Отрицательное
|
||||
значение означает, что удаление группы ухудшило качество; положительное — что
|
||||
группа мешала (возможно, из-за шума или переобучения).
|
||||
|
||||
### E4. POS-признаки
|
||||
|
||||
Сравните:
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli run --preset stylometry --model logreg --repeats 5
|
||||
python -m stylometry.cli run --preset stylometry_pos --model logreg --repeats 5
|
||||
```
|
||||
|
||||
Разница macro-F1 показывает вклад символьных и POS n-грамм.
|
||||
|
||||
### E5. LSA: варианты и число компонент
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli lsa-sweep \
|
||||
--variants word,content,fw,char,pos \
|
||||
--components 50,100,200 \
|
||||
--model logreg --repeats 1
|
||||
```
|
||||
|
||||
Затем лучшие `k` и варианты проверить с 5 повторами через `run`:
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli run --preset lsa_word --model logreg --repeats 5
|
||||
```
|
||||
|
||||
Для `lsa_word` и `lsa_pos` число компонент задаётся в `FeatureConfig`; в
|
||||
командной строке текущая версия использует значение из `presets`
|
||||
(`lsa_components=100`). Если нужно другое `k`, используйте `lsa-sweep` или
|
||||
измените `FeatureConfig` в сценарии.
|
||||
|
||||
### E6. Сравнение классификаторов
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli benchmark --preset stylometry_pos_lsa \
|
||||
--models logreg,linear_svc,random_forest,multinomial_nb,knn \
|
||||
--repeats 3
|
||||
```
|
||||
|
||||
Результат: `results/benchmark_*/summary.csv`, отдельные каталоги по моделям.
|
||||
|
||||
### E7. Стиль или тема
|
||||
|
||||
Сравните LSA-варианты:
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli lsa-sweep \
|
||||
--variants word,content,fw,char,pos \
|
||||
--components 50,100,200 --model logreg --repeats 1
|
||||
```
|
||||
|
||||
Ожидаемая интерпретация:
|
||||
|
||||
- `word` и `content` лучше — вклад темы велик;
|
||||
- `pos` и `fw` сопоставимы — стиль/синтаксис достаточно информативны;
|
||||
- `char` полезен для морфологии и пунктуации.
|
||||
|
||||
### E8. Объединение блоков
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --repeats 5
|
||||
python -m stylometry.cli run --preset all --model logreg --repeats 3
|
||||
```
|
||||
|
||||
Сравните с E2 и E5. Если объединение не лучше лучшего отдельного блока,
|
||||
проверьте веса блоков и размерности.
|
||||
|
||||
### E9. Влияние длины
|
||||
|
||||
1. Запустите `run --preset length`, `--preset stylometry`,
|
||||
`--preset stylometry_pos_lsa`.
|
||||
2. Для сохранённого запуска выполните:
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli length-report --run-dir results/<каталог_запуска>
|
||||
```
|
||||
|
||||
Команда сама соединяет предсказания с `data/processed/lines.csv`, разбивает
|
||||
реплики на группы 0–5, 6–10, 11–15, 16–20, 21–30, 31+ слов и считает
|
||||
macro-F1 с бутстрэп-интервалом. В каждой группе macro-F1 считается по
|
||||
классам, которые в ней присутствуют; поэтому сравнение групп с разным
|
||||
набором персонажей нужно интерпретировать осторожно. Результат сохраняется
|
||||
в `length_bins.csv` внутри каталога запуска.
|
||||
|
||||
Ожидание: качество может зависеть от длины, но монотонность не гарантирована.
|
||||
В предварительном прогоне объединённого набора лучшие значения оказались
|
||||
в группах 21–30 и 31+ слов, а группа 0–5 слов дала широкий интервал из-за
|
||||
малого числа объектов. Если длина вносит существенный вклад, сравните
|
||||
результаты с `--preset length` и без length-признаков (поочерёдное исключение
|
||||
групп).
|
||||
|
||||
### E10. Дисбаланс классов
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli benchmark --preset stylometry_pos_lsa \
|
||||
--models logreg,linear_svc,random_forest --repeats 3
|
||||
```
|
||||
|
||||
Смотрите не только macro-F1, но и F-меру по классам, сбалансированную долю
|
||||
правильных ответов и support. Сравните `class_weight="balanced"` (в коде
|
||||
включено для logreg, SVM, RF) с
|
||||
вариантом без балансировки: для этого нужно изменить `make_classifier` или
|
||||
передать параметр.
|
||||
|
||||
### E11. Дельта Барроуза
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli delta --features 100,200,500 --metrics manhattan,cosine --repeats 3
|
||||
```
|
||||
|
||||
Классическая стилометрическая базовая модель. Ожидается, что на коротких репликах
|
||||
он уступает ML-моделям; важен как независимая проверка.
|
||||
|
||||
### E12. Верификация «свой/чужой»
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli verify --preset stylometry_pos_lsa
|
||||
```
|
||||
|
||||
Для каждой тестовой реплики считается близость к центроидам всех персонажей.
|
||||
Положительный класс — центроид своего персонажа, отрицательный — чужие.
|
||||
Метрики: ROC-AUC, EER, TAR@FAR=1%, top-1. Это более мягкая
|
||||
постановка, чем 34-классовая классификация.
|
||||
|
||||
### E13. Кластеризация
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli cluster --preset stylometry_pos_lsa
|
||||
```
|
||||
|
||||
Строятся центроиды персонажей, иерархическая кластеризация и k-means.
|
||||
Метрики: ARI, NMI, силуэт. Кластеризация носит предварительный характер: она показывает, какие
|
||||
персонажи близки в признаковом пространстве, но не заменяет классификацию.
|
||||
|
||||
### E14. Анализ ошибок
|
||||
|
||||
После любого запуска откройте:
|
||||
|
||||
- `per_class_report.csv` — precision, recall, F1, support по персонажам;
|
||||
- `confusion_matrix_normalized.csv` — доли перепутывания;
|
||||
- `top_confusions.csv` — самые частые пары;
|
||||
- `figures/confusion_matrix.png` — тепловая карта.
|
||||
|
||||
Что искать:
|
||||
|
||||
- персонажи с малым support и низким F1;
|
||||
- пары с высокой взаимной ошибкой (например, дети, нелюди, персонажи с
|
||||
похожей ролью);
|
||||
- влияние длины: короткие реплики чаще путаются;
|
||||
- признаки, важные для лучшей модели (коэффициенты логистической регрессии,
|
||||
permutation importance для деревьев).
|
||||
|
||||
Для анализа по метаданным (пол, возраст, вид) используйте:
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
Команда сохраняет `subgroup_<group>_metrics.csv` и
|
||||
`subgroup_<group>_confusions.csv`. Метаданные лежат в
|
||||
`data/metadata/characters.csv`; это экспертные пометки, а не часть корпуса,
|
||||
поэтому они не используются как признаки классификатора.
|
||||
|
||||
### E15. Статистическое сравнение
|
||||
|
||||
Для двух лучших моделей:
|
||||
|
||||
```bash
|
||||
python -m stylometry.cli compare \
|
||||
--run-a results/<каталог_запуска_A> \
|
||||
--run-b results/<каталог_запуска_B>
|
||||
```
|
||||
|
||||
Команда соединяет out-of-fold предсказания по `line_id`, проверяет
|
||||
совпадение истинных классов и считает точный критерий Мак-Немара и
|
||||
бутстрэп-интервал разницы macro-F1. Результат сохраняется в
|
||||
`comparison_with_other.json`. Для корректного парного сравнения запускайте
|
||||
модели с одинаковыми `--folds` и `--seed`.
|
||||
|
||||
Для трёх и более моделей используйте `friedman_test` из
|
||||
`stylometry/stats.py` по метрикам блоков и поправку Холма.
|
||||
|
||||
### 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` и метрики внешних блоков.
|
||||
|
||||
### E17. Дополнительно: агрегация в псевдодокументы
|
||||
|
||||
Основной протокол — уровень реплик. Если понадобится формально закрыть
|
||||
требование «не менее 30 предложений на текст», можно реализовать отдельный
|
||||
сценарий: склеить реплики одного персонажа в псевдодокументы по 30 предложений
|
||||
и повторить E2–E9. Этот сценарий **не включён** в основной код, потому что
|
||||
меняет единицу анализа и уменьшает число объектов. Его результаты следует
|
||||
рассматривать как robustness check, а не как замену основного эксперимента.
|
||||
|
||||
---
|
||||
|
||||
## 10. Контроль утечек и воспроизводимости
|
||||
|
||||
Перед финальным запуском проверьте:
|
||||
|
||||
- [ ] `data/processed/tokenized.pkl` соответствует текущему SHA-256 корпуса.
|
||||
- [ ] В метаданных запуска `pos_available=true`; POS-признаки не отключились.
|
||||
- [ ] TF-IDF, SVD и масштабирование обучаются внутри блоков (это обеспечивает
|
||||
`Pipeline`; не выносите их наружу).
|
||||
- [ ] `k` LSA и гиперпараметры выбраны по внутренней CV, а не по тесту.
|
||||
- [ ] В корпусе нет точных дублей; при появлении почти одинаковых реплик
|
||||
используется группировка.
|
||||
- [ ] Для финальных чисел выполнено не менее 3–5 повторов.
|
||||
- [ ] Сохранены `run_metadata.json`, `fold_metrics.csv`, `pooled_metrics.csv`,
|
||||
`oof_predictions.csv`, `confusion_matrix.csv`.
|
||||
- [ ] Указаны версии библиотек и seed.
|
||||
|
||||
---
|
||||
|
||||
## 11. Текущие технические прогоны
|
||||
|
||||
Ниже — предварительные результаты одного повтора 5-блочной CV. Они нужны
|
||||
только для проверки работоспособности конвейера и **не являются финальными**:
|
||||
один повтор даёт широкий интервал, а гиперпараметры не настраивались.
|
||||
|
||||
| Набор признаков | Модель | Macro-F1 | Доля правильных ответов | Top-3 |
|
||||
|---|---|---:|---:|---:|
|
||||
| `stylometry` | logreg | 0,1002 | 0,0988 | 0,2389 |
|
||||
| `stylometry_pos` | logreg | 0,1780 | 0,1681 | 0,3367 |
|
||||
| `stylometry_pos_lsa` | logreg | 0,1802 | 0,1706 | 0,3387 |
|
||||
| `lsa_word`, k=50 | logreg | 0,0618 | 0,0628 | 0,1835 |
|
||||
| `lsa_pos`, k=50 | logreg | 0,0443 | 0,0459 | 0,1202 |
|
||||
| `char` | multinomial_nb | 0,0280 | 0,0973 | 0,2464 |
|
||||
|
||||
Наблюдения:
|
||||
|
||||
- символьные и POS n-граммы дают основной прирост относительно ручных
|
||||
признаков;
|
||||
- LSA по словам и POS сама по себе слабее, но в объединении даёт небольшой
|
||||
прирост;
|
||||
- доля правильных ответов у `char + multinomial_nb` около 9,7%, но
|
||||
сбалансированная доля правильных ответов 4,7% и macro-F1 2,8%: модель
|
||||
предсказывает частые классы. Это иллюстрация того, почему долю правильных
|
||||
ответов нельзя использовать как единственную метрику.
|
||||
|
||||
Верификация для `stylometry` (5 блоков): ROC-AUC ≈ 0,648, EER ≈ 0,395,
|
||||
top-1 ≈ 0,093. Это выше случайного уровня (ROC-AUC 0,5), но далеко от
|
||||
практически надёжного различения.
|
||||
|
||||
Поочерёдное исключение групп для `stylometry` (один повтор): удаление группы `characters`
|
||||
снижает macro-F1 примерно на 0,015, удаление `vocabulary` — примерно на
|
||||
0,008; остальные изменения в пределах шума. Эти числа нужно перепроверить с
|
||||
несколькими повторами.
|
||||
|
||||
---
|
||||
|
||||
## 12. Как интерпретировать результаты
|
||||
|
||||
1. **Сравнивайте с случайным уровнем.** Для 34 классов доля правильных
|
||||
ответов 2,9%, macro-F1 2,9%, top-3 8,8%.
|
||||
2. **Основной вывод — по macro-F1 и доверительному интервалу**, а не по
|
||||
доле правильных ответов.
|
||||
3. **Смотрите F-меру по классам.** Если редкие персонажи не различаются, это
|
||||
важный вывод, а не техническая деталь.
|
||||
4. **Сравнивайте стиль и тему.** Если `lsa_word`/`lsa_content` значительно
|
||||
лучше `lsa_pos`/`lsa_fw`, классификатор опирается на содержание.
|
||||
5. **Проверяйте длину.** Если `length` даёт заметный сигнал, часть результата
|
||||
объясняется длиной реплик, а не синтаксисом.
|
||||
6. **Не переинтерпретируйте небольшие различия.** При 2005 объектах и 34
|
||||
классах разница в 1–2 процентных пункта может быть шумом; нужны
|
||||
доверительные интервалы и парные тесты.
|
||||
7. **Помните про одного автора.** Результат говорит о различимости персонажей,
|
||||
а не о разных авторах.
|
||||
|
||||
---
|
||||
|
||||
## 13. Ограничения
|
||||
|
||||
- Короткие тексты: признаки словарного богатства и читаемости нестабильны.
|
||||
- Один автор: это классификация речевых масок, не авторская атрибуция.
|
||||
- Ручная фильтрация корпуса: короткие и общие фразы удалены, правила не
|
||||
восстановлены.
|
||||
- Дисбаланс классов: 15–139 реплик; редкие классы дают широкие интервалы.
|
||||
- Нет идентификаторов сцен: нельзя учесть корреляцию реплик внутри одной
|
||||
сцены.
|
||||
- NLTK-теггер ошибается на разговорных конструкциях.
|
||||
- LSA может отражать тему; сравнение вариантов обязательно.
|
||||
- Кластеризация и t-SNE — предварительный анализ, не доказательство.
|
||||
|
||||
---
|
||||
|
||||
## 14. Чек-лист перед защитой
|
||||
|
||||
- [ ] В отчёте описаны корпус, ручная фильтрация и её ограничения.
|
||||
- [ ] Указано, что задача — character idiolect, а не авторская атрибуция.
|
||||
- [ ] Перечислены группы признаков и обоснован выбор.
|
||||
- [ ] Описаны варианты LSA и способ выбора числа компонент.
|
||||
- [ ] Указаны классификаторы, гиперпараметры и схема валидации.
|
||||
- [ ] Основная метрика — macro-F1; приведены доверительные интервалы.
|
||||
- [ ] Есть отчёт по классам и матрица ошибок.
|
||||
- [ ] Есть сравнение стиля и темы (`lsa_word` vs `lsa_pos`/`lsa_fw`).
|
||||
- [ ] Есть анализ длины и поочерёдное исключение групп признаков.
|
||||
- [ ] Есть статистическое сравнение моделей.
|
||||
- [ ] Сформулированы ограничения и направления улучшения.
|
||||
- [ ] Код, отчёт и презентация воспроизводимы по `README.md`.
|
||||
|
||||
---
|
||||
|
||||
## 15. Куда сохраняются результаты
|
||||
|
||||
```text
|
||||
results/
|
||||
├── <preset>_<model>_<timestamp>/
|
||||
│ ├── run_metadata.json
|
||||
│ ├── fold_metrics.csv
|
||||
│ ├── fold_summary.csv
|
||||
│ ├── pooled_metrics.csv
|
||||
│ ├── bootstrap_ci.json
|
||||
│ ├── oof_predictions.csv
|
||||
│ ├── per_class_report.csv
|
||||
│ ├── confusion_matrix.csv
|
||||
│ ├── confusion_matrix_normalized.csv
|
||||
│ ├── top_confusions.csv
|
||||
│ ├── summary.md
|
||||
│ └── figures/
|
||||
├── benchmark_<preset>_<timestamp>/
|
||||
│ ├── summary.csv
|
||||
│ └── <model>/
|
||||
├── ablation_<preset>_<timestamp>/
|
||||
│ └── ablation.csv
|
||||
├── lsa_sweep_<timestamp>/
|
||||
│ └── lsa_sweep.csv
|
||||
├── delta_<timestamp>/
|
||||
│ └── delta_sweep.csv
|
||||
├── verification_<preset>_<timestamp>/
|
||||
│ ├── fold_metrics.csv
|
||||
│ ├── pair_scores.csv
|
||||
│ └── summary.json
|
||||
└── clustering_<preset>_<timestamp>/
|
||||
├── clustering_metrics.csv
|
||||
├── character_centroids.csv
|
||||
└── figures/
|
||||
```
|
||||
Reference in New Issue
Block a user