3b87fb9e33
Added the official DDMAL link at the first prose mention in README.md, docs/architecture.md, and docs/glossary.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
354 lines
23 KiB
Markdown
354 lines
23 KiB
Markdown
# 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](<https://ddmal.ca/research/The_McGill_Billboard_Project_(Chord_Analysis_Dataset)/>)) для усвоения общих гармонических закономерностей
|
||
поп-музыки.
|
||
- **Fine-tuning** на корпусе собственных произведений автора для адаптации
|
||
модели к индивидуальному композиторскому почерку.
|
||
|
||
Юнит обработки и генерации — **гармонический период**, а не пьеса целиком.
|
||
Это решение обеспечивает достаточный размер обучающей выборки при ограниченном
|
||
числе исходных произведений и снимает проблему обработки модуляций между
|
||
крупными разделами формы.
|
||
|
||
## 2. Контекст и цели
|
||
|
||
Проект преследует две сопряжённые цели.
|
||
|
||
**Учебная цель.** Закрытие дисциплины «Машинное обучение» с выполнением
|
||
курсового проекта, включающего полный цикл работы с генеративной моделью:
|
||
постановка задачи, проектирование формата данных, подготовка обучающего
|
||
корпуса, обучение, оценка и интерпретация результатов.
|
||
|
||
**Прикладная цель.** Получение работающего инструмента-помощника, который
|
||
автор сможет использовать в дальнейшей композиторской деятельности как
|
||
источник гармонических идей в собственном стилистическом ключе.
|
||
|
||
Срок реализации: менее одного месяца. Бюджет ручного труда: около 50 часов.
|
||
|
||
Подробное описание целей и формальных требований приведено в
|
||
[docs/requirements.md](docs/requirements.md).
|
||
|
||
## 3. Установка
|
||
|
||
Требования: Python 3.11 или новее, доступ к командной строке, git.
|
||
|
||
```bash
|
||
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) генерация одного периода
|
||
выполняется следующей командой:
|
||
|
||
```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
|
||
```
|
||
|
||
Модель достроит остаток периода в логике, выученной на собственном корпусе
|
||
автора.
|
||
|
||
## 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](<https://ddmal.ca/research/The_McGill_Billboard_Project_(Chord_Analysis_Dataset)/>) — открытый
|
||
размеченный профессиональными аннотаторами корпус из примерно семи сотен
|
||
пьес западной поп-музыки 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).
|
||
|
||
## 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), раздел «Точки расширения».
|