Приветствую всех читателей habrahabr!
В последнее время наблюдается значительный рост интереса к технологиям, связанным с распознаванием речи. Можно назвать несколько причин этого роста, в частности, значительное рост вычислительных возможностей и обучающего материала. На хабрахаре пользователем domage был опубликован целый цикл статей по основам технологий распознавания речи. Также стоит отметить статью Мел-кепстральные коэффициенты (MFCC) и распознавание речи и выполненную на её основе работу по идентификации человека по голосу: Кто там? — Идентификация человека по голосу.
В данной работе предлагается простой алгоритм (и его реализация на C++) системы распознавания речи по короткому словарю, основанный на анализе статистического распределения мел-кепстральных коэффициентов (Mel-frequency cepstrum coefficients, MFCC).
Постановка задачи
Существуют множество методов распознавания речи, в подавляющем большинстве случаев они основаны на методах статистического анализа и теории вероятностей (Hidden Markov Model, Gaussian Mixture Model и т.п.). Как известно, компания google предоставляет бесплатный сервис по распознаванию коротких речевых сообщений. На основе этого сервиса было даже предложено распознавание речи при помощи микроконтроллера: Распознавание речи на STM32F4-Discovery . Однако, возникает вопрос: есть ли возможность сделать свою систему распознавания речи, пусть даже на довольно ограниченном по размеру словаре, без использования «внешних» сервисов, при этом чтобы она работала быстро и с приемлемым качеством?
Основная идея
Итак, для распознавания речи будем использовать MFCC. Чтобы не вдаваться в подробности скажу, что относиться к ним стоит лишь как к некоторому фильтру, на входе которого — фонограмма, на выходе — набор векторов (коэффициенты), который мы и будем распознавать как некоторое слово или набор слов. Справедливости ради стоит отметить, что существуют множество других акустических признаков, использующихся для распознавания речи: Perceptual linear predictive (PLP), Linear prediction cepstral coefficient (LPCC), Linear frequency cepstral coefficients (LFCC).
Основная идея заключается в использовании линейного дискриминантного анализа для идентификации слова. Однако, он применим лишь для векторов одинаковой размерности. Т.к. слова могут быть различной длины, возникает вопрос: каким образом преобразовать последовательность произвольного числа MFCC-векторов в вектор фиксированной размерности?
Можно поступить следующим образом: находить места «сгущения» распределения этих векторов и в качества результирующего вектора брать конкатенацию векторов, являющихся центрами «сгущений». Такой конкатенированный вектор будем называть супервектором средних, а сами центры — средними значениями. При этом в качестве «отправной точки» будем использовать супервектор средних, полученный на всех MFCC-векторах всей базы обучения. Преобразовав таким образом последовательность MFCC-векторов в один супервектор средних фиксированной размерности, мы можем применять различные методы классификации.
Очевиден принципиальный недостаток такого подхода: не учитывается динамика распределения MFCC-признаков по времени, следовательно, система априори не способна различать, к примеру, слова «главрыба» и «абырвалг», т.к. общее распределение MFCC-векторов таких слов будет примерно одинаковым (соответственно, центры «сгущений» будут совпадать).
Описание алгоритма
В качестве базы обучения будем использовать множество файлов, каждый из которых представляет собой набор MFCC-векторов, полученных из фонограммы с записью того или иного слова. При этом файлы с записью одного и того же слова должны быть объединены в одну группу.
Вот как выглядит распределение первых двух компонент MFCC-векторов всей базы обучения:
Алгоритм состоит из следующих этапов:
- Находим супервектор средних для всей базы обучения при помощи алгоритма K-средних.
Пример работы алгоритма K-средних для K=10 представлен на рисунке:
где большие красные квадраты и есть искомые средние значения. - Для каждого файла базы находим собственные средние значения по формуле:
Mk = a * Mk0 + (1 — a) * Mk', k = 1:K
где Mk0 — среднее значение, найденное в п.1,
Mk' — среднее значение, полученное в результате применения одной итерации алгоритма K-средних для MFCC-векторов файла с использованием в качестве начального значения Mk0,
a = R/(R + Nk), где R — коэффициент «чувствительности», Nk — число MFCC-векторов, соответствующие среднему значению Mk'.
Найденные таким образом средние значения будем называть адапритованными средними значениями.
Пример адаптированных средних значений для файла представлен на рисунке:
- Имея теперь вместо исходных фонограмм адаптированные супервектора средних, проводим LDA для N классов (каждый класс соответствует одному слову).
В результате мы должны получить матрицу, состоящую из векторов нового базиса, при проекции на который исходные адаптированные супервектора средних должны достаточно хорошо разделяться. Пример для N=4:
- Проецируем все адаптированные супервектора средних на новый базис и находим средние значения и СКО (среднее квадратичное отклонение) проекций для каждого класса.
- Для определения принадлежности тестовой фонограммы тому или иному классу (т.е. распознавания), выполняем для неё пп. 2 и 4, далее находим расстояния полученной проекции до средних значений всех классов (можно дополнительно нормировать их на соответствующее СКО). Минимальное расстояние и будет соответствовать классу, к которому принадлежит тестовая фонограмма.
Реализация
Полную реализацию описанного алгоритма вместе с исходными кодами и базой для тестирования можно взять здесь.
Создание собственной системы распознавания слов состоит из следующих этапов:
- Запись фонограмм для обучения и тестирования
Для записи можно воспользоваться любой программой, умеющей записывать звук и сохранять его в формате WAVE. Я рекомендую использовать бесплатную программу Audacity.
Разработанная система не умеет выделять речевые сегменты, поэтому при записи нужно стараться, чтобы в фонограмме присутствовала только речь. Чем качественнее используется микрофон, тем качественнее получается система. Записывать необходимо в моно-режиме с частотой дискретизации 16000. - Построение MFCC-векторов
Для построения MFCC-векторов можно использовать бесплатную библиотеку SPro 5.0. Я взял на себя ответственность, немного перебрал эту библиотеку, исправил парочку ошибок и сделал сборку программы sfbcep.exe под windows (см. папку ../spro-5.0). 32-разрядная версия этой программы лежит в папке ../tools. Для построения MFCC-векторов я использовал следующие параметры:sfbcep.exe --format=wave --sample-rate=16000 --mel --freq-min=0 --freq-max=8000 --fft-length=256 --length=16.0 --shift=10.0 --num-ceps=13 [входной WAVE-файл] [выходной файл с MFCC-векторами]
- Обучение и тестирование системы
Для обучения и тестирования системы я написал программу wrsystem на языке C++. Полный исходный код находится в папке ../wrsystem. 32-разрядную версию этой программы можно взять в папке ../tools.
Релизация алгоритма LDA была позаимствована из библиотеки ALGLIB.
Программа wrsystem имеет два режима работы: обучение (в случае наличия параметра --learn) и тестирование. Эта программа принимает на вход три основных параметра:
— Путь к файлу с описанием базы обучения (тестирования) (параметр --base). Пример файла с описанием базы лежит в папке ../base, также описание формата можно посмотреть, запустив программу с параметром --help.
— Путь к бинарному файлу, хранящему результат обучения системы (параметр --system). В режиме обучения этот файл создается, в режиме тестирования — считывается.
— Путь к файлу, в который записывается результаты тестирования системы на указанной базе: матрица перепутывания и значение WER (Word Error Rate) (параметр --test_results).
Результаты экспериментов
В качестве эксперимента я создал систему, которая умеет распознавать 14 слов, записанных моим голосом. Для обучения системы я записал каждое слово 4-5 раз, а для тестирования — 7 раз. Итого база обучения содержит 63 файла, а база тестирования — 98. Использовались следующие параметры при обучении:
- Количество средних значений: 10
- Коэффициент «чувствительности» при адаптации: 20
- Размерность проекции: 20
- Использование нормализации на СКО: отсутствует
Результат тестирования на базе обучения показал уровень ошибки распознавания слов (WER) 1,6%, а на базе тестирования 5,1%.
На что стоит обратить внимание
Хотелось бы сказать несколько замечаний. Во-первых, для того, чтобы любая система (включая описанную здесь) могла качественно распознавать речь любого человека, необходимо иметь огромную базу обучения с записью всех слов, произнесенных разными людьми в разном эмоциональном состоянии с использованием различных записывающих устройств (телефон, микрофон, подслушивающее устройство и т.п.). Т.е. система, которую вы обучите, используя только свой голос и только вашу домашнюю гарнитуру, наверняка не будет работать для ваших знакомых и даже для вас, если вы будете использовать какой-нибудь другой микрофон. Во-вторых, описанная система имеет сильно ограниченный потенциал в силу своей тривиальности. Не смотря на то, что она работает, данный подход был предложен только в качестве эксперимента и не подходит для промышленного использования без каких-либо доработок.
На этом всё, спасибо за внимание!
Автор: yourich