# hamori
Авторегрессионная нейросетевая модель для генерации гармонических периодов
(замкнутых гармонических фраз 4–16 тактов) в авторском композиторском стиле.
Название проекта — _hamori_ (яп. ハモリ) — относится к понятию вокальной
гармонизации, добавлению второго голоса в существующую мелодическую линию.
Отсылка к этому понятию закрепляет основную идею проекта: модель не пишет
музыку с нуля, а предлагает гармонические идеи в дополнение к замыслу
композитора.
Проект разработан как курсовая работа по дисциплине «Машинное обучение» в
рамках обучения в РТУ МИРЭА и одновременно как практический инструмент для
композиторской работы.
## Содержание
- [hamori](#hamori)
- [Содержание](#содержание)
- [1. Краткое описание](#1-краткое-описание)
- [2. Контекст и цели](#2-контекст-и-цели)
- [3. Установка](#3-установка)
- [4. Структура репозитория](#4-структура-репозитория)
- [5. Быстрый старт](#5-быстрый-старт)
- [5.1 Веб-интерфейс](#51-веб-интерфейс)
- [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.2)
│ ├── requirements.md функциональные и нефункциональные требования
│ ├── architecture.md архитектура системы
│ └── glossary.md глоссарий терминов
├── data/
│ ├── raw_user/ .chord-файлы собственного корпуса
│ ├── raw_external/ публичные корпуса (McGill Billboard и др.)
│ ├── processed/
│ │ ├── mcgill/ токенизированные .pt-файлы McGill (train/val)
│ │ └── user/ токенизированные .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-ноутбуки: исследование данных и итоговый отчёт (report.ipynb)
├── checkpoints/ сохранённые состояния моделей
└── reports/ сгенерированные графики и примеры
```
## 5. Быстрый старт
После завершения обучения (см. разделы 6–7) генерация одного периода
выполняется следующей командой:
```bash
python scripts/generate.py \
--checkpoint checkpoints/finetuned.pt \
--mode major \
--key F# \
--style H1K0 \
--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 H1K0 --function verse --time 4/4 \
--prefix "Cmaj7 Am7 Dm7" \
--output reports/samples/continuation.chord
```
Модель достроит остаток периода в логике, выученной на собственном корпусе
автора.
### 5.1 Веб-интерфейс
Для интерактивной работы без командной строки предусмотрен простой
веб-интерфейс на базе Gradio. Запуск:
```bash
python app.py
```
После запуска интерфейс открывается в браузере по адресу
`http://127.0.0.1:7860`. На одной странице расположены форма выбора
параметров (модель, лад, тональность, стиль, функция, тактовый размер,
параметры сэмплирования, опциональный префикс) и блок результата —
текстовая сетка аккордов и кнопки скачивания `.chord`- и `.mid`-файлов.
Краткая инструкция на русском языке встроена в саму страницу (раздел
«Инструкция»).
Интерфейс является надстройкой над тем же модулем `src/generate.py`,
что и CLI; вся логика генерации общая. Полезные флаги:
```bash
python app.py --port 8000 # другой порт
python app.py --share # временная публичная ссылка
```
## 6. Подготовка датасета
Подготовка датасета — самая трудозатратная часть проекта (10–15 часов
чистого времени). Сокращать её за счёт автоматического извлечения аккордов
из аудио нецелесообразно: при плотной фактуре и нетривиальных гармонических
решениях современные алгоритмы chord detection дают слишком высокую долю
ошибок, тогда как ручная транскрипция при наличии абсолютного слуха выполняется
быстро и без потерь.
### 6.1 Собственный корпус
Из 20–25 собственных произведений (DAW-проекты в REAPER) необходимо извлечь
80–150 гармонических периодов и записать каждый в виде отдельного `.chord`-файла
в директории `data/raw_user/`.
Процедура транскрипции:
1. Прослушать пьесу, определить границы замкнутых гармонических фраз. Признаки
замкнутости — возврат к тонике или ясная полукаденция, отсутствие модуляции
внутри фрагмента.
2. Заполнить шапку `.chord`-файла: название, тональность, тактовый размер,
подразделение доли, стилевой тег `H1K0`, функциональная роль периода.
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 Предобучение
```bash
python scripts/pretrain.py
```
Обучает на корпусе McGill (`data/processed/mcgill/`). Выводит оценку времени
выполнения и по окончании сохраняет:
| Файл | Описание |
| ----------------------------------- | ----------------------------- |
| `checkpoints/pretrained.pt` | лучший чекпоинт (по val loss) |
| `checkpoints/pretrained.log.csv` | метрики по эпохам |
| `checkpoints/pretrained_curves.png` | график кривых train/val loss |
| `checkpoints/pretrained.report.txt` | сводный отчёт о прогоне |
Если обучение было прервано, повторно построить график и отчёт без
повторного обучения:
```bash
python scripts/pretrain.py --skip-training
```
### 7.2 Дообучение на собственном корпусе
```bash
python scripts/train.py
```
Загружает `checkpoints/pretrained.pt` и дообучает на собственном корпусе
(`data/processed/user/`). Сохраняет `checkpoints/finetuned.pt` и аналогичный
набор артефактов (`finetuned.log.csv`, `finetuned_curves.png`,
`finetuned.report.txt`).
Существенно более низкая скорость обучения (lr=1e-5 против 3e-4) и небольшое
число эпох (15) предотвращают катастрофическое забывание закономерностей,
выученных на этапе предобучения.
## 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).
Готовые результаты — численные метрики, графики распределений и качественный
разбор примеров — собраны в итоговом отчёте
[notebooks/report.ipynb](notebooks/report.ipynb).
## 9. Дополнительная документация
| Документ | Назначение |
| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [notebooks/report.ipynb](notebooks/report.ipynb) | Итоговый отчёт по проекту (Jupyter-ноутбук на русском): постановка задачи, формат данных, модель, обучение, оценка с графиками, хроника разработки и выводы. Запускается целиком. |
| [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.
- Ритмический паттерн внутри удержания аккорда (синкопы, проходящие фигуры,
альбертиевы басы).
- Аранжировка, тембр, динамика, артикуляция.
- Развитый графический интерфейс. Реализован лишь минимальный веб-интерфейс
(см. раздел 5.1) как надстройка над CLI; полноценного редактора с
визуализацией нотного стана, проигрывателем и историей версий нет.
- Прямая интеграция с REAPER в режиме реального времени. Обмен с DAW
происходит через файлы MIDI.
- Обработка модуляций внутри одного периода. При наличии модуляции в
исходном произведении периоды разрезаются по точке модуляции.
- Дообучение на корпусе японской поп-музыки (J-Pop). Запланировано как
отдельный эксперимент после защиты курсовой.
Подробное обсуждение каждого пункта и направления развития содержатся в
[docs/architecture.md](docs/architecture.md), раздел «Точки расширения».