В этом примере показано, как ускорить вычисление признаков вейвлет-рассеяния с помощью 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