Первичная версия: стилометрия реплик, LSA и протокол экспериментов

This commit is contained in:
2026-10-24 01:17:36 +03:00
commit c390224500
52 changed files with 10099 additions and 0 deletions

View File

@@ -0,0 +1,169 @@
#!/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_<timestamp>.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"