1/03/2011

Распознавание речи при помощи HTK Toolkit, основы

Данная статья является большей частью переводом и адаптацией Tutorial из HTKBook, и представляет собой пошаговое описание построения системы распознавания устного произношения украинских чисел от нуля до девяти. Данная статья дает лишь первое знакомство с HTK Toolkit и позволяет на практике познакомиться с основными компонентами инструментария. Ориентирована статья прежде всего на исследователей, начинающих заниматься проблемами распознавания речи, студентов и аспирантов. Все шаги, описанные ниже могут в принципе быть адаптированы для любого языка. Действия, описанные ниже проводились на операционной системе Windows XP, компиляция HTK Toolkit из исходных кодов проводилась при помощи Visual Studio 2005. Я не буду вдаваться в подробности того, для чего нужна та или иная команда или как они работаю «изнутри», т.к. это достаточно детально описано в HTKBook.

Шаг 1. Скачиваем и устанавливаем HTK Toolkit

HTK Toolkit версии 3.4.1 можно скачать с сайта http://htk.eng.cam.ac.uk/download.shtml
после регистрации на этом сайте.  Регистрируемся на сайте, качаем исходники  HTK, распаковываем их в любую директорию на локальном диске. Самый простой способ собрать HTK, если у вас есть Visual Studio 2003, 2005 или 2008 – при помощи утилиты HTK34xVSxCompile, которую можно скачать отсюда: http://www.co.it.pt/~aveiga/htk/ . Распаковываем архив с HTK34xVSxCompile в директорию, куда прежде был распакован HTK. В директории с HTK появятся два файла: HMMIRest.c и HTK34xVSxCompile.bat. Для сборки достаточно запустить на выполнение HTK34xVSxCompile.bat, и если у Вас в системе есть все необходимое, то сборка пройдет без проблем и в директории с HTK появится новая директория bin.win32, в которой будут все необходимые выполняемые файлы HTK Toolkit. Для того, чтобы создать нашу собственную языковую модель для распознавания, рекомендую скопировать все содержимое из директории bin.win32 в новую директорию, например numbers_UA. Далее, если не указано иначе, все действия производятся в директории numbers_UA, где есть все выполняемые файлы HTK.

Шаг 2. Строим словарь и грамматику.

Система, которую мы строим, должна распознавать любую последовательность украинских чисел от 0 до 9. Для описания грамматики создаем файл grammar со следующим содержимым:

(SENT-START <(ОДИН | ДВА | ТРИ | ЧОТИРИ | П'ЯТЬ | ШІСТЬ | СІМ | ВІСІМ | ДЕВ'ЯТЬ | НУЛЬ)> SENT-END)

Далее необходимо на основе грамматики создать сеть слов (word net). Для этого выполняем команду

HParse.exe grammar wnet

В результате выполнения команды будет создан файл wnet,  в котором будет содержаться  сеть слов.

Следующим шагом руками создаем список слов и словарь. Создаем в текстовом редакторе файл wlist со следующим содержимым:

SENT-END
SENT-START
ВІСІМ
ДВА
ДЕВ'ЯТЬ
НУЛЬ
ОДИН
П'ЯТЬ
СІМ
ТРИ
ЧОТИРИ
ШІСТЬ

Создаем также словарь с фонетической транскрипцией для каждого из приведенных выше слов. В текстовом редакторе создаем файл digits-ua.dic, внутри которого пишем:

SENT-END   [] sil
SENT-START [] sil
ВІСІМ    VV I SS I M sp
ДВА  D V AA sp
ДЕВ'ЯТЬ  D E V J A TT sp
НУЛЬ N U LL sp
ОДИН O D Y N sp
П'ЯТЬ    P J A TT sp
СІМ  SS I M sp
ТРИ  T R YY sp
ЧОТИРИ   CH OE T YY R Y sp
ШІСТЬ    SHI I SS TT sp

Для того, чтобы привести словарь к форме пригодной для HTK Toolkit, необходимо выполнить команду

HDMan.exe –m –w wlist –n monophones1 –l dlog dict digits-ua.dic

Эта команда создаст файл фонетического словаря dict и список фонем monophones1.

Шаг 3. Запись и кодирование обучающих данных.

Для того, чтобы построить модель скрытых цепей Маркова для системы распознавания речи, необходимо систему обучить. Для этого необходимо записать набор обучающих данных. Обучающими данными в нашем случае будет набор фраз, которые Вы можете записать самостоятельно. Сгенерировать набор фраз, соответствующих целевой грамматике, можно сгенерировать при помощи команды

HSGen –l –n 10 wnet dict > trainprompts

Эта команда создаст файл trainprompts со списком из 10 обучающих фраз (можно и больше, но 10 в принципе достаточно для обучения нашей системы). Файл может иметь приблизительно следующий вид:

1. SENT-START ОДИН ТРИ ЧОТИРИ ШІСТЬ ОДИН SENT-END
2. SENT-START ВІСІМ SENT-END
3. SENT-START ВІСІМ СІМ ОДИН ТРИ SENT-END

Записать обучающие фразы можно при помощи программы HSLab, которая входит в состав HTK Toolkit. Для записи каждой из 10 тренировочных фраз необходимо вызвать команду

HSLab <имя записи>

В качестве имени записей можно использовать имена вроде s01, s02,…, s10. У меня не получилось заставить программу HSLab создавать новый файл для новой записи без перезапуска программы, так что для записи каждой новой фразы имеет смысл выйти из HSLab при помощи кнопки Quit и запустить ее заново с новым именем записи. Для записи в программе HSLab надо нажать кнопку Rec, произнести фразу и нажать клавишу Stop. В результате записи в текущей директории будут созданы файлы s01_0, s02_0 и т.д.

После того, как данные записаны необходимо создать файл с описанием записанных данных. Его можно создать руками в текстовом редакторе. Назовем файл words.mlf и запишем в него следующее содержимое:

#!MLF!#
"*/s01.lab"
ОДИН
ТРИ
ЧОТИРИ
ШІСТЬ
ОДИН
.
"*/s02.lab"
ВІСІМ
.
"*/s03.lab"
ВІСІМ
СІМ
ОДИН
ТРИ
.

Для каждой фразы из набора обучающих данных  необходимо разбить фразу на отдельные слова и записать каждое слово с новой строки. В конце каждой фразы, кроме последней, в отдельной строке должна быть точка.

Для следующего шага нам понадобится еще один текстовый файл. Назовем его mkphones0.led. Сгенерируем фонетическую транскрипцию для записанных обучающих данных при помощи команды

HLed.exe –l * -d dict –l phones0.mlf mkphones0.led words.mlf

В результате выполнения будет создан файл phones0.mlf с фонетической транскрипцией для обучающих фраз.

Следующим шагом необходимо закодировать записанные обучающие данные, выделив из них характеристические векторы, основанные на коэффициентах мел-кепстр. Для этого создаем конфигурационный файл config со следующим содержимым:

TARGETKIND = MFCC_0
TARGETRATE = 100000.0
SAVECOMPRESSED = T
SAVEWITHCRC = T
WINDOWSIZE = 250000.0
USEHAMMING = T
PREEMCOEF = 0.97
NUMCHANS = 26
CEPLIFTER = 22
NUMCEPS = 12
ENORMALISE = F

Список файлов для кодирования задаем в текстовом файле codetr.scp, со следующим содержимым:

s01_0    s01.mfc
s02_0    s02.mfc
s03_0    s03.mfc
s04_0    s04.mfc
s05_0    s05.mfc
s06_0    s06.mfc
s07_0    s08.mfc
s09_0    s09.mfc
s10_0    s10.mfc

Кодирование данных осуществляем при помощи команды

HCopy –T 1 –C config –S codetr.scp


Шаг 4. Обучение скрытых моделей Маркова

В текстовом редакторе создаем файл прототип модели Маркова для системы распознавания названием proto, внутри которого помещаем текст:

~o 39
~h "proto"
     5
     2
         39
              0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
         39
                        1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
     3
         39
              0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
         39
                        1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
     4
         39
              0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
         39
                        1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
     5
         0.0 1.0 0.0 0.0 0.0
         0.0 0.6 0.4 0.0 0.0
         0.0 0.0 0.6 0.4 0.0
         0.0 0.0 0.0 0.7 0.3
         0.0 0.0 0.0 0.0 0.0
               

Также создаем файл со списком закодированных файлов с обучающими данными train.scp:

s01.mfc
s02.mfc
s03.mfc
s04.mfc
s05.mfc
s06.mfc
s08.mfc
s09.mfc
s10.mfc

В файле config первую строку заменяем на

TARGETKIND = MFCC_0_D_A

Далее в текущей директории создаем поддиректории hmm0, hmm1, hmm2, …, hmm9. В последствии в эти директории будут сохранены созданные модели. Создаем прототип модели при помощи команды

HCompV.exe –C config –f 0.01 –m –S train.scp –M hmm0 proto

В результате выполнения в директории hmm0 будут созданы файлы proto и vFloors. В основной директории создаем файл monophones0 копированием файла monophones1 и удалением из него строки sp. В директории hmm0 создаем файл hmmdefs, в котором будут описаны модели для кажой из фонем из файла monophones0, включая sil. Для этого внутри файла hmmdefs для каждой фонемы записываем строку типа

~h "sil"

(в кавычках пишем название фонемы, так как оно записано в monophones0), ниже этой строчки копируем из файла hmm0/proto секцию, начинающуюся со строки <BEGINHMM> и заканчивающуюся строкой <ENDHMM>. Эта секция должна быть одинаковой для каждой фонемы..

Также в директории hmm0 создаем файл macros, в содержимое которого пишем первые три строки из файла hmm0/proto и все содержимое файла vFloors.

После этого последовательно выполняем команды

HERest.exe –C config –I phones0.mlf –t 250.0 150.0 1000.0 –S train.scp –H hmm0/macros –H hmm0/hmmdefs –M hmm1 monophones0

HERest.exe –C config –I phones0.mlf –t 250.0 150.0 1000.0 –S train.scp –H hmm1/macros –H hmm1/hmmdefs –M hmm2 monophones0

HERest.exe –C config –I phones0.mlf –t 250.0 150.0 1000.0 –S train.scp –H hmm2/macros –H hmm2/hmmdefs –M hmm3 monophones0

Следующим шагом к текущим моделям нужно добавить модель короткой паузы. Для этого копируем содержимое директории hmm3 в директорию hmm4, и в файле hmm4/hmmdefs копируем описание модели для фонемы sil и создаем такое же  описание для фонемы sp (~hsp”). В основной директории создаем файл sel.hed с содержимым

AT 2 4 0.2 {sil.transP}
AT 4 2 0.2 {sil.transP}
AT 1 3 0.3 {sp.transP}
TI silst {sil.state[3],sp.state[2]}

И выполняем команду

HHEd.exe –H hmm4/macros –H hmm4/hmmdefs –M hmm5 sil.hed monophones1

После этого уточняем модель командами

HERest.exe –C config –I phones0.mlf –t 250.0 150.0 1000.0 –S train.scp –H hmm5/macros –H hmm5/hmmdefs –M hmm6 monophones1

HERest.exe –C config –I phones0.mlf –t 250.0 150.0 1000.0 –S train.scp –H hmm6/macros –H hmm6/hmmdefs –M hmm7 monophones1

Далее, в файл dict добавляем строку silence sil и создаем уточненную фонетическую транскрипцию, выполнением команды

HVite –l * -o SWT –b silence –C config –a –H hmm7/macros –H hmm7/hmmdefs –I aligned.mlf –m –t 250.0 –y lab –I words.mlf –S train.scp dict monophones1

Результатом будет файл aligned.mlf, в котором будут более точные фонетический транскрипции для всех обучающих данных. Некоторые из обучающих данных могут быть пропущены. Для того, чтобы в дальнейшем избежать ошибок, надо скопировать их транскрипции из файла phones0.mlf в aligned.mlf. После этого модель еще дважды нужно уточнить командами

HERest.exe –C config –I aligned.mlf –t 250.0 150.0 1000.0 –S train.scp –H hmm7/macros –H hmm7/hmmdefs –M hmm9 monophones1

HERest.exe –C config –I phones0.mlf –t 250.0 150.0 1000.0 –S train.scp –H hmm8/macros –H hmm8/hmmdefs –M hmm9 monophones1


Шаг 5. Распознавание речи на основе созданной модели.

Создаем текстовый файл config2 копированием файла config. В конце файла config2 дописываем строки:

SOURCERATE=625.0
SOURCEKIND=HAUDIO
SOURCEFORMAT=HTK
ENORMALISE=F
USESILDET=T
MEASURESIL=F
OUTSILWARN=T

Переключаем консоль Windows в кодировку Win1251 (в русскоязычных Windows она по умолчанию 866) командой

chcp 1251

Запускаем программу распознавания речи в «живом» режиме командой

HVite.exe –H hmm9/macros –H hmm9/hmmdefs –C config2 –w wdnet –p 0.0 –s 5.0 dict monophones1

Сразу после запуска программа проведет измерение уровней входящего сигнала. Для этого после отображения приглашения

READY[1]>
Please speak sentence – measuring levels

Необходимо произнести любое предложение. Обычно измерение уровня длится около 4 секунд. По окончанию измерения программа отобразит строку Level measurement completed. Если такая строка не появляется в течение 5-6 секунд, следует остановить программу нажатием Ctrl+C (другого способа я не нашел) и запустить ее заново.

Далее последовательно произносите последовательности чисел, которые система должна распознать и смотрите, как они появляются на экране.