2

i am very new in machine learning. I stumble on this source code on github that has no database, so i decided to use my own database. This code is to recognize speaker with MFCC and GMM-UBM. But when i try to run the code, i got this error "ValueError: Found array with 1 sample(s) (shape=(1, 13)) while a minimum of 2 is required". It seems like when the code is trying to fit the GMM on the 68th dataset, the MFCC shape of the data is broken. I assume there's something wrong on the feature extraction process.

Please help me! thank you very much. Here's the code

import python_speech_features as psf
from sklearn.mixture import GaussianMixture
from sklearn.externals import joblib
from scipy.io import wavfile
from functools import reduce
import numpy as np
from os import listdir
from os.path import isfile, join
import os
import re

DATA_PATH = 'dataCoba'


# Make a list of speakers from the newdata/data folder. The format for the files in the folder is
# name_1,wav for training and name_2.wav for testing
substring = "_2"
onlyfiles = [f for f in listdir(DATA_PATH) if isfile(join(DATA_PATH, f))]
onlyfiles.sort()
onlyones = []
for filename in onlyfiles:
    dups = re.search('[\w]+_2.wav', filename)
    #dups = re.search('[\w].wav', filename)
    if dups is None:
        onlyones.append(''.join(filename.split('_')[0]))
print(onlyones)

SPEAKERS = onlyones
TOTAL_SPEAKERS = len(SPEAKERS)
MODEL_SPEAKERS = len(SPEAKERS)

print(len(SPEAKERS))


class SpeakerRecognition:

    #  Create a GMM and UBM model for each speaker. The GMM is modelled after the speaker and UBM for each speaker
    #  is modelled after all the other speakers. Likelihood Ratio test is used to verify speaker
    def setGMMUBM(self, no_components):
        self.GMM = []
        self.UBM = []
        for i in range(MODEL_SPEAKERS):
            self.GMM.append(GaussianMixture(n_components= no_components, covariance_type= 'diag'))
            self.UBM.append(GaussianMixture(n_components= no_components, covariance_type= 'diag'))

    # Load in data from .wav files in data/
    # Extract mfcc (first 13 coefficients) from each audio sample
    def load_data(self):

        #training
        self.spk  = [wavfile.read(DATA_PATH + '/' + (str(i).replace('.wav','')) + '_1.wav') for i in SPEAKERS]
        self.spk_mfcc = [psf.mfcc(self.spk[i][1], self.spk[i][0])  for i in range(0, TOTAL_SPEAKERS)]

        #testing
        self.p_spk  = [wavfile.read(DATA_PATH + '/' + (str(i).replace('.wav','')) + '_2.wav') for i in SPEAKERS]
        self.p_spk_mfcc = [psf.mfcc(self.p_spk[i][1], self.p_spk[i][0])  for i in range(0, TOTAL_SPEAKERS)]
        print(self.spk_mfcc)


        for i in range(TOTAL_SPEAKERS):

            self.spk_train_size.append(len(self.spk_mfcc[i]))
            self.spk_start.append(len(self.total_mfcc))
            print("Speaker Number(train) = ",i)
            print ("self.spk_mfcc[i] = ", len(self.spk_mfcc[i]))

            for mfcc in self.spk_mfcc[i]:
                self.total_mfcc.append(mfcc)
                self.speaker_label.append(i)
            self.spk_end.append(len(self.total_mfcc))
            print("self.total_mfcc = ", len(self.total_mfcc))
            print("\n")

        for i in range(TOTAL_SPEAKERS):

            #print("self.p_spk_mfcc =", self.p_spk_mfcc)
            self.spk_test_size.append(len(self.p_spk_mfcc[i]))
            self.spk_start.append(len(self.p_total_mfcc))
            print("Speaker Num(test) = ",i)
            print("self.p_spk_mfcc = ",len(self.p_spk_mfcc[i]))
            print("MFCC Shape  = ",self.spk_mfcc[i].shape)

            for mfcc in self.p_spk_mfcc[i]:
                self.p_total_mfcc.append(mfcc)
                self.p_speaker_label.append(i)
            self.p_spk_end.append(len(self.p_total_mfcc))
            print("self.total_mfcc = ", len(self.p_total_mfcc))            
            print("\n")


    # Gaussian Mixture Model is made of a number of Gaussian distribution components.
    #  To model data, a suitable number o gaussian components have to be selected.
    # There is no method for finding this. It is done by trial and error. This runs
    # the program for different values of component and records accuracy for each one
    [![This is the error when i run the code][1]][1]


    def find_best_params(self):
        best_no_components = 1
        maxacc = 0
        for i in range(100, 256):
            self.setGMMUBM(i)
            self.fit_model()
            _, acc, _ = self.predict()
            print("Accuracy for n = {} is {}".format(i, acc))
            if acc > maxacc:
                maxacc = acc
                best_no_components = i
        return best_no_components

    # Fit the GMM UBM models with training data
    # fit = N buah data * dimensi data
    def fit_model(self):
        for i in range(MODEL_SPEAKERS):
            print("Fit start for {}".format(i))
            self.GMM[i].fit(self.spk_mfcc[i])
            print(self.spk_mfcc[i].shape)
            self.UBM[i].fit(self.total_mfcc[:self.spk_start[i]] + self.total_mfcc[self.spk_end[i]:])

            print("Fit end for {}".format(i))
            joblib.dump(self.UBM[i], 'dumps/new/ubm' + str(i) + '.pkl')
            joblib.dump(self.GMM[i], 'dumps/new/gmm' + str(i) + '.pkl')

    def model(self, no_components = 244):
        self.setGMMUBM(no_components)
        self.fit_model()

    # Predict the output for each model for each speaker and produce confusion matrix
    def load_model(self):
        for i in range(0, MODEL_SPEAKERS):
            self.GMM.append(joblib.load('dumps/new/gmm' + str(i) + '.pkl'))
            self.UBM.append(joblib.load('dumps/new/ubm' + str(i) + '.pkl'))

    def predict(self):
        avg_accuracy = 0

        confusion = [[ 0 for y in range(MODEL_SPEAKERS) ] for x in range(TOTAL_SPEAKERS)]

        for i in range(TOTAL_SPEAKERS):
            for j in range(MODEL_SPEAKERS):
                x = self.GMM[j].score_samples(self.p_spk_mfcc[i]) - self.UBM[j].score_samples(self.p_spk_mfcc[i])
                for score in x :
                    if score > 0:
                        confusion[i][j] += 1

        confusion_diag = [confusion[i][i] for i in range(MODEL_SPEAKERS)]

        diag_sum = 0
        for item in confusion_diag:
            diag_sum += item

        remain_sum = 0
        for i in range(MODEL_SPEAKERS):
            for j in range(MODEL_SPEAKERS):
                if i != j:
                    remain_sum += confusion[i][j]

        spk_accuracy = 0
        for i in range(MODEL_SPEAKERS):
            best_guess, _ = max(enumerate(confusion[i]), key=lambda p: p[1])
            print("For Accent {}, best guess is {}".format(SPEAKERS[i], SPEAKERS[best_guess]))
            if i == best_guess:
                spk_accuracy += 1

        #print(MODEL_SPEAKERS)
        spk_accuracy /= MODEL_SPEAKERS

        avg_accuracy = diag_sum/(remain_sum+diag_sum)
        return confusion, avg_accuracy, spk_accuracy

    def __init__(self):
        self.test_spk = []
        self.test_mfcc = []

        # Speaker data and corresponding mfcc
        self.spk = []
        self.spk_mfcc = []

        self.p_spk = []
        self.p_spk_mfcc = []

        # Holds all the training mfccs of all speakers and
        # speaker_label is the speaker label for the corresponding mfcc

        self.total_mfcc = []
        self.speaker_label = []
        self.spk_train_size = []  # Index upto which is training data for that speaker.

        self.p_total_mfcc = []
        self.p_speaker_label = []
        #print(self.p_speaker_label)
        self.spk_test_size = []

        # Since the length of all the audio files are different, spk_start and spk_end hold

        self.spk_start = []
        self.spk_end = []

        self.p_spk_start = []
        self.p_spk_end = []

        self.GMM = []
        self.UBM = []
        self.load_data()
        self.cepstral_mean_subtraction()

    # Cepstral Mean Subtraction (Feature Normalization step)
    def cepstral_mean_subtraction(self):
        for i, speaker_mfcc in enumerate(self.spk_mfcc):
            average = reduce(lambda acc, ele: acc + ele, speaker_mfcc)
            average = list(map(lambda x: x/len(speaker_mfcc), average))
            for j, feature_vector in enumerate(speaker_mfcc):
                for k, feature in enumerate(feature_vector):
                    self.spk_mfcc[i][j][k] -= average[k]
        for i, speaker_mfcc in enumerate(self.p_spk_mfcc):
            average = reduce(lambda acc, ele: acc + ele, speaker_mfcc)
            average = list(map(lambda x: x / len(speaker_mfcc), average))
            for j, feature_vector in enumerate(speaker_mfcc):
                for k, feature in enumerate(feature_vector):
                    self.p_spk_mfcc[i][j][k] -= average[k]


#TBD : Ten fold validation
def ten_fold():
    #fold_size = 0.1 * self.n
    fold_offset = 0.0
    accuracy_per_fold = 0
    average_accuracy = 0

    for i in range(0, 10):
        print("Fold start is {}  and fold end is {} ".format( fold_offset, fold_offset + fold_size))
        #accuracy = self.execute(int(fold_offset), int(fold_offset + fold_size))
        #print("Accuracy is of test {} is : {} ".format(i, accuracy))
        #average_accuracy += accuracy
        #fold_offset += fold_size

    average_accuracy /= 10.0
    print("Average accuracy  " + str(100 * average_accuracy))
    return average_accuracy


# Final result is a confusion matrix which represents the accuracy of the fit of the model
if __name__ == '__main__':

    SR = SpeakerRecognition()
    #SR.load_model()
    SR.setGMMUBM(no_components=13)
    #SR.find_best_params()
    SR.fit_model()
    confusion, mfcc_accuracy, spk_accuracy = SR.predict()

    print("Confusion Matrix")
    print(np.matrix(confusion))
    print("Accuracy in predicting speakers : {}".format(spk_accuracy))
    print("Accuracy in testing for MFCC : {}".format(mfcc_accuracy))
lorita
  • 21
  • 2
  • And what is the shape of mfcc when you extract it? It might help you to figure out where the problem is. You can simply add extra print to load_data. – Nikolay Shmyrev May 21 '20 at 19:51
  • When i try to print the shape of MFCC it shows that the 68th data is (1,13). I assume the problem is on this line "self.p_spk_mfcc = [psf.mfcc(self.p_spk[i][1], self.p_spk[i][0]) for i in range(0, TOTAL_SPEAKERS)]". The data thats error is the testing data. I can't seem to attach the error image here. please help, thank you! – lorita May 23 '20 at 07:09
  • Maybe 68th file is simply corrupted, you can remove it from dataset. You can certainly attach images if you like but it is better to paste text on pastebin and give here a link. – Nikolay Shmyrev May 23 '20 at 07:20
  • I tried to remove that 1 data that is corrupted, but apparently it appears 15% of my dataset experiencing the same issue. i dont understand why, because the dataset that is corrupted contains the same wav but different speaker. – lorita May 23 '20 at 09:14
  • Maybe wrong format of the input data or wrong sample rate, you can probably share that problematic file. – Nikolay Shmyrev May 23 '20 at 13:55
  • if that the case, does splitting the audio in 3 seconds is the problem? because the datasets that im using are splitted into 3 seconds every wav recording. Here's the code on pastebin https://pastebin.com/ZZhffihc – lorita May 25 '20 at 02:04
  • Audio split should not be the problem. You can share an audio file that creates problem for analysis. – Nikolay Shmyrev May 25 '20 at 16:56
  • how do i do that? – lorita May 26 '20 at 06:26

0 Answers0