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

    Я делаю простую систему авторизации по голосу. Я реализовал простенькую программу, которая разбивает аудиофайл на фреймы и вычисляет MFCC коэффициенты. В результате я получаю матрицу коэффициентов, а дальше скармливаю ее в алгоритм LBG и получаю на выходе кодовою книгу. Дальше я вычисляю расстояние Евклида и получаю некоторое значение. Если это значение минимально, то я примерно могу определить, кто говорил из зарегистрированных в базе пользователей. Но проблема в том, что таким способом я не смогу определить пользователя если в БД он не зарегистрирован. Т.е., чтобы предоставить пользователю доступ мне нужно сравнить кодовые книги 1 пользователя и принять решение о предоставлении доступа. Но как принять это решение?

    Подскажите, пожалуйста, какой-нибудь алгоритм, чтобы определить с какой вероятностью голос 2-х человек похож.


    P.S. Я понимаю, что это все очень сложно на самом деле, но я пытаюсь сделать очень простую систему.
      Цитата
      В результате я получаю матрицу коэффициентов, а дальше скармливаю ее в алгоритм LBG и получаю на выходе кодовою книгу. Дальше я вычисляю расстояние Евклида и получаю некоторое значение. Если это значение минимально, то я примерно могу определить, кто говорил из зарегистрированных в базе пользователей.


      Нужно тренировать не кодовую книгу, а распределение GMM. В результате тогда будет получаться не расстояние Евклида, а вероятность. Преимущество GMM перед кодовой книгой в том, что кроме среднего GMM включает вариацию, что позволяет понимать, в каких пределах может изменяться сигнал. Или, кроме кодовой книги нужно вычислять границы изменения сигнала.

      Цитата
      Но проблема в том, что таким способом я не смогу определить пользователя если в БД он не зарегистрирован.


      Для того, чтобы выделить пользователя от остальных нужно натренировать общее распределение сигнала для всех пользователей (UBM, или universal background model). Тогда можно принимать решение между гипотезами - пользователь ли это или другой человек, и оптимальное решение будет соотношением вероятностей P(пользователь)/P(все люди). GMM для всех людей будет иметь больший разброс по вариации и, таким образом, будет больше для человека со стороны.

      Про алгоритмы идентификации диктора можно прочесть в хорошей книге:

      http://www.amazon.com/Fundamentals-Speaker...i/dp/0387775919

      Скачать систему идентификации можно тут:

      http://mistral.univ-avignon.fr/publi_en.html

      Там же в статьях можно прочесть подробные описания применяемых алгоритмов, например, тут http://mistral.univ-avignon.fr/doc/publi/0...EY_Scheffer.pdf
        поделитесь, пожалуйста, простым для понимания исходником GMM, а то я не могу никак разобраться...

        желательно на Java или С#.

        Добавлено
        я долго искал примеры GMM:

        http://staff.aist.go.jp/s.akaho/MixtureEM.html
        http://www.lix.polytechnique.fr/~nielsen/MEF/index_old.htm
        http://www.scale.uni-saarland.de/cms/tl_fi...assp10-sgmm.pdf
        http://consortium.simple4all.org/files/201...amiya_et_al.pdf
        и много других...

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

        У меня есть массив коеф. MFCC:

        double [][] = new double[12][N];

        N - количество векторов
        12 - количество коеф. MFCC.

        Еще есть библиотека WEKA, но там непонятно как создавать *.arff файлы. Также встречал примеры с обработкой изображений с помощью GMM.
          Цитата
          поделитесь, пожалуйста, простым для понимания исходником GMM, а то я не могу никак разобраться...


          Чтобы понимать GMM, нужно разобраться в теории сначала, в алгоритме EM (expectation maximization). Без понимания теории исходный код не понять.

          Цитата
          Еще есть библиотека WEKA, но там непонятно как создавать *.arff файлы. Также встречал примеры с обработкой изображений с помощью GMM.


          В WEKA, например, можно использовать csv файлы вместо ARFF (текстовый файл со значениями, разделённый запятыми).

          http://weka.wikispaces.com/Can+I+use+CSV+files%3F
            В этой статье http://www.mathworks.com/company/newslette...-in-matlab.html для распознавания слов также используют MFCC+GMM.

            В чем отличия при использовании MFCC+GMM для распознавания человека по голосу и распознавания слов?

            Если я правильно понимаю, то алгоритм примерно тот, же: нормалиация->FFT->log->DCT->MFCC->GMM.

            Цитата
            В WEKA, например, можно использовать csv файлы вместо ARFF (текстовый файл со значениями, разделённый запятыми).

            http://weka.wikispaces.com/Can+I+use+CSV+files%3F


            Проблема у меня не в формате файла (CSV, ARFF), а в том как правильно создать этот файл и что дальше делать.

            Я создал такой файл (формат согласно http://www.cs.waikato.ac.nz/~ml/weka/arff.html):

            Скрытый текст
            Цитата

            @RELATION train_mfcc

            @ATTRIBUTE k1 NUMERIC
            @ATTRIBUTE k2 NUMERIC
            @ATTRIBUTE k3 NUMERIC
            @ATTRIBUTE k4 NUMERIC
            @ATTRIBUTE k5 NUMERIC
            @ATTRIBUTE k6 NUMERIC
            @ATTRIBUTE k7 NUMERIC
            @ATTRIBUTE k8 NUMERIC
            @ATTRIBUTE k9 NUMERIC
            @ATTRIBUTE k10 NUMERIC
            @ATTRIBUTE k11 NUMERIC
            @ATTRIBUTE k12 NUMERIC
            @ATTRIBUTE k13 NUMERIC
            @ATTRIBUTE k14 NUMERIC
            @ATTRIBUTE k15 NUMERIC
            @ATTRIBUTE k16 NUMERIC
            @ATTRIBUTE k17 NUMERIC
            @ATTRIBUTE k18 NUMERIC
            @ATTRIBUTE k19 NUMERIC
            @ATTRIBUTE k20 NUMERIC

            @DATA
            -32.3498, 4.0605, 5.8301, 3.0689, -2.8713, 4.5942, 1.2795, 4.3517, 0.5966, 1.0423, 0.2772, 1.8529, -0.3554, 0.682, -1.1851, 0.5094, -0.3388, -0.447, -0.477, -0.1983
            -22.1714, 11.6567, 0.9019, 3.1513, -4.0799, -0.1471, 0.0523, 3.1226, 0.4186, 0.3383, -0.1819, 0.2799, 0.9002, -0.1322, -0.0654, -0.4336, 0.0645, 0.0541, -0.4947, 0.4486
            -17.7415, 12.9399, -1.1669, 4.0394, -4.5064, -0.848, 0.8684, 3.3472, 0.1241, 0.7678, -0.437, 1.142, 1.1662, -0.4765, 0.1562, -0.6562, 0.1151, -0.4745, -0.2884, 0.5798
            -15.7587, 11.7175, -1.3064, 3.4384, -4.5473, 0.0878, -0.0937, 3.8573, -0.9389, 0.5959, -1.583, 2.5714, 0.0397, 0.1557, -0.2259, -0.5382, 0.0895, -0.5952, -0.1294, 0.5923
            -14.8299, 11.5163, -0.8506, 2.6221, -3.7514, -1.5211, 0.0827, 2.8456, -0.3039, -0.2845, -0.4518, 1.9514, 1.0591, -0.4259, -0.0208, -0.9849, 0.2597, -0.1178, 0.0367, 0.5465
            -16.5354, 13.0119, -0.7588, 2.7527, -4.0031, -1.4531, -0.014, 1.9984, -0.2771, -0.7085, -0.2466, 1.4909, 0.9616, -0.9521, -0.2399, -0.6355, 0.0683, 0.4254, -0.2596, 0.5112
            -17.0784, 12.9701, -0.3731, 3.6204, -4.8669, -0.7527, -0.0437, 2.3372, -0.9504, 0.6396, -1.045, 1.9671, 0.3374, -0.8312, 0.1097, -0.8346, 0.2744, -0.299, 0.1362, 0.584
            17.8279, 11.8431, -0.0373, 3.2749, -5.9843, -0.5036, -0.0407, 1.9581, -0.9016, -0.0151, -0.3362, 2.2256, 0.8158, -1.1666, -0.0412, -0.2118, 0.1392, -0.0786, -0.195, 0.3339
            -17.5583, 14.0317, 0.6605, 2.9566, -5.1855, 1.2289, 0.342, 1.768, -0.5752, -0.7489, 0.0884, 2.3976, 0.7062, -0.7034, -0.1701, 0.1148, -0.2311, 0.3706, -0.4088, 0.0948
            -14.2456, 11.5991, -0.8751, 2.7092, -5.1847, 1.0162, -0.1195, 1.3294, -1.4993, -0.5606, -0.3121, 2.1927, 0.5673, -0.3341, -0.7374, 0.2916, -0.3252, 0.368, -0.3364, 0.0532
            -14.96, 12.7157, -1.6107, 3.1761, -4.815, 1.2706, -0.0858, 1.4589, -1.7943, -0.3679, -0.0455, 1.2875, 0.6884, -0.5105, -1.2056, 0.1294, -0.3311, 0.3149, 0.0293, -0.1
            -16.1005, 13.5202, -1.0193, 4.1524, -4.2875, 1.1936, 1.3232, 0.2577, -1.629, -0.1102, 0.8293, 2.0851, 0.804, -0.3667, -0.3707, -0.194, -0.2832, 0.7501, 0.5325, 0.1284
            -16.9499, 11.8779, -0.5173, 4.1349, -4.0047, -0.9061, 2.6433, -1.121, -1.4609, -0.7473, 0.0262, 2.1373, 0.4892, -0.2107, 0.3484, -0.6026, -0.5675, 0.517, 0.2577, -0.4453
            -21.813, 12.656, -2.1174, 5.9518, -3.6495, -1.899, 1.914, -0.5438, -3.0692, -0.0507, -1.0886, 1.277, -0.535, -0.7092, 0.4369, -0.2334, -0.7128, 0.0336, 0.5755, 0.0062
            -29.7809, 10.5696, 1.8924, 4.8169, -0.6066, -1.1082, 2.8271, 0.4978, -1.384, 0.2966, 0.2374, 0.47, 1.0145, 0.3163, -0.3014, -0.5509, -0.9247, -0.0763, 0.3708, -0.2323
            -39.4665, 11.7038, 5.5216, 5.4122, 2.6301, 0.9113, 1.5733, 0.399, -0.6269, 0.9535, 0.7488, 0.5937, -0.1416, 0.2795, -0.2759, -0.4314, -0.2536, 0.5792, -0.3839, -0.8368
            -40.1275, 10.5679, 5.5873, 4.7788, 1.537, 0.9708, 0.9561, 0.7576, -0.1029, 0.252, 0.4989, 0.6563, 0.2654, -0.6313, -0.4296, 0.1563, -0.154, -0.0511, -0.0243, -0.5802
            -40.6595, 11.3106, 5.3157, 4.9205, 1.8858, 1.2899, 1.2226, 0.7896, -1.1021, -0.0255, 0.388, 1.4903, -0.946, -0.8741, -0.4228, -0.5073, -0.3334, 0.2134, 0.4922, 0.6576
            -40.7937, 9.4612, 6.3366, 5.3235, 1.7335, 2.8178, 1.3118, -0.0597, -0.5287, 0.6929, 0.1539, 0.4845, -0.2175, -0.1465, 0.0515, 0.2726, 0.0592, -0.1556, 0.1291, -0.2017
            -41.1384, 11.4818, 5.6535, 4.7051, 1.9337, 2.4688, 1.5602, 0.8369, -0.1301, 0.9709, 0.56, 0.5075, -0.1387, -0.4169, 0.1217, 0.5877, -0.294, 0.1396, -0.0018, -0.2662
            -40.8711, 10.9265, 6.0457, 5.6562, 2.0577, 1.0463, 0.546, 0.807, 0.6733, 1.3445, -0.2982, 0.0871, -0.4798, -0.1801, 0.5497, 0.607, -0.4527, -0.0106, -0.1941, -0.0726


            k1-k20 - это коэффициенты MFCC, каждая строка - это вектор, который я получаю для каждого фрейма.

            user posted image
            user posted image

            Log likelihood: -26.14818

            Дальше у меня будут, например, тестовые вектора, которые я хочу сравнить. А как это сделать?
              Цитата
              В чем отличия при использовании MFCC+GMM для распознавания человека по голосу и распознавания слов?


              При распознавании слов MFCC+GMM недостаточно, кроме выделения классов (звуков) нужно ещё и найти эти классы во времени (где каждый звук находится, какая последовательность звуков). Для распознавания речи используется MFCC + GMM + HMM (скрытая марковскаям модель). Именно использование скрытой марковской модели позволяет находить слова в непрерывном потоке речи. При распознавании человека не нужно выделять человека в потоке речи, записи каждого отдельного человека уже доступны. Достаточно их классифицировать (понять, к какому классу каждый образе относится).

              Цитата
              Если я правильно понимаю, то алгоритм примерно тот, же: нормалиация->FFT->log->DCT->MFCC->GMM.


              Алгоритм на этом не заканчивается - следующий этап это принятие решение о классификации. Если у нас есть набор распределений GMM, соответствующих классам, и тестовый образец, нам нужно сравнить оценки P(образец|GMM_i) и выбрать наилучший. Это и будет распознанный клас.

              Алгоритм одинаковый, и на странице matlab он изложен хорошо.

              Цитата
              Дальше у меня будут, например, тестовые вектора, которые я хочу сравнить. А как это сделать?


              Нужно построить набор GMM сначала для каждого человека. Затем вычислить P(образец|GMM_i), найти наилучший.

              Добавлено
              Weka не очень удобный инструмент для таких задач, по большому счету он не подходит, например, в Weka нет многомерных векторов в качестве признаков, только одномерные.

              Чтобы поэкспериментировать с классификацией в weka нужно создать один большой файл следующего формата с фреймами разных человек:

              ExpandedWrap disabled
                class_label1, feature1, feature2, feature3, feature4
                class_label1, feature1, feature2, feature3, feature4
                class_label2, feature1, feature2, feature3, feature4
                class_label2, feature1, feature2, feature3, feature4


              И запускать на закладке classify разные методы по классификации class_label по данным feature. Тестовый файл в подобном формате можно приложить тоже. Попробовать можно libSVM, но ничего хорошего не будет.

              Лучше использовать приведённый выше пример на matlab или, например, более продвинутые инструменты для машинного обучения - scikit-learn http://scikit-learn.org/stable/modules/gen...ixture.GMM.html (python) или на java что-нибудь поискать. Реализаций много, но толковых мало. Comirva можно посмотеть, там вроде было http://www.cp.jku.at/people/schedl/Researc...ge/CoMIRVA.html
                Пытаюсь использовать для GMM библиотеку Comirva: подключил библиотеку и с ее помощью получил MFCC коэффициенты. Дальше пытаюсь получить GMM так как показано в примерах, но почему-то возникает CovarianceSingularityException на этой строчке кода:

                ExpandedWrap disabled
                  user1_gmm.runEM(user1_pointList); //запуск Expectation-Maximization


                user1_pointList - список векторов с MFCC коэффициентами.

                Согласно http://www.cp.jku.at/people/schedl/researc...ianMixture.html

                Цитата

                Covariance Singularity Exception

                Description:
                This class indicates that during the EM training algorithm of a Gaussian Mixture Model one of the components got singular. A corrected list of points Might be passed through this exception, such that one can rerun the EM algorithm with the corrected list of points.


                Сделал еще один try/catch с getCorrectedPointList(), но все равно не работает - снова возникает Covariance Singularity Exception.


                Скрытый текст
                ExpandedWrap disabled
                  package net.test.VoiceControl;
                   
                  import java.io.File;
                  import java.io.IOException;
                   
                  import net.test.VoiceControl.audio.AudioRecorder;
                  import net.test.VoiceControl.audio.WaveData;
                  import comirva.audio.util.MFCC;
                  import comirva.audio.util.PointList;
                  import comirva.audio.util.gmm.CovarianceSingularityException;
                  import comirva.audio.util.gmm.GaussianMixture;
                  import comirva.audio.util.kmeans.KMeansClustering;
                   
                  public class VoiceTest {
                   
                      //SAMPLE_RATE,WINDOW_SIZE,NUMCOEFICCIENT - window size = (1/22050)*512 = 23.2 ms
                      private final int WINDOW_SIZE = 512;
                      private final int SAMPLE_RATE = 22050;
                      private final int MFCC_NUM = 13;
                      private final int GAUSSIANS_NUM = 16;
                      
                      public VoiceTest()
                      {
                          //get input signal
                          float [] signal1 = getSignalFromFile("user1_auth1.wav");
                          
                          //cut signal
                          int size = size = signal1.length / WINDOW_SIZE;
                          double [] inputData1 = new double[size * WINDOW_SIZE];
                          for(int z=0;z<size*WINDOW_SIZE;z++) inputData1[z] = signal1[z];
                          
                          //get MFCC
                          MFCC mfcc = new MFCC(SAMPLE_RATE,WINDOW_SIZE,MFCC_NUM,true);
                          
                          double [][] user1_mfcc = null;
                          
                          try
                          {
                              user1_mfcc = mfcc.process(inputData1);
                          } catch (IllegalArgumentException e) {
                              e.printStackTrace();
                          } catch (IOException e) {
                              e.printStackTrace();
                          }
                          
                          
                          ////get GMM
                          //create a point list with appropriate dimensions
                          PointList user1_pointList = new PointList(user1_mfcc[0].length);
                          
                          for(int z=0;z<user1_mfcc.length;z++) {double [] vector = user1_mfcc[z]; user1_pointList.add(vector);}
                   
                          GaussianMixture user1_gmm = null;
                          
                          try
                          {
                              //run k-means clustering algorithm to initialize the EM algorithem
                              KMeansClustering kmeans = new KMeansClustering(GAUSSIANS_NUM, user1_pointList, false);
                              kmeans.run();
                   
                              //run EM algorithem for gaussian mixture model
                              user1_gmm = new GaussianMixture(kmeans.getClusterWeights(), kmeans.getMeans(), kmeans.getFullCovariances());
                              user1_gmm.runEM(user1_pointList);
                          }
                          catch(CovarianceSingularityException cse)
                          {
                              //try to do the whole stuff once more with the corrected pointset
                              try
                              {
                                  //run k-means clustering algorithm to initialize the EM algorithem
                                  KMeansClustering kmeans = new KMeansClustering(GAUSSIANS_NUM, cse.getCorrectedPointList(), false);
                                  kmeans.run();
                   
                                  //run EM algorithem for gaussian mixture model
                                  user1_gmm = new GaussianMixture(kmeans.getClusterWeights(), kmeans.getMeans(), kmeans.getFullCovariances());
                                  user1_gmm.runEM(cse.getCorrectedPointList());
                              }
                              catch(CovarianceSingularityException cse2)
                              {
                                //well at this point we give up, we don't try further
                                throw new IllegalArgumentException("cannot create GMM for this song;");
                              }
                          }
                   
                          
                          System.out.println("ok");
                      }
                      
                      public float [] getSignalFromFile(String filename)
                      {
                          File audiofile = new File(filename);
                          
                          WaveData waveData = new WaveData();
                          float[] signal = waveData.extractAmplitudeFromFile(audiofile);
                          
                          ////Input signal normalization
                          AudioPreprocessor audioPreprocessor = new AudioPreprocessor();
                          float [] del_mic = audioPreprocessor.deleteMICEffects(signal,500); //delete MIC effect
                          //authAudioRecorder.DisplayAmplitude(del_mic);
                          float [] zero_amplitudes = audioPreprocessor.ZeroNormalization(del_mic);
                          //authAudioRecorder.DisplayAmplitude(zero_amplitudes);
                          float [] norm_amplitudes = audioPreprocessor.amplitudeNormalize(zero_amplitudes);
                          //AudioRecorder.DisplayAmplitude(norm_amplitudes);                
                          float [] no_silence = audioPreprocessor.GauseSilenceRemover(norm_amplitudes, 22050);
                          //AudioRecorder.DisplayAmplitude(no_silence);
                          
                          return no_silence;
                      }
                  }
                  Цитата
                  float [] norm_amplitudes = audioPreprocessor.amplitudeNormalize(zero_amplitudes);


                  Нужно делать нормализацию среднего коэффициентов MFCC (cepstral mean normalization, PointList.normalize()), что обеспечивает нормализацию амплитуды по различным частотным каналам, а не просто нормализовать амплитуду сигнала.

                  Цитата
                  for(int z=0;z<size*WINDOW_SIZE;z++) inputData1[z] = signal1[z];


                  На окна нужно нарезать с перекрытием, лучше использовать AudioPreProcessor из comirva

                  Цитата
                  private final int GAUSSIANS_NUM = 16;


                  Слишком много гауссианов, поэтому и не удаётся оценить GMM параметры. Попробуйте 1 гауссиан сначала или 2, если запись небольшая. Чтобы оценить 8 гауссианов нужна где-то минута записей.
                  Сообщение отредактировано: nsh -
                    Цитата
                    На окна нужно нарезать с перекрытием, лучше использовать AudioPreProcessor из comirva


                    Переписал код с использованием AudioPreProcessor, стандартное перекрытие 50%. Раньше у меня было перекрытие 60% и я удалял тишину из файлов, но судя по исходниках AudioPreProcessor.java (http://www.cp.jku.at/people/schedl/Researc.../doc/index.html и http://code.google.com/p/mirlastfm/source/...cessor.java?r=3) не удаляет фрагменты тишины из файлов.

                    Цитата

                    Нужно делать нормализацию среднего коэффициентов MFCC (cepstral mean normalization, PointList.normalize()), что обеспечивает нормализацию амплитуды по различным частотным каналам, а не просто нормализовать амплитуду сигнала.


                    Если делаю pointList.normalize(), то при создании GaussianMixture(kmeans.getClusterWeights(), kmeans.getMeans(), kmeans.getFullCovariances()) получаю IllegalArgumentException: mean and covariance matrix must have compatible shapes and the covarince matrix must not be singular.

                    Скрытый текст
                    Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: mean and covariance matrix must have compatible shapes and the covarince matrix must not be singular;
                    at comirva.audio.util.gmm.GaussianComponent.<init>(GaussianComponent.java:86)
                    at comirva.audio.util.gmm.GaussianMixture.<init>(GaussianMixture.java:94)


                    ExpandedWrap disabled
                      //z-normalization
                      //The normalization is done for every coordinate by subtracting
                      //the mean and dividing by the standard deviation.
                      user1_pointList = user1_pointList.normalize();
                      user2_pointList = user2_pointList.normalize();
                      user3_pointList = user3_pointList.normalize();


                    Цитата
                    Слишком много гауссианов, поэтому и не удаётся оценить GMM параметры. Попробуйте 1 гауссиан сначала или 2, если запись небольшая. Чтобы оценить 8 гауссианов нужна где-то минута записей.


                    Сделал 1 гауссиан - вроде работает(без pointList.normalize), но когда уже 2 гауссиана - то Covariance matrix got singular.

                    ExpandedWrap disabled
                      package net.test.VoiceControl;
                       
                      import java.io.File;
                      import java.io.IOException;
                      import java.util.Vector;
                       
                      import javax.sound.sampled.AudioInputStream;
                      import javax.sound.sampled.AudioSystem;
                      import javax.sound.sampled.UnsupportedAudioFileException;
                       
                      import comirva.audio.util.AudioPreProcessor;
                      import comirva.audio.util.MFCC;
                      import comirva.audio.util.PointList;
                      import comirva.audio.util.gmm.CovarianceSingularityException;
                      import comirva.audio.util.gmm.GaussianMixture;
                      import comirva.audio.util.kmeans.KMeansClustering;
                      import comirva.audio.util.math.Matrix;
                       
                      public class VoiceTest {
                       
                          //SAMPLE_RATE,WINDOW_SIZE,NUMCOEFICCIENT - window size = (1/22050)*512 = 23.2 ms
                          private final int WINDOW_SIZE = 512;
                          private final int SAMPLE_RATE = 22050;
                          private final int MFCC_NUM = 13;
                          private final int GAUSSIANS_NUM = 1;
                          
                          public VoiceTest()
                          {
                              
                              //get input signal  
                              AudioPreProcessor audioPreProcessor1 = getAudioPreProcessor("user1_auth1.wav");
                              AudioPreProcessor audioPreProcessor2 = getAudioPreProcessor("user1_auth2.wav");
                              AudioPreProcessor audioPreProcessor3 = getAudioPreProcessor("user1_auth3.wav");
                              
                              //get MFCC
                              MFCC mfcc = new MFCC(SAMPLE_RATE,WINDOW_SIZE,MFCC_NUM,true);
                              
                              Vector<double[]> user1_mfcc = null;
                              Vector<double[]> user2_mfcc = null;
                              Vector<double[]> user3_mfcc = null;
                              
                              try
                              {
                                  user1_mfcc = mfcc.process(audioPreProcessor1);
                                  user2_mfcc = mfcc.process(audioPreProcessor2);
                                  user3_mfcc = mfcc.process(audioPreProcessor3);
                              } catch (IllegalArgumentException e) {
                                  e.printStackTrace();
                              } catch (IOException e) {
                                  e.printStackTrace();
                              }
                                          
                              
                              ////get GMM
                              //create a point list with appropriate dimensions
                              PointList user1_pointList = new PointList(user1_mfcc.get(0).length);
                              PointList user2_pointList = new PointList(user2_mfcc.get(0).length);
                              PointList user3_pointList = new PointList(user3_mfcc.get(0).length);
                              
                              for(int z=0;z<user1_mfcc.size();z++) {double [] vector = user1_mfcc.get(z); user1_pointList.add(vector);}
                              for(int z=0;z<user2_mfcc.size();z++) {double [] vector = user2_mfcc.get(z); user2_pointList.add(vector);}
                              for(int z=0;z<user3_mfcc.size();z++) {double [] vector = user3_mfcc.get(z); user3_pointList.add(vector);}
                       
                              //z-normalization
                              //The normalization is done for every coordinate by subtracting
                              //the mean and dividing by the standard deviation.
                              user1_pointList = user1_pointList.normalize();
                              user2_pointList = user2_pointList.normalize();
                              user3_pointList = user3_pointList.normalize();
                              
                              GaussianMixture user1_gmm = null;
                              GaussianMixture user2_gmm = null;
                              GaussianMixture user3_gmm = null;
                              
                              //run k-means clustering algorithm to initialize the EM algorithem
                              KMeansClustering kmeans = new KMeansClustering(GAUSSIANS_NUM, user1_pointList, false);
                              kmeans.run();
                              
                              user1_gmm = new GaussianMixture(kmeans.getClusterWeights(), kmeans.getMeans(), kmeans.getFullCovariances());
                              
                              try {
                                  user1_gmm.runEM(user1_pointList);
                              } catch (CovarianceSingularityException e) {
                                  // TODO Auto-generated catch block
                                  e.printStackTrace();
                              }
                              
                              double d1 = user1_gmm.getLogLikelihood(user1_pointList);
                              double d2 = user1_gmm.getLogLikelihood(user2_pointList);
                              double d3 = user1_gmm.getLogLikelihood(user3_pointList);
                              
                              System.out.println("LogLikelihood: d1="+Double.toString(d1)+"; d2="+Double.toString(d2)+"; d3="+Double.toString(d3));
                          }
                          
                          public float [] getSignalFromFile(String filename)
                          {
                              File audiofile = new File(filename);
                              
                              WaveData waveData = new WaveData();
                              float[] signal = waveData.extractAmplitudeFromFile(audiofile);
                              
                              ////Input signal normalization
                              AudioPreprocessor audioPreprocessor = new AudioPreprocessor();
                              float [] del_mic = audioPreprocessor.deleteMICEffects(signal,500); //delete MIC effect
                              //authAudioRecorder.DisplayAmplitude(del_mic);
                              float [] zero_amplitudes = audioPreprocessor.ZeroNormalization(del_mic);
                              //authAudioRecorder.DisplayAmplitude(zero_amplitudes);
                              float [] norm_amplitudes = audioPreprocessor.amplitudeNormalize(zero_amplitudes);
                              //AudioRecorder.DisplayAmplitude(norm_amplitudes);                
                              float [] no_silence = audioPreprocessor.GauseSilenceRemover(norm_amplitudes, 22050);
                              //AudioRecorder.DisplayAmplitude(no_silence);
                              
                              return no_silence;
                          }
                          
                          public AudioPreProcessor getAudioPreProcessor(String filename)
                          {
                              File audiofile = new File(filename);
                              
                              AudioInputStream audioInputStream = null;
                              AudioPreProcessor audioPreProcessor = null;
                                      
                              try {
                                  audioInputStream = AudioSystem.getAudioInputStream(audiofile);
                              } catch (UnsupportedAudioFileException e) {
                                  e.printStackTrace();
                              } catch (IOException e) {
                                  e.printStackTrace();
                              }
                              
                              //check input type
                              if(audioInputStream == null || !(audioInputStream instanceof AudioInputStream))
                                  throw new IllegalArgumentException("input type for the td feature extraction process should be AudioPreProcessor and must not be null");
                                else
                                  audioPreProcessor = new AudioPreProcessor((AudioInputStream) audioInputStream);
                       
                              double sample_rate = audioPreProcessor.getSampleRate();
                              
                              return audioPreProcessor;
                          }
                      }


                    LogLikelihood: d1=-527.3006807672704; d2=-3111.5296058075746; d3=-Infinity

                    Если я правильно понимаю, то для того, чтобы получить Lamda_UBM = {mu_i;w_i;sigma_i} - мне нужно получить GMM модель для всех пользователей, тоесть в PointList будут вектора коэффициентов MFCC для всех пользователей. У меня будет GMM модель пользователя Lamda_user = {mu_i;w_i;sigma_i}, а дальше нужно получить LogLikelihood(gmm.getLogLikelihood(pointList)):

                    S = log[P(X|Lamda_user)] - log[P(X|Lamda_UBM)];

                    Если S < меньше порогового значения Q, то данный фрагмент речи не принадлежит человеку.
                      Цитата
                      mean and covariance matrix must have compatible shapes and the covarince matrix must not be singular.


                      Слишком мало данных для тренировки. Comirva тренирует full-covariance GMM, ему нужно очень много данных. Или нужно диагональный GMM реализовать

                      Цитата
                      Сделал 1 гауссиан - вроде работает(без pointList.normalize), но когда уже 2 гауссиана - то Covariance matrix got singular.


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

                      Цитата
                      Если я правильно понимаю, то для того, чтобы получить Lamda_UBM = {mu_i;w_i;sigma_i} - мне нужно получить GMM модель для всех пользователей, тоесть в PointList будут вектора коэффициентов MFCC для всех пользователей.


                      Правильно
                        Записал 2 аудио файла по 1 минуте каждый. Прочитал файлы с помощью AudioPreProcessor, получил MFCC, создал GMM для пользователя и UBM (сейчас только для 1 пользователя, но 2 разные аудиофайлы). Дальше пытаюсь получить LogLikelihood:

                        ExpandedWrap disabled
                          double d1 = user1_gmm.getLogLikelihood(user2_pointList);
                          double d2 = ubm_gmm.getLogLikelihood(user2_pointList);
                              
                          double L = user1_gmm.getLogLikelihood(user2_pointList) - ubm_gmm.getLogLikelihood(user2_pointList);
                                  
                          System.out.println("LogLikelihood: d1="+Double.toString(d1)+"; d2="+Double.toString(d2)+"; L="+Double.toString(L));


                        В ответ получаю LogLikelihood: d1=NaN; d2=NaN; L=NaN. :-?

                        Цитата

                        К операциям, приводящим к появлению NaN в качестве ответа, относятся:
                        -все математические операции, содержащие NaN в качестве одного из операндов;
                        -деление ноля на ноль;
                        -деление бесконечности на бесконечность;
                        -умножение ноля на бесконечность;
                        -сложение бесконечности с бесконечностью противоположного знака;
                        -вычисление квадратного корня отрицательного числа[1];
                        -логарифмирование отрицательного числа.


                        Цитата
                        Чтобы оценить 8 гауссианов нужна где-то минута записей.


                        Длина записи 1 минута, но если увеличиваю количество гауссианов до 2, то получаю ошибку: mean and covariance matrix must have compatible shapes and the covarince matrix must not be singular.

                        А тишину нужно удалять из файлов?

                        ExpandedWrap disabled
                          import java.io.File;
                          import java.io.IOException;
                          import java.util.Vector;
                           
                          import javax.sound.sampled.AudioInputStream;
                          import javax.sound.sampled.AudioSystem;
                          import javax.sound.sampled.UnsupportedAudioFileException;
                           
                          import net.mobfix.VoiceControl.audio.AudioRecorder;
                          import net.mobfix.VoiceControl.audio.WaveData;
                          import net.mobfix.VoiceControl.util.Graphics;
                          import comirva.audio.util.AudioPreProcessor;
                          import comirva.audio.util.MFCC;
                          import comirva.audio.util.PointList;
                          import comirva.audio.util.gmm.CovarianceSingularityException;
                          import comirva.audio.util.gmm.GaussianMixture;
                          import comirva.audio.util.kmeans.KMeansClustering;
                          import comirva.audio.util.math.Matrix;
                           
                          public class VoiceTest {
                           
                              //SAMPLE_RATE,WINDOW_SIZE,NUMCOEFICCIENT - window size = (1/22050)*512 = 23.2 ms
                              private final int WINDOW_SIZE = 512;
                              private final int SAMPLE_RATE = 22050;
                              private final int MFCC_NUM = 13;
                              private final int GAUSSIANS_NUM = 1;
                              
                              public VoiceTest()
                              {
                                  
                                  //get input signal      
                                  AudioPreProcessor audioPreProcessor1 = getAudioPreProcessor("user1_long_auth1.wav");
                                  AudioPreProcessor audioPreProcessor2 = getAudioPreProcessor("user1_long_auth2.wav");
                                  
                                  
                                  //get MFCC
                                  MFCC mfcc = new MFCC(SAMPLE_RATE,WINDOW_SIZE,MFCC_NUM,true);
                                  
                                  Vector<double[]> user1_mfcc = null;
                                  Vector<double[]> user2_mfcc = null;
                                  
                                  try
                                  {
                                      user1_mfcc = mfcc.process(audioPreProcessor1);
                                      user2_mfcc = mfcc.process(audioPreProcessor2);
                                  } catch (IllegalArgumentException e) {
                                      e.printStackTrace();
                                  } catch (IOException e) {
                                      e.printStackTrace();
                                  }
                                          
                                  
                                  ////get GMM
                                  //create a point list with appropriate dimensions      
                                  PointList user1_pointList = new PointList(MFCC_NUM);
                                  PointList user2_pointList = new PointList(MFCC_NUM);
                                  
                                  PointList ubm_pointList = new PointList(MFCC_NUM);
                                          
                                  for(int z=0;z<user1_mfcc.size();z++) {double [] vector = user1_mfcc.get(z); user1_pointList.add(vector);}
                                  for(int z=0;z<user2_mfcc.size();z++) {double [] vector = user2_mfcc.get(z); user2_pointList.add(vector);}
                           
                                  //add points to UBM
                                  for(int z=0;z<user1_mfcc.size();z++) {double [] vector = user1_mfcc.get(z); ubm_pointList.add(vector);}
                                  for(int z=0;z<user2_mfcc.size();z++) {double [] vector = user2_mfcc.get(z); ubm_pointList.add(vector);}
                                  //z-normalization
                                  //The normalization is done for every coordinate by subtracting
                                  //the mean and dividing by the standard deviation.
                                  user1_pointList = user1_pointList.normalize();
                                  user2_pointList = user2_pointList.normalize();
                                  
                                  ubm_pointList = ubm_pointList.normalize();
                                  
                                  GaussianMixture user1_gmm = null;
                                  GaussianMixture user2_gmm = null;
                                  
                                  GaussianMixture ubm_gmm = null;
                                  
                                  //run k-means clustering algorithm to initialize the EM algorithem
                                  KMeansClustering kmeans1 = new KMeansClustering(GAUSSIANS_NUM, user1_pointList, false);
                                  kmeans1.run();  
                                  user1_gmm = new GaussianMixture(kmeans1.getClusterWeights(), kmeans1.getMeans(), kmeans1.getFullCovariances());
                           
                                  //UBM-GMM
                                  KMeansClustering kmeans_ubm = new KMeansClustering(GAUSSIANS_NUM, ubm_pointList, false);
                                  kmeans_ubm.run();  
                                  ubm_gmm = new GaussianMixture(kmeans_ubm.getClusterWeights(), kmeans_ubm.getMeans(), kmeans_ubm.getFullCovariances());
                                  
                                  
                                  try {
                                      user1_gmm.runEM(user1_pointList);
                              
                                      ubm_gmm.runEM(ubm_pointList);
                                  } catch (CovarianceSingularityException e) {
                                      e.printStackTrace();
                                  }
                                  
                                  double d1 = user1_gmm.getLogLikelihood(user2_pointList);
                                  double d2 = ubm_gmm.getLogLikelihood(user2_pointList);
                              
                                  double L = user1_gmm.getLogLikelihood(user2_pointList) - ubm_gmm.getLogLikelihood(user2_pointList);
                                  
                                  System.out.println("LogLikelihood: d1="+Double.toString(d1)+"; d2="+Double.toString(d2)+"; L="+Double.toString(L));
                                  
                              }
                                  
                              public AudioPreProcessor getAudioPreProcessor(String filename)
                              {
                                  File audiofile = new File(filename);
                                  
                                  AudioInputStream audioInputStream = null;
                                  AudioPreProcessor audioPreProcessor = null;
                                          
                                  try {
                                      audioInputStream = AudioSystem.getAudioInputStream(audiofile);
                                  } catch (UnsupportedAudioFileException e) {
                                      e.printStackTrace();
                                  } catch (IOException e) {
                                      e.printStackTrace();
                                  }
                                  
                                  //check input type
                                  if(audioInputStream == null || !(audioInputStream instanceof AudioInputStream))
                                      throw new IllegalArgumentException("input type for the td feature extraction process should be AudioPreProcessor and must not be null");
                                    else
                                      audioPreProcessor = new AudioPreProcessor((AudioInputStream) audioInputStream);
                           
                                  double sample_rate = audioPreProcessor.getSampleRate();
                                  
                                  return audioPreProcessor;
                              }
                          }
                          Лучше весь проект выложить в архиве вместе с данными, чтобы воспроизвести проблему, а не один исходный файл.
                            Проект Java Eclipse

                            https://www.dropbox.com/s/pay1jalcmimtfoj/VoiceTest.rar

                            Добавлено
                            Основная часть кода в файле VoiceVerify.java.
                              Посмотрел я код, проблем там много, в большей части в Comirva, но проблемы могут быть решаемы:

                              1. MFCC почему-то иногда выдает фреймы с нулями в кепстре. Нужно разобраться откуда и по-хорошему решить эту проблему. Пока же можно их удалять:

                              ExpandedWrap disabled
                                        for (int z = 0; z < user2_mfcc.size(); z++) {
                                            double[] vector = user2_mfcc.get(z);
                                            if (vector[0] < 1)
                                                continue;
                                            ubm_pointList.add(vector);
                                        }


                              2. Пока можно нормализовать только средние, не делать нормализацию вариации.

                              3. Точности реализации матричных операций не хватает. Все операции нужно делать в логарифмической шкале, во многих местах идет значительная потеря точности.

                              4. Код по тренировке может быть таким, список точек обновляется по результатам exception, чтобы более стабильно тренировать. Тоже студент придумал такое, наверное:

                              ExpandedWrap disabled
                                        
                                        success = false;
                                        while (!success) {
                                            success = true;
                                            try {
                                                KMeansClustering kmeans_ubm = new KMeansClustering(
                                                        GAUSSIANS_NUM, ubm_pointList, false);
                                                kmeans_ubm.run();
                                                ubm_gmm = new GaussianMixture(kmeans_ubm.getClusterWeights(),
                                                        kmeans_ubm.getMeans(), kmeans_ubm.getFullCovariances());
                                                try {
                                                    ubm_gmm.runEM(ubm_pointList);
                                                } catch (CovarianceSingularityException e) {
                                                    ubm_pointList = e.getCorrectedPointList();
                                                }
                                            } catch (Exception e) {
                                                success = false;
                                            }
                                        }


                              Когда считается likelihood, по хорошему нужно считать в логарифмической шкале:

                              ExpandedWrap disabled
                                logTotalFrameLikelihood = logadd(logTotalFrameLikelihhood, logComponentLikelihood);

                              где

                              ExpandedWrap disabled
                                logadd(x,y) = max(x,y) + log(1+e^(x-y))


                              Но на крайний случай можно хотя бы на 0 проверять:
                              ExpandedWrap disabled
                                  public double getLogLikelihood(PointList points)
                                  {
                                    double p = 0;
                                    for (int j = 0; j < points.size(); j++) {
                                      double pr = getProbability((Matrix) points.get(j));
                                      if (pr < 1e-50) {
                                          continue;
                                      }
                                      p += Math.log(pr);
                                    }
                                    return p;
                                  }


                              5. Variance flooring нужно ещё делать, чтобы не было компонент с малой вариацией.


                              Для полного счастья хорошо бы обработать напильником.
                                nsh, большое спасибо за то, что посмотрели код!

                                В Comirva явно проблемы MFCC. Я переписал код для получения MFCC коэффициентов (остался тот вариант, который использовал до Comirva), сделал нормализацию MFCC по средним значениям:

                                ExpandedWrap disabled
                                      private void doCepstralMeanNormalization() {
                                          double sum;
                                          double mean;
                                          double mCeps[][] = new double[noOfFrames][numCepstra - 1];// same size
                                                                                                      // as mfcc
                                          // 1.loop through each mfcc coeff
                                          for (int i = 0; i < numCepstra - 1; i++) {
                                              // calculate mean
                                              sum = 0.0;
                                              for (int j = 0; j < noOfFrames; j++) {
                                                  sum += mfccFeature[j][i];// ith coeff of all frame
                                              }
                                              mean = sum / noOfFrames;
                                              // subtract
                                              for (int j = 0; j < noOfFrames; j++) {
                                                  mCeps[j][i] = mfccFeature[j][i] - mean;
                                              }
                                          }
                                      }


                                Вроде начали получаться адекватные результаты, но не совсем. Максимальное число гауссианов, которое мне удалось сделать - 3. Количество кепстральных коэффициентов - 13, размер фрейма 256 (примерно 32 ms при 8 кГц). Длина аудиозаписи для 1 пользователя 50-60сек вместе с тишиной, но я удаляю тишину.

                                Likelihood делал так:
                                ExpandedWrap disabled
                                  L = user1_gmm.getLogLikelihood(user1_auth1_pointList) / ubm_gmm.getLogLikelihood(user1_auth1_pointList);


                                Значения Likelihood не сильно отличаются, особенно для тех пользователей, которых нет в UBM (user4,user5,user6,user7 - не зарегистрированные пользователи).

                                Цитата
                                Verify user1
                                LogLikelihood(user1): L=0.8249521641940379
                                LogLikelihood(user2): L=1.1039434059625899
                                LogLikelihood(user3): L=1.020745193753429
                                LogLikelihood(user4): L=1.0241411114917134
                                LogLikelihood(user5): L=1.0805579201852602
                                LogLikelihood(user6): L=1.0127635231868999
                                LogLikelihood(user7): L=1.0356999111444292
                                Verify user2
                                LogLikelihood(user1): L=1.1695328088311627
                                LogLikelihood(user2): L=0.8453888963858318
                                LogLikelihood(user3): L=0.9834534072276123
                                LogLikelihood(user4): L=0.8796451716059582
                                LogLikelihood(user5): L=0.9084670757557486
                                LogLikelihood(user6): L=0.9166752706497352
                                LogLikelihood(user7): L=0.8799651912831838
                                Verify user3
                                LogLikelihood(user1): L=1.3761136000430545
                                LogLikelihood(user2): L=1.2776926979500356
                                LogLikelihood(user3): L=1.0156711637686784
                                LogLikelihood(user4): L=1.1377308499139034
                                LogLikelihood(user5): L=1.1814099472592825
                                LogLikelihood(user6): L=1.1155796762381176
                                LogLikelihood(user7): L=1.215022606631276


                                А иногда получается так, что для незарегистрированного пользователя L меньше чем для зарегистрированного:

                                Цитата

                                Verify user3
                                LogLikelihood(user1): L=1.1261525431561095
                                LogLikelihood(user2): L=1.0537272429065274
                                LogLikelihood(user3): L=1.0128126733670213 - зарегистрированный
                                LogLikelihood(user4): L=1.0930707321101896
                                LogLikelihood(user5): L=1.0314592923360855
                                LogLikelihood(user6): L=0.9491107399398667 - не зарегистрированный
                                LogLikelihood(user7): L=1.0422861426032701
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0677 ]   [ 15 queries used ]   [ Generated: 7.10.24, 07:31 GMT ]