- Распознавание команд с помощью ДПФ и библиотеки нейронной сети FANN

Практика для студентов. Мясищев А.А.

Распознавания речи - это процесс преобразования речевого сигнала в текстовый поток. Голосовое управление - способ взаимодействия с устройством при помощи голоса. В отличие от распознавания речи, голосовое управление предназначено для ввода команд — например, "включить свет", "показать погоду на завтра", "выключить телевизор" и т.д. Однако в любом случае необходимо выполнить преобразование сигнала, формируемого микрофоном в слово или набор слов.

Для создания системы распознавания речи нужно решить множество задач.

1. Необходимо преобразовать колебания воздуха в электрические сигналы при помощи микрофона, отфильтровав при этом помехи и шумы.

2. Далее сигнал необходимо представить в цифровой форме, доступной для обработки при помощи компьютера (оцифровать). Например, проанализировать спектральный состав сигнала, выделяя из сигнала набор основных частот и амплитуд (выполнить преобразование Фурье).

3. Выделить из оцифрованного звука лингвистические конструкции (например, фонемы), применив различные математические методы. Здесь наиболее широко в зависимости от постановки задачи используются методы статистического анализа - это метод скрытого Марковского моделирования (СММ), метод динамического программирования и метод нейронных сетей.

Таким образом, задачи, связанные с распознаванием голоса - это сложные наукоемкие задачи. Такие задачи широко используются при построении "умного дома".

Рассмотрим здесь решение практической задачи управления 3-мя устройствами и получения данных с температурного датчика с помощью 7-и голосовых командам. Причем выбор команд - отдельных слов выполнен так, чтобы слова были близки по произношению. Это сделано для оценки устойчивости представленного здесь решения распознавания команд. Ввод команд выполняется через стандартный микрофон, подключенный через популярный аудио адаптер CMI 8738/PCI к компьютеру, работающему под управлением операционной системы Linux Ubuntu 10.04. Решение задачи разбивается на этапы:

1. Выделение из общей звуковой оцифрованной осциллограммы длительностью 2 секунды осциллограммы конкретного слова - команды.

2. Разбиение осциллограммы на отдельные участки длиной ~15-23 миллисекунд(длина команды - слова ~0.65-0.90 секунды).

3. Применение дискретного преобразования Фурье (ДПФ) [1] к каждому участку слова (получение спектра сигнала на участке).

4. Выделение на каждом участке n - точек локальных максимумов амплитуд с их значениями частот (выделение форманты речевого сигнала).

5. Опытный поиск такого значения n, при котором после восстановления звука с помощью синусного преобразования Фурье будет однозначное субъективное "узнавание" преобразованного слова из набора выбранных 7-ми команд.

6. Формирование массива данных для каждого слова из участков слова, которые будут характеризовать конкретное слово.

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

8.Получив отдельные наборы массивов характерных для конкретных слов, используется математический аппарат нейронных сетей для распознавания конкретного введенного через микрофон слова. Здесь для создания и работы с нейронной сетью используется широко распространенная библиотека FANN[2].

Рассмотрим решение задачи в представленной выше последовательности.

1. Выделение из осциллограммы конкретного слова - команды.

Для записи голоса можно воспользоваться известной в Linux Ubuntu командой arecord. С помощью командной строки

arecord -q -d 2 -f cd -r 16000 -c 1 a.wav

создается 2-х секундный монофонический файл a.wav с частотой дискретизации 16000Гц и разрядностью или квантованием(-f cd) в 16 бит.

На рисунке 1 представлена осциллограмма слова "зеленый", отображенная в аудио редакторе audacity[3]. Здесь по оси абсцисс представлено время в секундах, по оси ординат - нормированное значение амплитуды.

Рис.1. Осциллограмма слова "зеленый" в 2-х секундном аудио файле a.wav

Для выделения осциллограммы слова "зеленый" составлена программа на языке c++ slice.c, текст которой представлен в источнике[4]. Работает программа следующим образом:

- Считывается файл a.wav.

- Определяется максимальная и минимальная амплитуда осциллограммы (для разрядности 16 бит максимальные и минимальные значения не могут превышать +32 767 и - 32 768 соответственно).

- Выполняется нормализация амплитуд (деление всех положительных амплитуд на максимальную амплитуду, отрицательных - на минимальную).

- Разбивается осциллограмма на 200 участков (из опыта).

- Для каждого участка определяется среднее положительное значение амплитуды.

- Выполняется "прогон" по участкам осциллограммы слева и справа. Если значение средней положительной амплитуды больше заданной величины(5% из опыта учета внешних шумов), то предполагается, что начало и конец слова достигнут.

- Запись выделенного слова "зеленый" в файл c.wav.

На рисунке 2 представлена осциллограмма выделенного слова "зеленый". Видно, что его временная длина примерно равна 0.73с.

Рис.2. Осциллограмма слова "зеленый" выделенного программой slice.c

2.Спектральный анализ сигнала.

Для распознавания слова необходимо найти массив чисел, который бы однозначно представлял именно это слово. В работе это сделано следующим образом. Делим любое из заданных семи слов на 40 интервалов (исходя из опыта). В этом случае длина интервала находится в пределах 15...23мс. К каждому интервалу применяем дискретное преобразование Фурье.

Известно, что прямое преобразование Фурье записывается в виде[1]:

Здесь

N - Количество значений сигнала, измеренных в одном из 40-ка интервалов;

- измеренные значения сигнала в n - й точке интервала;

- комплексная амплитуда;

k - й синусоидальный сигнал (k - й индекс частоты на кривой спектра). Индекс k изменяется от 0 до (N-1)/2, так как вторая половина из N комплексных амплитуд, фактически, является зеркальным отображением первой и не несёт дополнительной информации.

Разложим экспоненту по формуле Эйлера и получим:

или:

Определение действительной (вещественной) амплитуды выполняется по формуле:

частоты:

Здесь T - период времени в течении которого брались входные данные (длительность одного из 40-ка интервалов).

Геометрическая интерпретация представлена на рисунке 3.

.

а) – осциллограмма интервала (n – индекс времени), б) – спектрограмма (k – индекс частоты).

Фрагмент программы ДПФ имеет вид (программа new.c [4]):

N=yy/nom; // yy – число точек дискретизации команды, nom=40 – число

// интервалов, N – количество точек в интервале

tt0=nn*N; // nn – номер интервала (nn = 0, …, 39)

tt1=(nn+1)*N; // tt0, tt1 – номера точек начала и конца интервала

Tf=float(tt1-tt0)/16000; // Длительность интервала в сек.

{

j=0;

Nf=tt1-tt0; // Количество измерений (равно N)

for (kf=0; kf<Nf/2; kf++) // kf – соответствует k (индекс частоты)

{

summa_Re=0; summa_Im=0;

for (nf=0; nf<Nf; nf++) // nf – соответствует n (индекс времени)

{

Arg=2*3.141592653589793*nf*kf/Nf;

Re=cos(Arg)*an1[nf]/Nf;

Im=sin(Arg)*an1[nf]/Nf;

summa_Re=summa_Re+Re; // Расчет ReXk

summa_Im=summa_Im+Im; // Расчет ImXk

}

// Расчет вещественной амплитуды Ak и частоты Frk

A[kf]=1.5*(sqrt((summa_Re)*(summa_Re)+(summa_Im)*(summa_Im)));

Fr[kf]=(1/Tf)*kf;

}

В качестве примера на рисунке 4 представлена осциллограмма команды «температура», открытая в программе audacity. Затемненный вертикальный столбец соответствует интервалу №12.

Рис.3. Геометрическая интерпретация дискретного преобразования Фурье.

Рис.4. Осциллограмма слова «температура» с выделенным интервалом №12.

С помощью программы new.c рассчитана спектрограмма для этого интервала и для диапазона частот 0, …, 2500Гц, которая показана на рисунке 5. Амплитуды представлены целыми числами 16-и битной разрядности, как они представлены в wav файле.

Рис.5. Спектрограмма интервала №12 слова «температура»

На спектрограмме кружочками отмечено 8-м локальных экстремумов (формантов), имеющих наибольшее значение в этом интервале. В работе предполагается, что для описания слова в каждом из 40–а интервалов достаточно вычислить значения 8-ми векторов (каждый задается парой значений – частотой и амплитудой). Таким образом, слово однозначно для небольшой базы словарного запаса описывается массивом из 640 чисел. Доказательство этого выполнялось экспериментально путем восстановления осциллограммы слова – команды из полученной спектрограммы функциями синуса по 8-и амплитудам и частотам. Программа new.c формировала файл test.wav, который впоследствии прослушивался. Если при проигрывании файла звучание субъективно соответствовало произнесенному слову, то делался вывод о возможности описания слова таким набором из 8-ми векторов. Уменьшения количество векторов приводит к уменьшению субъективной различимости слова.

Ниже представлен фрагмент программы восстановления звука из 8-ми формантов с помощью функций синуса.

float pi=2.*3.14159265; float di;

for (i=tt0; i<tt1; i++) // tt0, tt1 – номера точек начала и конца интервала

{ di=pi*i/16000;

// buffer[i] – значения амплитуд поля данных wav – файла

// max0, …, max7 – максимальные амплитуды в интервале спектра

// maxf0, …, maxf7 – частоты максимальных амплитуд в интервале спектра

buffer[i] =(int)(max0*sin(di*maxf0))+(int)(max1* sin(di*maxf1));

buffer[i]=buffer[i]+(int)(max2 * sin(di*maxf2))+(int)(max3 * sin(di*maxf3));

buffer[i]=buffer[i]+(int)(max4 * sin(di*maxf4))+(int)(max5 * sin(di*maxf5));

buffer[i]=buffer[i]+(int)(max6 * sin(di*maxf6))+(int)(max7 * sin(di*maxf7));

}

bbuf=tt1; // количество элементов массива buffer

write_wav1(namefil, bbuf , buffer, 16000); // Запись wav файла

Результатом работы этого фрагмента программы new.c является формирование и запись wav файла с именем test.wav. На рисунке 6 представлена осциллограмма звука после синусоидального восстановления слова «зеленый». Сопоставляя осциллограммы на рисунках 2 и 6 можно заметить их близкое сходство.

Рис.6. Осциллограмма звука после синусоидального восстановления слова «зеленый»

Результатом работы программы new.c является также формирование массива из 640 чисел (320 векторов), определяющих произнесенное слово и запись его в файл r1.txt. Ниже представлен фрагмент программы:

// Цикл по интервалам

i6=0;

for(nn=0;nn<nom;nn++)

{

… amm[i6]=max0;amm[i6+1]=max1;amm[i6+2]=max2;

amm[i6+3]=max3;amm[i6+4]=max4;amm[i6+5]=max5;

amm[i6+6]=max6;amm[i6+7]=max7;

fmm[i6]=maxf0;fmm[i6+1]=maxf1;fmm[i6+2]=maxf2;

fmm[i6+3]=maxf3;fmm[i6+4]=maxf4;fmm[i6+5]=maxf5;

fmm[i6+6]=maxf6;fmm[i6+7]=maxf7;

i6=i6+8;

i7=i6; …

}

// Конец цикла по интервалам

// Формирование массива амплитуд и частот для произнесенного слова и

// запись его в файл r1.txt

FILE *filem;

filem = fopen("r1.txt","w");

for (i=0; i<i7; i++)

fprintf(filem,"%0.7f %0.7f\n",amm[i],fmm[i]);

fclose(filem);

Для того чтобы показать эффективность такого представления слов, слова-команды выбирались близкие по произношению:

- «синий», «сильный» - выполняют команды включить синий и выключить синий;

- «красный», «классный» - включить красный и выключить красный;

- «зеленый», «земля» - включить зеленый и выключить зеленый;

- «температура» - получить значение температуры с датчика температуры.

По этим командам контроллер Ардуино[5] должен включать и выключать три устройства, получать и передавать на компьютер данные с температурного датчика. Компьютер и Ардуино связаны с помощью Bluetooth устройств. В источнике [6] представлены примеры исходных звуковых файлов – команд и их звуки после ДПФ и восстановления синусом. Если прослушать полученные звуки, можно обнаружить их отличие друг от друга и субъективно установить соответствие их произносимым командам. Следовательно, можно выполнить несколько десятков повторений одной и той же команды и сформировать для нее несколько десятков массивов(r1.txt). То же сделать для всех остальных команд. Тогда будет получен наборов данных, каждый из которых соответствует своему слову-команде. По полученным наборам данных можно выполнить обучение нейронной сети. С появлением нового набора данных (произнесением команды) с помощью нейронной сети можно установить соответствие, к какому набору данных относится новый набор. Таким образом выполнить распознавание слова.

3. Создание с помощью библиотеки FANN[2] нейронной сети для распознавания команд.

Выполним установку библиотеки FANN для Linux Ubuntu 10.04. Работа с нейронной сетью будет выполняться в скриптовом языке PHP.

Устанавливаем пакеты:

sudo apt-get install php5-cli

sudo apt-get install php5-dev

Далее устанавливаем библиотеки FANN 1-й версии:

sudo apt-get install libfann1

sudo apt-get install libfann1-dev

Копируем с сайта http://pecl.php.net/package/fann Wrapper for FANN (для языка PHP) – программу fann-0.1.1.tgz

Распаковываем ее:

gzip -d fann-0.1.1.tgz

tar xf fann-0.1.1.tar

cd fann-0.1.1/

Запускаем команды

phpize

./configure

Выполняем компиляцию:

make

Исправляем ошибки компиляции. Для этого редактируем файл php_fann.h – необходимо закомментировать строчку 28

#define PHP_FANN_OO 1

Далее компилируем заново

make

и добавляем в php.ini строку

extension=fann.so

После этого скрипт, написанный на PHP будет работать с библиотекой FANN.

Опыт показал, что в качестве сети возможно использование классической полносвязной многослойной искусственной нейронной сети, основанной на алгоритме обучения с обратным распространением ошибок. На рисунке 7 представлена типичная структура сети, состоящая из одного входного слоя, одного скрытого слоя и выходного слоя из 5-и нейронов, которая может обслуживать 5 объектов.

Рис.7. Структура искусственной нейронной сети

Количество нейронов входного слоя должно быть равно числу элементов массива, характеризующего слово-команду. Представленная на рис.7 структура является типичной для создания модели сети в соответствии с библиотекой FANN. По условию задачи представленная на рис.7 структура должна иметь 640 нейронов во входном слое, 7 нейронов в выходном. Опыт показал, что сеть должна иметь 2 скрытых слоя по 100 нейронов. Обучение нейронной сети выполняется программой n.php [4]. Эта программа:

1. Считывает значения 42-массивов из 8-ми каталогов. В каталогах с 0 по 6 находятся 42 массива, которые сформированы из слов-команд синий, красный, зеленый, классный, сильный, земля, температура. Каждое слово произносилось 42 раза различной интонацией и с разным положением микрофона. В 7-м каталоге находится 42 массива, которые описывают другие слова.

2. Формирует массив данных для обучения нейронной сети. Он представляет собой перечисление наборов данных и значений, которые должны быть на выходе сети. Более подробно это представлено комментариями в программе n.php.

3. Создает сеть с помощью функции fann_create():

$ann = fann_create(array(640 ,100, 100, 7), 1.0, 0.7).

Здесь

640 - количество входных данных (640 нейронов входного слоя);

100 - количество нейронов 2-го скрытого слоя;

100 - количество нейронов 3-го скрытого слоя;

7 - количество выходных нейронов;

1.0 - Связность нейросети (1 – полносвязная для персептрона);

0.7 - Параметр, позволяющий управлять величиной коррекции весов на каждой итерации (в алгоритме обратного распространения ошибки он вводится, как коэффициент при градиенте).

4. Обучает сеть с помощью функции fann_train():

fann_train($ann, $my, 1000, 0.0001, 10).

Здесь

1000 – количество итераций при обучении сети;

0.0001 – допустимая погрешность;

10 - промежутки, через которые выводится отчет об обучении.

5. Сохраняет обученную сеть в файле "my.ann" для дальнейшего использования:

fann_save($ann, "my.ann").

Распознавание слова выполняется программой ru.php [4]. Эта программа:

1. Загружает обученную модель сети из файла "my.ann":

$ann = fann_create("my.ann");

2. Считывает из файла "r1.txt" массив $amm[], определяющий слово.

3. Запускает функцию fann_run($ann, $amm) для определения, какому слову соответствует считанный массив(т.е. выполняет распознавание). Распечатывает распознанное слово - команду.

4. Выполняет передачу данных кода распознанной команды на контроллер Ардуино через Bluetooth. Например, команда "красный" соответствует символу "1"(см. программу ru.php). После получения этого символа Ардуино выполняет включение соответствующего устройства. Команда "температура" посылает символ "6". После получения его Ардуино выполняет опрос температурного датчика, и значение температуры посылает обратно через Bluetooth компьютеру. Программа temp.php [4] постоянно прослушивает Bluetooth Ардуино и после получения температуры записывает ее значение в файл "aa.a". Программа ru.php считывает файл "aa.a" и распечатывает его на мониторе. Следует учитывать, что программа temp.php должна быть запущена на другой консоли.

Схема подключения Ардуино к Bluetooth, исполнительным устройствам и датчику температуры, программа для Ардуино представлены в источнике [7].

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

#!/bin/sh

while (true)

do

rm aa.a

echo

echo "ГОВОРИТЕ"

arecord -q -d 2 -f cd -r 16000 -c 1 a.wav

./slice

./new

./ru.php

sleep 3

done

Перед его запуском необходимо подключить Bluetooth командой

sudo rfcomm bind /dev/rfcomm1 98:D3:31:B0:86:16 1 (здесь используется адрес экспериментального Bluetooth устройства, подключенного к Ардуино) а в другой консоли запустить программу temp.php. Если будут возникать ошибки относительно занятости устройства, то необходимо перезапустить программу temp.php.

Выводы.

1. Показана возможность надежного распознавания слов с помощью ДПФ интервалов слов длиной 15...23мс с выделением 8-ми локальных максимумов амплитуд. Восстановление слова с помощью функций синуса показало близкое сходство звука исходному слову.

2. С помощью библиотеки FANN математической модели нейронной сети показана практическая возможность построения нейронной сети распознавания 7-и команд.

3. Представленный здесь подход практического решения задачи распознавания команд можно использовать для распознавания нескольких десятков команд и соответственно управление несколькими десятками устройствами через контроллер Ардуино.

4. Представленное здесь решение можно использовать для создания систем управления голосом на любом языке, любыми звуками.

5. Замеченные недостатки:

5.1. Зависимость качества распознавания от диктора, микрофона и даже расположения микрофона относительно диктора. Для решения этих проблем необходимо создания большой базы данных слов, произнесенных различными дикторами с разными микрофонами и при различных расположениях микрофонов.

5.2. Для надежного (практически 100% при правильном произношении слова) распознавания слов необходимо отсутствие посторонних звуков во время произношения слова. В основном посторонние шумы влияют на выделение слова из 2-х секундного аудио файла a.wav программой slice.c. Можно предположить, что если выделение слова при наличии шумов будет правильным, то нейронная сеть для различных вариантов слов с шумами сможет правильно выполнить распознавание (аналогия распознавания человеком слов с учетом помех).

5.3. При большом количестве слов необходимо формировать достаточно громоздкий массив данных для обучения нейронной сети при использовании библиотеки FANN(см. программу n.php). Можно предположить что это является основным ограничением использования библиотеки FANN методом распознавания по словам (любой язык имеет много слов).

Видео демонстрация

Литература.

1. Дискретное преобразование Фурье. Википедия. [Electronic resource]. - Mode of access: https://ru.wikipedia.org/wiki/Дискретное_преобразование_Фурье.

2. Fast Artificial Neural Network Library(FANN). [Electronic resource]. - Mode of access: http://leenissen.dk/fann/wp/.

3. Audacity. Википедия. [Electronic resource]. - Mode of access: https://ru.wikipedia.org/wiki/Audacity.

4. Мясищев А.А. Программы распознавания команд с помощью ДПФ и библиотеки FANN. [Electronic resource]. - Mode of access: http://webstm32.sytes.net/obrazec/prog.htm, 2015.

5. Arduino. Официальный сайт. [Electronic resource]. - Mode of access: http://arduino.cc , 2015.

6. Мясищев А.А. Примеры wav - файлов команд. [Electronic resource]. - Mode of access: http://webstm32.sytes.net/obrazec/zvuk.htm, 2015.

7. Мясищев А.А. Андроид и Ардуино в задачах управления голосом и синтеза речи с использованием Bluetooth. [Electronic resource]. - Mode of access: https://sites.google.com/site/webstm32/8-upravlenie-golosom-s-pomosu-android-i-arduino, - 2015.

Написано 06.06.2015г.