На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: RaD, nsh
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Распознавание отдельных слов , wav,mfcc,dtw
    Доброго времени суток. Просмотрев от начала и до конца раздел "Речевые Технологии" в поиске информации по распознаванию речи, многое для себя уяснил. Но после того, когда начал реализацию, появились некоторые вопросы, надеюсь кто-то сможет прояснить.

    Пытаюсь реализовать распознавание одного слова, для этого было записано два варианта этого слова с разной интонацией. Получил 2 файла ~1c, частота дискретизации 16кГц, 16бит.

    Далее пользуюсь DSP-библиотекой Aquila (github.com/zsiciarz/aquila) разбиваю весь wav файл окном с половинным перекрытием (окно ~20мс), к полученным отрезкам применяю ДПФ, перевожу на мел шкалу, делаю дискретное косинусное преобразование. Получаю по 12 MFCC векторов для каждого отрезка (Значения этих коэффициентов меня больше всего смущают, т.к. получаются большие как положительные, так и отрицательные).Аналогичный алгоритм применяю над вторым файлом.
    Далее пытаюсь применить DTW с помощью Евклидова расстояния для наборов отрезков из файла 1 и файла 2.
    Результаты получаю совсем не правдоподобные :( . Пытаюсь понять где ошибка, возможно она всплывет после этих вопросов:

    1. Нужно ли производить нормирование сигнала?
    2. Какие значения примерно имеют MFCC коэффициенты?
    3. Какое значение должно быть после сравнение DTW, чтобы принять решение о правильности распознавания.

    Буду признателен за любую помощь.
      Цитата
      1. Нужно ли производить нормирование сигнала?


      Нормировать нужно не сигнал, а MFCC коэффициенты. Вычитать среднее.

      Цитата
      2. Какие значения примерно имеют MFCC коэффициенты?


      Значения зависят от параметров. Они могут быть и положительными, и отрицательными.

      ExpandedWrap disabled
          8.693   1.382   0.202   0.412  -0.895  -0.527   0.005  -0.417  -0.101   0.113
          8.446   1.356   0.229   0.471  -0.889  -0.496   0.001  -0.477  -0.102   0.118
          8.202   1.337   0.317   0.441  -0.795  -0.477  -0.075  -0.495  -0.079   0.151
          8.083   1.186   0.430   0.375  -0.735  -0.419  -0.091  -0.533  -0.074   0.121
          8.155   1.184   0.376   0.356  -0.753  -0.427  -0.094  -0.547  -0.002   0.098
          8.644   1.221   0.284   0.295  -0.885  -0.479  -0.040  -0.462  -0.024   0.064
          9.417   1.249   0.150   0.165  -1.004  -0.543   0.057  -0.354   0.001   0.092
         10.137   1.239  -0.082  -0.018  -1.049  -0.501   0.182  -0.313   0.065   0.070
         10.700   1.220  -0.345  -0.175  -1.023  -0.358   0.266  -0.230  -0.113   0.111
         11.269   1.086  -0.528  -0.299  -0.852  -0.271   0.343  -0.287  -0.280   0.114
         11.571   0.986  -0.806  -0.205  -0.618  -0.265   0.307  -0.375  -0.383   0.302
         11.476   1.072  -1.116  -0.057  -0.358  -0.319   0.168  -0.325  -0.447   0.414


      Цитата
      3. Какое значение должно быть после сравнение DTW, чтобы принять решение о правильности распознавания.


      Чтобы протестировать DTW нужно убедиться в следующих фактах:

      1. DTW от одинаковых файлов должно быть 0

      2. DTW от похожих файлов должно быть меньше DTW от непохожих файлов. Чем больше файлы похожи, тем меньше должно быть расстояние DTW.

      Далее, используя похожие и непохожие файлы, нужно экспериментально подобрать порог значения, при котором считать, что слово обнаружено.
        nsh, спасибо за ответ. Усреднив коэффициенты для всех отрезков, получаю такой результат:
        user posted image

        Схожесть между файлами прослеживается, DTW одинаковых файлов равно 0, DTW похожих файлов меньше, чем при сравнении разных файлов, но ненамного (Например при похожих файлах получаю расстояние 44860, а при разных файлах 68190).
          Цитата
          Усреднив коэффициенты для всех отрезков, получаю такой результат:


          В Вашей библиотеке ещё бы lifter не помешало бы применить после dct, чтобы придать больше значения коэффициентам высокого порядка. Результаты получше будут.

          Цитата
          Схожесть между файлами прослеживается, DTW одинаковых файлов равно 0, DTW похожих файлов меньше, чем при сравнении разных файлов, но ненамного (Например при похожих файлах получаю расстояние 44860, а при разных файлах 68190).


          В целом нормально это, но может быть и лучше.

          Этот результата с вычетом среднего или без?
          Сообщение отредактировано: nsh -
            Цитата
            В целом нормально это, но может быть и лучше.
            Этот результата с вычетом среднего или без?


            Немного не понял фразу "с вычетом среднего". Я Находил среднее для каждого коэффициента по всем отрезкам (У меня 66 перекрывающихся отрезков сигнала, для каждого отрезка по 12 коэффициентов, усреднив получаю 12 коэффициентов но уже для всего файла).

            Возник еще вопрос, сможет ли улучшить ситуацию, если пропустить сигнал через оконную функцию, например Хемминга?
              Цитата
              Немного не понял фразу "с вычетом среднего". Я Находил среднее для каждого коэффициента по всем отрезкам (У меня 66 перекрывающихся отрезков сигнала, для каждого отрезка по 12 коэффициентов, усреднив получаю 12 коэффициентов но уже для всего файла).


              Чего-то Вы в алгоритме не разобрались. Файл разбивается на 66 окон, для каждого окна высчитывается 12 коэффициентов. Затем для каждого коэффициента находится среднее по всем окнам. Вычитается, в результате получается всё равно 66 окон по 12 коэффициентов. Эти 66x12 чисел подается в DTW. Если Вы в DTW подаете только 12 чисел, не удивительно, что он не работает.
                nsh, спасибо исправления. Будем разбираться.
                Поправил программу, теперь сверяю все окна, но результаты пока не лучше, DTW от одинаковых файлов 0, а вот DTW от разных в некоторых случаях может быть меньше, чем DTW от похожих, например сравнение звуков с числами:

                Число1|Число2 = Расстояние DTW
                "Один"|"Один" (2 вариант) = 13897
                "Один"|"Один" (3 вариант) = 17927
                "Один"|"Один" (4 вариант) = 21856
                ----------------
                "Один"|"Два" = 12258
                "Один"|"Три" = 10124
                "Один"|"Четыре" = 21084
                "Один"|"Пять" = 19774
                ----------------
                "Два"|"Два" (второй вариант) = 16631
                "Два"|"Три" = 18693
                "Два"|"Четыре" = 25692
                "Два"|"Пять" = 17617
                  Цитата
                  Поправил программу, теперь сверяю все окна, но результаты пока не лучше


                  Нужно искать ошибку. Код не мешало бы показать.
                    На данный момент у меня такой код:
                    Скрытый текст


                    ExpandedWrap disabled
                      #include "aquila/global.h"
                      #include "aquila/source/WaveFile.h"
                      #include "aquila/source/SignalSource.h"
                      #include "aquila/transform/Mfcc.h"
                      #include "aquila/ml/Dtw.h"
                      #include "aquila/ml/DtwPoint.h"
                      #include "aquila/transform/FftFactory.h"
                       
                      #include <iostream>
                      #include <vector>
                       
                      using namespace std;
                       
                      /* Rounding  number of samples */
                      unsigned int RoundSize (Aquila::WaveFile& wav, int& Sample)
                      {
                          int SIZE = 0;
                          if (wav.getSamplesCount()%Sample == 0)
                          {
                              SIZE = wav.getSamplesCount();
                          }
                          else
                          {
                              SIZE = wav.getSamplesCount()-(wav.getSamplesCount()%Sample);
                          }
                          return SIZE;
                      }
                       
                      /* Transform wavfile to frame matrix with double overlap */
                      vector< vector<double> > MatrixFromFile (Aquila::WaveFile& wav, int Row, int Col,int Window)
                       {
                          /* Filling the matrix */
                          vector< vector<double> > WindowMatrix(Row);
                          int PairCount = 0;
                          for(int i = 0; i < Row; i=i+2)
                          {
                              WindowMatrix[i].resize(Col);
                              for(int j = 0; j < Col; ++j)
                              {
                                  WindowMatrix[i][j] = wav.sample(PairCount++);
                              }
                          }
                          int NoPairCount = Window/2;
                          for(int i = 1; i < Row; i=i+2)
                          {
                              WindowMatrix[i].resize(Col);
                              for(int j = 0; j < Col; j++)
                              {
                                  WindowMatrix[i][j] = wav.sample(NoPairCount++);
                              }
                          }
                       
                          return WindowMatrix;
                       }
                       
                       /* Calculation of Mel Frequency Cepstral Coefficients for FrameMatrix with subtracting the average */
                      vector< vector<double> > CalcMFCCforMatrix (vector< vector<double> >& WindowMatrix, int FFTSize, int Row)
                      {
                          vector< vector<double> > result (Row);
                          for(int i = 0; i < Row; ++i)
                          {
                             result[i].resize(FFTSize);
                             Aquila::SignalSource WavFromArr(WindowMatrix.at(i),16000);
                             Aquila::Mfcc fftMFCC (FFTSize);
                             result.at(i) = fftMFCC.calculate(WavFromArr);
                          }
                       
                          /* Searching the average */
                           vector<double> AverangeMFCC;
                           for(int i = 0; i < 12; ++i)
                           {
                               double TempSum = 0.0;
                               for(int j = 0; j < Row; ++j)
                               {
                                   TempSum+= result[j][i];
                               }
                               AverangeMFCC.push_back(TempSum/Row);
                           }
                       
                           /* Subtracting the average */
                           for(int i = 0; i < 12; ++i)
                           {
                               for(int j = 0; j < Row; ++j)
                               {
                                   result[j][i] = (result[j][i]) - AverangeMFCC.at(i);
                               }
                           }
                           return result;
                      }
                       
                      int main()
                      {
                       
                          Aquila::WaveFile wav("d:\\QT\\Projects\\console\\build-wav-Desktop_Qt_5_0_2_MinGW_32bit-Debug\\debug\\Numbers\\one.wav");
                       
                          /* firs file */
                          int Window = 500; /*16kHz = 62.5uS per sample*/
                       
                          unsigned int Wav1Size = RoundSize (wav,Window);
                          /* Matrix vector< vector<double> > size:
                           * Row - number of windows (one sample = 62.5uS, one WindowSize = sample*window, double overlap)
                           * Column - Window*/
                          const int RowWav1 = 2*(Wav1Size/Window);
                          const int ColWav1 = Window;
                       
                          /*Wav file to FrameMatrix*/
                          vector< vector<double> > WindowMatrixWav1 = MatrixFromFile (wav,RowWav1,ColWav1,Window);
                       
                         /* Calculation of Mel Frequency Cepstral Coefficients */
                          unsigned int FFTSize = 32;
                          vector< vector<double> > Wav1MatrixMFCC = CalcMFCCforMatrix (WindowMatrixWav1,FFTSize,RowWav1);
                       
                          /* second file */  
                          std::cout<<"--------"<<std::endl;
                          Aquila::WaveFile wav2("d:\\QT\\Projects\\console\\build-wav-Desktop_Qt_5_0_2_MinGW_32bit-Debug\\debug\\Numbers\\four.wav");
                          unsigned int Wav2Size = RoundSize (wav2,Window);
                          /* Matrix vector< vector<double> > size:
                           * Row - number of windows (one sample = 62.5uS, one WindowSize = sample*window, double overlap)
                           * Column - Window*/
                          const int RowWav2 = 2*(Wav2Size/Window);
                          const int ColWav2 = Window;
                       
                          /*Wav file to FrameMatrix*/
                          vector< vector<double> > WindowMatrixWav2 = MatrixFromFile (wav2,RowWav2,ColWav2,Window);
                       
                         /* Calculation of Mel Frequency Cepstral Coefficients */
                          vector< vector<double> > Wav2MatrixMFCC = CalcMFCCforMatrix (WindowMatrixWav2,FFTSize,RowWav2);
                       
                          /*DTW comparison*/
                          Aquila::DtwDataType from, to;
                          from = Wav1MatrixMFCC;
                          to = Wav2MatrixMFCC;
                          Aquila::Dtw dtw;
                          double distance = dtw.getDistance(from, to);
                          std::cout << "DTW distance (neighbors): " << distance << "\n";
                          Aquila::Dtw dtwDiag(Aquila::euclideanDistance, Aquila::Dtw::Diagonals);
                          distance = dtwDiag.getDistance(from, to);
                          std::cout << "DTW distance (diagonals): " << distance << "\n";
                       
                          return 0;
                       
                      }
                      Цитата
                      unsigned int FFTSize = 32;


                      Должно быть 512 для 16khz.
                        При FFTSize = 512, получаю DTW = inf. Увеличил длительность окна до 62.5 мс, получил такие результаты:

                        Число1|Число2 = Расстояние DTW
                        "Один"|"Один" (2 вариант) = 3.8e+6
                        "Один"|"Один" (3 вариант) = 5.9e+6
                        "Один"|"Один" (4 вариант) = 7.4e+6
                        ----------------
                        "Один"|"Два" = 6.1e+6
                        "Один"|"Три" = 3.2e+6
                        "Один"|"Четыре" = 6.9e+6
                        "Один"|"Пять" = 7.1e+6
                        ----------------
                        "Два"|"Два" (второй вариант) = 3.1e+6
                        "Два"|"Три" = 2.9e+6
                        "Два"|"Четыре" = 5.4e+6
                        "Два"|"Пять" = 4.3e+6
                          Посмотрел код, как-то он не вызывает доверия. MFCС в библиотеке неправильно вычисляется без лог-компрессии энергии. Надо смотреть ещё.
                            Цитата
                            Посмотрел код, как-то он не вызывает доверия. MFCС в библиотеке неправильно вычисляется без лог-компрессии энергии. Надо смотреть ещё.

                            Спасибо за помощь. Не встречалось ли Вам похожих библиотек с готовым функционалом?
                              Цитата valeros @
                              Спасибо за помощь. Не встречалось ли Вам похожих библиотек с готовым функционалом?

                              Поднимите взгляд к шапке сайта, там есть ссылка "Алгоритмы"
                                уважаемый автор и формутчане ) у кого есть наработки? или готовое решение. ищу именно такое по чтоб натрененровать и понимало меня.

                                Добавлено
                                прошу связаться со мной )) откликнитесь ау.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0431 ]   [ 15 queries used ]   [ Generated: 8.09.24, 09:42 GMT ]