#!/usr/bin/env bash # Полная серия экспериментов для лабораторной работы. # # Запуск из каталога lab1: # bash scripts/run_all_experiments.sh # # С другим интерпретатором: # PYTHON=../.venv/bin/python bash scripts/run_all_experiments.sh # # Быстрая проверка (1 повтор, без вложенной кросс-валидации): # QUICK=1 bash scripts/run_all_experiments.sh # # Все команды пишутся в results/logs/run_all_.log. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" cd "${PROJECT_ROOT}" PYTHON="${PYTHON:-python}" if [[ "${PYTHON}" == */* ]]; then PYTHON_DIR="$(cd "$(dirname "${PYTHON}")" && pwd)" PYTHON="${PYTHON_DIR}/$(basename "${PYTHON}")" fi if ! "${PYTHON}" -c "import sklearn, pandas, nltk" >/dev/null 2>&1; then echo "ОШИБКА: в интерпретаторе ${PYTHON} не установлены зависимости." echo "Выполните: ${PYTHON} -m pip install -r requirements.txt" exit 1 fi REPEATS_MAIN="${REPEATS_MAIN:-5}" REPEATS_FAST="${REPEATS_FAST:-3}" REPEATS_LSA="${REPEATS_LSA:-3}" REPEATS_ABLATE="${REPEATS_ABLATE:-3}" REPEATS_DELTA="${REPEATS_DELTA:-2}" SKIP_NESTED="${SKIP_NESTED:-0}" if [[ "${QUICK:-0}" == "1" ]]; then REPEATS_MAIN=1 REPEATS_FAST=1 REPEATS_LSA=1 REPEATS_ABLATE=1 REPEATS_DELTA=1 SKIP_NESTED=1 fi 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}/run_all_${RUN_ID}.log" exec > >(tee -a "${LOG_FILE}") 2>&1 step() { echo echo "============================================================" echo "== $*" echo "============================================================" } run() { echo echo ">>> $*" "$@" } latest_dir() { local prefix="$1" ls -1dt results/"${prefix}"_* 2>/dev/null | head -n 1 || true } echo "Начало серии: $(date)" echo "Интерпретатор: ${PYTHON}" echo "Повторы: main=${REPEATS_MAIN}, fast=${REPEATS_FAST}, lsa=${REPEATS_LSA}, ablate=${REPEATS_ABLATE}, delta=${REPEATS_DELTA}" echo "Вложенная кросс-валидация: ${SKIP_NESTED} (1 — пропустить)" echo "Лог: ${LOG_FILE}" step "0. Проверка окружения и тесты" run "${PYTHON}" scripts/check_environment.py run "${PYTHON}" -m pytest -q step "1. Аудит корпуса и ручные признаки (E0)" run "${PYTHON}" -m stylometry.cli audit run "${PYTHON}" -m stylometry.cli features step "2. Нижние границы (E1)" run "${PYTHON}" -m stylometry.cli run --preset length --model dummy --repeats 1 run "${PYTHON}" -m stylometry.cli run --preset length --model logreg --repeats "${REPEATS_MAIN}" run "${PYTHON}" -m stylometry.cli run --preset char --model multinomial_nb --repeats "${REPEATS_FAST}" run "${PYTHON}" -m stylometry.cli run --preset pos --model multinomial_nb --repeats "${REPEATS_FAST}" run "${PYTHON}" -m stylometry.cli run --preset fw --model logreg --repeats "${REPEATS_FAST}" step "3. Классическая стилометрия (E2)" run "${PYTHON}" -m stylometry.cli run --preset stylometry --model logreg --repeats "${REPEATS_MAIN}" run "${PYTHON}" -m stylometry.cli run --preset stylometry --model linear_svc --repeats "${REPEATS_MAIN}" step "4. Ручные признаки + n-граммы (E4)" run "${PYTHON}" -m stylometry.cli run --preset stylometry_pos --model logreg --repeats "${REPEATS_MAIN}" step "5. Основной объединённый набор (E8)" run "${PYTHON}" -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --repeats "${REPEATS_MAIN}" step "6. Варианты LSA по отдельности (E5, E7)" for variant in word word2 content fw char pos; do run "${PYTHON}" -m stylometry.cli run --preset "lsa_${variant}" --model logreg --repeats "${REPEATS_LSA}" done step "7. Перебор числа компонент LSA (E5)" run "${PYTHON}" -m stylometry.cli lsa-sweep \ --variants word,content,fw,char,pos \ --components 50,100,200 \ --model logreg --repeats 1 step "8. Сравнение классификаторов (E6)" run "${PYTHON}" -m stylometry.cli benchmark \ --preset stylometry_pos_lsa \ --models logreg,linear_svc,random_forest,multinomial_nb,knn \ --repeats "${REPEATS_FAST}" step "9. Поочерёдное исключение групп признаков (E3)" run "${PYTHON}" -m stylometry.cli ablate \ --preset stylometry_pos_lsa --model logreg --repeats "${REPEATS_ABLATE}" step "10. Дельта Барроуза (E11)" run "${PYTHON}" -m stylometry.cli delta \ --features 100,200,500 --metrics manhattan,cosine --repeats "${REPEATS_DELTA}" step "11. Верификация «свой/чужой» (E12)" run "${PYTHON}" -m stylometry.cli verify --preset stylometry_pos_lsa step "12. Кластеризация персонажей (E13)" run "${PYTHON}" -m stylometry.cli cluster --preset stylometry_pos_lsa if [[ "${SKIP_NESTED}" != "1" ]]; then step "13. Вложенная кросс-валидация (E16)" run "${PYTHON}" -m stylometry.cli run --preset stylometry_pos_lsa --model logreg --nested run "${PYTHON}" -m stylometry.cli run --preset stylometry_pos_lsa --model linear_svc --nested else echo echo "Вложенная кросс-валидация пропущена (SKIP_NESTED=1 или QUICK=1)." fi step "14. Анализ длины, подгрупп и сравнение запусков (E9, E14, E15)" MAIN_DIR="$(latest_dir stylometry_pos_lsa_logreg)" POS_DIR="$(latest_dir stylometry_pos_logreg)" if [[ -n "${MAIN_DIR}" ]]; then run "${PYTHON}" -m stylometry.cli length-report --run-dir "${MAIN_DIR}" for group in gender age_group species; do run "${PYTHON}" -m stylometry.cli subgroup-report \ --run-dir "${MAIN_DIR}" --group "${group}" done if [[ -n "${POS_DIR}" ]]; then run "${PYTHON}" -m stylometry.cli compare \ --run-a "${MAIN_DIR}" --run-b "${POS_DIR}" \ --out "${MAIN_DIR}/comparison_main_vs_pos.json" fi else echo "Не найден каталог основного запуска; анализ пропущен." fi step "Готово" echo "Конец серии: $(date)" echo echo "Основные каталоги результатов:" ls -1dt results/*/ 2>/dev/null | head -n 30 || true echo echo "Полный лог: ${LOG_FILE}" echo "Для упаковки результатов: bash scripts/collect_results.sh"