I wrote little program for isolated word recognition using DTW algorithm. In folder with main program i have another folder "Data20dict", with 20 more folders in it, and each one is called by voice command, like copy, exit, input etc. Each of these 20 folders has aobut 20 utterances of this command, recorded in *.wav format. Total amount of utterances is 437. For DTW algorithm i use this module:https://github.com/pierre-rouanet/dtw.
My code is below:
from numpy.linalg import norm
from dtw import dtw
import os
import timeit
import librosa
from sklearn.model_selection import train_test_split
DATA_PATH = './Data20dict/'
SAMPLE_RATE = 16000
train = dict()
test = dict()
#Read all sound files from all directories
#and create dictionary with all commands(keys) with their utterances
for path in sorted(os.listdir(DATA_PATH)):
full_path = os.path.join(DATA_PATH, path)
if os.path.isdir(full_path):
class_name = path.upper()
class_files = [os.path.join(full_path, f) for f in sorted(os.listdir(full_path))][:-15]
waves = [librosa.load(file, sr=SAMPLE_RATE)[0] for file in class_files]
train_waves, test_waves = train_test_split(waves, test_size=0.2)
train[class_name] = train_waves
test[class_name] = test_waves
train_mfccs = dict()
test_mfccs = dict()
#All utterances are transformed to mfcc matrices
for class_name in train:
mfccs = []
for sound in train[class_name]:
mfcc = librosa.feature.mfcc(y = sound, sr = SAMPLE_RATE, hop_length = 512, n_mfcc = 13)
mfccs.append(mfcc)
train_mfccs[class_name] = mfccs
mfccs = []
for sound in test[class_name]:
mfcc = librosa.feature.mfcc(y = sound, sr = SAMPLE_RATE, hop_length = 512, n_mfcc = 13)
mfccs.append(mfcc)
test_mfccs[class_name] = mfccs
#Each utternace from test samples compares with
#all utternaces from train samples
correct_dtw = 0
total = 0
a = timeit.default_timer()
for key_test, val_test in test_mfccs.items():
for test_words in val_test:
total += 1
max_dist = [float("inf")]
for key_train, val_train in train_mfccs.items():
for train_words in val_train:
dist, _, _, _ = dtw(test_words.T, train_words.T, dist=lambda x, y: norm(x - y, ord=1))
if dist < max_dist:
max_dist = dist
output_label_dtw = key_train
if key_test == output_label_dtw:
correct_dtw += 1
dtw_time = timeit.default_timer() - a
print('\nNumber of test samples: {}'.format(total))
print('\nDTW: Correct recognized {} from {} test samples'.format(correct_dtw, total))
percent_correct_dtw = round((correct_dtw/total * 100.0),2)
print('\nDTW: Percent of recognition: ', percent_correct_dtw)
print('\nDTW: Spent time for recognition: ', dtw_time, 'seconds')
Results are next:
1 attempt:
Number of test samples: 34
DTW: Correct recognized 33 from 34 test samples
DTW: Percent of recognition: 97.06
DTW: Spent time for recognition: 35.58901049389533 seconds
2 attempt:
Number of test samples: 97
DTW: Correct recognized 96 from 97 test samples
DTW: Percent of recognition: 98.97
DTW: Spent time for recognition: 384.3671420063365 seconds
Do you have any ideas, what can slow my code, or how to improve it by decreasing time, needed for word recognition?