MFCC: классические признаки речи
Финальный классический признак речи, десятилетиями бывший стандартом ASR.
MFCC (Mel-Frequency Cepstral Coefficients) — компактный набор коэффициентов, описывающих огибающую мел-спектра; долгое время это был главный признак для распознавания речи.
Мел-спектрограмма уже неплоха, но у неё есть проблема: соседние мел-каналы сильно скоррелированы (энергия «течёт» между ними), и данных всё ещё много. MFCC решают это, выжимая из мел-спектра самое существенное — форму огибающей — в 13–20 чисел на кадр.
Путь к MFCC
MFCC — это финал длинной цепочки, в которой собрано всё, что мы прошли. Каждый шаг убирает лишнее и оставляет полезное.
сигнал --> окна (STFT) --> спектр мощности --> мел-фильтры (мел-спектр) --> логарифм (лог-мел) --> DCT (косинусное преобразование) --> MFCC: 13-20 коэффициентов на кадр
Зачем DCT в конце
Последний шаг — DCT (дискретное косинусное преобразование). Оно делает две вещи: убирает корреляцию между каналами (коэффициенты становятся почти независимыми) и концентрирует информацию в первых нескольких коэффициентах. Поэтому хватает первых 13: они описывают общую форму спектра (форманты), а высшие — мелкие детали, которые часто отбрасывают. Это та же идея, что в сжатии JPEG.
MFCC и мел-спектрограмма: что выбрать
| Мел-спектрограмма | MFCC | |
| Размер | 40–80 на кадр | 13–20 на кадр |
| Корреляция | высокая | низкая |
| Для нейросетей | лучше (есть детали) | избыточно сжато |
| Для классики (HMM/GMM) | хуже | стандарт |
Важный нюанс: в эпоху глубокого обучения часто возвращаются к мел-спектрограмме, потому что нейросеть сама найдёт нужные комбинации, и лишнее сжатие DCT ей мешает. MFCC же остаются королём для лёгких классических моделей и задач вроде определения говорящего.
Имитация DCT-сжатия
Покажем суть DCT на пальцах: возьмём лог-мел-«вектор» и посчитаем несколько косинусных коэффициентов. Первый отражает общий уровень, следующие — форму.
import math
log_mel = [2.0, 2.1, 1.8, 1.2, 0.9, 0.7] # лог-энергии мел-каналов
N = len(log_mel)
def dct_coef(k):
s = sum(log_mel[n] * math.cos(math.pi * k * (n + 0.5) / N) for n in range(N))
return round(s, 3)
mfcc = [dct_coef(k) for k in range(4)]
print("Первые 4 MFCC:", mfcc)Вывод:
Первые 4 MFCC: [8.7, 2.26, -0.26, -0.354]
Первый коэффициент большой (общая энергия), остальные малы — информация сконцентрировалась в начале. Именно поэтому хватает 13 коэффициентов вместо всех мел-каналов.
Чтобы понять, зачем вообще нужен финальный шаг DCT, полезно увидеть проблему мел-спектрограммы наглядно. Соседние мел-каналы почти никогда не бывают независимыми: если в речи усилилась некая полоса частот, подсветятся сразу несколько соседних фильтров — их треугольники перекрываются и ловят одну и ту же энергию. Для классических моделей вроде GMM это была беда: они предполагали, что признаки не коррелируют между собой, и «спотыкались» на дублирующей информации. DCT решает это одним движением — переупаковывает скоррелированные каналы в набор почти независимых коэффициентов, на которых старым моделям дышалось куда легче.
Связь MFCC с JPEG — не просто красивое сравнение, а буквально одна и та же математика. И там, и там сигнал раскладывают косинусным преобразованием и обнаруживают, что почти вся энергия скапливается в первых, низкочастотных коэффициентах, а хвост описывает мелкие детали, которыми можно пожертвовать. JPEG отбрасывает хвост, чтобы сжать картинку; MFCC отбрасывают высшие коэффициенты, чтобы оставить только общую форму спектра — огибающую, несущую форманты. Поэтому 13 чисел на кадр — это не магическая константа, а тот же принцип «80% смысла в 20% коэффициентов», что лежит в основе половины алгоритмов сжатия.
Полезно понимать, почему вокруг MFCC и мел-спектрограммы регулярно ломают копья — ответ зависит от того, кто потребляет признак. Жёсткое DCT-сжатие — это решение, принятое за модель человеком: «вот тебе готовая огибающая, остальное лишнее». Для слабой классической модели это подарок. Но глубокая нейросеть сама прекрасно находит нужные комбинации мел-каналов и даже учитывает их корреляции как полезный сигнал, поэтому навязанное DCT лишь обедняет вход. Отсюда практическое правило эпохи Whisper: лёгким моделям и задачам вроде верификации диктора давайте MFCC, а большим сетям — сырую лог-мел-спектрограмму и не мешайте им учиться.
Как работает под капотом
К статичным MFCC обычно добавляют их производные — дельты (как быстро меняются) и дельта-дельты (ускорение). Это даёт модели представление о динамике речи между кадрами. В классических ASR вектор признаков выглядел как 13 MFCC + 13 дельт + 13 дельта-дельт = 39 чисел на кадр. Эти 39 чисел и были входом HMM/GMM, о которых — следующий раздел.
Частые ошибки
- Брать MFCC для глубоких сетей по инерции. Часто лог-мел-спектрограмма работает лучше — сеть сама извлечёт нужное.
- Оставлять все коэффициенты. Высшие MFCC шумны; обычно берут первые 13.
- Забывать дельты. Без производных теряется динамика речи между кадрами.
Итоги
- MFCC — сжатые коэффициенты огибающей мел-спектра (обычно 13 на кадр).
- DCT убирает корреляцию каналов и концентрирует информацию в начале.
- Для классики MFCC — стандарт; для глубоких сетей часто лучше мел-спектрограмма.
- К MFCC добавляют дельты и дельта-дельты, чтобы захватить динамику.