diff --git a/lab1/TUNING_EXPERIMENTS.md b/lab1/TUNING_EXPERIMENTS.md new file mode 100644 index 0000000..d12881e --- /dev/null +++ b/lab1/TUNING_EXPERIMENTS.md @@ -0,0 +1,407 @@ +# Серия настройки (T1–T11) + +Документ описывает **дополнительные** эксперименты поверх полной серии +`scripts/run_all_experiments.sh`. Они не заменяют протокол E0–E16 из +`EXPERIMENTS.md` и не повторяют его запуски с теми же параметрами. + +Полная серия измеряет качество на **значениях по умолчанию**. Эта серия +проверяет, меняется ли macro-F1, если изменить регуляризацию, состав +признаков, n-граммы, веса блоков, число компонент LSA или гиперпараметры +деревьев. + +Справочник «где в коде лежит параметр» — `TUNING.md`. Здесь — что запускать, +зачем и как интерпретировать. + +--- + +## 1. Зачем эта серия + +Исследовательский вопрос тот же: различимы ли 34 персонажа по одной реплике. +Базовый ответ даёт `stylometry_pos_lsa` + `logreg` из полной серии. + +Дополнительно нужно понять: + +- не слишком ли слабая или сильная регуляризация при 2005 объектах и 34 классах; +- не вредят ли нестабильные группы (`vocabulary`, `readability`) и признаки длины; +- не переобучаются ли широкие символьные n-граммы; +- не давит ли один блок признаков на остальные после L2-нормировки; +- не лучше ли другое число компонент LSA, чем `k=100`; +- не лучше ли более мелкие деревья, чем лес без ограничения глубины; +- даёт ли дельта Барроуза что-то на краях диапазона MFW (50 и 1000 слов). + +Главная метрика по-прежнему **macro-F1** с бутстрэп-интервалом. Разница в +1–2 процентных пункта часто шум: сравнивайте запуски через `compare` +(Мак-Немар и бутстрэп-разница), а не «на глаз» по одному числу. + +--- + +## 2. Что нельзя путать с полной серией + +| Полная серия (`run_all_experiments.sh`) | Эта серия | +|---|---| +| Базовые пресеты, абляции leave-one-out, LSA 50/100/200, benchmark моделей, nested CV | Перебор **внутри** лучшего пресета | +| Logreg/SVM с `C=1`, `class_weight="balanced"` | Другие `C`, отключение весов классов | +| Char `[2,5]` / 5000, POS `[1,3]` / 500, `min_df=3` | Узкие и широкие n-граммы | +| Равные веса блоков | Заданные веса | +| Дельта 100/200/500 MFW | Дельта 50 и 1000 MFW | +| Extra trees нет | Один контролируемый запуск extra trees | + +Не запускайте эту серию вместо E0–E16. Сначала нужна база: каталог +`results/stylometry_pos_lsa_logreg_/` с 5 повторами (или хотя бы 3). + +--- + +## 3. Как запускать + +Все команды — из каталога `lab1`. Схема CV та же, что в протоколе: +5 блоков, seed `42`. Для черновика достаточно 1 повтора, для отчёта — 3 +(лучшие 1–2 конфигурации потом перепроверьте с 5). + +### 3.1. Вся серия скриптом + +```bash +cd lab1 +bash scripts/run_tuning_experiments.sh +``` + +Быстрый прогон: + +```bash +REPEATS=1 bash scripts/run_tuning_experiments.sh +``` + +Другой интерпретатор: + +```bash +PYTHON=../.venv/bin/python bash scripts/run_tuning_experiments.sh +``` + +Лог: `results/logs/tune_.log`. +Каждый `run` создаёт **новый** каталог `results/__/`. +У двух запусков с одним пресетом имена отличаются только меткой времени; +какой это был вариант, смотрите в `run_metadata.json` (`model_params`, +`feature_config`). + +### 3.2. Один эксперимент вручную + +Конфиги лежат в `configs/tune_*.toml`. Каждый файл — **одна** точка перебора +признаков. Модель и пресет задаются в команде, не в имени файла. + +```bash +python -m stylometry.cli run \ + --config configs/tune_no_vocab_readability.toml \ + --preset stylometry_pos_lsa \ + --model logreg \ + --repeats 3 \ + --seed 42 +``` + +Параметры классификатора toml не требуют — их передаёт `--model-params`. + +### 3.3. Сравнение с базой + +```bash +python -m stylometry.cli compare \ + --run-a results/stylometry_pos_lsa_logreg_<база> \ + --run-b results/stylometry_pos_lsa_logreg_<тюнинг> +``` + +Оба запуска должны иметь одинаковые `--folds` и `--seed`. Иначе парное +сравнение некорректно. + +--- + +## 4. Конфиги признаков + +Файлы не «включают серию целиком»: каждый подменяет только указанные поля +`FeatureConfig`. Остальное берётся из пресета `stylometry_pos_lsa`. + +| Файл | Что меняет | +|---|---| +| `configs/tune_no_vocab_readability.toml` | группы без `vocabulary` и `readability` | +| `configs/tune_no_vocab_readability_length.toml` | ещё без `length` | +| `configs/tune_char_narrow.toml` | char `[2,4]`, 3000 признаков, POS 500, `min_df=5` | +| `configs/tune_char_wide.toml` | char `[2,6]`, 8000, POS `[1,4]` / 800, `min_df=2` | +| `configs/tune_block_weights.toml` | веса `stylo/char/pos/lsa_word/lsa_pos` | +| `configs/tune_lsa_k150.toml` | `lsa_components = 150` | +| `configs/tune_lsa_k300.toml` | `lsa_components = 300` | + +--- + +## 5. Эксперименты + +Базовый пресет везде `stylometry_pos_lsa`, если не сказано иное. +Ориентир для сравнения — pooled macro-F1 базового logreg из полной серии. + +### T1. Логистическая регрессия: `C` + +**Зачем.** `C` — обратная сила L2-регуляризации. На широком признаковом +пространстве (ручные признаки + n-граммы + LSA) модель с `C=1` может +переобучаться или, наоборот, быть слишком простой. Нужно найти диапазон, +а не одно «магическое» число. + +**Что меняется.** `C ∈ {0.03, 0.1, 0.3, 1, 3, 10}`. Остальное как в базе +(`class_weight="balanced"`). Значение `C=1` совпадает с полной серией; +его можно не гонять, если база уже есть. + +**Как запускать.** + +```bash +for c in 0.03 0.1 0.3 1 3 10; do + python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg \ + --repeats 3 --seed 42 --model-params "{\"C\": $c}" +done +``` + +**Как читать.** Меньше `C` — проще модель. Если macro-F1 растёт при уменьшении +`C`, база переобучалась. Если растёт только при `C ≥ 3`, регуляризации в базе +было слишком много. Смотрите также log loss: он показывает калибровку, не +только точность меток. + +### T2. Линейный SVM: `C` + +**Зачем.** Та же логика, другой критерий (зазор вместо логистической потери). +SVM в полной серии тоже шёл с `C=1`. Если лучший `C` у SVM и logreg близки, +вывод про регуляризацию устойчив. + +**Как запускать.** + +```bash +for c in 0.03 0.1 0.3 1 3 10; do + python -m stylometry.cli run --preset stylometry_pos_lsa --model linear_svc \ + --repeats 3 --seed 42 --model-params "{\"C\": $c}" +done +``` + +**Ограничение.** У `linear_svc` нет вероятностей: log loss не считается, +top-k строится по решающей функции. + +### T3. Logreg без балансировки классов + +**Зачем.** В корпусе 15–139 реплик на персонажа. `class_weight="balanced"` +почти наверняка нужен, но это надо показать: иначе macro-F1 может казаться +низким «из-за модели», хотя виноват сдвиг к частым классам (Abigail и т.д.). + +**Как запускать.** + +```bash +python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg \ + --repeats 3 --seed 42 --model-params '{"class_weight": null}' +``` + +**Как читать.** Если accuracy почти не падает, а macro-F1 и balanced accuracy +падают, модель без весов игнорирует редких персонажей. Это аргумент в пользу +macro-F1 как основной метрики. + +### T4. Без `vocabulary` и `readability` + +**Зачем.** На репликах ~19 слов TTR, индексы Honore/Yule и формулы читаемости +нестабильны (`FEATURES.md`, гипотеза H2). Полная серия делает leave-one-out +(`ablate`): удаляет **по одной** группе. Здесь обе шумные группы снимаются +сразу — ближе к тому, как собирали бы «очищенный» основной набор. + +**Конфиг.** `configs/tune_no_vocab_readability.toml` + +```bash +python -m stylometry.cli run --config configs/tune_no_vocab_readability.toml \ + --preset stylometry_pos_lsa --model logreg --repeats 3 --seed 42 +``` + +**Как читать.** Рост или отсутствие падения macro-F1 значит, что эти группы +не несут устойчивого сигнала (или мешают). Сильное падение — в протоколе их +нельзя вычёркивать без оговорки. + +### T5. Ещё без `length` + +**Зачем.** Гипотеза H4: длинные реплики классифицируются лучше. Если качество +не падает после удаления length-признаков, различимость персонажей не сводится +к «кто говорит длиннее». Если падает — часть результата объясняется длиной, +это нужно явно написать в отчёте. + +**Конфиг.** `configs/tune_no_vocab_readability_length.toml` + +```bash +python -m stylometry.cli run --config configs/tune_no_vocab_readability_length.toml \ + --preset stylometry_pos_lsa --model logreg --repeats 3 --seed 42 +``` + +Имеет смысл сопоставить с `length-report` по базовому запуску. + +### T6. Символьные и POS n-граммы: узкие vs широкие + +**Зачем.** В полной серии фиксированы char 2–5 / 5000 и POS 1–3 / 500. +Узкий вариант (короче n-граммы, выше `min_df`) проверяет переобучение на +редких орфографических шаблонах. Широкий (2–6, больше признаков, `min_df=2`) +проверяет, не теряем ли морфологию и пунктуационные привычки. + +**Конфиги.** `tune_char_narrow.toml`, `tune_char_wide.toml` + +```bash +python -m stylometry.cli run --config configs/tune_char_narrow.toml \ + --preset stylometry_pos_lsa --model logreg --repeats 3 --seed 42 + +python -m stylometry.cli run --config configs/tune_char_wide.toml \ + --preset stylometry_pos_lsa --model logreg --repeats 3 --seed 42 +``` + +**Как читать.** Если wide лучше на обучении блоков, но pooled macro-F1 не выше +базы (или хуже на редких классах) — переобучение. Если narrow не хуже базы — +лишняя размерность не нужна. + +### T7. Веса блоков + +**Зачем.** После L2-нормировки каждый блок имеет единичную норму и конкурирует +наравне, даже если один из них шумный. В базе веса равны. Здесь ослабляются +char и особенно `lsa_word` (тематический риск, гипотеза H3), POS и стилометрия +остаются сильнее. + +**Конфиг.** `configs/tune_block_weights.toml` + +```text +stylo = 1.0 +char = 0.5 +pos = 0.7 +lsa_word = 0.3 +lsa_pos = 0.5 +``` + +```bash +python -m stylometry.cli run --config configs/tune_block_weights.toml \ + --preset stylometry_pos_lsa --model logreg --repeats 3 --seed 42 +``` + +**Как читать.** Веса — такой же гиперпараметр, как `C`. Один удачный набор не +доказывает оптимум. Если macro-F1 вырос и `lsa_word` при этом ослаблен, это +дополнительный довод, что тема мешала стилю. + +### T8. Число компонент LSA: 150 и 300 + +**Зачем.** В полной серии `lsa-sweep` смотрит `k ∈ {50, 100, 200}` по +**отдельным** вариантам LSA. В основном пресете всегда `k=100` сразу для +`word` и `pos`. Здесь проверяется, помогает ли больше компонент **в +объединённом** наборе, плюс недостающие точки 150 и 300 в переборе вариантов. + +**Конфиги.** `tune_lsa_k150.toml`, `tune_lsa_k300.toml` + +```bash +python -m stylometry.cli run --config configs/tune_lsa_k150.toml \ + --preset stylometry_pos_lsa --model logreg --repeats 3 --seed 42 + +python -m stylometry.cli run --config configs/tune_lsa_k300.toml \ + --preset stylometry_pos_lsa --model logreg --repeats 3 --seed 42 + +python -m stylometry.cli lsa-sweep \ + --variants word,content,fw,char,pos \ + --components 150,300 \ + --model logreg --repeats 1 --seed 42 +``` + +**Как читать.** Рост `k` без роста macro-F1 — лишние компоненты ловят шум. +Сравнивайте `word`/`content` с `pos`/`fw`: если выигрыш только у word-LSA, +это снова тема, а не стиль. + +### T9. Случайный лес: глубина и лист + +**Зачем.** В `benchmark` лес идёт с дефолтами (`n_estimators=400`, +`max_depth=None`, `min_samples_leaf=1`). На 2005×34 такая модель легко +запоминает обучающие блоки. Сначала ограничивают глубину и увеличивают лист, +а не число деревьев. + +**Как запускать.** + +```bash +for depth in 10 20 30; do + for leaf in 2 3 5; do + python -m stylometry.cli run --preset stylometry_pos_lsa --model random_forest \ + --repeats 3 --seed 42 \ + --model-params "{\"max_depth\": $depth, \"min_samples_leaf\": $leaf}" + done +done + +python -m stylometry.cli run --preset stylometry_pos_lsa --model random_forest \ + --repeats 3 --seed 42 \ + --model-params '{"max_depth": 20, "min_samples_leaf": 3, "max_features": 0.1}' +``` + +**Как читать.** Если мелкие деревья не хуже (или лучше) дефолтного леса из +benchmark, сложность в базе была лишней. Сравнивайте с logreg, а не только +друг с другом: лес может выигрывать accuracy и проигрывать macro-F1. + +### T10. Сверхслучайные деревья + +**Зачем.** Extra trees не входили в `benchmark` полной серии. Случайные пороги +обычно снижают дисперсию относительно RF. Один контролируемый запуск +(не полный перебор) проверяет, есть ли смысл включать модель в сравнение. + +```bash +python -m stylometry.cli run --preset stylometry_pos_lsa --model extra_trees \ + --repeats 3 --seed 42 \ + --model-params '{"max_depth": 20, "min_samples_leaf": 3}' +``` + +Если результат заметно хуже logreg, модель достаточно упомянуть как проверку, +не раздувая сетку. + +### T11. Дельта Барроуза: 50 и 1000 MFW + +**Зачем.** Классическая стилометрия на самых частотных словах. Полная серия +уже смотрит 100/200/500. Края диапазона: 50 слов — очень компактный профиль, +1000 — больше лексики и больше темы. На коротких репликах дельта обычно +слабее ML; это независимая нижняя граница, не конкурент основному пресету. + +```bash +python -m stylometry.cli delta \ + --features 50,1000 --metrics manhattan,cosine --repeats 2 --seed 42 +``` + +`zscore` в CLI не переключается (в коде по умолчанию включён), поэтому его +здесь нет. + +--- + +## 6. Рекомендуемый порядок, если запускаете вручную + +Не гоните все циклы сразу, если времени мало. Порядок совпадает с `TUNING.md`: + +1. T4, T5 — состав групп (дешево и часто полезно). +2. T6 — n-граммы. +3. T8 — `k` LSA в объединённом наборе. +4. T7 — веса, если после T4–T6 остался шумный блок. +5. T1, затем T2 — `C`. +6. T3 — один раз, для отчёта про дисбаланс. +7. T9, T10 — только если линейные модели уже сняты. +8. T11 — короткая классическая проверка. + +После отбора 1–2 лучших конфигураций: + +```bash +python -m stylometry.cli run --preset stylometry_pos_lsa --model logreg \ + --repeats 5 --seed 42 --nested +``` + +Вложенная CV с расширенной сеткой честнее, чем выбор `C` по тем же OOF, +что потом публикуете. Узкая сетка `{0.1, 1, 10}` уже есть в полной серии; +имеет смысл `--nested` только если T1 сдвинул разумный диапазон (например, +к `{0.03, 0.1, 0.3}`). Для этого нужно изменить `PARAM_GRIDS` в +`stylometry/pipelines.py` — это уже правка кода, не конфиг. + +--- + +## 7. Как фиксировать и чего не делать + +Для каждого запуска сохраняются стандартные файлы: `run_metadata.json`, +`pooled_metrics.csv`, `bootstrap_ci.json`, `per_class_report.csv`, +матрица ошибок. Перед сравнением откройте `run_metadata.json` и убедитесь, +что отличаются только задуманные поля. + +Нельзя: + +- выбирать победителя по тестовой выборке вне CV; +- менять `--folds` или `--seed` «чтобы стало лучше»; +- сравнивать `QUICK=1` / `REPEATS=1` с финальными 5 повторами как равные; +- объявлять улучшение без интервала и `compare`; +- подменять macro-F1 долей правильных ответов. + +Ограничения корпуса те же, что в `EXPERIMENTS.md`: короткие реплики, один +автор, ручная фильтрация, дисбаланс 15–139. Настройка модели эти ограничения +не снимает. diff --git a/lab1/configs/tune_block_weights.toml b/lab1/configs/tune_block_weights.toml new file mode 100644 index 0000000..9c87daa --- /dev/null +++ b/lab1/configs/tune_block_weights.toml @@ -0,0 +1,13 @@ +# Ослабить потенциально шумные блоки после L2-нормировки. + +[cv] +folds = 5 +repeats = 3 +seed = 42 + +[features.block_weights] +stylo = 1.0 +char = 0.5 +pos = 0.7 +lsa_word = 0.3 +lsa_pos = 0.5 diff --git a/lab1/configs/tune_char_narrow.toml b/lab1/configs/tune_char_narrow.toml new file mode 100644 index 0000000..b545c68 --- /dev/null +++ b/lab1/configs/tune_char_narrow.toml @@ -0,0 +1,13 @@ +# Более короткие char n-граммы, меньше признаков, строже min_df. + +[cv] +folds = 5 +repeats = 3 +seed = 42 + +[features] +char_ngram_range = [2, 4] +char_max_features = 3000 +pos_ngram_range = [1, 3] +pos_max_features = 500 +min_df = 5 diff --git a/lab1/configs/tune_char_wide.toml b/lab1/configs/tune_char_wide.toml new file mode 100644 index 0000000..cb85a86 --- /dev/null +++ b/lab1/configs/tune_char_wide.toml @@ -0,0 +1,13 @@ +# Более длинные n-граммы и больше признаков: риск переобучения. + +[cv] +folds = 5 +repeats = 3 +seed = 42 + +[features] +char_ngram_range = [2, 6] +char_max_features = 8000 +pos_ngram_range = [1, 4] +pos_max_features = 800 +min_df = 2 diff --git a/lab1/configs/tune_lsa_k150.toml b/lab1/configs/tune_lsa_k150.toml new file mode 100644 index 0000000..6f9a438 --- /dev/null +++ b/lab1/configs/tune_lsa_k150.toml @@ -0,0 +1,7 @@ +[cv] +folds = 5 +repeats = 3 +seed = 42 + +[features] +lsa_components = 150 diff --git a/lab1/configs/tune_lsa_k300.toml b/lab1/configs/tune_lsa_k300.toml new file mode 100644 index 0000000..f630ef8 --- /dev/null +++ b/lab1/configs/tune_lsa_k300.toml @@ -0,0 +1,7 @@ +[cv] +folds = 5 +repeats = 3 +seed = 42 + +[features] +lsa_components = 300 diff --git a/lab1/configs/tune_no_vocab_readability.toml b/lab1/configs/tune_no_vocab_readability.toml new file mode 100644 index 0000000..4ad5e42 --- /dev/null +++ b/lab1/configs/tune_no_vocab_readability.toml @@ -0,0 +1,20 @@ +# Без нестабильных групп на коротких репликах. +# Остальные поля пресета (n-граммы, LSA) не переопределяются. + +[cv] +folds = 5 +repeats = 3 +seed = 42 + +[features] +groups = [ + "length", + "lexical", + "characters", + "punctuation", + "function_words", + "pronouns", + "pos", + "syntax", + "dialogue", +] diff --git a/lab1/configs/tune_no_vocab_readability_length.toml b/lab1/configs/tune_no_vocab_readability_length.toml new file mode 100644 index 0000000..83f78b4 --- /dev/null +++ b/lab1/configs/tune_no_vocab_readability_length.toml @@ -0,0 +1,18 @@ +# То же + без length: проверка, не объясняется ли сигнал длиной реплики. + +[cv] +folds = 5 +repeats = 3 +seed = 42 + +[features] +groups = [ + "lexical", + "characters", + "punctuation", + "function_words", + "pronouns", + "pos", + "syntax", + "dialogue", +] diff --git a/lab1/scripts/run_tuning_experiments.sh b/lab1/scripts/run_tuning_experiments.sh new file mode 100755 index 0000000..7fb499e --- /dev/null +++ b/lab1/scripts/run_tuning_experiments.sh @@ -0,0 +1,140 @@ +#!/usr/bin/env bash +# Тюнинг поверх полной серии scripts/run_all_experiments.sh. +# Не повторяет E0–E16: только гиперпараметры, состав признаков, веса, k LSA. +# +# Запуск из каталога lab1: +# bash scripts/run_tuning_experiments.sh +# +# Быстрый черновик: +# REPEATS=1 bash scripts/run_tuning_experiments.sh + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +cd "${PROJECT_ROOT}" + +PYTHON="${PYTHON:-python}" +REPEATS="${REPEATS:-3}" +SEED="${SEED:-42}" +PRESET="${PRESET:-stylometry_pos_lsa}" + +LOG_DIR="${PROJECT_ROOT}/results/logs" +mkdir -p "${LOG_DIR}" +RUN_ID="${RUN_ID:-$(date +%Y%m%d_%H%M%S)}" +LOG_FILE="${LOG_DIR}/tune_${RUN_ID}.log" +exec > >(tee -a "${LOG_FILE}") 2>&1 + +step() { + echo + echo "============================================================" + echo "== $*" + echo "============================================================" +} + +run() { + echo + echo ">>> $*" + "$@" +} + +echo "Тюнинг: $(date)" +echo "Интерпретатор: ${PYTHON}" +echo "Повторы: ${REPEATS}, seed: ${SEED}, пресет: ${PRESET}" +echo "Лог: ${LOG_FILE}" + +step "T1. Logreg: C" +for c in 0.03 0.1 0.3 1 3 10; do + run "${PYTHON}" -m stylometry.cli run \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" \ + --model-params "{\"C\": ${c}}" +done + +step "T2. Linear SVM: C" +for c in 0.03 0.1 0.3 1 3 10; do + run "${PYTHON}" -m stylometry.cli run \ + --preset "${PRESET}" --model linear_svc \ + --repeats "${REPEATS}" --seed "${SEED}" \ + --model-params "{\"C\": ${c}}" +done + +step "T3. Logreg без балансировки классов" +run "${PYTHON}" -m stylometry.cli run \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" \ + --model-params '{"class_weight": null}' + +step "T4. Без vocabulary и readability" +run "${PYTHON}" -m stylometry.cli run \ + --config configs/tune_no_vocab_readability.toml \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" + +step "T5. Без vocabulary, readability и length" +run "${PYTHON}" -m stylometry.cli run \ + --config configs/tune_no_vocab_readability_length.toml \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" + +step "T6. Char/POS n-граммы" +run "${PYTHON}" -m stylometry.cli run \ + --config configs/tune_char_narrow.toml \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" +run "${PYTHON}" -m stylometry.cli run \ + --config configs/tune_char_wide.toml \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" + +step "T7. Веса блоков" +run "${PYTHON}" -m stylometry.cli run \ + --config configs/tune_block_weights.toml \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" + +step "T8. LSA k=150 и k=300 (в полной серии были 50/100/200)" +run "${PYTHON}" -m stylometry.cli run \ + --config configs/tune_lsa_k150.toml \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" +run "${PYTHON}" -m stylometry.cli run \ + --config configs/tune_lsa_k300.toml \ + --preset "${PRESET}" --model logreg \ + --repeats "${REPEATS}" --seed "${SEED}" +run "${PYTHON}" -m stylometry.cli lsa-sweep \ + --variants word,content,fw,char,pos \ + --components 150,300 \ + --model logreg --repeats 1 --seed "${SEED}" + +step "T9. Случайный лес: глубина и лист" +for depth in 10 20 30; do + for leaf in 2 3 5; do + run "${PYTHON}" -m stylometry.cli run \ + --preset "${PRESET}" --model random_forest \ + --repeats "${REPEATS}" --seed "${SEED}" \ + --model-params "{\"max_depth\": ${depth}, \"min_samples_leaf\": ${leaf}}" + done +done +run "${PYTHON}" -m stylometry.cli run \ + --preset "${PRESET}" --model random_forest \ + --repeats "${REPEATS}" --seed "${SEED}" \ + --model-params '{"max_depth": 20, "min_samples_leaf": 3, "max_features": 0.1}' + +step "T10. Extra trees (не было в benchmark полной серии)" +run "${PYTHON}" -m stylometry.cli run \ + --preset "${PRESET}" --model extra_trees \ + --repeats "${REPEATS}" --seed "${SEED}" \ + --model-params '{"max_depth": 20, "min_samples_leaf": 3}' + +step "T11. Дельта: 50 и 1000 MFW (100/200/500 уже в полной серии)" +run "${PYTHON}" -m stylometry.cli delta \ + --features 50,1000 --metrics manhattan,cosine \ + --repeats 2 --seed "${SEED}" + +step "Готово" +echo "Конец тюнинга: $(date)" +echo "Лог: ${LOG_FILE}" +echo +echo "Сравнить два каталога:" +echo " python -m stylometry.cli compare --run-a results/ --run-b results/"