На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: RaD, nsh
  
> Распознавание отдельных слов , 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 @
                              Спасибо за помощь. Не встречалось ли Вам похожих библиотек с готовым функционалом?

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

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


                                  Спасибо за совет, этот вариант я попробовал в первую очередь, из этой библиотеки я использовал БПФ, но вскоре нашел библиотеку в которой было все в одном. Но к сожалению, товарищ nsh обнаружил в этой библиотеке недоработки.

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


                                  К сожалению, я пока не добился нужного результата. Думаю для вашей задачи будет достаточно готового продукта CMU Sphinx.
                                    nsh Пожалуйста помогите мне никак не могу получить MFCC коэфиценты. Хочу написать программу распознование речи на c++, но мне нужен сначала получить MFcc коэфиценты а потом пуду использовать нейронные сети.Очень важно для меня.
                                      Конечно. Покажите свой код, опишите, что не работает. Разберемся. Какая-нибудь реализация у вас есть? Под какую платформу Вы программируете, под какую ОС.
                                        Цитата nsh @
                                        Конечно. Покажите свой код, опишите, что не работает. Разберемся. Какая-нибудь реализация у вас есть? Под какую платформу Вы программируете, под какую ОС.

                                        У меня есть код, в этом разделе у кого-то тоже был такой же вопрос вы помогли ему, я смотрел код который он написал но у меня есть вопросы.
                                        Я не понимаю почему wav фаил разбиваем по окном и почему для 16кГц выбираем int Window = 500, для чего надо разбивать а не взять весь wav фаил. И второй вопрос не могу понять с каким алгоритмом напсан функция MatrixFromFile, почему NoPairCount Начинается с Window/2? Буду очень блогодарень если поможете.

                                        Это более хороший код.

                                        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>
                                          #include <math.h>
                                           
                                          #ifdef NAN
                                          /* NAN is supported */
                                          #endif
                                          #ifdef INFINITY
                                          /* INFINITY is supported */
                                          #endif
                                          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)
                                           {
                                              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++)
                                                  {
                                                      cout << NoPairCount << endl;
                                                      WindowMatrix[i][j] = wav.sample(NoPairCount);
                                                      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("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 = 512;
                                              vector< vector<double> > Wav1MatrixMFCC = CalcMFCCforMatrix (WindowMatrixWav1,FFTSize,RowWav1);
                                           
                                           
                                              for(int i = 0; i < Wav1MatrixMFCC.size(); ++i){
                                                  for(int j = 0; j < Wav1MatrixMFCC.at(i).size(); ++j){
                                                      cout << Wav1MatrixMFCC.at(i).at(j) << " ";
                                                  }
                                                  cout << endl;
                                              }
                                           
                                           
                                            
                                              return 0;
                                           
                                          }
                                        Сообщение отредактировано: nsh -
                                          nsh Вы будете помочь мне? :(
                                            Цитата
                                            Я не понимаю почему wav фаил разбиваем по окном и почему для 16кГц выбираем int Window = 500, для чего надо разбивать а не взять весь wav фаил.


                                            Частотный состав звуков речи очень быстро изменяется. Преобразование Фурье подразумевает сигнал с постоянным частотным составом. Для того, чтобы проанализировать состав звуков по частотам с помощью преобразования Фурье, нужно разбить речь на интервалы, где частотный состав почти постоянен и заняться анализом каждого интервала в отдельности.

                                            Цитата
                                            И второй вопрос не могу понять с каким алгоритмом напсан функция MatrixFromFile, почему NoPairCount Начинается с Window/2? Буду очень блогодарень если поможете.


                                            Чтобы обеспечить плавность анализа, окна берутся с перекрытием. Второе окно начинается от середины первого. Третье окно начинается от конца первого и от середины второго. NoPairCount это на самом деле индекс в звуковых данных, откуда данные копируются в окно. Во последовательности перекрывающихся окон четные окна начинаются со сдвигом в половину окна. Попробуйте нарисовать картинку, станет более понятно.
                                              nsh Спасибо. А вы можете мне сказать какую книгу прочитать чтобы понимать как все это делается. Я совсем не предстовляю как энкодируется и декодируется wav фаил, в чем разница между stereo и моно, 8 бит и 16 бит, right channel left channel, что вообще channel? И в моем коде не понимаю что из себя представляет sample, и от чего зависит калияество sample-ов.
                                                Это достаточно простые вещи, я не думаю, что стоит искать книгу. Достаточно просто посмотреть на файлы. Например запись может содержать несколько потоков звука одновременно, это и есть каналы. Правый канал - это то, что слышит правое ухо, левый канал - левое. Значения сигналов для каждого из каналов сохраняется в файле по очереди. Сначала значение первого канала, затем второго. Размерность значения и есть битность.
                                                  nsh У меня еще один вопрос. Кажется все понял, но не могу понять для чего нужен FFt size, с чем он связан и почему для 16KHz нужно взяать его размер 512.
                                                    David1993, я тем же вопросом интересовался, прочитай тему - Некоторые ньюансы, связанные с FFT
                                                      У меня возникло пару вопросов.
                                                      1) Звук пропускаю через БПФ, выделяю 3 полосы(можно больше) в линейном масштабе, пропускаю каждую через скользящее среднее, чтобы отсеить резкие изменения и прочую нестабильность. Затем делаю DTW получившихся последовательностей с эталоном.
                                                      Как на картинке: http://s16.postimg.org/b877y36ut/sounds_dtw.png
                                                      Имеет ли право на жизнь такой подход?
                                                      2) Когда я запускаю DTW мне кажется, что результат ошибки сильно зависит от длины сравниваемых последовательностей. Например, 2 длинные похожие последовательности будут иметь абсолютную ошибку намного больше, чем 2 короткие непохожие.
                                                      Я сейчас подумываю перейти от абсолютной к относительной оценке: делить ошибку на число точек в наиболее длинной последовательности. Таким образом можно в более вменяемых величинах задавать порог срабатывания команды.
                                                      Что посоветуете или скажете?

                                                      О применении:
                                                      Хочу распознавать 2-3 слова(умный выключатель для своего дома). Вполне допустимо чтобы система была дикторозависимой. Приемлемое качество 70-80%.
                                                      Пока моделирую на ПК, в случае успеха алгоритм переедет во встроенную систему(до 16КБ ОЗУ, до 40 MIPS, процессор правда 32бит).
                                                        Цитата
                                                        Имеет ли право на жизнь такой подход?


                                                        Да, но лучше ещё логарифмическую шкалу ввести и среднее вычесть. Это сделает систему инвариантной к громкости сигнала.

                                                        Цитата
                                                        Я сейчас подумываю перейти от абсолютной к относительной оценке: делить ошибку на число точек в наиболее длинной последовательности. Таким образом можно в более вменяемых величинах задавать порог срабатывания команды.


                                                        Деление на длину большого смысла не имеет. Порог может быть различным даже для слов одинаковой длины. Проще всего порог настраивать для каждого слова в отдельности на тестовых примерах - запустить большой объем записи и выбрать минимальный порог для допустимого числа ложных срабатываний.
                                                          Я правильно понял, что мне надо просто преобразовать последовательности в логарифмическую шкалу(Мел-шкалу?), а затем делать DTW между ними?
                                                            Цитата
                                                            Я правильно понял, что мне надо просто преобразовать последовательности в логарифмическую шкалу(Мел-шкалу?), а затем делать DTW между ними?


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

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


                                                            Рейтинг@Mail.ru
                                                            [ Script execution time: 0,0663 ]   [ 15 queries used ]   [ Generated: 18.09.24, 14:59 GMT ]