Содержание курса 33 / 33

33 / 33 · Генерация звука

Генерация звука: синтез речи и музыка

Инструменты курса в применении к звуку: формы волны и мел-спектрограммы, конвейер синтеза речи, Glow-TTS как нормализующий поток с априорным распределением, заданным текстом, и поиском монотонного выравнивания, нейросетевые аудиокодеки с остаточным векторным квантованием и MusicGen — один трансформер над параллельными потоками кодов с условием на текст, мелодию или начало записи.

На этой странице 11

Предыдущая заметка превращала изображения в последовательности дискретных токенов и генерировала их трансформером, управляя сэмплированием с помощью температуры, top-kk и classifier-free guidance. Звук ставит ту же задачу в большем масштабе. Одна секунда звука — это десятки тысяч чисел, больше, чем в небольшом изображении, а музыкальное произведение длится минуты. В этой заметке разобраны два ответа. Синтез речи сохраняет непрерывное промежуточное представление — мел-спектрограмму (mel spectrogram), и Glow-TTS генерирует её нормализующим потоком (normalizing flow), априорное распределение которого задаётся текстом. Генерация музыки сжимает форму волны нейросетевым кодеком в несколько параллельных потоков токенов, и MusicGen моделирует их все одним трансформером с условием на текст, мелодию или начало записи.

Обозначения. Форма волны (waveform) a∈Rdfsa \in \mathbb R^{d f_s} — это dd секунд звука, дискретизированного с частотой fsf_s отсчётов в секунду. Мел-спектрограмма x∈RF×Tmelx \in \mathbb R^{F \times T_{\text{mel}}} состоит из FF частотных полос и TmelT_{\text{mel}} кадров. Текст — последовательность токенов c=(c1,…,cTtext)c = (c_1, \dots, c_{T_{\text{text}}}): фонем для речи, подслов для описаний музыки. Кодек кодирует форму волны в T=dfrT = d f_r латентных кадров zt∈RDz_t \in \mathbb R^D с частотой кадров fr≪fsf_r \ll f_s и квантует каждый кадр с помощью KK словарей кодов (codebooks) C1,…,CK\mathcal C_1, \dots, \mathcal C_K по MM векторов в каждом, что даёт коды qt,k∈{1,…,M}q_{t,k} \in \{1, \dots, M\}. Как и в заметках о потоках, поток отображает латентную переменную в данные, f:z↦xf: z \mapsto x, а второй аргумент N\mathcal N — дисперсия.

Звук как сигнал#

Микрофон записывает давление воздуха. Если измерять его fsf_s раз в секунду, получается форма волны — последовательность чисел из [−1,1][-1, 1], и по теореме отсчётов (теореме Котельникова, sampling theorem) сохраняются частоты до fs/2f_s / 2. Речь обычно дискретизируют с частотой от 16 до 22.05 кГц; музыке нужен весь слышимый диапазон, и её записывают с частотой 44.1 или 48 кГц (Copet et al., 2023, §1). Набор данных LJ Speech, стандартный корпус с одним диктором, хранит 16-битный монофонический звук с частотой 22 050 Гц: 352 800 бит и 22 050 чисел в секунду (Ito and Johnson, 2017). Авторегрессионная модель над отдельными отсчётами, например WaveNet (van den Oord et al., 2016), делает один проход сети на отсчёт — 22 050 проходов на секунду речи.

Спектрограмма описывает тот же звук через то, какие частоты в какой момент присутствуют. Оконное преобразование Фурье (short-time Fourier transform, STFT) разрезает форму волны на перекрывающиеся окна и берёт преобразование Фурье каждого из них; амплитуды образуют частотно-временное изображение. Например, при окне в 1024 отсчёта (46.4 мс при 22 050 Гц) и шаге (hop) в 256 отсчётов (11.6 мс) получается 22 050/256≈86.1322\,050 / 256 \approx 86.13 кадра в секунду.

Мел-спектрограмма сжимает ось частот так, как это делает слух. Восприятие высоты тона примерно линейно ниже 1 кГц и логарифмично выше, и мел-шкала следует ему; одна из распространённых форм — m(f)=2595log⁡10(1+f/700)m(f) = 2595 \log_{10}(1 + f / 700), она переводит 1000 Гц в 1000 мел, а 11 025 Гц — в 3176 мел. Банк треугольных фильтров, равномерно расположенных по мел-шкале, суммирует амплитуды в FF полос, узких на низких частотах и широких на высоких, и результат переводится в логарифмическую шкалу. При F=80F = 80 полосах секунда речи превращается в 80×22 050/256≈689180 \times 22\,050 / 256 \approx 6891 число вместо 22 050, примерно в 3.2 раза меньше, а соседние кадры сильно коррелированы, что облегчает моделирование последовательности.

Цена — фаза. Амплитуды говорят, сколько в сигнале каждой частоты, но не говорят, как выровнены волны, а банк фильтров к тому же отбрасывает детали, так что мел-спектрограмма не определяет свою форму волны однозначно. Подходящую форму волны должен построить вокодер (vocoder). Классический метод Гриффина–Лима (Griffin and Lim, 1984) поочерёдно переходит между временной и частотной областями, сохраняя заданные амплитуды и заново оценивая фазу; он не требует обучения, но фаза получается лишь приближённой, и в результате слышны артефакты. Нейросетевые вокодеры обучаются этому отображению на данных.

Отсюда два пути этой заметки. Синтез речи генерирует мел-спектрограмму и передаёт её вокодеру. Генерация музыки обучает дискретный код самой формы волны, как VQGAN делал это для изображений, и генерирует код.

Конвейер синтеза речи#

Система синтеза речи по тексту (text-to-speech, TTS) превращает письменный текст в форму волны поэтапно, и каждый этап — условная модель.

  1. Нормализация текста записывает словами то, что пишется не так, как произносится: числа, даты, сокращения, символы. «Dr. Smith paid £5 on 3 May» нужно превратить в слова, прежде чем что-либо произносить. LJ Speech хранит текст каждого фрагмента дважды: в исходном виде и в нормализованном, где числа, порядковые числительные и денежные единицы записаны словами.
  2. Преобразование графем в фонемы (grapheme-to-phoneme, G2P) переводит буквы в фонемы, например в символы Международного фонетического алфавита. Английская орфография неоднозначна: «read» произносится двумя способами, а в «though», «through» и «tough» окончание «ough» обозначает три разных гласных. Фонемизатор на правилах, например eSpeak, или обученная модель G2P снимает эту нагрузку с акустической модели.
  3. Лингвистический и фонетический анализ добавляет то, чего не говорят фонемы: ударение, границы фраз, интонацию. В нейросетевых системах это по большей части неявно делает акустическая модель.
  4. Акустическая модель переводит последовательность фонем в мел-спектрограмму.
  5. Вокодер переводит мел-спектрограмму в форму волны.

Акустическая модель сталкивается с главной трудностью TTS — выравниванием (alignment). На входе десятки фонем, на выходе сотни кадров, и сколько кадров длится каждая фонема, в данных не указано. Tacotron 2 (Shen et al., 2018) декодирует кадры авторегрессионно и обучает внимание по входным токенам, которое кадр за кадром решает, какой из них сейчас произносится; затем вокодер WaveNet строит форму волны. Генерация последовательна, а ошибки внимания приводят к пропуску или повтору слов, особенно на длинных или повторяющихся входах (Kim et al., 2020, §1). FastSpeech (Ren et al., 2019) генерирует все кадры параллельно: регулятор длины (length regulator) повторяет скрытый вектор каждой фонемы столько раз, какова её предсказанная длительность. Однако целевые длительности для него берутся из внимания предобученной авторегрессионной модели-учителя, так что параллельная модель всё ещё зависит от внешнего источника выравнивания.

Вокодеры охватывают семейства курса. WaveNet — авторегрессионная модель над отсчётами. WaveGlow (Prenger, Valle and Catanzaro, 2019) — нормализующий поток из гауссовского шума в форму волны с условием на мел-спектрограмму, обученный методом максимального правдоподобия. Быстрее всех GAN-вокодеры: HiFi-GAN (Kong, Kim and Bae, 2020) обучает свёрточный генератор против многомасштабного дискриминатора и многопериодного дискриминатора (multi-period discriminator), поддискриминаторы которого смотрят на каждый pp-й отсчёт при p=2,3,5,7,11p = 2, 3, 5, 7, 11, чтобы уловить периодическую структуру вокализованной речи; к этому добавляются функция потерь L1L_1 на мел-спектрограммах и функция потерь сопоставления признаков (feature matching). На LJ Speech средняя экспертная оценка (mean opinion score, MOS), которую ему дают слушатели, 4.36, приближается к 4.45 у записей, а работает он в 167.9 раза быстрее реального времени на одном GPU V100. Multi-band MelGAN (Yang et al., 2020) — более лёгкий GAN-вокодер того же рода, а LPCNet (Valin and Skoglund, 2019) сочетает классическое линейное предсказание с небольшой рекуррентной сетью и достаточно дёшев для телефонов и встраиваемых устройств.

Конвейер можно и свернуть в одну модель. VITS (Kim, Kong and Son, 2021) — условный VAE, априорное распределение которого — нормализующий поток с условием на фонемы, а декодер — генератор HiFi-GAN, обучаемый состязательно; он сразу выдаёт форму волны. Голос диктора (speaker identity) — ещё одно условие. Модель с несколькими дикторами либо обучает эмбеддинг для каждого идентификатора диктора, как VITS для 109 дикторов корпуса VCTK, либо получает эмбеддинг диктора, вычисленный отдельным энкодером диктора по эталонной записи. YourTTS (Casanova et al., 2022) строится на VITS с таким энкодером, поэтому короткой записи голоса, которого не было при обучении, достаточно, чтобы синтезировать им новый текст.

Glow-TTS: поток с априорным распределением, заданным текстом#

Glow-TTS (Kim et al., 2020) — параллельная акустическая модель, которая сама обучается выравниванию. Она сочетает две идеи курса: точное правдоподобие нормализующего потока и поиск по выравниваниям с помощью динамического программирования.

Правдоподобие#

Декодер fdec:z↦xf_{\text{dec}}: z \mapsto x — обратимый поток из латентной последовательности z=(z1,…,zTmel)z = (z_1, \dots, z_{T_{\text{mel}}}), zj∈RFz_j \in \mathbb R^F, в мел-спектрограмму. Для фиксированного выравнивания AA латентных кадров с токенами текста, определённого ниже, замена переменных даёт

log⁡pθ(x∣c;A)=log⁡pZ(fdec−1(x)∣c;A)+log⁡∣det⁡∂fdec−1(x)∂x∣.\log p_\theta(x \mid c; A) = \log p_Z\big(f_{\text{dec}}^{-1}(x) \mid c; A\big) + \log \left\lvert \det \frac{\partial f_{\text{dec}}^{-1}(x)}{\partial x} \right\rvert .

Декодер не видит текста. Текст входит через априорное распределение: текстовый энкодер fencf_{\text{enc}} читает фонемы и выдаёт для каждого токена ii среднее μi∈RF\mu_i \in \mathbb R^F и стандартные отклонения σi∈RF\sigma_i \in \mathbb R^F. Выравнивание A:{1,…,Tmel}→{1,…,Ttext}A: \{1, \dots, T_{\text{mel}}\} \to \{1, \dots, T_{\text{text}}\} указывает, к какому токену относится каждый латентный кадр, и априорное распределение — произведение гауссиан:

log⁡pZ(z∣c;A)=∑j=1Tmellog⁡N(zj; μA(j), diag⁡σA(j)2).\log p_Z(z \mid c; A) = \sum_{j=1}^{T_{\text{mel}}} \log \mathcal N\big(z_j;\ \mu_{A(j)},\ \operatorname{diag} \sigma_{A(j)}^2\big) .

Человек читает текст по порядку, не пропуская слов, поэтому от AA требуется быть монотонным (оно никогда не возвращается назад) и сюръективным (каждый токен получает хотя бы один кадр).

Максимизировать одновременно по параметрам θ\theta и выравниванию AA вычислительно неразрешимо (intractable), поэтому обучение чередует два шага. При фиксированных θ\theta находим наиболее вероятное выравнивание A∗A^*; при фиксированном A∗A^* делаем градиентный шаг по θ\theta. Поскольку z=fdec−1(x)z = f_{\text{dec}}^{-1}(x) и логарифм определителя не зависят от AA, на первом шаге достаточно максимизировать априорное слагаемое. Это обучение по Витерби (Viterbi training): оно максимизирует max⁡Alog⁡pθ(x∣c;A)\max_A \log p_\theta(x \mid c; A) — правдоподобие при единственном лучшем выравнивании, которое находит описанный ниже поиск. Маргинальное правдоподобие при одном тексте, pθ(x∣c)p_\theta(x \mid c), потребовало бы модели выравниваний и суммы по всем ним.

Монотонных сюръективных выравниваний (Tmel−1Ttext−1)\binom{T_{\text{mel}} - 1}{T_{\text{text}} - 1} — по одному на каждый выбор кадров, с которых начинается новый токен. Для примерно 50 фонем и 430 кадров, пяти секунд речи, это 9.3⋅10649.3 \cdot 10^{64}. Поиск монотонного выравнивания (monotonic alignment search, MAS) находит лучшее из них динамическим программированием. Пусть Qi,jQ_{i,j} — наибольшее логарифмическое правдоподобие первых jj кадров, выровненных с первыми ii токенами так, что кадр jj приходится на токен ii. Монотонность и сюръективность оставляют кадру j−1j - 1 только два варианта, токен ii или токен i−1i - 1, поэтому

Qi,j=max⁡(Qi−1, j−1, Qi, j−1)+log⁡N(zj; μi, diag⁡σi2),Q1,j=∑k=1jlog⁡N(zk; μ1, diag⁡σ12).Q_{i,j} = \max\big(Q_{i-1,\, j-1},\ Q_{i,\, j-1}\big) + \log \mathcal N\big(z_j;\ \mu_i,\ \operatorname{diag} \sigma_i^2\big), \qquad Q_{1,j} = \sum_{k=1}^{j} \log \mathcal N\big(z_k;\ \mu_1,\ \operatorname{diag} \sigma_1^2\big) .

Таблица содержит Ttext×TmelT_{\text{text}} \times T_{\text{mel}} клеток, 21 500 в примере выше. Выравнивание восстанавливается обратным проходом: начинаем с A∗(Tmel)=TtextA^*(T_{\text{mel}}) = T_{\text{text}} и на каждом предыдущем кадре берём того из двух предшественников, у которого QQ больше. По данным статьи, на CPU это занимает меньше 20 мс на итерацию, менее 2% времени обучения, а при инференсе MAS не нужен.

Разобранный пример. Возьмём три токена с одномерными средними μ=(0,2,4)\mu = (0, 2, 4) и σ=1\sigma = 1 — значение, которое статья фиксирует при обучении, — и шесть латентных кадров z=(−0.2, 0.3, 2.4, 0.9, 3.7, 4.1)z = (-0.2,\ 0.3,\ 2.4,\ 0.9,\ 3.7,\ 4.1). При σ=1\sigma = 1 имеем log⁡N(zj;μi,1)=−12log⁡2π−12(zj−μi)2\log \mathcal N(z_j; \mu_i, 1) = -\tfrac12 \log 2\pi - \tfrac12 (z_j - \mu_i)^2, а каждое выравнивание использует каждый кадр ровно один раз, поэтому максимизировать QQ — то же самое, что минимизировать сумму квадратов расстояний Ci,j=min⁡(Ci−1,j−1, Ci,j−1)+(zj−μi)2C_{i,j} = \min(C_{i-1,j-1},\ C_{i,j-1}) + (z_j - \mu_i)^2, где Qi,j=−j2log⁡2π−12Ci,jQ_{i,j} = -\tfrac j2 \log 2\pi - \tfrac12 C_{i,j}:

z1=−0.2z_1 = -0.2z2=0.3z_2 = 0.3z3=2.4z_3 = 2.4z4=0.9z_4 = 0.9z5=3.7z_5 = 3.7z6=4.1z_6 = 4.1
токен 1, μ1=0\mu_1 = 00.040.135.896.7020.3937.20
токен 2, μ2=2\mu_2 = 2—2.930.291.504.398.80
токен 3, μ3=4\mu_3 = 4——5.499.901.591.60

Обратный проход из угла, 1.60, выбирает выделенные клетки: A∗=(1,1,2,2,3,3)A^* = (1, 1, 2, 2, 3, 3), длительности d=(2,2,2)d = (2, 2, 2), суммарная стоимость 1.60 и логарифм априорной плотности −3log⁡2π−0.80=−6.31-3 \log 2\pi - 0.80 = -6.31. Кадр z4=0.9z_4 = 0.9 ближе к μ1\mu_1 (квадрат расстояния 0.81), чем к μ2\mu_2 (1.21). Если отнести каждый кадр к ближайшему среднему, получится (1,1,2,1,3,3)(1, 1, 2, 1, 3, 3) с меньшей суммой, 1.20, но это выравнивание возвращается от токена 2 к токену 1, чего читающий человек никогда не делает. MAS платит 1.60 за лучшее из допустимых выравниваний.

Длительности и сэмплирование#

При инференсе нет мел-спектрограммы, с которой можно было бы выравнивать, поэтому выравнивание приходится предсказывать. MAS даёт целевые значения для обучения: длительность токена ii — число выровненных с ним кадров, di=∣{j:A∗(j)=i}∣d_i = \lvert \{ j : A^*(j) = i \} \rvert, в примере (2,2,2)(2, 2, 2). Предсказатель длительностей (duration predictor) fdurf_{\text{dur}}, два свёрточных слоя поверх выхода энкодера hh, обучается с квадратичной ошибкой на логарифмах длительностей,

Ldur=1Ttext∑i=1Ttext(fdur(sg[h])i−log⁡di)2,\mathcal L_{\text{dur}} = \frac{1}{T_{\text{text}}} \sum_{i=1}^{T_{\text{text}}} \Big( f_{\text{dur}}\big(\mathrm{sg}[h]\big)_i - \log d_i \Big)^2 ,

где остановка градиента (stop-gradient) sg\mathrm{sg} не даёт этой функции потерь менять энкодер, который обучается через правдоподобие.

Дальше синтез параллелен. Энкодер даёт μi,σi\mu_i, \sigma_i; предсказатель даёт длительности, которые округляются вверх и разворачивают средние и стандартные отклонения в последовательность кадров, как это делает регулятор длины в FastSpeech; латентная переменная сэмплируется как zj=μA(j)+τ σA(j)⊙εjz_j = \mu_{A(j)} + \tau\,\sigma_{A(j)} \odot \varepsilon_j с εj∼N(0,I)\varepsilon_j \sim \mathcal N(0, I); один проход декодера даёт x=fdec(z)x = f_{\text{dec}}(z). Температура τ\tau масштабирует стандартные отклонения априорного распределения. В экспериментах статьи стандартное отклонение фиксировано: σ=1\sigma = 1 (Kim et al., 2020, §4); так же сделано в опубликованной авторами конфигурации и по умолчанию в Coqui TTS (mean_only): энкодер предсказывает только средние, латентная переменная равна zj=μA(j)+τεjz_j = \mu_{A(j)} + \tau \varepsilon_j, и τ\tau — стандартное отклонение, используемое при сэмплировании, как в формуле 8 статьи. Разный шум ε\varepsilon даёт разные акценты и интонацию одного и того же предложения, изменение одного лишь τ\tau сдвигает высоту тона, сохраняя похожую интонацию, а умножение всех длительностей на константу меняет темп речи; статья показывает множители от 0.5 до 1.25. Слушатели выше всего оценили τ=0.333\tau = 0.333.

Внутри декодера#

Декодер — стек в стиле Glow (архитектуры потоков). Сначала пары соседних 80-полосных кадров сжимаются (squeeze) в одиночные 160-канальные кадры, что вдвое сокращает длину. Затем каждый из 12 блоков применяет слой ActNorm, обратимую свёртку 1×11 \times 1 и аффинный слой связи (affine coupling layer), масштаб и сдвиг которого вычисляет свёрточная сеть в духе WaveNet, как в WaveGlow. Свёртка 1×11 \times 1 удешевлена: 160 каналов делятся на 40 групп по четыре, которые перемешиваются одной общей матрицей 4×44 \times 4, так что логарифм её определителя равен 4040, умноженному на число сжатых кадров и на log⁡∣det⁡W∣\log \lvert \det W \rvert одной матрицы 4×44 \times 4. Энкодер — энкодер Transformer с относительными позиционными представлениями, 6 блоков ширины 192. Во всей модели 28.6 миллиона параметров — меньше, чем 30.1 миллиона у FastSpeech.

На LJ Speech (13 100 фрагментов, около 24 часов) с вокодером WaveGlow слушатели дали Glow-TTS среднюю экспертную оценку 4.01 против 3.88 у Tacotron 2. Записи получили 4.54, а записи, переведённые в мел-спектрограммы и обратно вокодером WaveGlow, — 4.19. Это базовый уровень реконструкции для этого вокодера в этом тесте: точность вокодера — практическое узкое место для любой акустической модели, которая его питает, но оценка, измеренная на восстановленных записях, — не доказанный максимум по всем спектрограммам, которые может выдать акустическая модель, и, как любая оценка слушателей, она несёт неопределённость от слушателей и предложений. Glow-TTS генерировал мел-спектрограммы в 15.7 раза быстрее Tacotron 2, почти за постоянные 40 мс независимо от длины; на минуту речи весь синтез занимал 1.5 секунды, 96% из которых приходилось на вокодер. На длинных предложениях доля ошибок в символах (character error rate) у Tacotron 2 начинала расти примерно после 260 символов, а Glow-TTS оставался устойчивым, потому что жёсткое монотонное выравнивание не может ничего пропустить или повторить. Как собирают и сравнивают такие оценки слушателей, разбирается в заметке об оценке людьми.

Нейросетевые аудиокодеки: звук как токены#

Музыке нужна полная полоса частот и множество перекрывающихся инструментов, а авторегрессионному трансформеру нужны дискретные токены. Ответ, найденный для изображений, переносится и сюда: обучить автоэнкодер с дискретным узким местом (bottleneck), здесь на форме волны, и моделировать его коды. Тридцать секунд музыки при 32 кГц — это 960 000 отсчётов; кодек должен сократить это число на порядки, сохранив звук.

EnCodec#

EnCodec (Défossez et al., 2023) следует SoundStream (Zeghidour et al., 2022). Энкодер — одномерная свёрточная сеть: первая свёртка с 32 каналами, затем четыре блока из остаточного модуля и свёртки с шагом (strided convolution) 2, 4, 5 и 8, причём при каждом понижении разрешения число каналов удваивается, затем двухслойная LSTM и последняя свёртка в DD каналов. Общий шаг равен 2⋅4⋅5⋅8=3202 \cdot 4 \cdot 5 \cdot 8 = 320 отсчётам, так что звук с частотой 24 кГц даёт 75 латентных кадров в секунду, а с частотой 48 кГц — 150. Декодер зеркально повторяет энкодер с транспонированными свёртками. Между ними остаточный векторный квантизатор (residual vector quantizer) превращает каждый кадр в KK кодов.

Функции потерь — те же, что в семействе VQGAN, адаптированные к звуку. Реконструкция измеряется расстоянием L1L_1 на форме волны и расстояниями L1L_1 и L2L_2 между 64-полосными мел-спектрограммами на семи разрешениях, с окнами от 252^5 до 2112^{11} отсчётов. Многомасштабный STFT-дискриминатор — пять свёрточных сетей одинаковой структуры, работающих на спектрограммах с окнами от 2048 до 128 отсчётов, — добавляет состязательную кусочно-линейную функцию потерь (hinge loss) и функцию потерь сопоставления признаков. Квантизатор добавляет слагаемое привязки (commitment loss). Балансировщик функций потерь (loss balancer) нормирует градиент каждой функции потерь по выходу на его скользящую норму, так что каждая функция потерь вносит в суммарный градиент долю, пропорциональную своему весу, каков бы ни был её естественный масштаб; веса равны 0.1 для временной области, 1 для частотной, 3 для состязательной функции потерь и 3 для сопоставления признаков.

Одна модель обслуживает несколько битрейтов: при обучении в каждом батче сохраняется случайно выбранное число словарей — 2, 4, 8, 16 или 32 при 24 кГц. Необязательный небольшой трансформер предсказывает коды для энтропийного кодирования и экономит ещё до 40%. В тестах прослушивания потоковых моделей (MUSHRA, баллы от 0 до 100) при 6 кбит/с EnCodec получил 83.1 на чистой речи и 92.9 на музыке против 30.1 и 20.6 у кодека Opus при том же битрейте. Внутри MusicGen используется 32-килогерцовый монофонический EnCodec с шагом 640, то есть 50 кадрами в секунду, и четырьмя словарями по 2048 векторов (Copet et al., 2023, §3.1).

Остаточное векторное квантование#

VQ-VAE заменяет каждый вектор энкодера ближайшим элементом одного словаря. Остаточное векторное квантование (residual vector quantization, RVQ) снова и снова квантует то, что при этом остаётся. Для кадра zz

r(0)=z,e(k)=arg⁡min⁡e∈Ck∥r(k−1)−e∥2,r(k)=r(k−1)−e(k),k=1,…,K,r^{(0)} = z, \qquad e^{(k)} = \arg\min_{e \in \mathcal C_k} \big\lVert r^{(k-1)} - e \big\rVert^2, \qquad r^{(k)} = r^{(k-1)} - e^{(k)}, \qquad k = 1, \dots, K,

а декодер получает сумму выбранных векторов,

z^=∑k=1Ke(k)=∑k=1K(r(k−1)−r(k))=z−r(K).\hat z = \sum_{k=1}^{K} e^{(k)} = \sum_{k=1}^{K} \big(r^{(k-1)} - r^{(k)}\big) = z - r^{(K)} .

Сумма телескопически сокращается, поэтому ошибка квантования в точности равна последнему остатку. Код кадра — список из KK индексов, и этапу kk нужно описать лишь то, что упустили этапы 1,…,k−11, \dots, k - 1: его словарь обучается на остатках, которые меньше самих кадров. При K=1K = 1 это VQ-VAE, и обучение то же: прямой проброс градиента (straight-through estimator) через argmin, слагаемое привязки на каждом этапе, ∑k∥r(k−1)−sg[e(k)]∥2\sum_k \lVert r^{(k-1)} - \mathrm{sg}[e^{(k)}] \rVert^2, и словари, обновляемые как скользящие средние назначенных им векторов, причём неиспользуемые элементы заменяются векторами из текущего батча.

Рисунок

Остаточное квантование: три словаря по четыре вектора

Остаточное квантование: три словаря по четыре вектораТри панели. В первой облако из 160 точек и четыре вектора словаря 1; стрелка от ближайшего к z вектора словаря к самому z — остаток. Во второй и третьей — облака остатков в увеличенном масштабе и словари 2 и 3. Внизу сумма выбранных векторов (2.39, 0.76) против z = (2.67, 0.93) и полосы ошибки 1.40, 0.39, 0.14, 0.05 после 0, 1, 2 и 3 словарей.±3.5этап 1: словарь 111234z = (2.67, 0.93) → код 2e⁽¹⁾ = (1.42, 1.25)‖r⁽¹⁾‖² = 1.66±2этап 2: словарь 221234r⁽¹⁾ = (1.25, −0.32) → код 1e⁽²⁾ = (0.56, −0.52)‖r⁽²⁾‖² = 0.51±1.5этап 3: словарь 331234r⁽²⁾ = (0.69, 0.21) → код 4e⁽³⁾ = (0.40, 0.03)‖r⁽³⁾‖² = 0.11ẑ = e⁽¹⁾ + e⁽²⁾ + e⁽³⁾ = (2.39, 0.76)z = (2.67, 0.93)3 кода × 2 бита = 6 бит4ошибка на координату по 160 точкам0 словарей1.401 словарь0.392 словаря0.143 словаря0.05Остаточное квантование: три словаря по четыре вектораТри панели. В первой облако из 160 точек и четыре вектора словаря 1; стрелка от ближайшего к z вектора словаря к самому z — остаток. Во второй и третьей — облака остатков в увеличенном масштабе и словари 2 и 3. Внизу сумма выбранных векторов (2.39, 0.76) против z = (2.67, 0.93) и полосы ошибки 1.40, 0.39, 0.14, 0.05 после 0, 1, 2 и 3 словарей.±3.5словарь 111234→ код 2e⁽¹⁾ = (1.42, 1.25)‖r⁽¹⁾‖² = 1.66±2словарь 221234→ код 1e⁽²⁾ = (0.56, −0.52)‖r⁽²⁾‖² = 0.51±1.5словарь 331234→ код 4e⁽³⁾ = (0.40, 0.03)‖r⁽³⁾‖² = 0.114ошибка01.4010.3920.1430.05ẑ = (2.39, 0.76)z = (2.67, 0.93)3 × 2 = 6 бит
Игрушечный пример с построением при сборке: 160 точек двумерного облака (зелёные), три словаря по M = 4 вектора (жёлтые квадраты), каждый подобран k-means к остаткам предыдущих этапов. Панели 2 и 3 показывают облака остатков (синие) в своём масштабе, ±2 и ±1.5 против ±3.5 у первой. Выделенный вектор z = (2.67, 0.93) получает коды (2, 1, 4), квадрат его остатка падает 8.01 → 1.66 → 0.51 → 0.11, а сумма выбранных векторов ẑ = (2.39, 0.76) (красный крест) приближается к z. Средняя квадратичная ошибка на координату по всем точкам: 1.396 → 0.394 → 0.137 → 0.051. Каждый словарь добавляет 2 бита к коду точки.

Разобранный пример. Рисунок прослеживает один вектор игрушечного облака через три словаря по четыре элемента, каждый из которых подобран k-means к остаткам предыдущих этапов (значения округлены до двух знаков). Вектор z=(2.67,0.93)z = (2.67, 0.93) с ∥z∥2=8.01\lVert z \rVert^2 = 8.01 ближе всего к элементу 2 первого словаря, e(1)=(1.42,1.25)e^{(1)} = (1.42, 1.25), что оставляет r(1)=(1.25,−0.32)r^{(1)} = (1.25, -0.32) с ∥r(1)∥2=1.66\lVert r^{(1)} \rVert^2 = 1.66. Второй словарь выбирает элемент 1, e(2)=(0.56,−0.52)e^{(2)} = (0.56, -0.52), и остаётся r(2)=(0.69,0.21)r^{(2)} = (0.69, 0.21) с квадратом нормы 0.51. Третий выбирает элемент 4, e(3)=(0.40,0.03)e^{(3)} = (0.40, 0.03), и остаётся r(3)=(0.28,0.18)r^{(3)} = (0.28, 0.18) с квадратом нормы 0.11. Код — (2,1,4)(2, 1, 4), шесть бит, и декодер восстанавливает z^=(2.39,0.76)=z−r(3)\hat z = (2.39, 0.76) = z - r^{(3)}. По всем 160 точкам среднеквадратичная ошибка на координату падает с 1.396 (дисперсия облака) до 0.394, 0.137 и 0.051: каждый этап убирает от 63 до 72% оставшегося.

Почему не один большой словарь? Это объясняет пример из SoundStream (Zeghidour et al., 2022, §III-C). При 6 кбит/с и 75 кадрах в секунду на каждый кадр приходится 6000/75=806000 / 75 = 80 бит. Одному словарю понадобилось бы 280≈1.2⋅10242^{80} \approx 1.2 \cdot 10^{24} элементов; восемь остаточных этапов по 210=10242^{10} = 1024 элемента тратят те же 80 бит, храня 8192 вектора и вычисляя 8192 расстояния на кадр. При том же числе бит один словарь не хуже: MKM^K возможных сумм RVQ образуют один конкретный словарь такого размера с жадным поиском, поэтому лучший словарь размера MKM^K по меньшей мере так же хорош. Игрушечное облако показывает разрыв. С 2000 обучающих и 2000 тестовых точек из одного распределения (дисперсия на тесте 1.525 на координату):

Бит на точкуRVQ: этапы × элементыОшибка на тестеОдин словарь: элементыОшибка на тесте
21 × 40.44740.447
42 × 40.165160.139
63 × 40.066640.044

RVQ расплачивается некоторой ошибкой на бит за словарь, который растёт линейно по числу бит, а не экспоненциально. Зато оно даёт ещё два свойства. Первые коды несут больше всего информации, поэтому потоки упорядочены от грубого к точному. А обучение со случайным числом этапов для каждого примера, которое в SoundStream называется дропаутом квантизатора (quantizer dropout), даёт одну модель для многих битрейтов, поскольку отбрасывание последних этапов убирает лишь уточнения.

Сколько бит#

Кодек с KK словарями по MM элементов при frf_r кадрах в секунду тратит

R=K⋅log⁡2M⋅fr бит в секунду.R = K \cdot \log_2 M \cdot f_r \ \text{бит в секунду}.
КодекЧастота дискретизацииШагКадров в секундуKKMMБит на кадрБитрейт
SoundStream, 6 кбит/с24 кГц3207581024806 кбит/с
EnCodec, 24 кГц24 кГц32075от 2 до 321024от 20 до 320от 1.5 до 24 кбит/с
EnCodec, 48 кГц, стерео48 кГц320150от 2 до 161024от 20 до 160от 3 до 24 кбит/с
EnCodec в MusicGen32 кГц6405042048442.2 кбит/с

Для кодека MusicGen R=4⋅11⋅50=2200R = 4 \cdot 11 \cdot 50 = 2200 бит в секунду против 32 000⋅16=512 00032\,000 \cdot 16 = 512\,000 для 16-битных отсчётов: в 233 раза меньше. Как последовательность одна секунда — это 200 кодов вместо 32 000 отсчётов. Трансформеру, который, как MusicGen, выдаёт за шаг один кадр из четырёх кодов, нужно 50 шагов на секунду — в 640 раз меньше, чем модели над отдельными отсчётами.

MusicGen: один трансформер над параллельными потоками#

MusicGen (Copet et al., 2023) генерирует четыре потока кодов этого кодека одним авторегрессионным декодером-трансформером с условием на текстовое описание и, по желанию, на мелодию, а затем декодирует коды с помощью EnCodec. Более ранние системы строили над такими потоками каскады из нескольких моделей: MusicLM (Agostinelli et al., 2023) моделирует семантические и акустические токены иерархией трансформеров, а VALL-E (Wang et al., 2023), модель речи, генерирует первый словарь авторегрессионно, а остальные — второй, неавторегрессионной моделью. Вопрос MusicGen — как уложить KK параллельных потоков так, чтобы их могла предсказывать одна модель.

Чередование словарей#

Точный ответ — развернуть (flatten) коды в одну последовательность, кадр за кадром и внутри кадра словарь за словарём: q1,1,q1,2,…,q1,K,q2,1,…q_{1,1}, q_{1,2}, \dots, q_{1,K}, q_{2,1}, \dots. Тогда формула умножения вероятностей (chain rule) точно факторизует совместное распределение, как для пикселей, но в последовательности K⋅TK \cdot T шагов, 6000 на 30 секунд, и выигрыш от низкой частоты кадров частично теряется.

Дешёвый ответ предсказывает несколько кодов за один шаг по одному и тому же прошлому. Предсказывать все KK кодов кадра tt вместе — значит моделировать

p(qt,1,…,qt,K∣q<t)≈∏k=1Kp(qt,k∣q<t),p(q_{t,1}, \dots, q_{t,K} \mid q_{<t}) \approx \prod_{k=1}^{K} p(q_{t,k} \mid q_{<t}) ,

что точно, только если коды кадра независимы при условии прошлого. В RVQ это не так: этап kk кодирует в точности то, что упустили этапы до него. Статья описывает все такие варианты как схему (pattern): последовательность множеств P1,…,PSP_1, \dots, P_S, разбивающих клетки (t,k)(t, k), причём каждый словарь входит в каждое множество не более одного раза. На шаге nn модель параллельно предсказывает все клетки PnP_n по клеткам P1,…,Pn−1P_1, \dots, P_{n-1}. Четыре схемы:

  • Развёртка (flattening), по одной клетке на шаг: S=KTS = K T.
  • Параллельная схема (parallel), Pn={(n,k):k=1,…,K}P_n = \{(n, k) : k = 1, \dots, K\}: S=TS = T, и коды кадра выбираются независимо друг от друга.
  • Сначала грубая (coarse first): весь словарь 1, затем словари со 2 по KK параллельно, кадр за кадром: S=2TS = 2T. Это схема VALL-E в одной модели.
  • Задержка (delay), Pn={(n−k+1,k):k=1,…,K, n≥k}P_n = \{(n - k + 1, k) : k = 1, \dots, K,\ n \ge k\} (Copet et al., 2023, формула 6): словарь kk сдвинут на k−1k - 1 шагов, поэтому S=T+K−1S = T + K - 1.
Рисунок

Четыре способа уложить четыре потока кодов в шаги генерации

Схемы укладки кодовЧетыре сетки 4 на 4: кадры по горизонтали, словари по вертикали, в клетках номера шагов. Развёртка: 1…16 по кадрам. Параллельная: номер шага равен номеру кадра. Сначала грубая: словарь 1 на шагах 1…4, остальные на шагах 5…8. Задержка: номер шага равен t + k − 1, от 1 до 7.развёртка12345678910111213141516k1k2k3k4t1t2t3t416 шагов · K·T30 с: 6000 шаговпараллельная1111222233334444k1k2k3k4t1t2t3t44 шага · T30 с: 1500 шаговсначала грубая1555266637774888k1k2k3k4t1t2t3t48 шагов · 2T30 с: 3000 шаговзадержка1234234534564567k1k2k3k4t1t2t3t47 шагов · T + K − 130 с: 1503 шагачисло в клетке — шаг генерации, на котором предсказывается этот код;красная рамка — код 3 кадра 3, пунктир — коды того же кадра из словарей 1 и 2Схемы укладки кодовЧетыре сетки 4 на 4: кадры по горизонтали, словари по вертикали, в клетках номера шагов. Развёртка: 1…16 по кадрам. Параллельная: номер шага равен номеру кадра. Сначала грубая: словарь 1 на шагах 1…4, остальные на шагах 5…8. Задержка: номер шага равен t + k − 1, от 1 до 7.развёртка12345678910111213141516k1k2k3k4t1t2t3t416 шагов · K·T30 с: 6000 шаговпараллельная1111222233334444k1k2k3k4t1t2t3t44 шага · T30 с: 1500 шаговсначала грубая1555266637774888k1k2k3k4t1t2t3t48 шагов · 2T30 с: 3000 шаговзадержка1234234534564567k1k2k3k4t1t2t3t47 шагов · T + K − 130 с: 1503 шагачисло — шаг генерации кода;красная рамка: код 3 кадра 3;пунктир: кадр 3, словари 1 и 2
Столбцы — кадры кодека t = 1…4 (50 кадров в секунду), строки — словари k = 1…4 (словарь 1 снизу, он самый грубый). В клетке — номер шага, на котором предсказывается код; клетки с одинаковым номером предсказываются вместе, без взаимного учёта. Развёртка точна, но длиннее всех: K·T шагов. Параллельная схема короче всех, T шагов, но четыре кода кадра выбираются независимо. Схема «сначала грубая» генерирует весь словарь 1, затем остальные параллельно, 2T шагов. Задержка сдвигает словарь k на k − 1 шагов: T + K − 1 шагов, и код словаря 3 в кадре 3 (красная рамка, шаг 5) видит коды словарей 1 и 2 того же кадра (пунктир, шаги 3 и 4); в параллельной схеме те же коды выбираются на том же шаге. Строка под сеткой — число шагов для 4 кадров и для 30 секунд (1500 кадров).

В схеме с задержкой код (t,k)(t, k) предсказывается на шаге t+k−1t + k - 1, после кодов словарей 1,…,k−11, \dots, k - 1 того же кадра, которые приходятся на шаги t,…,t+k−2t, \dots, t + k - 2. Поэтому он видит более грубые коды своего кадра — ту зависимость, которую создаёт RVQ, — почти по цене параллельной схемы. Не видит он более точных кодов последних кадров: код словаря 1 кадра tt предсказывается на том же шаге, что и код словаря 2 кадра t−1t - 1, словаря 3 кадра t−2t - 2 и словаря 4 кадра t−3t - 3. Абляция в статье (таблица 4, модель с 300 миллионами параметров, 30-секундные фрагменты) измеряет этот компромисс расстоянием Фреше для звука (Fréchet audio distance, FAD) — аналогом FID для звука, который вычисляется на эмбеддингах аудиоклассификатора VGGish (Kilgour et al., 2018). Развёртка даёт 0.86 при 6000 шагах, задержка — 0.96 при 1500, «сначала грубая» — 1.98 при 3000, параллельная схема — 2.58 при 1500. Слушатели оценили развёртку и задержку одинаково, в 79.7, а параллельную схему ниже, в 72.2. Схема с задержкой даёт почти то же качество, что и точная факторизация, за четверть её шагов, и MusicGen использует именно её.

Трансформер и его целевая функция#

На шаге nn вход — сумма KK эмбеддингов размерности dmodeld_{\text{model}}, равной ширине трансформера, по одному из собственной таблицы каждого словаря из MM элементов; словарь, отсутствующий в PnP_n, вносит специальный пустой токен. Добавляется синусоидальное кодирование номера nn. Каждый из LL слоёв содержит каузальный self-attention по предыдущим шагам, перекрёстное внимание (cross-attention) к условию и полносвязный блок из ширины dmodeld_{\text{model}} в 4dmodel4 d_{\text{model}} и обратно, с нормализацией слоя перед каждым блоком. Выход подаётся на KK линейных выходных слоёв (heads), по одному на словарь; каждый выдаёт MM логитов для клетки своего словаря в Pn+1P_{n+1}. Обучение минимизирует кросс-энтропию каждого кода при условии предыдущих шагов,

L(θ)=−∑n=1S∑(t,k)∈Pnlog⁡pθ(qt,k∣qP1,…,qPn−1, C),\mathcal L(\theta) = -\sum_{n=1}^{S} \sum_{(t,k) \in P_n} \log p_\theta\big(q_{t,k} \mid q_{P_1}, \dots, q_{P_{n-1}},\ C\big) ,

где CC — условие. Модели имеют 300 миллионов параметров (dmodel=1024d_{\text{model}} = 1024, 16 голов, 24 слоя), 1.5 миллиарда (1536, 24, 48) и 3.3 миллиарда (2048, 32, 48). Их обучали на 30-секундных фрагментах 20 000 часов лицензированной музыки (10 000 высококачественных треков и 390 000 инструментальных треков из стоковых коллекций), сведённых в моно при 32 кГц, в течение миллиона шагов с AdamW и батчами по 192.

Условие на текст#

Описание вроде «90s rock song with a guitar riff» кодируется предобученным энкодером T5 (Raffel et al., 2020), который в опубликованных моделях заморожен, и линейно проецируется на ширину декодера: получается последовательность векторов C∈RTC×dmodelC \in \mathbb R^{T_C \times d_{\text{model}}}, по одному на токен описания. Каждый слой декодера читает её через перекрёстное внимание: запросы — из звуковых шагов, ключи и значения — из текста, как в U-Net латентной диффузии. Статья пробовала также FLAN-T5 и CLAP — совместный текстово-звуковой эмбеддинг. T5 и FLAN-T5 показали себя одинаково (FAD 3.12 и 3.36 на MusicCaps), CLAP — хуже (4.16). Обучающие описания аугментируются: с вероятностью 0.25 к описанию добавляются метаданные, например жанр, тональность и темп, затем с вероятностью 0.5 отбрасывается само описание, а отдельные слова отбрасываются с вероятностью 0.3.

Classifier-free guidance на логитах#

Как и в латентной диффузии, при обучении условие отбрасывается, здесь с вероятностью 0.2, так что одна сеть учит и pθ(q∣C)p_\theta(q \mid C), и pθ(q∣∅)p_\theta(q \mid \varnothing); в опубликованных реализациях пустое условие — нулевое текстовое представление. При сэмплировании для каждого кода два набора логитов экстраполируются с масштабом guidance ss:

ℓ~=ℓ∅+s (ℓC−ℓ∅).\tilde\ell = \ell_\varnothing + s\,(\ell_C - \ell_\varnothing) .

Логиты — это логарифмы вероятностей с точностью до своей константы для каждого распределения: ℓC(q)=log⁡pθ(q∣C)+a\ell_C(q) = \log p_\theta(q \mid C) + a и ℓ∅(q)=log⁡pθ(q∣∅)+b\ell_\varnothing(q) = \log p_\theta(q \mid \varnothing) + b. Отсюда ℓ~(q)=(1−s)log⁡pθ(q∣∅)+slog⁡pθ(q∣C)+const\tilde\ell(q) = (1 - s) \log p_\theta(q \mid \varnothing) + s \log p_\theta(q \mid C) + \text{const}, и softmax убирает константу:

p~(q)∝pθ(q∣∅)1−s pθ(q∣C)s.\tilde p(q) \propto p_\theta(q \mid \varnothing)^{1-s}\, p_\theta(q \mid C)^{s} .

Это тот же наклон (tilt), который направленный score имеет на каждом уровне шума в диффузии, и здесь он точен для одного шага: при данных предыдущих кодах каждый код вытягивается из наклонённого условного распределения. Для всей последовательности сэмплируемое распределение — произведение этих наклонов, каждый из которых нормирован отдельно, и в общем случае это не наклон всей последовательности с одной нормировкой — так же, как диффузия с guidance в общем случае не сэмплирует наклонённое конечное распределение. Записав по формуле Байеса pθ(q∣C)∝p(C∣q) pθ(q∣∅)p_\theta(q \mid C) \propto p(C \mid q)\, p_\theta(q \mid \varnothing), получаем p~(q)∝pθ(q∣∅) p(C∣q)s\tilde p(q) \propto p_\theta(q \mid \varnothing)\, p(C \mid q)^{s}: безусловное распределение, перевзвешенное неявным классификатором в степени ss. MusicGen сэмплирует с s=3s = 3.

Разобранный пример. Возьмём три кода с p(⋅∣∅)=(0.5,0.3,0.2)p(\cdot \mid \varnothing) = (0.5, 0.3, 0.2) и p(⋅∣C)=(0.2,0.3,0.5)p(\cdot \mid C) = (0.2, 0.3, 0.5). При s=3s = 3 ненормированные веса равны 0.5−2⋅0.23=0.0320.5^{-2} \cdot 0.2^{3} = 0.032, 0.3−2⋅0.33=0.30.3^{-2} \cdot 0.3^{3} = 0.3 и 0.2−2⋅0.53=3.1250.2^{-2} \cdot 0.5^{3} = 3.125, что после нормировки даёт (0.009,0.087,0.904)(0.009, 0.087, 0.904). Код, который условие предпочитает сильнее, чем безусловное распределение, забирает почти всю массу, а энтропия падает с 1.49 до 0.50 бита: guidance заставляет сэмплы точнее следовать тексту и меньше различаться между собой. Каждый шаг стоит двух прямых проходов, которые выполняются одним батчем.

Условие на мелодию#

Текст описывает стиль, но не мотив. MusicGen может также следовать мелодии эталонной записи через её хромаграмму (chromagram) — энергию в каждом из 12 звуковысотных классов (pitch classes: C, C♯, …, B, все октавы вместе) во времени. Эталон сначала разделяется на источники с помощью Demucs (Défossez et al., 2019), и его ударные и бас отбрасываются, потому что они доминируют в хромаграмме. Хромаграмма вычисляется с окнами в 2142^{14} отсчётов и шагом 2122^{12} (0.128 с, около 7.8 кадра в секунду), и в каждом кадре сохраняется только самый сильный звуковысотный класс. Это информационное узкое место важно: с полной хромаграммой модель научилась восстанавливать эталон вместо того, чтобы сочинять. Квантованная хромаграмма подаётся как префикс ко входу декодера, а не через перекрёстное внимание; в опубликованной мелодической модели в тот же префикс помещено и текстовое представление. Размеченные данные о мелодии не нужны. Для модели с 1.5 миллиарда параметров косинусное сходство хромаграмм эталона и выхода выросло с 0.10 без условия на мелодию до 0.66 с ним, а оценки слушателей за соответствие мелодии — с 64.4 до 72.9 (таблица 2).

Продолжение записи#

Кодек работает и в обратном направлении. Первые секунды записи кодируются в коды, укладываются по схеме с задержкой и подаются как начало последовательности; модель продолжает её, с текстовым описанием или без него, и EnCodec декодирует начало и продолжение вместе. Это достраивание изображений из ImageGPT, только со звуком. Ограничения — те же, что у постановки обучения: позиции обучались на 30-секундных фрагментах, 1500 кадрах, и звуковой промпт входит в это число.

Сэмплирование и результаты#

Коды сэмплируются с фильтрацией top-kk, k=250k = 250 из 2048 кодов, при температуре 1, после guidance. На бенчмарке MusicCaps модель с 3.3 миллиарда параметров получила лучшее общее качество в тесте прослушивания, 84.8 из 100 против 80.5 у MusicLM, а модель с 1.5 миллиарда — лучшее соответствие тексту, 83.7 (таблица 1). По FAD модель с 300 миллионами параметров, 3.1, превзошла MusicLM, 4.0, но не диффузионную модель Noise2Music, 2.1. Масштаб помогает тексту больше, чем звуку: на тестовом наборе авторов общее качество было максимальным при 1.5 миллиарда параметров (81.9 против 78.3 и 79.2), а соответствие тексту улучшалось монотонно (82.5, 82.9, 83.5; таблица 5).

Что изменилось#

Трансформеры для изображений (предыдущая заметка)Glow-TTSMusicGen
Генерируемый сигнализображениемел-спектрограмма речиформа волны музыки при 32 кГц
Представлениесетка кодов из одного словарянепрерывные кадры, 80×8680 \times 86 в секунду4 параллельных потока RVQ, 50 кадров в секунду
Генераторкаузальный трансформер, один токен за шагнормализующий поток, все кадры за один проходкаузальный трансформер, один шаг по кадрам за проход
Правдоподобиеточное по токенамточное по мел-кадрам при лучшем выравниванииточное, коды одного шага моделируются как независимые
Условиетекстовые токены в последовательности или энкодераприорные средние из текстового энкодера, длительности из предсказателязамороженный T5 через перекрёстное внимание; префикс хромаграммы; звуковой префикс
Выравнивание с текстомне нужнопоиск монотонного выравниваниянет: решает внимание
Управлениеtop-kk, top-pp, guidance, переранжированиетемпература априорного распределения, масштаб длительностейtop-kk с k=250k = 250, guidance с s=3s = 3
От кодов к сигналудекодер VQGANотдельный вокодердекодер EnCodec

Ограничения#

  • Вокодер — узкое место. Записи, пропущенные через мел-спектрограммы и обратно, получили 4.19 против 4.54 у оригиналов; на практике двухэтапную систему ограничивает её второй этап, и оценка реконструкции — обычный ориентир, а не доказанный максимум (как сравнивают такие оценки).
  • Один ритм на предложение. Glow-TTS предсказывает длительности детерминированно, поэтому предложение всегда произносится с одними и теми же длительностями; с шумом меняется только интонация. Именно поэтому в VITS добавлен стохастический предсказатель длительностей. Кроме того, обучение по Витерби учится только на лучшем выравнивании.
  • Кодек — узкое место. Как FID реконструкций VQGAN служит практическим ориентиром для его трансформера изображений, так качество реконструкции EnCodec при 2.2 кбит/с на практике ограничивает MusicGen.
  • Факторизация приближённая. Коды, предсказываемые на одном шаге, считаются независимыми при условии прошлого; схема с задержкой сокращает разрыв с точной развёрткой (FAD 0.96 против 0.86), но не устраняет его.
  • Длина. Обучение на 30-секундных фрагментах ограничивает генерацию 30 секундами; более длинные произведения строятся многократным продолжением, без модели их общей формы.
  • Последовательное сэмплирование. MusicGen нужно 50 проходов декодера на секунду звука, и каждый — по удвоенному батчу с guidance.
  • Управление и данные. Текст даёт грубое управление, в основном через масштаб guidance. Обучающая музыка в основном западная, а самый крупный жанр — Dance/EDM. Клонирование голоса по короткой записи упрощает выдачу себя за другого человека, а речевые корпуса с немногими дикторами приводят к тому, что их голоса легко начинают использоваться слишком широко.

Итоги#

  • Звук длинный: от 22 050 до 48 000 отсчётов в секунду. Системы синтеза речи сокращают его мел-спектрограммой, около 6900 чисел на секунду речи, а вокодер восстанавливает фазу; системы генерации музыки обучают дискретный код самой формы волны.
  • Конвейер TTS — это нормализация текста, преобразование графем в фонемы, акустическая модель и вокодер. Его главная трудность — выравнивание между десятками фонем и сотнями кадров.
  • Glow-TTS — нормализующий поток из мел-кадров в гауссовское априорное распределение, средние которого даёт текстовый энкодер. Поиск монотонного выравнивания находит наиболее вероятное монотонное выравнивание динамическим программированием за O(TtextTmel)O(T_{\text{text}} T_{\text{mel}}); при инференсе его заменяет предсказатель длительностей, а поток генерирует все кадры за один проход.
  • Нейросетевые кодеки, такие как EnCodec, — это VQ-VAE, обучаемые с функциями потерь GAN на формах волны. Остаточное векторное квантование кодирует каждый кадр KK словарями, каждый из которых квантует остаток предыдущих; ошибка равна последнему остатку, а битрейт — Klog⁡2MfrK \log_2 M f_r, 2.2 кбит/с для кодека MusicGen.
  • MusicGen предсказывает четыре потока кодов одним трансформером. Схема с задержкой сдвигает словарь kk на k−1k - 1 шагов, так что каждый код видит более грубые коды своего кадра, а шагов нужно T+K−1T + K - 1 вместо KTK T.
  • Текст входит через замороженный энкодер T5 и перекрёстное внимание, мелодия — через префикс из argmax-хромаграммы, запись — через свои коды в качестве префикса. Classifier-free guidance на логитах сэмплирует каждый код из p(⋅∣∅)1−sp(⋅∣C)sp(\cdot \mid \varnothing)^{1-s} p(\cdot \mid C)^s при данных предыдущих кодах, с s=3s = 3 и top-kk 250.

Ноутбук#

Ноутбук о генерации звука из репозитория HSE-LAMBDA Deep Generative Models запускает синтез речи с библиотекой Coqui TTS и генерацию музыки с MusicGen в Hugging Face Transformers (ячейки нумеруются с 1, считая все ячейки подряд, включая текстовые).

  • Ячейки 1–2: конвейер TTS. Оглавление и четыре этапа: предобработка текста с нормализацией и G2P, лингвистический и фонетический анализ, акустическая модель (Tacotron, FastSpeech или VITS) и вокодер (WaveGlow, HiFi-GAN или LPCNet).
  • Ячейки 3–5: подготовка. Устанавливаются transformers, datasets[audio] и пакет TTS от Coqui, а также фонемизатор eSpeak, который Coqui использует для G2P в английском.
  • Ячейки 6–9: инференс предобученных моделей. tts --list_models печатает реестр моделей Coqui. Ячейка 8 синтезирует «hello world» моделью tts_models/en/ljspeech/glow-tts — Glow-TTS, обученной на LJ Speech, которой реестр по умолчанию сопоставляет вокодер multi-band MelGAN; ячейка 9 воспроизводит результат.
  • Ячейки 10–14: идентификаторы дикторов. У модели с одним диктором один голос; модель с несколькими дикторами принимает диктора как условие. --list_speaker_idxs выводит дикторов tts_models/en/vctk/vits — сквозной модели VITS, обученной на VCTK, а ячейка 13 синтезирует предложение голосом диктора p341.
  • Ячейки 15–18: клонирование голоса. Ячейка 16 скачивает энкодер диктора, его конфигурацию и один фрагмент LJ Speech. Ячейка 17 запускает YourTTS (tts_models/multilingual/multi-dataset/your_tts) с --speaker_wav, указывающим на этот фрагмент, и --language_idx en: энкодер диктора превращает фрагмент в эмбеддинг, который служит условием синтеза.
  • Ячейки 19–22: данные. LJ Speech скачивается и распаковывается в tts_train_dir, а BaseDatasetConfig применяет к metadata.csv форматтер ljspeech; форматтер читает столбец с нормализованным текстом.
  • Ячейки 23–25: конфигурация обучения. GlowTTSConfig с размером батча 32 (16 для оценки), 4 процессами загрузки данных, включённой оценкой, синтезом тестовых предложений с первой эпохи (test_delay_epochs=-1), 100 эпохами, очисткой текста phoneme_cleaners (раскрытие чисел и сокращений), фонемами для en-us с кэшем фонем, строкой лога каждые 25 шагов, смешанной точностью и контрольной точкой каждые 1000 шагов. Сама модель сохраняет значения библиотеки по умолчанию: 12 блоков потока ширины 192, шестислойный энкодер Transformer с относительными позициями и двумя головами, априорное распределение с σ=1\sigma = 1, как в статье (mean_only=True), 10 шагов инициализации ActNorm по данным и RAdam с шагом обучения 10−310^{-3} и прогревом Noam на 4000 шагов.
  • Ячейки 26–28: аудиопроцессор. AudioProcessor.init_from_config с настройками звука по умолчанию: 22 050 Гц, окно и FFT в 1024 отсчёта, шаг 256, 80 мел-полос от 0 Гц до частоты Найквиста, логарифмические амплитуды, нормированные в [−4,4][-4, 4], и Griffin–Lim с 60 итерациями для обращения. Это те же настройки, что в разобранных числах раздела «Звук как сигнал». Ячейка 27 фиксирует numpy==1.21.0 (см. проблемы ниже).
  • Ячейки 29–30: токенизатор. TTSTokenizer.init_from_config строит словарь фонем МФА и фонемизатор eSpeak и возвращает обновлённую конфигурацию.
  • Ячейки 31–32: разбиение. load_tts_samples откладывает для оценки 1% по умолчанию — 131 из 13 100 фрагментов. Примеры — это словари Python с ключами text, audio_file, speaker_name и root_path; текстовая ячейка 31 всё ещё описывает их как списки.
  • Ячейки 33–34: модель. GlowTTS(config, ap, tokenizer, speaker_manager=None) — модель с одним диктором.
  • Ячейки 35–38: проверка на одном батче. Текстовая ячейка предлагает переобучить модель на одном батче, train_samples[:batch_size], с помощью «TrainingArgs». Ячейка 36 создаёт TrainerArgs(shuffle=False, steps_per_epoch=1, epochs=100, output_path="output/", lr=1e-4, save_step=100, save_optimizer_state=True) и Trainer на train_samples[:1] и eval_samples[:1]; ячейка 37 вызывает trainer.fit(), а ячейка 38 открывает TensorBoard на tts_train_dir.
  • Ячейки 39–44: тестирование. Текстовая ячейка говорит, что переобученная модель запоминает своё единственное предложение. Ячейка 41 собирает пути к контрольным точкам и конфигурациям с помощью glob, но не использует их. Ячейка 43 синтезирует «This is the test script for the GlowTTS model» из жёстко заданной контрольной точки /content/tts_train_dir/run-February-28-2025_01+53PM-0000000/best_model_1624.pth, а ячейка 42 предлагает контрольную точку после 20 эпох по пустой ссылке. Без --vocoder_path команда tts обращает мел-спектрограмму методом Гриффина–Лима, поэтому качество этого теста ограничено восстановлением фазы, как бы хорошо ни была обучена модель. Температура сэмплирования — параметр конфигурации inference_noise_scale, который GlowTTSConfig объявляет дважды, со значениями 0.33 и затем 0.0; действует второе объявление, так что обученная модель синтезирует из априорных средних, τ=0\tau = 0.
  • Ячейки 45–46: MusicGen в теории. Три части (текстовый энкодер, авторегрессионный декодер, EnCodec), энкодер, квантизатор и декодер EnCodec, подсчёт 4 словаря × 50 кадров = 200 токенов в секунду против 32 000 отсчётов, рекурсия RVQ и сумма z^=∑ke(k)\hat z = \sum_k e^{(k)}, трансформер с эмбеддингами кодов, позициями, self- и cross-attention, кросс-энтропийная целевая функция, схемы чередования и список проектных решений.
  • Ячейки 47–52: загрузка. facebook/musicgen-small, модель с 300 миллионами параметров (комментарий перечисляет medium 1.5B, melody 1.5B и large 3.3B), переносится на GPU, если он есть.
  • Ячейки 53–54: конфигурация генерации. model.generation_config содержит do_sample=True, guidance_scale=3.0, max_length=1500 (30 секунд), а также начальный токен и токен паддинга 2048 — следующий номер после последнего кода.
  • Ячейки 55–61: безусловная генерация. get_unconditional_inputs(num_samples=1) даёт нулевое текстовое представление и guidance 1; generate(..., do_sample=True, max_new_tokens=256); звук воспроизводится с частотой кодека 32 000 Гц и сохраняется с помощью scipy.io.wavfile.write; ячейка 61 вычисляет длительность как 256 / frame_rate = 5.12 с.
  • Ячейки 62–66: генерация по тексту. Процессор токенизирует с паддингом два промпта, романтическую балладу с акустической гитарой и синтвейв-трек в стиле 80-х, и generate(..., do_sample=True, guidance_scale=3, max_new_tokens=256) генерирует оба; ячейка 66 объясняет масштаб guidance: значения больше 1 включают classifier-free guidance, бо́льшие значения точнее следуют тексту ценой некоторой потери качества, а 3 — рекомендуемое значение по умолчанию.
  • Ячейки 67–68: генерация по звуковому промпту. Первый фрагмент потоково загружаемой копии GTZAN (999 фрагментов с частотой 32 кГц — той, которую требует процессор) обрезается до первой половины, около 15 секунд, и кодируется вместе с текстом «add heavy drums»; generate продолжает его с guidance 3 на 256 шагов. Возвращённый звук содержит промпт, за которым следует продолжение.
  • Ячейка 69: заключение.

Сохранённые выходы. Их нет: ни одна ячейка ноутбука не запускалась, поэтому он документирует процедуры, и цитировать нечего — ни звуковых сэмплов, ни значений функций потерь, ни времени выполнения.

Проблемы ноутбука.

  • TrainerArgs не принимает эти аргументы. В пакете trainer от Coqui TrainerArgs — это dataclass с полями вроде restore_path, overfit_batch и small_run; полей shuffle, steps_per_epoch, epochs, output_path, lr, save_step и save_optimizer_state у него нет, поэтому ячейка 36 останавливается с TypeError. epochs, lr, save_step и output_path — поля конфигурации модели (GlowTTSConfig их наследует), а остальных трёх нет нигде. Рабочая версия задаёт их в конфигурации и вызывает TrainerArgs() или TrainerArgs(overfit_batch=True), что обучает на одном батче, как и задумано в текстовой ячейке.
  • Один пример, а не один батч. train_samples[:1] обучает на одном фрагменте; train_samples[:batch_size] из текстовой ячейки дал бы батч из 32.
  • NumPy 1.21.0. Ячейка 27 фиксирует версию, для которой есть сборки (wheels) только под Python 3.7–3.9, а сам TTS 0.22.0 от Coqui требует numpy==1.22.0 на Python 3.10 и numpy>=1.24.3 на более новых версиях, так что фиксация либо не собирается, либо конфликтует с пакетом. Исходный пакет TTS поддерживает только Python 3.9–3.11 и больше не выпускается; на более новом Python поддерживаемый форк coqui-tts устанавливает тот же модуль TTS и команду tts.
  • Энкодер для клонирования голоса. YourTTS поставляется с собственным энкодером диктора и использует его, когда задан только --speaker_wav; --encoder_path в ячейке 17 заменяет его энкодером, отдельно скачанным в ячейке 16. (--encoder_config работает как сокращение --encoder_config_path.)
  • VITS — не акустическая модель. Ячейка 2 относит VITS к моделям, предсказывающим мел-спектрограмму; VITS сразу выдаёт форму волны.
  • Две из четырёх схем описаны неверно. Ячейка 46 называет развёрткой «все токены из словаря 1, затем все токены из словаря 2»; развёртка в статье чередует словари внутри каждого кадра, как описано выше. «Схема VALL-E» из первой версии статьи (в окончательной версии она переименована в coarse first) генерирует словарь 1 для всех кадров, а затем остальные параллельно, за 2T2T шагов; это не вариант параллельной схемы со сдвигами.
  • Другие неточности в ячейке 46. Опубликованные модели MusicGen кодируют текст с помощью T5; BART не используется; кодек — 32-килогерцовый EnCodec (48 кГц — стереомодель из статьи об EnCodec); энкодер EnCodec свёрточный с LSTM, а трансформер есть только в его необязательном энтропийном кодере. RVQ не точнее одного словаря при том же битрейте; его преимущество — словарь, который можно хранить и в котором можно искать, как показано выше.
  • Top-kk отличается от статьи. Конфигурация генерации не задаёт top_k, поэтому Transformers использует своё значение по умолчанию, 50 кодов, тогда как статья и исходная реализация сэмплируют из 250 наиболее вероятных. Передача top_k=250 в generate воспроизводит настройку статьи.
  • Длительность немного меньше. С начальным токеном и схемой с задержкой 256 шагов содержат 256+1−4=253256 + 1 - 4 = 253 полных кадра, 5.06 с, а не 5.12 с, как в ячейке 61.
  • «add heavy drums» — это описание. MusicGen обучался на описаниях звучащей музыки, а не на инструкциях по редактированию, поэтому промпт запрашивает музыку с тяжёлыми ударными, а не правку фрагмента.

Курс в одном абзаце#

Шесть семейств моделей из курса по-разному отвечают на один и тот же вопрос: как обучить генератор, если p(x)p(x) неизвестно. VAE оценивают правдоподобие снизу с помощью энкодера. GAN обходятся без правдоподобия и обучаются в противостоянии с дискриминатором; те же состязательные функции потерь переводят изображения из одного домена в другой. Нормализующие потоки вычисляют правдоподобие точно с помощью обратимых слоёв. Модели, основанные на энергии, позволяют любой сети задать плотность с точностью до нормирующей константы и расплачиваются за это марковскими цепями при обучении и сэмплировании. Диффузионные модели снова оценивают правдоподобие снизу, с фиксированным энкодером — цепочкой зашумления, — так что оценка сводится к регрессии на шум, или, что то же самое, на score. Авторегрессионные модели вычисляют его точно как произведение условных распределений и платят за это при сэмплировании. Самые большие модели сочетают семейства: дискретный или непрерывный автоэнкодер сжимает изображение или звук, а диффузионная модель или авторегрессионный трансформер генерирует в его латентном пространстве. Все они оцениваются одними и теми же метриками — от Inception Score до точности и полноты и оценки людьми, — и все опираются на KL-дивергенцию и родственные ей величины.

Литература#