Классический ASR: HMM и GMM
Заглядываем в донейросетевую эпоху ASR, чтобы понять, что улучшили современные модели.
HMM (скрытая марковская модель) — статистическая модель последовательностей со скрытыми состояниями; в классическом ASR состояния соответствуют частям фонем, а переходы — течению речи во времени.
До 2012 года распознавание речи строилось на статистике, а не на глубоких сетях. Эта система работала десятилетиями (Dragon, голосовой набор телефонов) и заложила понятия, которые живут до сих пор: фонемы, акустическая и языковая модели. Понять её — значит оценить, что именно упростили нейросети.
Из чего состоял классический ASR
Система делилась на несколько компонентов, каждый со своей ролью. Их соединяли в конвейер.
| Компонент | Роль |
| Признаки (MFCC) | превращали звук в векторы |
| Акустическая модель (GMM-HMM) | звук → вероятности фонем |
| Произносительный словарь | фонемы → слова |
| Языковая модель (n-граммы) | какие слова вероятнее рядом |
Роль HMM
Речь разворачивается во времени, а длительность звуков переменна: «а-а-а» и короткое «а» — одна фонема. HMM элегантно это моделирует: каждая фонема — цепочка скрытых состояний, и модель может «задержаться» в состоянии сколько нужно. Алгоритм Витерби находит наиболее вероятную последовательность состояний (а значит, фонем) для данного звука.
Роль GMM
HMM нужно знать, насколько данный кадр MFCC похож на каждое состояние. Это оценивала GMM (смесь гауссиан) — она моделировала распределение признаков для каждого звука. Связку называли GMM-HMM: GMM отвечала «как звучит», HMM — «как тянется во времени».
Языковая модель спасает от похожих слов
Акустика часто неоднозначна: «код» и «кот» звучат почти одинаково. Тут вступает языковая модель: она знает, что «написал код» вероятнее, чем «написал кот». Простейшая ЯМ — n-граммы: вероятности слов по предыдущим. Покажем идею биграммы.
bigrams = {
("написал", "код"): 0.8,
("написал", "кот"): 0.05,
("погладил", "кот"): 0.7,
}
def score(prev, word):
return bigrams.get((prev, word), 0.01)
print("написал код:", score("написал", "код"))
print("написал кот:", score("написал", "кот"))
print("Выбор ASR:", "код" if score("написал","код") > score("написал","кот") else "кот")Вывод:
написал код: 0.8 написал кот: 0.05 Выбор ASR: код
Даже при одинаковом звуке языковая модель склоняет выбор к осмысленному варианту. Этот приём дожил до современных систем — только теперь ЯМ — это нейросеть.
Полезно представлять классический ASR как сборочный цех с отдельными бригадами: одна превращает звук в MFCC, другая считает похожесть кадров на фонемы, третья собирает фонемы в слова, четвёртая решает, какая фраза осмысленнее. Пока бригады работают слаженно, конвейер выдаёт текст. Но стоит одной ошибиться — например, словарю не знать редкого имени — и сбой тянется по всей цепочке. Именно эта хрупкость на стыках и стала главным мотивом перехода к единой нейросети: проще обучить один организм целиком, чем согласовывать десяток независимых деталей.
Алгоритм Витерби, сердце декодирования в HMM, по сути перебирает огромное число путей через состояния и находит самый вероятный — но делает это умно, не перебирая каждый путь отдельно, а накапливая лучшие частичные решения. Эта идея динамического программирования настолько фундаментальна, что встречается далеко за пределами речи: в биоинформатике она выравнивает последовательности ДНК, в связи — декодирует помехоустойчивые коды. Поняв Витерби на примере фонем, вы получаете инструмент, который пригодится в десятке других областей, где надо найти лучший путь сквозь последовательность скрытых состояний.
Любопытно, что переход к нейросетям случился не сразу и не целиком. Сначала в связке GMM-HMM заменили только GMM: распределения фонем стала оценивать глубокая сеть (так появились DNN-HMM-гибриды), а HMM с её состояниями и словарём осталась на месте. Это сразу дало заметный прирост точности при минимуме переделок. И лишь потом, с приходом CTC и seq2seq, отказались и от самой HMM. Такая постепенность — обычная история в инженерии: революции редко происходят одним скачком, чаще старую систему перестраивают по детали за раз.
Как работает под капотом
Итоговое распознавание — это поиск последовательности слов, максимизирующей произведение акустической и языковой вероятностей. Делали это в огромном графе (WFST) алгоритмом поиска. Система была мощной, но хрупкой: десятки настраиваемых блоков, отдельный словарь произношений, ручная работа лингвистов для каждого языка. Любая ошибка в звене портила результат.
Почему ушли от HMM/GMM
- Сложность. Много отдельных компонентов, каждый надо обучать и согласовывать.
- Ручной труд. Произносительные словари составляли вручную для каждого языка.
- Точность. Нейросети, заменив сперва GMM, а потом и весь пайплайн, резко снизили число ошибок.
Частые ошибки
- Считать HMM устаревшим хламом. Идеи фонем, ЯМ и Витерби живут в современных системах.
- Думать, что ЯМ исчезла. Она стала нейросетевой, но роль «выбрать осмысленный вариант» осталась.
- Недооценивать данные. Классика требовала размеченных фонем; нейросети научились обходиться расшифровками.
Итоги
- Классический ASR = MFCC + GMM-HMM + словарь + языковая модель.
- HMM моделировал течение речи во времени, GMM — звучание фонем.
- Языковая модель выбирает осмысленный вариант из похожих по звуку.
- Ушли из-за сложности, ручного труда и проигрыша нейросетям по точности.