Вейвлет с ускорением графический процессор - распознавание разговорных цифр

В этом примере показано, как ускорить вычисление признаков вейвлет-рассеяния с помощью gpuArray (Parallel Computing Toolbox). Вы должны иметь Toolbox™ Parallel Computing и поддерживаемый графический процессор. Для получения дополнительной информации см. раздел Поддержка графического процессора по версии (Parallel Computing Toolbox). Этот пример использует графический процессор NVIDIA Titan V с вычислительными возможностями 7.0. Раздел примера, в котором вычисляется преобразование рассеяния, предоставляет опцию использования GPU или CPU, если вы хотите сравнить эффективность GPU и CPU.

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

Данные

Клон или скачать бесплатный набор данных Spoken Digit (FSDD), доступный в https://github.com/Jakobovski/free-spoken-digit-dataset. FSDD является открытым набором данных, что означает, что он может расти с течением времени. Этот пример использует версию, зафиксированную на 08/20/2020, которая состоит из 3000 записей английских цифр от 0 до 9, полученных от шести дикторов. Данные отбираются с частотой дискретизации 8000 Гц.

Использование audioDatastore управлять доступом к данным и обеспечивать случайное деление записей на обучающие и тестовые наборы. Установите location свойство для расположения папки записей FSDD на вашем компьютере. В этом примере данные хранятся в папке в tempdir.

location = fullfile(tempdir,'free-spoken-digit-dataset','recordings');
ads = audioDatastore(location);

Функция помощника, helpergenLabels, заданный в конце этого примера, создает категориальный массив меток из файлов FSDD. Перечислите классы и количество примеров в каждом классе.

ads.Labels = helpergenLabels(ads);
summary(ads.Labels)
     0      300 
     1      300 
     2      300 
     3      300 
     4      300 
     5      300 
     6      300 
     7      300 
     8      300 
     9      300 

Набор данных FSDD состоит из 10 сбалансированных классов с 300 записями каждый. Записи в FSDD не имеют равной длительности. Прочтите файлы FSDD и создайте гистограмму длин сигнала.

LenSig = zeros(numel(ads.Files),1);
nr = 1;
while hasdata(ads)
    digit = read(ads);
    LenSig(nr) = numel(digit);
    nr = nr+1;
end
reset(ads)
histogram(LenSig)
grid on
xlabel('Signal Length (Samples)')
ylabel('Frequency')

Гистограмма показывает, что распределение длин записи положительно искажено. Для классификации в этом примере используется общая длина сигнала 8192 выборки. Значение 8192, консервативный выбор, гарантирует, что усечение более длинных записей не влияет (обрезает) на речевое содержимое. Если сигнал больше 8192 отсчетов, или 1,024 секунды, в длину, запись обрезается до 8192 выборок. Если длина сигнала меньше 8192 отсчетов, сигнал симметрично дополняется и добавляется нулями к длине 8192 отсчетов.

Вейвлет вейвлет-времени

Создайте вейвлет сеть рассеяния времени с помощью инвариантного масштаба 0,22 секунды. Поскольку векторы функций будут созданы путем усреднения преобразования рассеяния во всех временных выборках, установите OversamplingFactor к 2. Установка значения 2 приведет к четырехкратному увеличению количества коэффициентов рассеяния для каждого пути относительно критически пониженного значения.

sn = waveletScattering('SignalLength',8192,'InvarianceScale',0.22,...
    'SamplingFrequency',8000,'OversamplingFactor',2);

Настройки сети рассеяния приводят к 326 путям. Можно проверить это с помощью следующего кода.

[~,npaths] = paths(sn);
sum(npaths)
ans = 326

Разделите FSDD на обучающие и тестовые наборы. Выделите 80% данных наборов обучающих данных и сохраните 20% для тестового набора. Обучающие данные предназначены для настройки классификатора на основе преобразования рассеяния. Тестовые данные предназначены для оценки способности модели обобщать до невидимых данных.

rng default;
ads = shuffle(ads);
[adsTrain,adsTest] = splitEachLabel(ads,0.8);
summary(adsTrain.Labels)
     0      240 
     1      240 
     2      240 
     3      240 
     4      240 
     5      240 
     6      240 
     7      240 
     8      240 
     9      240 
summary(adsTest.Labels)
     0      60 
     1      60 
     2      60 
     3      60 
     4      60 
     5      60 
     6      60 
     7      60 
     8      60 
     9      60 

Сформируйте матрицу 8192 на 2400, где каждый столбец является записью разговорных цифр. Функция помощника helperReadSPData обрезает или заполняет данные до длины 8192 и нормализует каждую запись по ее максимальному значению. Функция helper приводит данные к одинарной точности.

Xtrain = [];
scatds_Train = transform(adsTrain,@(x)helperReadSPData(x));
while hasdata(scatds_Train)
    smat = read(scatds_Train);
    Xtrain = cat(2,Xtrain,smat);
    
end

Повторите процесс для удерживаемого тестового набора. Получившаяся матрица 8192 на 600.

Xtest = [];
scatds_Test = transform(adsTest,@(x)helperReadSPData(x));
while hasdata(scatds_Test)
    smat = read(scatds_Test);
    Xtest = cat(2,Xtest,smat);
    
end

Примените преобразование рассеяния к обучающим и тестовым наборам. Переместите наборы обучения и тестовых данных на графический процессор с помощью gpuArray. Использование gpuArray графический процессор NVIDIA с поддержкой CUDA обеспечивает значительное ускорение. С помощью этой сети рассеяния, размера пакета и графический процессор, реализация графический процессор вычисляет функции рассеяния примерно в 15 раз быстрее, чем версия центральный процессор. Если вы не хотите использовать графический процессор, задайте useGPU на false. Можно также чередовать значение useGPU для сравнения графического процессора и центрального процессора эффективности.

useGPU = true;
if useGPU
    Xtrain = gpuArray (Xtrain);
    Штамм = sn.featureMatrix (Xtrain);
    Xtrain = сбор (Xtrain);
    Xtest = gpuArray (Xtest);
    Stest = sn.featureMatrix (Xtest);
    Xtest = собирать (Xtest);
else
    Штамм = sn.featureMatrix (Xtrain);
    Stest = sn.featureMatrix (Xtest);
end

Получите функции рассеяния для обучающих и тестовых наборов.

TrainFeatures = Strain(2:end,:,:);
TrainFeatures = squeeze(mean(TrainFeatures,2))';
TestFeatures = Stest(2:end,:,:);
TestFeatures = squeeze(mean(TestFeatures,2))';

Этот пример использует классификатор машины опорных векторов (SVM) с квадратичным полиномиальным ядром. Подбор модели SVM к функциям рассеяния.

template = templateSVM(...
    'KernelFunction', 'polynomial', ...
    'PolynomialOrder', 2, ...
    'KernelScale', 'auto', ...
    'BoxConstraint', 1, ...
    'Standardize', true);
classificationSVM = fitcecoc(...
    TrainFeatures, ...
    adsTrain.Labels, ...
    'Learners', template, ...
    'Coding', 'onevsone', ...
    'ClassNames', categorical({'0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'}));

Используйте перекрестную валидацию k-fold, чтобы предсказать точность обобщения модели. Разделите набор обучающих данных на пять групп для перекрестной проверки.

partitionedModel = crossval(classificationSVM, 'KFold', 5);
[validationPredictions, validationScores] = kfoldPredict(partitionedModel);
validationAccuracy = (1 - kfoldLoss(partitionedModel, 'LossFun', 'ClassifError'))*100
validationAccuracy = 97.2500

Предполагаемая точность обобщения составляет приблизительно 97%. Теперь используйте модель SVM, чтобы предсказать задержанный набор тестов.

predLabels = predict(classificationSVM,TestFeatures);
testAccuracy = sum(predLabels==adsTest.Labels)/numel(predLabels)*100
testAccuracy = 97

Точность также составляет приблизительно 97% на задержанном тестовом наборе.

Результирующая эффективность модели на тестовом наборе с графиком неточностей. Отображение точности и отзыва для каждого класса с помощью сводных данных по столбцам и строкам. Таблица в нижней части графика неточностей показывает значения точности для каждого класса. Таблица справа от графика неточностей показывает значения отзыва.

figure('Units','normalized','Position',[0.2 0.2 0.5 0.5]);
ccscat = confusionchart(adsTest.Labels,predLabels);
ccscat.Title = 'Wavelet Scattering Classification';
ccscat.ColumnSummary = 'column-normalized';
ccscat.RowSummary = 'row-normalized';

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

reset(ads);
sig1 = helperReadSPData(read(ads));
scat1 = sn.featureMatrix(sig1);
scat1 = mean(scat1(2:end,:),2)';
plab1 = predict(classificationSVM,scat1);

Прочтите следующую запись и спрогнозируйте цифру.

sig2 = helperReadSPData(read(ads));
scat2 = sn.featureMatrix(sig2);
scat2 = mean(scat2(2:end,:),2)';
plab2 = predict(classificationSVM,scat2);
t = 0:1/8000:(8192*1/8000)-1/8000;
plot(t,[sig1 sig2])
grid on
axis tight
legend(char(plab1),char(plab2))
title('Spoken Digit Prediction - GPU')

Приложение

В этом примере используются следующие вспомогательные функции.

helpergenLabels - генерирует метки на основе имен файлов в FSDD.

function Labels = helpergenLabels(ads)
% This function is only for use in Wavelet Toolbox examples. It may be
% changed or removed in a future release.
tmp = cell(numel(ads.Files),1);
expression = "[0-9]+_";
for nf = 1:numel(ads.Files)
    idx = regexp(ads.Files{nf},expression);
    tmp{nf} = ads.Files{nf}(idx);
end
Labels = categorical(tmp);

end

helperReadSPData - гарантирует, что каждая запись разговорных цифр имеет длину 8192 выборки.

function x = helperReadSPData(x)
% This function is only for use Wavelet Toolbox examples. It may change or
% be removed in a future release.
N = numel(x);
if N > 8192
    x = x(1:8192);
elseif N < 8192
    pad = 8192-N;
    prepad = floor(pad/2);
    postpad = ceil(pad/2);
    x = [zeros(prepad,1) ; x ; zeros(postpad,1)];
end
x = single(x./max(abs(x)));

end

См. также

Похожие темы