H1K0 9e73fa5d32 feat: add --bars arg to control output length
generate_period() now accepts n_bars=N to stop after exactly N complete
bars. bars_completed is seeded from the prefix length so --bars counts
the full output, not just the generated tail.

scripts/generate.py exposes this as --bars (default: None = model decides).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 20:29:44 +03:00

hamori

Авторегрессионная нейросетевая модель для генерации гармонических периодов (замкнутых гармонических фраз 4–16 тактов) в авторском композиторском стиле.

Название проекта — hamori (яп. ハモリ) — относится к понятию вокальной гармонизации, добавлению второго голоса в существующую мелодическую линию. Отсылка к этому понятию закрепляет основную идею проекта: модель не пишет музыку с нуля, а предлагает гармонические идеи в дополнение к замыслу композитора.

Проект разработан как курсовая работа по дисциплине «Машинное обучение» в рамках обучения в РТУ МИРЭА и одновременно как практический инструмент для композиторской работы.

Содержание


1. Краткое описание

Система принимает на вход параметры желаемого периода (тональность, тактовый размер, стилевой тег, функциональная роль) и опционально первые несколько аккордов. На выходе формируется гармоническая последовательность, представленная как .chord-файл лид-шит-нотации и MIDI-файл для воспроизведения и работы в цифровой звуковой рабочей станции.

Модель обучается в две стадии:

  • Pre-training на публичном корпусе аккордовых последовательностей (McGill Billboard Project) для усвоения общих гармонических закономерностей поп-музыки.
  • Fine-tuning на корпусе собственных произведений автора для адаптации модели к индивидуальному композиторскому почерку.

Юнит обработки и генерации — гармонический период, а не пьеса целиком. Это решение обеспечивает достаточный размер обучающей выборки при ограниченном числе исходных произведений и снимает проблему обработки модуляций между крупными разделами формы.

2. Контекст и цели

Проект преследует две сопряжённые цели.

Учебная цель. Закрытие дисциплины «Машинное обучение» с выполнением курсового проекта, включающего полный цикл работы с генеративной моделью: постановка задачи, проектирование формата данных, подготовка обучающего корпуса, обучение, оценка и интерпретация результатов.

Прикладная цель. Получение работающего инструмента-помощника, который автор сможет использовать в дальнейшей композиторской деятельности как источник гармонических идей в собственном стилистическом ключе.

Срок реализации: менее одного месяца. Бюджет ручного труда: около 50 часов.

Подробное описание целей и формальных требований приведено в docs/requirements.md.

3. Установка

Требования: Python 3.11 или новее, доступ к командной строке, git.

git clone <repository-url> 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-ноутбуки для исследования и отчётности
├── checkpoints/                       сохранённые состояния моделей
└── reports/                           графики, примеры и итоговый отчёт

5. Быстрый старт

После завершения обучения (см. разделы 6–7) генерация одного периода выполняется следующей командой:

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:

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

Модель достроит остаток периода в логике, выученной на собственном корпусе автора.

6. Подготовка датасета

Подготовка датасета — самая трудозатратная часть проекта (10–15 часов чистого времени). Сокращать её за счёт автоматического извлечения аккордов из аудио нецелесообразно: при плотной фактуре и нетривиальных гармонических решениях современные алгоритмы chord detection дают слишком высокую долю ошибок, тогда как ручная транскрипция при наличии абсолютного слуха выполняется быстро и без потерь.

6.1 Собственный корпус

Из 20–25 собственных произведений (DAW-проекты в REAPER) необходимо извлечь 80–150 гармонических периодов и записать каждый в виде отдельного .chord-файла в директории data/raw_user/.

Процедура транскрипции:

  1. Прослушать пьесу, определить границы замкнутых гармонических фраз. Признаки замкнутости — возврат к тонике или ясная полукаденция, отсутствие модуляции внутри фрагмента.
  2. Заполнить шапку .chord-файла: название, тональность, тактовый размер, подразделение доли, стилевой тег H1K0, функциональная роль периода.
  3. Транскрибировать гармонию по позициям, аккуратно фиксируя инверсии и расширения.
  4. Запустить парсер для проверки корректности файла:
    python scripts/validate_chord_file.py data/raw_user/2024_001_song_chorus.chord
    
  5. Запустить экспорт в MIDI и прослушать результат в DAW параллельно с оригиналом для контроля точности транскрипции:
    python -m src.midi_export data/raw_user/2024_001_song_chorus.chord /tmp/check.mid
    

Полная спецификация формата приведена в docs/chord_format_spec.md. Чек-лист транскрипции — в разделе 10 спецификации.

6.2 Публичный корпус

Для предобучения используется McGill Billboard Project — открытый размеченный профессиональными аннотаторами корпус из примерно семи сотен пьес западной поп-музыки 1950–1990-х годов. Корпус необходимо скачать с официального сайта и распаковать в директорию data/raw_external/mcgill_billboard/.

Конвертация в формат .chord:

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-файлы готовы, выполняется пакетная токенизация:

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 Предобучение

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 сводный отчёт о прогоне

Если обучение было прервано, повторно построить график и отчёт без повторного обучения:

python scripts/pretrain.py --skip-training

7.2 Дообучение на собственном корпусе

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. Оценка результатов

Скрипт оценки сравнивает базовую (только предобученную) и дообученную модели на отложенной выборке:

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.

9. Дополнительная документация

Документ Назначение
docs/chord_format_spec.md Полная спецификация формата .chord, словарь токенов, правила парсинга. Авторитетный источник по формату.
docs/requirements.md Функциональные и нефункциональные требования, критерии приёмки.
docs/architecture.md Архитектура системы, схемы потоков данных, описания модулей, обоснование ключевых проектных решений.
docs/glossary.md Глоссарий музыкальных, машинно-обучательных и проектных терминов.
CLAUDE.md Постоянный контекст для Claude Code (на английском). Описывает правила разработки, чего нельзя делать без согласования и какие модули за что отвечают.

10. Ограничения текущей версии

Текущая версия проекта сознательно ограничена для соблюдения сроков курсовой работы. Перечисленные ниже возможности не реализованы и являются кандидатами для дальнейшего развития.

  • Генерация мелодии. Текущая модель работает только с гармонической последовательностью.
  • Расположение голосов внутри аккорда (voicing) выше баса. Бас передаётся, остальное оставлено на ручную работу композитора в DAW.
  • Ритмический паттерн внутри удержания аккорда (синкопы, проходящие фигуры, альбертиевы басы).
  • Аранжировка, тембр, динамика, артикуляция.
  • Графический пользовательский интерфейс. Взаимодействие осуществляется через командную строку.
  • Прямая интеграция с REAPER в режиме реального времени. Обмен с DAW происходит через файлы MIDI.
  • Обработка модуляций внутри одного периода. При наличии модуляции в исходном произведении периоды разрезаются по точке модуляции.
  • Дообучение на корпусе японской поп-музыки (J-Pop). Запланировано как отдельный эксперимент после защиты курсовой.

Подробное обсуждение каждого пункта и направления развития содержатся в docs/architecture.md, раздел «Точки расширения».

S
Description
Small autoregressive transformer for harmonic period generation — pre-trains on McGill Billboard, fine-tunes on personal compositions
Readme 34 MiB
Languages
Jupyter Notebook 58.5%
Python 41.5%