diff --git a/CLAUDE.md b/CLAUDE.md index 713dd9e..c735fec 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,11 +4,20 @@ This file gives Claude Code persistent context for the project. Read it before a ## Project overview -**Goal.** Train a small autoregressive transformer to generate harmonic periods (4–16 bar chord progressions) in the author's compositional style. Coursework deliverable for an ML class at RTU MIREA; also intended as a working creative tool. +**Name.** _hamori_ (Japanese ハモリ, "harmonization" in the sense of vocal +harmony — adding a second voice to a melodic line). The name reflects the +project's core idea: the model proposes harmonic ideas to complement a +composer's existing intent, rather than writing music from scratch. + +**Goal.** Train a small autoregressive transformer to generate harmonic +periods (4–16 bar chord progressions) in the author's compositional style. +Coursework deliverable for an ML class at RTU MIREA; also intended as a +working creative tool. **Unit of generation.** A single closed harmonic phrase (a "period"), not a full song. **Pipeline.** + 1. Hand-transcribe own compositions from REAPER DAW projects into `.chord` text files. 2. Parse `.chord` → factorized token sequences. 3. Pre-train on a public corpus (McGill Billboard or similar). @@ -34,7 +43,7 @@ Avoid heavy abstractions. This is coursework, not a production system. Prefer si ## Repository layout ``` -chord-gen/ +hamori/ ├── CLAUDE.md ← this file ├── README.md ├── requirements.txt @@ -88,6 +97,7 @@ The authoritative specification is in `docs/chord_format_spec.md`. **Always read ## Model A small autoregressive transformer: + - Layers: 2–4 - d_model: 128–256 - Heads: 4–8 @@ -111,6 +121,7 @@ Pre-training uses the full public corpus. Fine-tuning uses the own corpus with a ## Evaluation For the report: + 1. **Perplexity** on the holdout set, comparing pre-trained baseline vs fine-tuned. 2. **Distribution shift plots** — histograms over chord qualities, extension presence, inversion frequency, root motion intervals — showing how fine-tuning moves the distribution toward the author's corpus. 3. **Qualitative cherry-picked generations** — 3 examples with the same seed/prefix, generated by baseline vs fine-tuned, rendered to MIDI. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c943f13 --- /dev/null +++ b/README.md @@ -0,0 +1,349 @@ +# hamori + +Авторегрессионная нейросетевая модель для генерации гармонических периодов +(замкнутых гармонических фраз 4–16 тактов) в авторском композиторском стиле. + +Название проекта — _hamori_ (яп. ハモリ) — относится к понятию вокальной +гармонизации, добавлению второго голоса в существующую мелодическую линию. +Отсылка к этому понятию закрепляет основную идею проекта: модель не пишет +музыку с нуля, а предлагает гармонические идеи в дополнение к замыслу +композитора. + +Проект разработан как курсовая работа по дисциплине «Машинное обучение» в +рамках обучения в РТУ МИРЭА и одновременно как практический инструмент для +композиторской работы. + +## Содержание + +- [hamori](#hamori) + - [Содержание](#содержание) + - [1. Краткое описание](#1-краткое-описание) + - [2. Контекст и цели](#2-контекст-и-цели) + - [3. Установка](#3-установка) + - [4. Структура репозитория](#4-структура-репозитория) + - [5. Быстрый старт](#5-быстрый-старт) + - [6. Подготовка датасета](#6-подготовка-датасета) + - [6.1 Собственный корпус](#61-собственный-корпус) + - [6.2 Публичный корпус](#62-публичный-корпус) + - [6.3 Отложенная выборка](#63-отложенная-выборка) + - [6.4 Токенизация](#64-токенизация) + - [7. Обучение моделей](#7-обучение-моделей) + - [7.1 Предобучение](#71-предобучение) + - [7.2 Дообучение на собственном корпусе](#72-дообучение-на-собственном-корпусе) + - [8. Оценка результатов](#8-оценка-результатов) + - [9. Дополнительная документация](#9-дополнительная-документация) + - [10. Ограничения текущей версии](#10-ограничения-текущей-версии) + +--- + +## 1. Краткое описание + +Система принимает на вход параметры желаемого периода (тональность, тактовый +размер, стилевой тег, функциональная роль) и опционально первые несколько +аккордов. На выходе формируется гармоническая последовательность, представленная +как `.chord`-файл лид-шит-нотации и MIDI-файл для воспроизведения и работы +в цифровой звуковой рабочей станции. + +Модель обучается в две стадии: + +- **Pre-training** на публичном корпусе аккордовых последовательностей + (McGill Billboard Project) для усвоения общих гармонических закономерностей + поп-музыки. +- **Fine-tuning** на корпусе собственных произведений автора для адаптации + модели к индивидуальному композиторскому почерку. + +Юнит обработки и генерации — **гармонический период**, а не пьеса целиком. +Это решение обеспечивает достаточный размер обучающей выборки при ограниченном +числе исходных произведений и снимает проблему обработки модуляций между +крупными разделами формы. + +## 2. Контекст и цели + +Проект преследует две сопряжённые цели. + +**Учебная цель.** Закрытие дисциплины «Машинное обучение» с выполнением +курсового проекта, включающего полный цикл работы с генеративной моделью: +постановка задачи, проектирование формата данных, подготовка обучающего +корпуса, обучение, оценка и интерпретация результатов. + +**Прикладная цель.** Получение работающего инструмента-помощника, который +автор сможет использовать в дальнейшей композиторской деятельности как +источник гармонических идей в собственном стилистическом ключе. + +Срок реализации: менее одного месяца. Бюджет ручного труда: около 50 часов. + +Подробное описание целей и формальных требований приведено в +[docs/requirements.md](docs/requirements.md). + +## 3. Установка + +Требования: Python 3.11 или новее, доступ к командной строке, git. + +```bash +git clone hamori +cd hamori +python -m venv venv +source venv/bin/activate # Linux, macOS +venv\Scripts\activate # Windows +pip install -r requirements.txt +``` + +Для воспроизведения сгенерированных MIDI-файлов требуется цифровая звуковая +рабочая станция (рекомендуется REAPER) с подключённым программным +синтезатором, либо стандартный плеер MIDI операционной системы. + +Обучение модели возможно как на CPU, так и на GPU. Модель компактна +(порядка одного-трёх миллионов параметров), и pre-training на полном +корпусе укладывается в несколько часов на CPU современного ноутбука, +fine-tuning — в десятки минут. + +## 4. Структура репозитория + +``` +hamori/ +├── CLAUDE.md постоянный контекст для Claude Code +├── README.md этот файл +├── requirements.txt зависимости Python +├── docs/ +│ ├── chord_format_spec.md спецификация формата .chord (версия 2.0) +│ ├── requirements.md функциональные и нефункциональные требования +│ ├── architecture.md архитектура системы +│ └── glossary.md глоссарий терминов +├── data/ +│ ├── raw_user/ .chord-файлы собственного корпуса +│ ├── raw_external/ публичные корпуса (McGill Billboard и др.) +│ ├── processed/ токенизированные .pt-файлы для обучения +│ └── holdout/ отложенная выборка для итоговой оценки +├── src/ +│ ├── chord_parser.py парсинг аккордовых символов +│ ├── tokenizer.py преобразование .chord ↔ токены +│ ├── midi_export.py экспорт периодов в MIDI +│ ├── dataset.py PyTorch-датасет +│ ├── model.py определение модели +│ ├── train.py логика обучения +│ ├── generate.py инференс и сэмплирование +│ ├── evaluate.py метрики и распределения +│ └── external_converters/ конвертеры публичных корпусов +├── scripts/ CLI-обёртки над модулями src +├── tests/ модульные тесты и фикстуры +├── notebooks/ Jupyter-ноутбуки для исследования и отчётности +├── checkpoints/ сохранённые состояния моделей +└── reports/ графики, примеры и итоговый отчёт +``` + +## 5. Быстрый старт + +После завершения обучения (см. разделы 6–7) генерация одного периода +выполняется следующей командой: + +```bash +python scripts/generate.py \ + --checkpoint checkpoints/finetuned.pt \ + --mode major \ + --key F# \ + --style user \ + --function chorus \ + --time 4/4 \ + --output reports/samples/period.chord \ + --midi reports/samples/period.mid \ + --seed 42 +``` + +После выполнения в указанной директории появятся два файла: +текстовый `.chord` с гармонической последовательностью и MIDI-файл, +готовый к открытию в DAW. + +Если у пользователя есть начальная гармоническая идея, её можно передать +параметром `--prefix`: + +```bash +python scripts/generate.py \ + --checkpoint checkpoints/finetuned.pt \ + --mode major --key C --style user --function verse --time 4/4 \ + --prefix "Cmaj7 Am7 Dm7" \ + --output reports/samples/continuation.chord +``` + +Модель достроит остаток периода в логике, выученной на собственном корпусе +автора. + +## 6. Подготовка датасета + +Подготовка датасета — самая трудозатратная часть проекта (10–15 часов +чистого времени). Сокращать её за счёт автоматического извлечения аккордов +из аудио нецелесообразно: при плотной фактуре и нетривиальных гармонических +решениях современные алгоритмы chord detection дают слишком высокую долю +ошибок, тогда как ручная транскрипция при наличии абсолютного слуха выполняется +быстро и без потерь. + +### 6.1 Собственный корпус + +Из 20–25 собственных произведений (DAW-проекты в REAPER) необходимо извлечь +80–150 гармонических периодов и записать каждый в виде отдельного `.chord`-файла +в директории `data/raw_user/`. + +Процедура транскрипции: + +1. Прослушать пьесу, определить границы замкнутых гармонических фраз. Признаки + замкнутости — возврат к тонике или ясная полукаденция, отсутствие модуляции + внутри фрагмента. +2. Заполнить шапку `.chord`-файла: название, тональность, тактовый размер, + подразделение доли, стилевой тег `user`, функциональная роль периода. +3. Транскрибировать гармонию по позициям, аккуратно фиксируя инверсии и расширения. +4. Запустить парсер для проверки корректности файла: + ```bash + python scripts/validate_chord_file.py data/raw_user/2024_001_song_chorus.chord + ``` +5. Запустить экспорт в MIDI и прослушать результат в DAW параллельно с оригиналом + для контроля точности транскрипции: + ```bash + python -m src.midi_export data/raw_user/2024_001_song_chorus.chord /tmp/check.mid + ``` + +Полная спецификация формата приведена в [docs/chord_format_spec.md](docs/chord_format_spec.md). +Чек-лист транскрипции — в разделе 10 спецификации. + +### 6.2 Публичный корпус + +Для предобучения используется McGill Billboard Project — открытый +размеченный профессиональными аннотаторами корпус из примерно семи сотен +пьес западной поп-музыки 1950–1990-х годов. Корпус необходимо скачать с +официального сайта и распаковать в директорию `data/raw_external/mcgill_billboard/`. + +Конвертация в формат `.chord`: + +```bash +python -m src.external_converters.mcgill_to_chord \ + --input data/raw_external/mcgill_billboard/ \ + --output data/raw_external/mcgill_converted/ +``` + +Конвертер автоматически разрезает каждую пьесу на периоды по границам секций +и сохраняет каждый период как отдельный `.chord`-файл со стилевым тегом `other`. + +### 6.3 Отложенная выборка + +Из собственного корпуса необходимо отложить 10–15 периодов в директорию +`data/holdout/` ещё до начала обучения. Эти периоды не должны попасть ни в +тренировочную, ни в валидационную выборки и используются только для итоговой +оценки качества модели. Откладывать следует репрезентативные для авторского +стиля примеры, а не самые экспериментальные. + +### 6.4 Токенизация + +После того как `.chord`-файлы готовы, выполняется пакетная токенизация: + +```bash +python scripts/prepare_data.py \ + --input-dir data/raw_user/ \ + --output-dir data/processed/user/ \ + --split-ratios 0.9 0.1 + +python scripts/prepare_data.py \ + --input-dir data/raw_external/mcgill_converted/ \ + --output-dir data/processed/mcgill/ \ + --split-ratios 0.9 0.1 +``` + +Скрипт автоматически разделяет файлы на тренировочную и валидационную выборки, +выводит статистику по длине последовательностей и распределениям метаданных. + +## 7. Обучение моделей + +Обучение выполняется в две стадии. + +### 7.1 Предобучение + +Обучение базовой модели на конвертированном корпусе McGill Billboard: + +```bash +python scripts/train.py \ + --data-dir data/processed/mcgill/ \ + --output checkpoints/pretrained.pt \ + --epochs 50 \ + --batch-size 32 \ + --lr 3e-4 \ + --warmup-steps 200 \ + --seed 42 +``` + +По окончании обучения в директории `checkpoints/` появятся: сам чекпоинт, +лог обучения в формате CSV и график кривых train/val loss. + +### 7.2 Дообучение на собственном корпусе + +```bash +python scripts/train.py \ + --init-from checkpoints/pretrained.pt \ + --data-dir data/processed/user/ \ + --output checkpoints/finetuned.pt \ + --epochs 15 \ + --batch-size 16 \ + --lr 1e-5 \ + --warmup-steps 20 \ + --seed 42 +``` + +Существенно более низкая скорость обучения (на два порядка меньше, чем на +предобучении) и небольшое число эпох предотвращают катастрофическое забывание +закономерностей, выученных на этапе предобучения. + +## 8. Оценка результатов + +Скрипт оценки сравнивает базовую (только предобученную) и дообученную модели +на отложенной выборке: + +```bash +python scripts/evaluate.py \ + --baseline checkpoints/pretrained.pt \ + --target checkpoints/finetuned.pt \ + --holdout data/processed/holdout/ \ + --output-dir reports/ +``` + +В директории `reports/` будут сформированы: + +- Таблица в формате JSON с численными метриками (perplexity обеих моделей). +- Графики распределений типов аккордов, частот инверсий, интервалов движения + корня, наиболее частых функциональных пар. Каждый график показывает баланс + baseline-распределения и target-распределения. +- Сгенерированные образцы для качественного сравнения (3 затравки × 3 семпла + × 2 модели). + +Подробное описание метрик и методологии оценки — в разделе 6 файла +[docs/architecture.md](docs/architecture.md). + +## 9. Дополнительная документация + +| Документ | Назначение | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [docs/chord_format_spec.md](docs/chord_format_spec.md) | Полная спецификация формата `.chord`, словарь токенов, правила парсинга. Авторитетный источник по формату. | +| [docs/requirements.md](docs/requirements.md) | Функциональные и нефункциональные требования, критерии приёмки. | +| [docs/architecture.md](docs/architecture.md) | Архитектура системы, схемы потоков данных, описания модулей, обоснование ключевых проектных решений. | +| [docs/glossary.md](docs/glossary.md) | Глоссарий музыкальных, машинно-обучательных и проектных терминов. | +| [CLAUDE.md](CLAUDE.md) | Постоянный контекст для Claude Code (на английском). Описывает правила разработки, чего нельзя делать без согласования и какие модули за что отвечают. | + +## 10. Ограничения текущей версии + +Текущая версия проекта сознательно ограничена для соблюдения сроков курсовой +работы. Перечисленные ниже возможности **не реализованы** и являются +кандидатами для дальнейшего развития. + +- Генерация мелодии. Текущая модель работает только с гармонической + последовательностью. +- Расположение голосов внутри аккорда (voicing) выше баса. Бас передаётся, + остальное оставлено на ручную работу композитора в DAW. +- Ритмический паттерн внутри удержания аккорда (синкопы, проходящие фигуры, + альбертиевы басы). +- Аранжировка, тембр, динамика, артикуляция. +- Графический пользовательский интерфейс. Взаимодействие осуществляется + через командную строку. +- Прямая интеграция с REAPER в режиме реального времени. Обмен с DAW + происходит через файлы MIDI. +- Обработка модуляций внутри одного периода. При наличии модуляции в + исходном произведении периоды разрезаются по точке модуляции. +- Дообучение на корпусе японской поп-музыки (J-Pop). Запланировано как + отдельный эксперимент после защиты курсовой. + +Подробное обсуждение каждого пункта и направления развития содержатся в +[docs/architecture.md](docs/architecture.md), раздел «Точки расширения». diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..e2d59a3 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,915 @@ +# Архитектура системы hamori + +**Версия документа:** 1.0 +**Дата:** 2026-05-19 + +Документ описывает архитектуру проекта _hamori_ — генератора гармонических +периодов: высокоуровневую структуру, потоки данных, состав модулей, ключевые +проектные решения и их обоснование, а также точки расширения. + +--- + +## Содержание + +1. [Высокоуровневая архитектура](#1-высокоуровневая-архитектура) +2. [Потоки данных](#2-потоки-данных) +3. [Состав модулей](#3-состав-модулей) +4. [Модель машинного обучения](#4-модель-машинного-обучения) +5. [Конвейер обучения](#5-конвейер-обучения) +6. [Конвейер инференса и оценки](#6-конвейер-инференса-и-оценки) +7. [Ключевые проектные решения](#7-ключевые-проектные-решения) +8. [Точки расширения](#8-точки-расширения) + +--- + +## 1. Высокоуровневая архитектура + +Система состоит из шести логических уровней. + +**Уровень человекочитаемых данных.** Текстовые `.chord`-файлы лид-шит-нотации, +с которыми работает автор-композитор при ручной транскрипции. Каждый файл +описывает один гармонический период. + +**Уровень парсинга и валидации.** Модули, преобразующие `.chord`-файлы в +структурированные внутренние представления и проверяющие их корректность. + +**Уровень токенизации.** Модули, преобразующие структурированные представления +в последовательности целочисленных идентификаторов и обратно. Здесь же +выполняется нормализующая транспозиция в каноническую тональность. + +**Уровень обучения и инференса.** Реализация нейросетевой модели, циклы +обучения и сэмплирования, работа с чекпоинтами. + +**Уровень оценки.** Расчёт метрик, построение распределений, формирование +графических артефактов для отчёта. + +**Уровень внешних адаптеров.** Конвертеры публичных корпусов в формат `.chord`, +экспорт периодов в MIDI. + +Схема информационных связей между уровнями: + +``` + автор-композитор + │ + ▼ + .chord-файлы (raw_user) + │ + │ + │ публичный корпус + │ │ + │ ▼ + │ внешний конвертер + │ │ + │ ▼ + │ .chord-файлы (raw_external) + │ │ + └────────┬────────┘ + │ + ▼ + парсер + валидатор + │ + ▼ + транспозиция в C/Am + │ + ▼ + токенизатор + │ + ▼ + .pt-файлы (processed) + │ + ┌──────────────────┼──────────────────┐ + ▼ ▼ ▼ + train выборка val выборка holdout выборка + │ │ │ + └────────┬─────────┘ │ + ▼ │ + трансформер: pre-train + fine-tune │ + │ │ + ▼ │ + чекпоинты ◄───────────────────────┘ + │ │ + ┌────────────────┼────────────────────────────┘ + ▼ ▼ + инференс оценка + │ │ + ▼ ▼ +.chord + MIDI метрики + графики + образцы + │ │ + ▼ ▼ + автор-композитор отчёт +``` + +--- + +## 2. Потоки данных + +### 2.1 Поток подготовки собственного корпуса + +``` +DAW-проект (REAPER) + │ + │ ручная транскрипция + ▼ +.chord-файл в data/raw_user/ + │ + │ валидация формата + │ (опционально: MIDI-санитарная проверка) + ▼ +.chord-файл прошёл проверку + │ + │ скрипт prepare_data.py + │ ├── чтение + │ ├── транспозиция в C major / A minor + │ ├── токенизация + │ └── разбиение train / val + ▼ +.pt-файлы в data/processed/user/{train,val}/ +``` + +### 2.2 Поток подготовки публичного корпуса + +``` +McGill Billboard (Harte-аннотации) + │ + │ скрипт mcgill_to_chord.py + │ ├── парсинг Harte-нотации + │ ├── разрезание на периоды по секциям + │ ├── определение тональности + │ └── конвертация в .chord + ▼ +.chord-файлы в data/raw_external/mcgill_converted/ + │ + │ скрипт prepare_data.py + ▼ +.pt-файлы в data/processed/mcgill/{train,val}/ +``` + +### 2.3 Поток обучения + +``` +data/processed/mcgill/ ◄── предобучение + │ + ▼ +checkpoints/pretrained.pt + │ + │ инициализация весов + ▼ +data/processed/user/ ◄── дообучение + │ + ▼ +checkpoints/finetuned.pt +``` + +### 2.4 Поток инференса + +``` +пользовательские параметры (CLI) + │ + │ построение prompt-токенов + │ ▼ +prompt = + метатокены + опциональный prefix + │ + │ авторегрессионная генерация (top-p sampling) + ▼ +последовательность токенов до + │ + │ детокенизация + ▼ +ChordPeriod в канонической тональности C/Am + │ + │ транспозиция в целевую тональность + ▼ +ChordPeriod в требуемой тональности + │ + │ сериализация + MIDI-экспорт + ▼ +.chord и .mid файлы +``` + +### 2.5 Поток оценки + +``` +data/processed/holdout/ + │ + ▼ +вычисление перплексии для base и target + │ + ▼ +извлечение признаков (типы аккордов, инверсии, интервалы корня) + │ + ▼ +построение гистограмм и таблиц + │ + ▼ +reports/figures/, reports/metrics.json +``` + +--- + +## 3. Состав модулей + +### 3.1 `src/chord_parser.py` + +**Назначение.** Разбор отдельных аккордовых символов в строго типизированное +представление. + +**Публичный интерфейс.** + +- `parse_chord_symbol(symbol: str) -> ChordTokens` — парсит строку вида `Am7`, + `Cmaj9`, `F/G`, `Bb7b9/D` в dataclass `ChordTokens(root, quality, extension, bass)`. +- `ChordParseError` — исключение, поднимаемое при невалидном символе. + +**Ключевые соображения реализации.** Модуль не использует регулярные +выражения для парсинга качеств: вместо этого выполняется последовательное +распознавание из таблицы альтернативных написаний по принципу самого длинного +совпадения. Это упрощает добавление новых качеств в будущем и снижает риск +тонких ошибок с приоритетами совпадений. + +Бемольные написания корня и баса нормализуются к диезной форме на этапе парсинга. + +**Связи.** Используется модулем `tokenizer.py` для разбора аккордов внутри +периода. Не имеет зависимостей внутри проекта, кроме стандартной библиотеки +Python и опционально `music21` (как fallback для нетипичных написаний). + +### 3.2 `src/tokenizer.py` + +**Назначение.** Преобразование `.chord`-файлов в последовательности +целочисленных идентификаторов и обратно. Реализация словаря токенов. +Реализация нормализующей транспозиции. + +**Публичный интерфейс.** + +- Константа `VOCAB: list[str]` — словарь токенов в порядке, описанном в + спецификации формата (81 токен). +- Константа `TOKEN_TO_ID: dict[str, int]` — обратное отображение. +- Функция `parse_chord_file(path: Path) -> ChordPeriod` — парсинг + `.chord`-файла в структурированное представление. +- Функция `transpose_to_canonical(period: ChordPeriod) -> ChordPeriod` — + транспозиция мажорных периодов в C major, минорных в A minor. +- Функция `tokenize_period(period: ChordPeriod) -> list[int]` — последовательно + выполняет транспозицию и преобразование в токены. +- Функция `detokenize_to_period(token_ids: list[int]) -> ChordPeriod` — + обратная операция, возвращает период в канонической тональности. +- Функция `transpose_period(period, target_key) -> ChordPeriod` — + транспозиция в произвольную целевую тональность (используется на этапе + инференса для возврата результата в требуемую тональность). +- Исключение `ChordFormatError` — для ошибок формата файла. + +**Ключевые соображения реализации.** Словарь токенов является константой +модуля; его изменение приводит к несовместимости с ранее обученными моделями, +поэтому любые изменения должны сопровождаться инкрементом версии спецификации +формата и переобучением моделей. + +Транспозиция реализуется через расчёт интервала в полутонах между исходным и +целевым тонами, после чего к каждому корневому тону и бассу применяется +циклический сдвиг по 12-тоновой системе. Качество и расширения аккорда при +транспозиции не меняются. + +**Связи.** Используется всеми остальными модулями для входа и выхода из +токенизированного пространства. Зависит от `chord_parser.py`. + +### 3.3 `src/midi_export.py` + +**Назначение.** Преобразование `.chord`-файлов в стандартные MIDI-файлы для +прослушивания в DAW и для использования сгенерированных периодов в +композиторской работе. + +**Публичный интерфейс.** + +- `chord_file_to_midi(chord_path, midi_path, tempo=90)` — основная функция. +- `period_to_midi(period: ChordPeriod, midi_path, tempo=90)` — вариант, + принимающий уже распарсенный период. + +**Ключевые соображения реализации.** MIDI-файл содержит два инструментальных +трека: трек аккордов и трек баса. Аккорды раскладываются в средней октаве +(C4–B5) тремя или четырьмя одновременными нотами, бас — в нижней октаве (C2–B2) +одной нотой. Длительности соответствуют длительностям удержания аккордов в +исходном `.chord`-файле. + +Voicing внутри аккорда выполняется минимально — простое расположение нот в +тесном расположении от корня. Это не задача данного модуля и сознательно +оставлено простым. + +**Связи.** Зависит от `tokenizer.py` (для парсинга `.chord`) и `pretty_midi`. + +### 3.4 `src/dataset.py` + +**Назначение.** Реализация PyTorch-датасета над предварительно +токенизированными `.pt`-файлами. + +**Публичный интерфейс.** + +- Класс `ChordDataset(torch.utils.data.Dataset)`. + - Конструктор принимает путь к директории с `.pt`-файлами и максимальную + длину последовательности. + - `__getitem__` возвращает тензор токенов, обрезанный или дополненный + паддингом до максимальной длины. +- Функция `make_dataloader(dataset, batch_size, shuffle) -> DataLoader` — + удобная фабрика. + +**Ключевые соображения реализации.** Все `.pt`-файлы загружаются в память при +создании датасета. Это допустимо при текущем размере данных (тысячи периодов +максимум) и существенно ускоряет обучение по сравнению с подгрузкой с диска. + +Паддинг выполняется специальным токеном `` с индексом 2 в словаре. +В функции потерь этот индекс игнорируется через параметр `ignore_index`. + +### 3.5 `src/model.py` + +**Назначение.** Определение нейросетевой архитектуры. + +**Публичный интерфейс.** + +- Класс `ChordTransformer(nn.Module)` с параметрами конструктора: + `vocab_size`, `d_model`, `n_layers`, `n_heads`, `d_ff`, `max_seq_len`, + `dropout`. + +**Архитектурные детали.** Декодер-only трансформер с pre-normalization +(нормализация перед остаточной связью, а не после). Эмбеддинги токенов и +позиционные эмбеддинги — обучаемые. Веса входного эмбеддинга и финальной +проекции на словарь связаны (tied weights), что сокращает число параметров +и стабилизирует обучение на малых данных. + +Каждый блок трансформера состоит из: + +- LayerNorm +- Causal multi-head self-attention с маскированием будущих позиций +- Residual connection +- LayerNorm +- Feedforward с активацией GELU +- Residual connection + +После последнего блока — финальная LayerNorm и линейная проекция на размер +словаря. + +**Связи.** Используется в модулях обучения и инференса. + +### 3.6 `src/train.py` + +**Назначение.** Логика обучения, общая для предобучения и дообучения. + +**Публичный интерфейс.** + +- Функция `train_model(config: TrainConfig) -> Path` — основная точка + входа. Возвращает путь к лучшему чекпоинту. +- Dataclass `TrainConfig` с полями для всех гиперпараметров. + +**Особенности.** Один общий цикл обучения параметризуется аргументом +`init_from`. Если этот аргумент задан, веса модели инициализируются из +указанного чекпоинта, иначе — случайно. Это позволяет использовать один и +тот же код для предобучения и дообучения, различающихся только параметрами +запуска (низкий learning rate, меньшее число эпох для дообучения). + +Логирование: после каждой эпохи в stdout выводится строка с номером эпохи, +тренировочной потерей, валидационной потерей и валидационной перплексией. +Параллельно строка добавляется в CSV-лог. Лучший по валидационной потере +чекпоинт сохраняется отдельно. + +Ранняя остановка: если валидационная потеря не улучшается на протяжении N +эпох (по умолчанию 5), обучение завершается досрочно. + +### 3.7 `src/generate.py` + +**Назначение.** Сэмплирование из обученной модели. + +**Публичный интерфейс.** + +- Функция `generate_period(model, mode, time, subdivision, style, function, +key, prefix=None, temperature=1.0, top_p=0.9, max_tokens=300, seed=None) +-> ChordPeriod`. + +**Ключевые соображения реализации.** Авторегрессионная генерация выполняется +по одному токену за раз. Для каждого шага: + +1. Прогон последовательности через модель, получение распределения над + следующим токеном. +2. Деление логитов на температуру. +3. Применение nucleus sampling: оставляем минимальный по числу элементов + набор кандидатов с накопленной вероятностью не менее top_p. +4. Маскирование грамматически невалидных кандидатов (например, токена + расширения сразу после токена удержания). +5. Сэмплирование из оставшегося распределения. +6. Останов при появлении `` или при достижении лимита токенов. + +После завершения генерации последовательность детокенизируется, получившийся +период транспонируется из канонической тональности в целевую и возвращается +вызывающему. + +### 3.8 `src/evaluate.py` + +**Назначение.** Расчёт метрик качества и построение распределений. + +**Публичный интерфейс.** + +- `compute_perplexity(model, dataloader) -> float`. +- `extract_features(period: ChordPeriod) -> dict` — извлекает гармонические + признаки периода: список типов качеств, доли инверсий, интервалы движения + корня, биграммы корней. +- `compare_distributions(baseline_features, target_features) -> dict` — + агрегирует признаки и формирует структуры для построения графиков. +- `plot_comparison(distributions, output_dir)` — рисует и сохраняет графики. + +### 3.9 `src/external_converters/mcgill_to_chord.py` + +**Назначение.** Конвертация аннотаций McGill Billboard Project в формат +`.chord`. + +**Публичный интерфейс.** + +- `convert_directory(input_dir, output_dir, log_path=None)` — конвертирует + все пьесы из исходной директории. +- `convert_song(song_dir, output_dir) -> list[Path]` — конвертирует одну + пьесу, возвращает список путей к созданным файлам периодов. + +**Ключевые соображения реализации.** Harte-нотация McGill отличается от +формата проекта по ряду признаков: использует другие имена качеств, явно +указывает интервальный состав в скобках, имеет иную систему обозначения +длительностей. Конвертер реализует таблицу соответствий между Harte и форматом +проекта и приводит к ближайшему допустимому аккорду в случаях, когда точное +соответствие отсутствует. + +Разрезание на периоды выполняется по разметке секций в исходных файлах +(`verse`, `chorus`, `bridge` и т.д.). Периоды длиной менее 4 или более 16 +тактов пропускаются. + +--- + +## 4. Модель машинного обучения + +### 4.1 Выбор архитектуры + +Архитектура декодер-only трансформера выбрана по следующим причинам. + +**Соответствие задаче.** Гармоническая последовательность — это +последовательность дискретных символов с сильными локальными +зависимостями (соседние аккорды связаны функциональными отношениями) и +менее сильными глобальными зависимостями (начало и конец периода связаны +тонально). Self-attention отражает оба типа зависимостей естественным +образом. + +**Совместимость со схемой предобучения + дообучения.** Архитектуры +семейства трансформеров — стандартный выбор для задач с малой целевой +выборкой и большим объёмом предобучающих данных. + +**Простота реализации с нуля.** При выбранном масштабе модели (несколько +блоков, небольшая размерность) реализация умещается в нескольких сотнях +строк кода и не требует тяжёлых зависимостей. + +Альтернатива в виде LSTM была рассмотрена и отвергнута на основании того, +что: + +- При сопоставимом числе параметров трансформер обычно работает не хуже на + задачах с дискретными последовательностями. +- Параллелизация обучения трансформера эффективнее. +- Стандартное предобучение языковых моделей через next-token prediction + легче переносится на трансформер, чем на рекуррентные сети. + +### 4.2 Параметры модели + +Размер модели сознательно выбран небольшим — порядка одного-трёх миллионов +параметров. Это обусловлено объёмом обучающих данных: при тысячах примеров +крупная модель неизбежно переобучится, а компактная сохранит способность +к обобщению. Рекомендуемая конфигурация: + +| Параметр | Значение | +| ---------------------------- | ----------- | +| Число слоёв | 3 | +| Размерность модели (d_model) | 192 | +| Число голов внимания | 6 | +| Размерность FFN | 768 | +| Длина контекста | 512 токенов | +| Размер словаря | 81 | +| Dropout | 0.1 | + +При необходимости конфигурация может быть пересмотрена в сторону уменьшения +(если модель не сходится) или увеличения (если результаты явно недостаточны +и есть запас времени на эксперимент). + +### 4.3 Функция потерь и оптимизация + +Стандартная кросс-энтропия с игнорированием ``-токена. Оптимизатор — +AdamW. Расписание learning rate — косинусное снижение с линейным разогревом +на 5% от общего числа шагов. + +**Предобучение.** Стартовый learning rate 3·10⁻⁴, 50 эпох (с возможностью +ранней остановки). + +**Дообучение.** Стартовый learning rate 1·10⁻⁵, 15 эпох с ранней остановкой. + +Двухпорядковая разница в learning rate между предобучением и дообучением — +ключевой приём для предотвращения катастрофического забывания: на этапе +дообучения веса модели изменяются медленно, что сохраняет общие +гармонические закономерности, выученные на крупном корпусе. + +### 4.4 Генерация + +Используется nucleus sampling (top-p) с температурой 1.0 по умолчанию. +Параметры регулируются на этапе инференса. + +Beam search отвергнут на основании опыта генеративных задач: он склонен +порождать монотонные, многократно повторяющиеся последовательности, что +особенно нежелательно в задаче создания творческих идей. + +--- + +## 5. Конвейер обучения + +### 5.1 Подготовка данных + +``` +сырьё (.chord) + │ + ▼ +парсинг и валидация + │ + ▼ +транспозиция в каноническую тональность + │ + ▼ +токенизация + │ + ▼ +случайное разбиение на train/val (90/10) + │ + ▼ +сохранение .pt-файлов +``` + +Разбиение train/val выполняется на уровне периодов, а не на уровне исходных +пьес. Для собственного корпуса это компромиссное решение: разбиение по +пьесам было бы методологически чище, но при 20–25 пьесах привело бы к +слишком высокой дисперсии валидационной потери. Holdout-выборка, в свою +очередь, специально формируется на уровне пьес, что обеспечивает честность +итоговой оценки. + +### 5.2 Цикл предобучения + +``` +инициализация модели случайными весами + │ + ▼ +для каждой эпохи (1..50): + │ + ├── проход по train: forward, loss, backward, optimizer step + │ │ + │ ▼ + │ агрегация train_loss за эпоху + │ + ├── проход по val (без градиентов): forward, loss + │ │ + │ ▼ + │ агрегация val_loss и val_perplexity + │ + ├── запись строки в CSV-лог + │ + ├── если val_loss улучшилась — сохранение чекпоинта + │ + └── если val_loss не улучшалась 5 эпох подряд — выход +``` + +### 5.3 Цикл дообучения + +Идентичен циклу предобучения по структуре, отличается: + +- Инициализация модели из чекпоинта предобучения. +- Меньший learning rate. +- Меньшее максимальное число эпох (15). +- Опционально: меньший patience для ранней остановки. + +### 5.4 Контроль качества обучения + +В процессе обучения отслеживаются следующие признаки нормального хода: + +- Train loss монотонно снижается. +- Val loss снижается синхронно с train loss до точки, после которой + начинается расхождение (типичное переобучение). Лучший чекпоинт + сохраняется до точки расхождения. +- Val perplexity на сошедшейся модели находится в диапазоне 2–6 для нашей + задачи. Существенно меньшие значения указывают на ошибку (например, + пересечение train и val выборок). Существенно большие — на плохую + сходимость или несоответствие модели данным. + +Если эти признаки нарушаются, необходимо в первую очередь проверить +корректность подготовленных данных: токенизацию случайных файлов руками, +отсутствие пересечений между выборками, баланс распределения метаданных. + +--- + +## 6. Конвейер инференса и оценки + +### 6.1 Инференс + +Подробное описание процесса генерации приведено в разделе 3.7. Ключевые +особенности: + +- Все параметры запроса передаются через CLI-аргументы. +- Случайное зерно фиксируется, что обеспечивает воспроизводимость отдельных + семплов. +- Невалидные грамматические последовательности маскируются на каждом шаге + сэмплирования. +- Результат сразу сохраняется в двух форматах: `.chord` (для возможного + редактирования или подачи модели как затравки в дальнейшем) и MIDI (для + прослушивания). + +### 6.2 Количественная оценка + +**Перплексия** на отложенной выборке рассчитывается как экспонента средней +кросс-энтропии. Сравнение перплексий базовой и целевой моделей на одной +выборке показывает, насколько сильно дообучение сместило распределение +вероятностей модели в сторону распределения собственного корпуса автора. + +Снижение перплексии на отложенной выборке после дообучения является +основным численным индикатором успеха проекта. Ожидаемая величина снижения — +от 10% до 50% относительно базовой модели. + +### 6.3 Качественная оценка через распределения + +Качественная сторона эффекта дообучения оценивается через сравнение +гистограмм по следующим признакам. + +**Типы качеств аккордов.** Распределение по 18 базовым качествам. На малых +данных авторский стиль часто проявляется в смещении этого распределения: +например, повышенная частота больших септаккордов и нонаккордов или, +напротив, преобладание простых трезвучий. + +**Доля инверсий.** Процент аккордов с явно указанным басом, отличным от +корня. Этот признак особенно характерен для индивидуального стиля и для +конкретных жанров (J-Pop, например, активно использует слэш-аккорды). + +**Интервалы движения корня.** Распределение интервалов между корнями +соседних аккордов в полутонах. Например, доминирование интервала –5 +полутонов (квинтовый ход вниз) характерно для барочной и классической +гармонии; преобладание интервалов –2, +2 — для более поп-ориентированных +стилей. + +**Биграммы корней.** Частоты пар «текущий корень → следующий корень». Эти +биграммы захватывают функциональные предпочтения автора: например, +характерные переходы IV → V или V → vi. + +Графики строятся как наложение двух гистограмм (baseline-распределение и +target-распределение) на одной координатной плоскости. Визуальный сдвиг +target относительно baseline — прямое подтверждение того, что дообучение +сработало. + +### 6.4 Качественная оценка через прослушивание + +Для отчёта формируются три специально подобранные («cherry-picked») пары +сгенерированных образцов: для каждой из выбранных гармонических затравок — +по одному примеру от базовой и от дообученной модели с одним и тем же +случайным зерном. Эти примеры конвертируются в MIDI и прилагаются к отчёту +(в виде ссылок и описаний). + +Слепой listening-тест с привлечением сторонних слушателей не проводится из +соображений ограничения по времени. + +--- + +## 7. Ключевые проектные решения + +В этом разделе фиксируются проектные решения, принятые на этапе +проектирования, и обоснования к ним. Решения изложены в виде записей в +стиле Architectural Decision Records. + +### 7.1 ПР-01. Юнит обработки — гармонический период, а не пьеса целиком + +**Контекст.** Изначально рассматривался вариант обучения модели на целых +пьесах. При объёме собственного корпуса 20–25 пьес и средней длине каждой +40–100 тактов это давало бы датасет из 20–25 длинных последовательностей — +крайне малый объём для генеративной модели. + +**Решение.** Единицей обработки и генерации является гармонический период — +замкнутая фраза 4–16 тактов. Из одной пьесы извлекается 4–8 периодов. + +**Последствия.** + +- Эффективный объём датасета увеличивается в 4–8 раз. +- Проблема обработки модуляций между секциями исчезает: внутри периода + модуляций нет. +- Длина обучающей последовательности становится меньшей и более однородной + (50–250 токенов вместо 500–1500), что упрощает обучение. +- Юнит хорошо соответствует реальному композиторскому воркфлоу: помощник + выдаёт идеи периодами, а не целыми пьесами. + +### 7.2 ПР-02. Нормализующая транспозиция в C major / A minor + +**Контекст.** Если каждый период хранится в исходной тональности, +функционально эквивалентные последовательности в разных тональностях +становятся для модели разными последовательностями. Это резко увеличивает +эффективное разнообразие данных в 12 раз и затрудняет обобщение. + +**Решение.** Перед токенизацией все периоды транспонируются: мажорные — в +C major, минорные — в A minor. Тональность в словарь модели не входит. +На инференсе результат транспонируется обратно в требуемую тональность +постпроцессингом. + +**Последствия.** + +- Эффективное увеличение датасета в 12 раз. +- Сокращение словаря на 24 токена. +- Цвет конкретной тональности (характерное звучание Fis-dur против C-dur) + теряется. Это исполнительское свойство, не функционально-гармоническое, + и для задачи генерации прогрессий не релевантно. +- Внутренние модуляции и тонизации записываются обычными функциональными + аккордами и обрабатываются единообразно. + +### 7.3 ПР-03. Факторизованная токенизация аккордов + +**Контекст.** Каждый аккорд можно представить либо одним атомарным токеном +(`Cmaj7`, `Am7`, `F/G` как отдельные элементы словаря), либо разложенным +на несколько токенов (корень, качество, расширение, бас). + +**Решение.** Каждый аккорд представляется ровно четырьмя токенами: +`ROOT_x`, `QUAL_x`, `EXT_x`, `BASS_x`. Словарь содержит 81 токен против +нескольких сотен в случае атомарной токенизации. + +**Последствия.** + +- Существенно меньший словарь, легче обучаемый на малых данных. +- Модель видит общность между, например, всеми минорными септаккордами, + а не учит их как 12 несвязанных слов. +- Каждый аккорд занимает в последовательности четыре позиции вместо одной, + что увеличивает длину последовательности и нагрузку на attention. При + выбранной длине контекста 512 это не создаёт проблем. +- Появляется необходимость грамматического маскирования при генерации: + не любой токен может следовать за любым. + +### 7.4 ПР-04. Двухстадийное обучение + +**Контекст.** Прямое обучение модели на собственном корпусе автора +невозможно из-за крайне малого объёма данных. + +**Решение.** Двухстадийная схема: предобучение на крупном публичном +корпусе (McGill Billboard Project) и последующее дообучение на собственном +корпусе с пониженным learning rate. + +**Последствия.** + +- Базовые гармонические закономерности (функциональная гармония, + стандартные каденции) выучиваются на этапе предобучения. +- Индивидуальный стиль автора подмешивается на этапе дообучения без + необходимости заново выучивать общие законы. +- Появляется естественная схема сравнения «до и после» дообучения для + отчёта. +- Существует риск катастрофического забывания на этапе дообучения, что + митигируется низким learning rate и небольшим числом эпох. + +### 7.5 ПР-05. Минималистичная реализация без тяжёлых фреймворков + +**Контекст.** Существует ряд готовых фреймворков для обучения трансформеров +(PyTorch Lightning, HuggingFace Trainer, fastai), которые скрывают +boilerplate кода тренировочного цикла. + +**Решение.** Использовать чистый PyTorch с явным циклом обучения. + +**Последствия.** + +- Код полностью прозрачен и поддаётся пошаговой отладке, что важно для + учебного проекта. +- Снижается риск проблем с совместимостью версий и сложным поведением + фреймворков «из коробки». +- Объём кода тренировочного цикла остаётся небольшим (порядка двух сотен + строк). +- Теряется доступ к некоторым удобствам фреймворков (готовые callbacks, + логирование в TensorBoard и т.п.). Для масштабов проекта это + несущественно. + +### 7.6 ПР-06. Ручная транскрипция собственного корпуса + +**Контекст.** Альтернатива — автоматическое извлечение аккордов из аудио +с помощью библиотек вроде Chordino, librosa, или нейросетевых детекторов. + +**Решение.** Транскрипция выполняется автором вручную, на основе +DAW-проектов с использованием абсолютного слуха. + +**Последствия.** + +- Качество транскрипции существенно выше автоматического: тонкие гармонические + решения, нестандартные расширения, точные инверсии — всё это передаётся + без потерь. +- Существенные временные затраты (10–15 часов). Это самая трудозатратная + часть проекта. +- Невозможность масштабирования на большой корпус. Для текущей задачи + (80–150 периодов) это приемлемо. + +### 7.7 ПР-07. Английский язык в коде, русский — в документации и отчёте + +**Контекст.** Учебное заведение требует оформления отчёта на русском +языке. С другой стороны, стандарты разработки и совместимость с +инструментами вроде Claude Code предполагают английский язык в коде. + +**Решение.** Чёткое разделение по слоям: + +- Код, идентификаторы, комментарии, сообщения логов, коммиты — английский. +- Документация (README, спецификация, требования, архитектура, + глоссарий) — русский. +- Итоговый отчёт — русский с оформлением по ГОСТу. + +**Последствия.** Однозначность для всех участников разработки. +Двуязычность не создаёт неудобств, поскольку слои разделены. + +--- + +## 8. Точки расширения + +Перечисленные ниже направления развития проекта оставлены явно за рамками +текущей версии. Их реализация может рассматриваться в будущем. + +### 8.1 Дообучение на корпусе японской поп-музыки + +**Описание.** После защиты курсовой работы планируется собрать второй +авторский корпус — гармонические периоды из японских поп-песен (Royal Road +прогрессии, mu-аккорды, характерные секундовые надстройки, on-аккорды) — и +выполнить дополнительное дообучение модели на этом материале с тегом +`STYLE_jpop`. + +**Что уже подготовлено для этого расширения.** В словаре токенов +зарезервирован токен `STYLE_jpop`. Формат `.chord` поддерживает любые +характерные для J-Pop приёмы (расширенные аккорды, инверсии, слэш-аккорды). +В шапке файла предусмотрено поле `style`. + +**Что нужно дополнительно сделать.** Собрать и транскрибировать корпус +J-Pop периодов. Выполнить дообучение существующей модели на смешанном +корпусе (свой + J-Pop) или последовательное дообучение (свой → J-Pop). +Сравнить генерации с разными значениями стилевого conditioning. + +### 8.2 Генерация мелодии + +**Описание.** Расширение модели на генерацию монофонической мелодической +линии, привязанной к гармонической последовательности. + +**Что нужно сделать.** Расширить формат `.chord` дополнительным полем для +мелодической линии (или ввести отдельный формат). Расширить словарь +токенов мелодическими токенами (вероятно, через раздельное представление +ступени, длительности, артикуляции). Архитектура модели может остаться +прежней. + +**Сложность.** Существенная: задача мелодизации сложнее, чем гармонизации, +требует больше данных, имеет другие критерии оценки. + +### 8.3 Voicing внутри аккорда + +**Описание.** Автоматическое расположение нот внутри аккорда выше баса +с учётом голосоведения (минимизация суммарного движения голосов, запрет +параллельных квинт и октав, разрешение тяготеющих ступеней). + +**Что нужно сделать.** Эта задача может быть решена rule-based методом без +машинного обучения. Простой алгоритм минимизации суммарного межаккордового +смещения голосов с дополнительными правилами укладывается в несколько +сотен строк кода. + +**Сложность.** Низкая, выполнима за день-два после защиты курсовой. + +### 8.4 Графический пользовательский интерфейс + +**Описание.** Веб- или десктоп-приложение, позволяющее задавать параметры +генерации интерактивно, прослушивать результат прямо в браузере, сохранять +понравившиеся варианты. + +**Что нужно сделать.** Любой современный веб-фреймворк (FastAPI на backend, +любой минимальный frontend) поверх существующего CLI. Воспроизведение +MIDI в браузере через `Tone.js` или подобные библиотеки. + +**Сложность.** Невысокая по нынешним стандартам, но требует существенного +времени. + +### 8.5 Интеграция с REAPER + +**Описание.** Плагин или внешний инструмент, который при работе в REAPER +позволяет запрашивать генерацию следующего фрагмента прямо из проекта, +учитывая текущий гармонический контекст. + +**Сложность.** REAPER предоставляет ReaScript для расширений на Lua и +Python. Реализация возможна, но требует погружения в API REAPER. + +### 8.6 Обработка модуляций внутри периода + +**Описание.** Текущая версия требует разрезания периодов по точке +модуляции. Альтернатива — введение inline-токена `MODULATE__`, +переключающего тонический центр в середине последовательности. + +**Что нужно сделать.** Расширить словарь токенов на 24 модуляционных +токена. Дополнить парсер и токенизатор поддержкой inline-меток модуляции. +Накопить достаточное число обучающих примеров с модуляциями (что +проблематично при малом исходном корпусе). + +**Сложность.** Средняя, основное ограничение — данные. + +### 8.7 Поддержка большего числа альтераций в аккорде + +**Описание.** Текущая версия поддерживает один слот расширения на аккорд. +Альтерированные доминанты с несколькими альтерациями одновременно +(`C7♯9♭13`) сворачиваются до одной альтерации. + +**Что нужно сделать.** Перейти от единственного `EXT_x` токена к множеству +одновременных токенов расширений. Это требует пересмотра грамматики +последовательности и формата представления одного аккорда (теперь его +описание становится не четырёхтокеновым, а переменной длины). + +**Сложность.** Средняя, в основном проектная — требуется аккуратное +обновление формата с инкрементом версии. + +--- + +## 9. История изменений + +- **1.0** (2026-05-19) — первоначальная редакция документа. diff --git a/docs/chord_format_spec.md b/docs/chord_format_spec.md index ab3fec4..41d43ab 100644 --- a/docs/chord_format_spec.md +++ b/docs/chord_format_spec.md @@ -1,6 +1,4 @@ -# Спецификация формата данных - -## Проект: генератор аккордовых последовательностей +# Спецификация формата данных hamori **Версия:** 2.0 **Дата:** 2026-05-16 diff --git a/docs/glossary.md b/docs/glossary.md new file mode 100644 index 0000000..5147716 --- /dev/null +++ b/docs/glossary.md @@ -0,0 +1,567 @@ +# Глоссарий hamori + +**Версия документа:** 1.0 +**Дата:** 2026-05-19 + +Документ содержит определения терминов, используемых в проекте _hamori_, +разделённые на три тематические группы: музыкальные термины, термины +машинного обучения и проектные термины. Внутри каждой группы записи +упорядочены по алфавиту. + +--- + +## 1. Музыкальные термины + +### Аккорд + +Гармоническая единица — одновременное звучание трёх и более нот. В контексте +проекта аккорд представляется в текстовой нотации (например, `Cmaj7`, `Am`, +`F/G`) и характеризуется четырьмя признаками: корневой тон, качество, +расширение, бас. + +### Аккордовая последовательность (прогрессия) + +Последовательность аккордов, сопровождающая мелодию или существующая +самостоятельно. Является основным объектом генерации в данном проекте. + +### Альтерация + +Хроматическое изменение ступени аккорда — повышение или понижение её на +полутон. В рамках формата проекта альтерации записываются как расширения +вида `b9`, `#9`, `#11`, `b13`. + +### Анакруза (затакт) + +Несколько нот или один аккорд, предшествующих первой сильной доле такта. +В формате проекта затакт записывается через специальное значение `NC` +(no chord) на пустых позициях первого такта. + +### Бас + +Самая нижняя нота аккорда. Может совпадать с корневым тоном (основной +позиции) или отличаться от него (в инверсиях и слэш-аккордах). В формате +проекта бас выделен в отдельный слот токенизации. + +### Гармоническая функция + +Роль аккорда в тональной системе: тоника (T), субдоминанта (S), доминанта +(D) и их побочные ступени. Хотя в формате проекта аккорды записываются +абсолютными именами, а не функциональными цифрами, нормализующая +транспозиция в C major / A minor делает функциональные роли явно читаемыми: +после транспозиции `C` всегда тоника мажорной пьесы, `A` — тоника +минорной. + +### Гармонический период + +Замкнутая гармоническая фраза длиной обычно 4, 8 или 16 тактов, имеющая +ясное начало и завершение (возврат к тонике или полукаденция). Является +**единицей обработки и генерации** в проекте. + +### Голосоведение + +Способ соединения нот в соседних аккордах: плавное движение голосов, +запрет параллельных квинт и октав, разрешение тяготеющих ступеней. +В текущей версии проекта голосоведение **не моделируется** — +сгенерированные аккорды передаются как абстрактные гармонические единицы, +а конкретное расположение голосов оставлено на ручную работу композитора +в DAW. + +### Доминанта + +Аккорд пятой ступени лада. Содержит вводный тон и создаёт сильное +тяготение к тонике. Обычная запись в виде доминантового септаккорда — `G7` +в C major, `E7` в A minor (с альтерированной третьей ступенью минора). + +### Инверсия (обращение) + +Аккорд, в котором в качестве баса выступает не корневой тон, а одна из +других нот аккорда (терция, квинта, септима). В формате проекта инверсии +записываются через слэш-нотацию: `C/E` (C мажор с басом E, первое +обращение), `C/G` (с басом G, второе обращение). + +### Каденция + +Гармонический оборот, завершающий музыкальную фразу. Полная каденция — +переход доминанты в тонику (V → I). Полукаденция — остановка на +доминанте, создающая ожидание продолжения. Полукаденция — характерный +признак середины периода в классических формах. + +### Качество (тип) аккорда + +Интервальная структура аккорда независимо от его корневого тона. Базовые +качества, поддерживаемые форматом проекта: мажорное и минорное трезвучия, +уменьшённое и увеличенное трезвучия, sus2 и sus4, мажорный, минорный, +доминантовый, полууменьшённый и уменьшённый септаккорды, минорно-мажорный +септаккорд, доминанта на sus4, увеличенный септаккорд, мажорный и минорный +аккорды с секстой, аккорды с добавленной ноной. Всего 18 качеств. + +### Корневой тон + +Основная нота, на которой строится аккорд. Не обязательно совпадает с +басом (см. _Инверсия_). В формате проекта корневой тон выделен в отдельный +слот токенизации. + +### Лад + +Структурно-функциональная организация звуков вокруг центра (тоники). +В проекте моделируются два лада: натуральный мажор и натуральный минор +(включая гармонический и мелодический миноры как разновидности — отдельно +не различаются). Лад фиксируется отдельным метатокеном `MODE_major` или +`MODE_minor`. + +### Лид-шит-нотация + +Способ записи музыки, при котором над тактами выписывается мелодия, а +гармония указывается аккордовыми символами без точной нотации каждой ноты +аккорда. Формат `.chord` в проекте — упрощённый аналог лид-шита, +содержащий только гармоническую часть. + +### Минор гармонический + +Разновидность минорного лада с повышенной седьмой ступенью, создающая +выраженную доминанту. Внутренние альтерации (V становится мажорным, +появляется уменьшённый VII7) трактуются в формате проекта как обычные +аккорды. + +### Модуляция + +Смена тональности в произведении. В рамках текущей версии формата +поддерживается только модуляция **между периодами** (каждый период +хранится в своей тональности). Модуляция **внутри периода** обрабатывается +через разрезание периода на два — до и после момента модуляции. + +### Нонаккорд + +Аккорд, расширенный девятой ступенью от корня. В формате проекта — +`Cmaj9` (мажорный септаккорд + натуральная нона), `C9` (доминантовый +септаккорд + нона), `Cm9` (минорный септаккорд + нона), `Cmaj7#11` (с +повышенной квартой), и другие. Записывается как качество + расширение в +слоте `EXT`. + +### Подразделение доли (subdivision) + +Параметр формата, определяющий, на сколько временных позиций делится один +такт. При `subdivision: 4` в размере 4/4 каждый такт делится на четыре +четверти (четыре позиции). При `subdivision: 8` — на восемь восьмых +(восемь позиций). Выбирается в зависимости от того, как часто меняются +аккорды в конкретной пьесе. + +### Полиаккорд + +Одновременное звучание двух функционально различных аккордов в разных +регистрах (например, мажорное трезвучие D-F♯-A над мажорным трезвучием +C-E-G). В текущей версии формата полиаккорды **не поддерживаются**. +Близкие по звучанию структуры записываются через слэш-нотацию (`C/D`, +`F/G`) или ближайший один аккорд с расширениями. + +### Расширение аккорда + +Дополнительный интервал, надстраивающийся над септаккордом: нона (9), +ундецима (11), терцдецима (13), с возможными альтерациями (`b9`, `#9`, +`#11`, `b13`). В формате проекта расширение записывается одним токеном +в отдельном слоте `EXT`. Поддерживается ровно один слот расширения на +аккорд. + +### Royal Road progression + +Характерная гармоническая прогрессия японской популярной музыки: +IV — V — iii — vi (например, в C major: `F → G → Em → Am`). Прогрессия +ассоциируется с мелодичной, ностальгической эмоциональной окраской и +встречается в значительной части анисонга и J-Pop в широком смысле. + +### Sus-аккорды + +Аккорды с задержанной квартой (sus4) или секундой (sus2), заменяющей +терцию. Лишены терцового тона, не определены как мажорные или минорные. +В формате проекта — `Csus4`, `Csus2`, а также `C7sus4` (доминантовый +септаккорд на sus4, часто встречается перед разрешением в обычный +доминантовый аккорд). + +### Слэш-аккорд (slash chord, on-аккорд) + +Аккорд с явно указанным басом, отличным от любой ноты собственного состава. +Записывается как `<аккорд>/<бас>`. Характерный приём японской поп-музыки: +`F/G`, `C/D`, `Em7/A` — обеспечивают плавное движение баса и характерное +напряжение. + +### Тактовый размер + +Соотношение числа долей в такте и их длительности. В формате проекта +поддерживаются `4/4`, `3/4`, `6/8`, `2/4`, `12/8`. Большинство периодов +ожидается в размере `4/4`. + +### Тональность + +Конкретное положение лада на звукоряде, определяемое тоникой и видом +лада (`F# major`, `B♭ minor`, `C major`). В формате `.chord` указывается +в шапке файла полем `key`. Перед обучением модели все периоды +нормализуются в C major / A minor; в словарь модели тональность не +входит. + +### Тонизация (отклонение) + +Кратковременный заход в другую тональность через её собственную доминанту +без полноценной модуляции. Например, в C major последовательность +`Dm — A7 — Dm` содержит тонизацию D minor. В формате проекта тонизации +записываются обычными аккордовыми символами и не требуют специальной +разметки. + +### Тоника + +Главный устойчивый тон лада, опора. В формате после нормализующей +транспозиции тоника — `C` для мажорных периодов и `A` для минорных. + +### Функциональная роль периода + +Роль данного периода в форме исходной пьесы: куплет, припев, пре-припев, +бридж, вступление, проигрыш, концовка. В формате `.chord` указывается в +шапке поле `function`. Передаётся в модель как метатокен `FUNC_x` и может +использоваться как conditioning на инференсе. + +--- + +## 2. Термины машинного обучения + +### Авторегрессионная модель + +Модель, генерирующая последовательность по одному элементу за раз, причём +каждый следующий элемент условен на всех предыдущих. Декодер-only +трансформер, используемый в проекте, — пример авторегрессионной модели. + +### Beam search + +Алгоритм поиска наиболее вероятной последовательности при генерации: +вместо сэмплирования удерживается несколько лучших кандидатов на каждом +шаге, выбирается итоговая последовательность с максимальной совместной +вероятностью. В проекте **не используется**, поскольку для генеративных +творческих задач даёт монотонные результаты. + +### Catastrophic forgetting (катастрофическое забывание) + +Феномен, при котором при дообучении модели на новом наборе данных она +теряет знания, выученные на исходном корпусе. В проекте митигируется +существенным снижением скорости обучения на этапе дообучения и +ограничением числа эпох. + +### Causal mask (причинная маска) + +Маска внимания в декодер-only трансформере, не позволяющая каждой позиции +«видеть» будущие позиции в последовательности. Обеспечивает корректное +обучение задачи предсказания следующего токена. + +### Cross-entropy loss + +Функция потерь, измеряющая расхождение между предсказанным моделью +распределением вероятностей следующего токена и истинным значением. Стандартная +функция потерь для задач классификации и генерации последовательностей. + +### Декодер-only трансформер + +Архитектура нейросети, состоящая из стека одинаковых блоков, каждый из +которых содержит self-attention с причинной маской и feedforward-слой. +В отличие от encoder-decoder архитектуры, у декодер-only нет отдельного +блока для кодирования входа — всё обрабатывается одной башней. GPT-семейство +языковых моделей — наиболее известный пример. Используется в данном проекте. + +### Дообучение (fine-tuning) + +Адаптация модели, ранее обученной на большом корпусе, к конкретной задаче +или домену через дополнительное обучение на меньшем целевом наборе данных. +В проекте после предобучения на McGill Billboard модель дообучается на +собственном корпусе автора. + +### Embedding (эмбеддинг) + +Числовое векторное представление дискретного элемента (токена). В трансформере +эмбеддинги токенов и позиций суммируются и подаются в первый блок. Размерность +эмбеддинга равна размерности модели (`d_model`). + +### Epoch (эпоха) + +Один полный проход обучающего цикла по всем элементам тренировочной выборки. +В проекте предобучение длится до 50 эпох с ранней остановкой, +дообучение — до 15. + +### Holdout (отложенная выборка) + +Часть данных, отделённая до начала обучения и не используемая ни в +тренировочной, ни в валидационной выборках. Применяется только для итоговой +оценки качества модели. В проекте формируется на уровне исходных пьес +(не на уровне периодов), что обеспечивает методологическую честность +сравнения. + +### LayerNorm (нормализация слоя) + +Нормализующее преобразование, стабилизирующее распределение активаций +внутри сети. В архитектуре проекта применяется в pre-norm варианте +(перед residual connection, не после). + +### Learning rate + +Скорость обучения, коэффициент шага оптимизатора. В проекте используется +значение `3e-4` на этапе предобучения и `1e-5` на этапе дообучения — +двухпорядковая разница принципиальна для предотвращения катастрофического +забывания. + +### Logits + +Выход модели перед применением softmax — нормализованные числовые +оценки, отражающие предпочтения модели по каждому возможному следующему +токену. Используются в функции потерь и в процессе сэмплирования. + +### Multi-head attention + +Механизм self-attention, в котором операция внимания выполняется +параллельно несколькими «головами», каждая со своими обучаемыми +проекциями. Результаты голов конкатенируются. В проекте используется +6 голов. + +### Nucleus sampling (top-p sampling) + +Стратегия сэмплирования, при которой на каждом шаге сохраняется +минимальный по числу элементов набор кандидатов с накопленной +вероятностью не менее заданного порога `p`, после чего из этого набора +происходит сэмплирование. Применяется в проекте с `p = 0.9` по умолчанию. + +### Padding + +Дополнение коротких последовательностей до фиксированной длины специальным +токеном. В проекте — токен `` (индекс 2 в словаре), игнорируемый в +функции потерь через параметр `ignore_index`. + +### Perplexity (перплексия) + +Метрика качества языковой модели, рассчитываемая как экспонента средней +кросс-энтропии. Содержательно — «эффективное число равновероятных +альтернатив», между которыми модель колеблется на каждом шаге. Чем +меньше, тем лучше. В проекте используется как основная численная метрика +сравнения базовой и дообученной моделей. + +### Positional embedding (позиционный эмбеддинг) + +Векторное представление позиции токена в последовательности, добавляемое +к токеновому эмбеддингу. Позволяет модели учитывать порядок элементов +(сам по себе self-attention перестановочно-инвариантен). В проекте +используются обучаемые позиционные эмбеддинги. + +### Pre-norm vs post-norm + +Два варианта размещения LayerNorm в блоке трансформера: до residual +connection (pre-norm) или после (post-norm). Pre-norm обычно более +стабилен при обучении. В проекте используется pre-norm. + +### Предобучение (pre-training) + +Этап обучения модели на большом и общем по содержанию корпусе данных, +после которого следует адаптация модели к более узкой задаче или домену. +В проекте предобучение выполняется на McGill Billboard Project. + +### Ранняя остановка (early stopping) + +Приём, прекращающий обучение, когда метрика на валидационной выборке +перестаёт улучшаться на протяжении заданного числа эпох. Предотвращает +переобучение. В проекте используется с параметром терпения 5 эпох. + +### Round-trip эквивалентность + +Свойство пары взаимно обратных преобразований: при последовательном +применении прямого и обратного преобразования исходное представление +восстанавливается с точностью до канонической нормализации. В проекте +требуется для пары «парсинг + токенизация / детокенизация + сериализация» +и проверяется автоматизированными тестами. + +### Self-attention + +Механизм внимания, в котором последовательность взаимодействует сама с +собой: для каждой позиции рассчитываются взвешенные средние значений с +других позиций, веса определяются скалярными произведениями обучаемых +проекций. Центральный элемент архитектуры трансформера. + +### Softmax с температурой + +Модификация softmax, в которой логиты предварительно делятся на +параметр температуры. При температуре больше 1 распределение становится +более равномерным (генерация разнообразнее), при меньше 1 — более +концентрированным (генерация консервативнее). По умолчанию в проекте — 1.0. + +### Tied weights (связанные веса) + +Приём, при котором веса входного эмбеддинга и финальной проекции на +словарь совпадают (одна и та же матрица). Снижает число параметров и +часто улучшает обобщающую способность. Применяется в проекте. + +### Токен + +Элементарная единица обработки модели — целочисленный идентификатор +из конечного словаря. В данном проекте словарь содержит 81 токен, +обозначающих служебные значения, метаданные периода и компоненты +аккордов. + +### Токенизация + +Преобразование исходного представления данных в последовательность +токенов. В проекте — преобразование `.chord`-файла в последовательность +целочисленных идентификаторов. + +### Тренировочная и валидационная выборки (train / val) + +Разбиение обучающих данных: тренировочная выборка используется для +обновления весов модели, валидационная — для контроля переобучения и +выбора лучшего чекпоинта. В проекте используется разбиение 90/10. Кроме +того, отдельно выделяется отложенная выборка (см. _Holdout_). + +### Warmup (разогрев) + +Начальная фаза обучения, в течение которой learning rate линейно растёт +от нуля до целевого значения. Стабилизирует обучение трансформеров на +первых шагах. В проекте — 5% от общего числа шагов. + +### Чекпоинт + +Сохранённое на диск состояние модели (веса, конфигурация, опционально +состояние оптимизатора), пригодное для возобновления обучения или для +инференса. В проекте сохраняются чекпоинты `pretrained.pt` и +`finetuned.pt`. + +--- + +## 3. Проектные термины + +### `.chord`-файл + +Текстовый файл в формате, описанном в `docs/chord_format_spec.md`. Содержит +шапку с метаданными периода и тело — последовательность тактов с +аккордовыми символами. Один файл = один гармонический период. + +### hamori + +Название проекта. Транслитерация японского слова ハモリ, означающего +вокальную гармонизацию — практику добавления второго или третьего голоса +к основной мелодической линии в певческом ансамбле. Само слово образовано +от глагола ハモる (_hamoru_) — «гармонизировать», в свою очередь +заимствованного из английского _harmony_. Название отражает основную +функциональную идею проекта: модель не пишет музыку с нуля, а предлагает +гармонические идеи в дополнение к замыслу композитора. + +### BAR (токен) + +Служебный токен, отмечающий конец такта в токенизированной +последовательности. Помогает модели усваивать ритмическую сетку периода. + +### ``, ``, ``, `` + +Служебные токены словаря: начало последовательности, конец последовательности, +паддинг и неизвестный токен соответственно. + +### `ChordTokens` + +Dataclass, представляющий разобранный аккорд: четыре строковых поля — +`root`, `quality`, `extension`, `bass`. Является промежуточным +представлением между текстовым аккордовым символом и токенами модели. + +### `ChordPeriod` + +Dataclass, представляющий полностью разобранный гармонический период: +метаданные шапки и список тактов, каждый из которых — список позиций. +Является промежуточным представлением между `.chord`-файлом и токенами. + +### `ChordFormatError` / `ChordParseError` + +Типы исключений, поднимаемые при некорректном формате файла или +некорректном аккордовом символе соответственно. Содержат информативные +сообщения с указанием места ошибки. + +### EXT (расширение) + +Один из четырёх слотов токенизации аккорда. Кодирует расширение аккорда: +`EXT_none` (расширения нет), `EXT_9`, `EXT_b9`, `EXT_#9`, `EXT_11`, +`EXT_#11`, `EXT_13`, `EXT_b13`. Восемь возможных значений. + +### FUNC (функциональная роль) + +Метатокен периода, указывающий на функциональную роль в исходной пьесе. +Возможные значения: `FUNC_verse`, `FUNC_chorus`, `FUNC_prechorus`, +`FUNC_bridge`, `FUNC_intro`, `FUNC_outro`, `FUNC_interlude`, `FUNC_other`, +`FUNC_unspecified`. + +### HOLD (токен) + +Служебный токен, означающий, что текущая позиция продолжает звучание +предыдущего аккорда. Использование `HOLD` существенно сокращает длину +последовательности по сравнению с повторением всех четырёх токенов +аккорда. + +### MODE (лад) + +Метатокен периода, указывающий на лад. Только два значения: `MODE_major` +для мажора и `MODE_minor` для минора. После нормализующей транспозиции +этот токен — единственный носитель информации о ладе в обучающих данных. + +### NC (No Chord) + +Специальное значение позиции, обозначающее паузу в гармонии — отсутствие +аккорда. Применяется, например, в анакрузах. Имеет соответствующий +служебный токен `NC` в словаре. + +### Нормализующая транспозиция + +Преобразование, переводящее любой период в каноническую тональность: +мажорные периоды — в C major, минорные — в A minor. Применяется перед +токенизацией. На инференсе обратное преобразование возвращает результат +в требуемую пользователем тональность. + +### Период (см. также _Гармонический период_ в музыкальной части) + +Единица обработки и генерации в проекте. Замкнутая гармоническая фраза +4–16 тактов, представленная одним `.chord`-файлом. + +### QUAL (качество) + +Один из четырёх слотов токенизации аккорда. Кодирует качество аккорда: +`QUAL_maj`, `QUAL_m`, `QUAL_dim`, `QUAL_aug`, `QUAL_sus2`, `QUAL_sus4`, +`QUAL_maj7`, `QUAL_m7`, `QUAL_7`, `QUAL_m7b5`, `QUAL_dim7`, `QUAL_mM7`, +`QUAL_7sus4`, `QUAL_aug7`, `QUAL_6`, `QUAL_m6`, `QUAL_add9`, +`QUAL_m_add9`. Восемнадцать возможных значений. + +### ROOT (корень) + +Один из четырёх слотов токенизации аккорда. Кодирует корневой тон: +`ROOT_C`, `ROOT_C#`, ..., `ROOT_B`. Двенадцать возможных значений. + +### BASS (бас) + +Один из четырёх слотов токенизации аккорда. Кодирует басовый тон: +`BASS_root` (бас совпадает с корнем) или конкретная нота +(`BASS_C`, `BASS_C#`, ..., `BASS_B`). Тринадцать возможных значений. + +### Стилевой тег (STYLE) + +Метатокен периода, указывающий на стилистическую принадлежность. +Возможные значения: `STYLE_user` (собственный корпус автора), `STYLE_jpop` +(японская поп-музыка), `STYLE_classical` (классическая музыка), +`STYLE_jazz` (джазовая музыка), `STYLE_other` (прочее, включая публичные +корпуса вроде McGill Billboard). Может использоваться как conditioning +на инференсе. + +### SUB (подразделение доли) + +Метатокен периода, указывающий, как делится такт на временные позиции. +Возможные значения: `SUB_4` (по четвертям) и `SUB_8` (по восьмым). + +### TIME (тактовый размер) + +Метатокен периода, указывающий тактовый размер. Возможные значения: +`TIME_4/4`, `TIME_3/4`, `TIME_6/8`, `TIME_2/4`, `TIME_12/8`. + +### Шапка файла + +Часть `.chord`-файла, содержащая метаданные периода. Строки шапки +начинаются с символа `#` и имеют вид `# key: value`. Шапка обязательно +содержит поля `title`, `key`, `time`, `subdivision`, `style` и +опционально — `function`. + +--- + +## 4. История изменений + +- **1.0** (2026-05-19) — первоначальная редакция документа. diff --git a/docs/requirements.md b/docs/requirements.md new file mode 100644 index 0000000..09e2912 --- /dev/null +++ b/docs/requirements.md @@ -0,0 +1,467 @@ +# Требования к проекту hamori + +**Версия документа:** 1.0 +**Дата:** 2026-05-19 + +Документ описывает функциональные и нефункциональные требования к проекту +_hamori_ — генератору гармонических периодов в авторском композиторском +стиле. Описываются ограничения, критерии приёмки и явно выведенные за рамки +возможности. + +--- + +## 1. Контекст и цели проекта + +### 1.1 Постановка задачи + +Разработать генеративную нейросетевую модель, способную создавать +гармонические последовательности заданной длины и стилистики, обученную в +том числе на корпусе собственных произведений автора, с целью использования +получившейся модели как творческого инструмента в композиторской работе. + +### 1.2 Заинтересованные стороны + +| Сторона | Интерес | +| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| Автор-разработчик (студент) | Закрытие курсовой дисциплины, получение работающего инструмента для собственной композиторской практики | +| Преподаватель курса | Демонстрация владения полным циклом ML-проекта: постановка задачи, подготовка данных, обучение, оценка, интерпретация | +| Потенциальные читатели исходного кода | Понимание принятых архитектурных решений и возможность повторного использования компонентов | + +### 1.3 Учебные цели + +Демонстрация компетенций в следующих областях машинного обучения: + +- Проектирование задачи генерации последовательностей в условиях ограниченного + объёма обучающих данных. +- Выбор и реализация архитектуры авторегрессионной модели для дискретных + последовательностей. +- Подготовка и токенизация специализированного датасета. +- Применение схемы предобучение / дообучение. +- Количественная и качественная оценка генеративной модели. +- Анализ распределений и интерпретация результатов. + +### 1.4 Прикладные цели + +Получение программного инструмента, обладающего следующими функциональными +характеристиками: + +- Принимает на вход параметры желаемой гармонической последовательности. +- Принимает опциональную гармоническую затравку из нескольких аккордов. +- Генерирует последовательность аккордов, согласованную с заданными параметрами + и стилистически приближенную к авторскому корпусу. +- Сохраняет результат в формате, пригодном для непосредственного использования + в цифровой звуковой рабочей станции. + +--- + +## 2. Ограничения + +### 2.1 Временные ограничения + +Жёсткий срок реализации: менее одного календарного месяца с момента начала +работ. Бюджет ручного труда автора: около 50 часов. + +Распределение времени: + +- Подготовка инфраструктуры данных: ~12 часов. +- Ручная транскрипция собственного корпуса: ~10–15 часов. +- Реализация модели и обучение: ~12 часов. +- Оценка и подготовка примеров: ~6 часов. +- Написание отчёта и оформление: ~10 часов. + +### 2.2 Ресурсные ограничения + +Аппаратные ресурсы: персональный ноутбук автора. Использование облачных +GPU-ресурсов (Google Colab) допустимо, но не должно быть критически +необходимым — модель проектируется так, чтобы обучение было выполнимо на CPU. + +Программные ресурсы: открытое программное обеспечение, бесплатные публичные +датасеты. + +### 2.3 Ограничения по данным + +Объём собственного корпуса автора ограничен числом существующих +композиторских работ и временем, доступным на ручную транскрипцию. +Реалистичный ориентир: 80–150 гармонических периодов из 20–25 пьес. + +Это значение на два-три порядка меньше типичного объёма данных, на которых +обучаются современные музыкальные генеративные модели. Из этого ограничения +вытекает принципиальное архитектурное решение: модель должна использовать +схему «предобучение на публичном корпусе плюс дообучение на собственном +корпусе», обучение с нуля исключительно на собственных данных нецелесообразно. + +### 2.4 Языковые требования + +Согласно требованиям учебного заведения: + +- Итоговый отчёт оформляется на русском языке по стандартам ГОСТ для + студенческих работ. +- Документация для пользователя (README, спецификация формата, описания + архитектуры) ведётся на русском языке. +- Технические артефакты кода (идентификаторы, комментарии, сообщения логов, + сообщения коммитов) ведутся на английском языке для совместимости с + общепринятыми стандартами разработки и удобства совместной работы с + инструментами вроде Claude Code. + +--- + +## 3. Функциональные требования + +### 3.1 Подсистема работы с форматом данных + +**ФТ-1.** Система должна поддерживать чтение `.chord`-файлов в формате, +описанном в `docs/chord_format_spec.md` версии 2.0, включая: + +- Парсинг шапки с метаданными. +- Парсинг тела файла, состоящего из последовательности тактов. +- Распознавание аккордовых символов по правилам §4 спецификации. +- Поддержку всех восемнадцати базовых качеств аккордов с альтернативными + написаниями. +- Поддержку расширений аккордов (одиночный слот). +- Поддержку слэш-нотации для инверсий. +- Распознавание специальных значений (точка для удержания, `NC` для паузы, + `?` для неизвестного аккорда). + +**ФТ-2.** Система должна выполнять валидацию `.chord`-файлов: + +- Проверять корректность шапки (все обязательные поля присутствуют, значения + входят в допустимые множества). +- Проверять, что число позиций в каждом такте соответствует тактовому + размеру и подразделению доли. +- Поднимать информативные ошибки с указанием имени файла, номера такта и + позиции при обнаружении нарушений. + +**ФТ-3.** Система должна выполнять нормализующую транспозицию: +все мажорные периоды приводятся к тональности C major, минорные — к A minor. + +**ФТ-4.** Система должна выполнять токенизацию `.chord`-файлов в +последовательности целочисленных идентификаторов согласно словарю, +описанному в §5 спецификации формата. Словарь содержит 81 токен. + +**ФТ-5.** Система должна поддерживать обратную детокенизацию: преобразование +последовательности целочисленных идентификаторов обратно в `.chord`-файл, +с последующей опциональной транспозицией в произвольную тональность. + +**ФТ-6.** Система должна обеспечивать round-trip эквивалентность: для +любого корректного `.chord`-файла операция `parse → tokenize → detokenize → +serialize` должна давать `.chord`-файл, эквивалентный исходному по +гармоническому содержанию. + +### 3.2 Подсистема экспорта в MIDI + +**ФТ-7.** Система должна обеспечивать экспорт `.chord`-файлов в стандартный +формат MIDI с двумя треками: трек аккордов и трек баса. Темп задаётся +параметром, по умолчанию 90 ударов в минуту. + +**ФТ-8.** Длительности нот в MIDI должны соответствовать длительностям +удержания аккордов в исходном `.chord`-файле. + +### 3.3 Подсистема конвертации внешних корпусов + +**ФТ-9.** Система должна предоставлять конвертер McGill Billboard Project → +формат `.chord`, выполняющий: + +- Чтение Harte-нотации. +- Разрезание исходных пьес на гармонические периоды по границам секций. +- Сохранение каждого периода как отдельного `.chord`-файла. +- Простановку стилевого тега и функциональной роли в шапке. + +**ФТ-10.** Конвертер должен быть устойчив к некорректным или неполным +аннотациям в исходном корпусе: периоды, которые не могут быть однозначно +сконвертированы, пропускаются с записью в лог, выполнение скрипта при этом +не прерывается. + +### 3.4 Подсистема обучения + +**ФТ-11.** Система должна реализовывать архитектуру авторегрессионного +трансформера со следующими параметрами: + +- Количество слоёв: настраиваемое, 2–4 по умолчанию. +- Размерность модели: настраиваемая, 128–256 по умолчанию. +- Число голов внимания: настраиваемое, 4–8 по умолчанию. +- Контекстное окно: 512 токенов. +- Связанные веса входного и выходного эмбеддингов. + +**ФТ-12.** Система должна предоставлять единый скрипт обучения, параметризуемый +аргументами командной строки, поддерживающий: + +- Обучение модели с нуля (предобучение). +- Дообучение существующей модели (fine-tuning) — через параметр инициализации + весов из указанного чекпоинта. +- Настройку всех ключевых гиперпараметров через аргументы. +- Установку случайного зерна для воспроизводимости. +- Автоматический выбор вычислительного устройства (CPU/GPU) с возможностью + принудительного задания. + +**ФТ-13.** В процессе обучения система должна: + +- Логировать значения функции потерь на тренировочной и валидационной + выборках после каждой эпохи. +- Логировать перплексию на валидационной выборке. +- Сохранять лучший по валидационной потере чекпоинт. +- Поддерживать раннюю остановку по валидационной потере с настраиваемым + параметром терпения. +- Сохранять полный лог обучения в формате CSV. + +### 3.5 Подсистема инференса + +**ФТ-14.** Система должна предоставлять CLI-инструмент генерации со +следующими настраиваемыми параметрами: + +- Путь к чекпоинту модели. +- Лад (мажор / минор). +- Тональность (любой из 12 классов высоты). +- Тактовый размер. +- Подразделение доли. +- Стилевой тег. +- Функциональная роль. +- Опциональная гармоническая затравка (последовательность аккордовых символов). +- Температура сэмплирования. +- Параметр top-p (nucleus sampling). +- Максимальное число токенов. +- Случайное зерно. +- Пути для сохранения `.chord`- и MIDI-файлов. + +**ФТ-15.** Инференс должен использовать nucleus sampling с настраиваемой +температурой. Beam search не используется. + +**ФТ-16.** Система должна предотвращать генерацию грамматически невалидных +последовательностей токенов (например, токена расширения сразу после токена +удержания) через маскирование невалидных кандидатов на каждом шаге. + +### 3.6 Подсистема оценки + +**ФТ-17.** Система должна предоставлять скрипт оценки, принимающий на вход +два чекпоинта (базовый и целевой) и отложенную выборку, и формирующий: + +- Численные метрики перплексии для обеих моделей. +- Графики распределений по ключевым гармоническим признакам. +- Сгенерированные образцы для качественного сравнения. + +**ФТ-18.** Графики распределений должны включать: + +- Распределение типов качеств аккордов. +- Долю аккордов с расширениями. +- Долю аккордов с инверсиями. +- Распределение интервалов движения корня. +- Распределение наиболее частых пар «корень-корень» (биграммы). + +Каждый график должен показывать baseline-распределение и target-распределение +на одной координатной плоскости с легендой. + +--- + +## 4. Нефункциональные требования + +### 4.1 Производительность + +**НФТ-1.** Парсинг одного `.chord`-файла должен выполняться менее чем за +100 миллисекунд на стандартном персональном компьютере. + +**НФТ-2.** Один проход обучения по тренировочной выборке (одна эпоха) на +полном McGill корпусе должен укладываться в 10 минут на CPU современного +ноутбука. + +**НФТ-3.** Генерация одного периода должна занимать менее 10 секунд на CPU. + +### 4.2 Корректность + +**НФТ-4.** Парсер аккордовых символов должен корректно обрабатывать все +примеры, перечисленные в §4.6 спецификации формата. + +**НФТ-5.** Round-trip эквивалентность (см. ФТ-6) должна подтверждаться +автоматизированными тестами для всех тестовых фикстур. + +**НФТ-6.** Транспозиция должна быть точной: после транспозиции мажорного +периода в C major все аккорды должны находиться в правильных функциональных +отношениях с новой тоникой. + +### 4.3 Воспроизводимость + +**НФТ-7.** Все скрипты обучения, инференса и оценки должны принимать параметр +случайного зерна и устанавливать его одновременно для PyTorch, NumPy и +стандартного модуля random. + +**НФТ-8.** При фиксированном случайном зерне и идентичных входных данных +запуски обучения должны давать численно воспроизводимые результаты. + +**НФТ-9.** Все эксперименты, упомянутые в итоговом отчёте, должны быть +воспроизводимы посредством запуска документированных команд. + +### 4.4 Надёжность работы с данными + +**НФТ-10.** Невалидные или непарсимые аккордовые символы должны вызывать +явные ошибки с информативным сообщением. Тихая подмена неизвестных символов +на «ближайшие» категорически запрещена: это приводит к молчаливому +повреждению обучающего корпуса. + +**НФТ-11.** Файлы из отложенной выборки не должны использоваться на этапах +тренировки или валидации. Любой скрипт подготовки данных, при обнаружении +файла в `data/holdout/`, должен направлять его в отдельную holdout-выборку. + +### 4.5 Сопровождаемость + +**НФТ-12.** Все публичные функции в модулях `src/` должны иметь аннотации +типов и краткие docstrings. + +**НФТ-13.** Логика парсинга, токенизации и MIDI-экспорта должна покрываться +модульными тестами с использованием pytest. + +**НФТ-14.** Спецификация формата `.chord` является контрактом между уровнем +человекочитаемых данных и уровнем обучения модели. Любые изменения формата +должны сопровождаться обновлением `docs/chord_format_spec.md` и инкрементом +номера версии спецификации. + +### 4.6 Удобство использования + +**НФТ-15.** Каждый CLI-скрипт должен поддерживать флаг `--help` с +информативным описанием параметров. + +**НФТ-16.** Сообщения об ошибках должны содержать достаточно информации для +самостоятельного устранения проблемы пользователем: имя файла, номер строки, +характер нарушения, ожидаемое значение. + +--- + +## 5. Критерии приёмки + +Проект считается завершённым при выполнении всех нижеперечисленных условий. + +### 5.1 Учебные критерии + +| ID | Критерий | +| ---- | ----------------------------------------------------------------------------------------------------------- | +| УК-1 | Реализован полный цикл подготовки данных, обучения, инференса и оценки. | +| УК-2 | Имеется как минимум одна обученная модель, прошедшая стадии предобучения и дообучения. | +| УК-3 | Подготовлен итоговый отчёт, оформленный по стандартам ГОСТ для учебных работ. | +| УК-4 | Отчёт содержит количественное сравнение базовой и дообученной моделей. | +| УК-5 | Отчёт содержит качественные примеры сгенерированных периодов. | +| УК-6 | Все эксперименты, упомянутые в отчёте, воспроизводимы по командам, приведённым в README или в самом отчёте. | + +### 5.2 Технические критерии + +| ID | Критерий | +| ---- | --------------------------------------------------------------------------------------------------------------- | +| ТК-1 | Все автоматизированные тесты проходят. | +| ТК-2 | Round-trip эквивалентность парсера-токенизатора подтверждена на всех тестовых фикстурах. | +| ТК-3 | Транспозиция протестирована для мажорных и минорных периодов с разными исходными тональностями. | +| ТК-4 | Модель обучается до сходимости (валидационная потеря выходит на плато или снижается монотонно). | +| ТК-5 | Перплексия дообученной модели на отложенной выборке ниже перплексии базовой модели на той же выборке. | +| ТК-6 | На графиках распределений виден заметный сдвиг от baseline в сторону характеристик собственного корпуса автора. | + +### 5.3 Прикладные критерии + +| ID | Критерий | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------ | +| ПК-1 | Автор может сгенерировать гармоническую последовательность по произвольным входным параметрам и воспроизвести её в DAW. | +| ПК-2 | Сгенерированные последовательности отличаются от случайного шума: соблюдается тональная стабильность, аккорды функционально связаны. | +| ПК-3 | На качественном уровне в нескольких из сгенерированных примеров автор слышит элементы собственного стиля. | + +--- + +## 6. Намеренно выведенное за рамки + +Перечисленные ниже возможности **не входят** в требования к текущей версии +проекта. Их реализация может рассматриваться как направления дальнейшего +развития после защиты курсовой работы. + +| Возможность | Причина выведения | +| -------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| Генерация мелодической линии | Кратно увеличивает сложность задачи; не помещается в срок | +| Расположение голосов в аккорде (voicing) выше баса | Требует существенно большего датасета; ручная реализация в DAW проще | +| Ритмический паттерн внутри удержания аккорда | Требует моделирования времени с большим разрешением; не критично для задачи | +| Дообучение на корпусе японской поп-музыки | Запланировано как отдельный последующий эксперимент | +| Графический интерфейс | Не добавляет ценности с точки зрения учебных целей; занимает время | +| Прямая интеграция с REAPER | Обмен через MIDI-файлы достаточен и проще в реализации | +| Сравнение нескольких архитектур модели | Не помещается в срок; выбрана одна архитектура с обоснованием | +| Слепой listening-тест с привлечением слушателей | Не помещается в срок; используются качественные примеры | +| Обработка модуляций внутри одного периода | Решено разрезанием периодов по точке модуляции | +| Поддержка микротональных аккордов | Не встречается в целевом материале; округление до темперированного эквивалента | +| Поддержка полиаккордов | Редкое явление в целевом материале; запись через слэш-нотацию или ближайший single chord | + +--- + +## 7. Сценарии использования + +### 7.1 Сценарий У-1. Транскрипция собственной пьесы + +**Действующее лицо:** автор-композитор. + +**Предусловия:** в DAW-проекте имеется готовая пьеса с гармонической +структурой, доступной анализу. Установлена и настроена среда разработки. + +**Основной поток:** + +1. Автор прослушивает пьесу и определяет границы периодов. +2. Для каждого периода создаёт `.chord`-файл и заполняет шапку. +3. Транскрибирует гармонию по позициям, фиксируя инверсии и расширения. +4. Запускает валидатор формата для проверки корректности. +5. Экспортирует периоды в MIDI и прослушивает в DAW параллельно с оригиналом. +6. Корректирует транскрипцию в случае расхождений. + +**Постусловия:** в `data/raw_user/` появились новые `.chord`-файлы, +прошедшие валидацию. + +### 7.2 Сценарий У-2. Полный цикл обучения + +**Действующее лицо:** автор-композитор. + +**Предусловия:** подготовлен собственный корпус и сконвертирован публичный +корпус. + +**Основной поток:** + +1. Запуск скрипта подготовки данных для публичного корпуса. +2. Запуск скрипта подготовки данных для собственного корпуса. +3. Запуск скрипта предобучения, ожидание сходимости. +4. Запуск скрипта дообучения с инициализацией из чекпоинта предобучения. +5. Запуск скрипта оценки для сравнения базовой и дообученной моделей. +6. Анализ полученных графиков и метрик. + +**Постусловия:** в `checkpoints/` сохранены обученные модели, в `reports/` +сформированы графики и численные метрики. + +### 7.3 Сценарий У-3. Генерация гармонической идеи + +**Действующее лицо:** автор-композитор в процессе работы над новой пьесой. + +**Предусловия:** имеется обученная модель. + +**Основной поток:** + +1. Автор определяет желаемые параметры будущего периода: тональность, + функциональную роль, общий характер. +2. Запускает скрипт генерации с этими параметрами. +3. Получает `.chord`-файл и MIDI-файл результата. +4. Открывает MIDI-файл в DAW и прослушивает. +5. В случае удовлетворительного результата — переносит гармоническую + последовательность в свой композиторский проект. +6. В противном случае — повторяет генерацию с другим случайным зерном или + другими параметрами сэмплирования. + +**Постусловия:** автор получает гармоническую идею в требуемом стилистическом +ключе. + +### 7.4 Сценарий У-4. Продолжение начатой идеи + +**Действующее лицо:** автор-композитор, у которого уже есть начало +гармонической последовательности. + +**Предусловия:** имеется обученная модель и сформулированная гармоническая +затравка из нескольких аккордов. + +**Основной поток:** + +1. Автор формулирует затравку в виде строки аккордовых символов. +2. Запускает скрипт генерации с параметром `--prefix`. +3. Модель достраивает остаток периода с учётом затравки. +4. Получает MIDI и прослушивает. + +**Постусловия:** автор получает варианты продолжения для своей гармонической +идеи. + +--- + +## 8. История изменений + +- **1.0** (2026-05-19) — первоначальная редакция документа.