Ускорьте аудио глубокое обучение Используя основанное на графическом процессоре извлечение признаков

В этом примере вы усиливаете графические процессоры для извлечения признаков и увеличения, чтобы уменьшить время, требуемое обучать модель глубокого обучения. Модель, которую вы обучаете, является сверточной нейронной сетью (CNN) для акустического распознавания отказа.

Audio Toolbox™ включает gpuArray (Parallel Computing Toolbox) поддержка большинства экстракторов функции, включая популярные единицы, такие как melSpectrogram и mfcc. Для обзора поддержки графического процессора смотрите Поддержка графического процессора и Генерация кода.

Загрузите обучающие данные

Загрузите и разархивируйте воздушный набор данных компрессора [1]. Этот набор данных состоит из записей от воздушных компрессоров в здоровом состоянии или одном из семи дефектных состояний.

url = 'https://www.mathworks.com/supportfiles/audio/AirCompressorDataset/AirCompressorDataset.zip';
downloadFolder = fullfile(tempdir,'AirCompressorDataset');
datasetLocation = tempdir;

if ~isfolder(fullfile(datasetLocation,'AirCompressorDataset'))
    loc = websave(downloadFolder,url);
    unzip(loc,fullfile(datasetLocation,'AirCompressorDataset'))
end

Создайте audioDatastore объект управлять данными и разделить его в наборы обучения и валидации.

ads = audioDatastore(downloadFolder,'IncludeSubfolders',true,'LabelSource','foldernames');
rng default
[adsTrain,adsValidation] = splitEachLabel(ads,0.8);

Визуализируйте количество файлов в наборах обучения и валидации.

uniqueLabels = unique(adsTrain.Labels);
tblTrain = countEachLabel(adsTrain);
tblValidation = countEachLabel(adsValidation);
H = bar(uniqueLabels,[tblTrain.Count, tblValidation.Count],'stacked');
legend(H,["Training Set","Validation Set"],'Location','NorthEastOutside')

Выберите случайные примеры из набора обучающих данных для графического вывода. Каждая запись имеет 50 000 выборок, произведенных на уровне 16 кГц.

t = (0:5e4-1)/16e3;
tiledlayout(4,2,'TileSpacing','compact','Padding','compact')
for n = 1:numel(uniqueLabels)
    idx = find(adsTrain.Labels==uniqueLabels(n));
    [x,fs] = audioread(adsTrain.Files{idx(randperm(numel(idx),1))});

    nexttile
    plotHandle = plot(t,x);
    if n == 7 || n == 8
        xlabel('Seconds');
    else
        set(gca,'xtick',[])
    end
    title(string(uniqueLabels(n)));
end

Предварительно обработайте данные по центральному процессору и графическому процессору

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

Создайте audioFeatureExtractor возразите, чтобы извлечь mel спектры с помощью 200 мс mel окна с транзитным участком на 5 мс. Выход от extract numHops- 128 1 массивом.

afe = audioFeatureExtractor('SampleRate',fs, ...
    'FFTLength',4096, ...
    'Window',hann(round(fs*0.2),'periodic'), ...
    'OverlapLength',round(fs*0.195), ...
    'melSpectrum',true);
setExtractorParams(afe,"melSpectrum",'NumBands',128);

featureVector = extract(afe,x);
[numHops,numFeatures,numChannels] = size(featureVector)
numHops = 586
numFeatures = 128
numChannels = 1

Методы глубокого обучения голодны данных, и обучающий набор данных в этом примере относительно мал. Используйте путаницу [2] метод увеличения, чтобы эффективно увеличить набор обучающих данных. В путанице вы объединяете функции, извлеченные из двух звуковых сигналов как взвешенная сумма. Два сигнала имеют различные метки, и метка, присвоенная объединенной матрице функции, вероятностно присвоена на основе смесительного коэффициента. Увеличение путаницы реализовано в объекте поддержки, Mixup.

Создайте трубопровод, чтобы выполнить следующие шаги:

  1. Извлеките логарифмическую-mel спектрограмму.

  2. Примените путаницу к матрицам функции. Mixup поддержка объектных выходных параметров массив ячеек, содержащий функции и метку.

Создайте две версии трубопровода для сравнения: тот, который выполняет трубопровод на вашем центральном процессоре и тот, который преобразует необработанный звуковой сигнал в gpuArray так, чтобы трубопровод был выполнен на вашем графическом процессоре.

offset = eps;

adsTrainCPU = transform(adsTrain,@(x)log10(extract(afe,x)+offset));
mixerCPU = Mixup(adsTrainCPU);
adsTrainCPU = transform(adsTrainCPU,@(x,info)mix(mixerCPU,x,info),'IncludeInfo',true);

adsTrainGPU = transform(adsTrain,@gpuArray);
adsTrainGPU = transform(adsTrainGPU,@(x)log10(extract(afe,x)+offset));
mixerGPU = Mixup(adsTrainGPU);
adsTrainGPU = transform(adsTrainGPU,@(x,info)mix(mixerGPU,x,info),'IncludeInfo',true);

Для набора валидации примените трубопровод извлечения признаков, но не увеличение. Поскольку вы не применяете путаницу, создаете объединенный datastore, чтобы вывести массив ячеек, содержащий функции и метку. Снова, создайте один трубопровод валидации, который выполняется на вашем графическом процессоре и одном трубопроводе валидации, который выполняется на вашем центральном процессоре.

adsValidationGPU = transform(adsValidation,@gpuArray);
adsValidationGPU = transform(adsValidationGPU,@(x){log10(extract(afe,x)+offset)});
adsValidationGPU = combine(adsValidationGPU,arrayDatastore(adsValidation.Labels));

adsValidationCPU = transform(adsValidation,@(x){log10(extract(afe,x)+offset)});
adsValidationCPU = combine(adsValidationCPU,arrayDatastore(adsValidation.Labels));

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

tic
for ii = 1:numel(adsTrain.Files)
    x = read(adsTrainCPU);
end
cpuPipeline = toc;
reset(adsTrainCPU)

tic
for ii = 1:numel(adsTrain.Files)
    x = read(adsTrainGPU);
end
wait(gpuDevice) % Ensure all calculations are completed
gpuPipeline = toc;
reset(adsTrainGPU)

fprintf(['Read, extract, and augment train set (CPU): %0.2f seconds\n' ...
    'Read, extract, and augment train set (GPU): %0.2f seconds\n' ...
    'Speedup (CPU time)/(GPU time): %0.3f\n\n'], ...
    cpuPipeline,gpuPipeline,cpuPipeline/gpuPipeline)
Read, extract, and augment train set (CPU): 110.80 seconds
Read, extract, and augment train set (GPU): 34.65 seconds
Speedup (CPU time)/(GPU time): 3.198

Чтение от datastore вносит существенное количество полного времени к трубопроводу. Сравнение только экстракции и увеличения показывает еще большее ускорение. Сравните только извлечение признаков на графическом процессоре по сравнению с на центральном процессоре.

x = read(ads);

extract(afe,x); % Incur initialization cost outside timing loop
tic
for ii = 1:numel(adsTrain.Files)
    features = log10(extract(afe,x)+offset);
end
cpuFeatureExtraction = toc;

x = gpuArray(x); % Incur initialization cost outside timing loop
extract(afe,x);
tic
for ii = 1:numel(adsTrain.Files)
    features = log10(extract(afe,x)+offset);
end
wait(gpuDevice) % Ensure all calculations are completed
gpuFeatureExtraction = toc;

fprintf(['Extract features from train set (CPU): %0.2f seconds\n' ...
    'Extract features from train set (GPU): %0.2f seconds\n' ...
    'Speedup (CPU time)/(GPU time): %0.3f\n\n'], ...
    cpuFeatureExtraction,gpuFeatureExtraction,cpuFeatureExtraction/gpuFeatureExtraction)
Extract features from train set (CPU): 50.57 seconds
Extract features from train set (GPU): 4.48 seconds
Speedup (CPU time)/(GPU time): 11.299

Сеть Define

Задайте сверточную нейронную сеть, которая берет увеличенную mel спектрограмму, как введено. Эта сеть применяет один сверточный слой, состоящий из 48 фильтров с 3х3 ядрами, сопровождаемыми слоем нормализации партии. и слоем активации ReLU. Измерение времени затем сворачивается с помощью макс. слоя объединения. Наконец, выход слоя объединения сокращен с помощью полносвязного слоя, сопровождаемого слоями классификации и softmax. Смотрите Список слоев глубокого обучения (Deep Learning Toolbox) для получения дополнительной информации.

numClasses = numel(categories(adsTrain.Labels));
imageSize = [numHops,afe.FeatureVectorLength];

layers = [
    imageInputLayer(imageSize,'Normalization','none')

    convolution2dLayer(3,48,'Padding','same')
    batchNormalizationLayer
    reluLayer

    maxPooling2dLayer([numHops,1])

    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer('Classes',categories(adsTrain.Labels));
    ];

Чтобы задать опции обучения, используйте trainingOptions (Deep Learning Toolbox). Установите ExecutionEnvironment к multi-gpu усиливать несколько графических процессоров, при наличии. В противном случае можно установить ExecutionEnvironment к gpu. Компьютер, используемый в этом примере, имеет доступ к четырем Титанам V устройств графического процессора. В этом примере сетевое обучение всегда усиливает графические процессоры.

miniBatchSize = 128;
options = trainingOptions('adam', ...
    'Shuffle','every-epoch', ...
    'MaxEpochs',40, ...
    'LearnRateSchedule',"piecewise", ...
    'LearnRateDropPeriod',15, ...
    'LearnRateDropFactor',0.2, ...
    'MiniBatchSize',miniBatchSize, ...
    'Plots','training-progress', ...
    'Verbose',false, ...
    'ValidationData',adsValidationCPU, ...
    'ValidationFrequency',ceil(numel(adsTrain.Files)/miniBatchSize), ...
    'ExecutionEnvironment','multi-gpu');

Обучение сети

Обучите сеть Используя основанную на центральном процессоре предварительную обработку

Вызовите trainNetwork (Deep Learning Toolbox), чтобы обучить сеть с помощью центрального процессора для трубопровода извлечения признаков. Средой выполнения для сетевого обучения является ваш графический процессор (процессоры).

tic
net = trainNetwork(adsTrainCPU,layers,options);

cpuTrainTime = toc;

Обучите сеть Используя основанную на графическом процессоре предварительную обработку

Замените данные о валидации в опциях обучения с основанным на графическом процессоре трубопроводом. Обучите сеть с помощью графического процессора (процессоров) для трубопровода извлечения признаков. Средой выполнения для сетевого обучения является ваш графический процессор (процессоры).

options.ValidationData = adsValidationGPU;
tic
net = trainNetwork(adsTrainGPU,layers,options);

gpuTrainTime = toc;

Сравните центральный процессор - и основанная на графическом процессоре предварительная обработка

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

fprintf(['Training time (CPU): %0.2f seconds\n' ...
    'Training time (GPU): %0.2f seconds\n' ...
    'Speedup (CPU time)/(GPU time): %0.3f\n\n'], ...
    cpuTrainTime,gpuTrainTime,cpuTrainTime/gpuTrainTime)
Training time (CPU): 4242.82 seconds
Training time (GPU): 731.77 seconds
Speedup (CPU time)/(GPU time): 5.798

Сравните эффективность вывода центрального процессора и графического процессора

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

signalToClassify = read(ads);

gpuFeatureExtraction = gputimeit(@()predict(net,log10(extract(afe,gpuArray(signalToClassify))+offset)));
cpuFeatureExtraction = gputimeit(@()predict(net,log10(extract(afe,(signalToClassify))+offset)));

fprintf(['Prediction time for 3 s of data (feature extraction on CPU): %0.2f ms\n' ...
    'Prediction time for 3 s of data (feature extraction on GPU): %0.2f ms\n' ...
    'Speedup (CPU time)/(GPU time): %0.3f\n\n'], ...
    cpuFeatureExtraction*1e3,gpuFeatureExtraction*1e3,cpuFeatureExtraction/gpuFeatureExtraction)
Prediction time for 3 s of data (feature extraction on CPU): 41.62 ms
Prediction time for 3 s of data (feature extraction on GPU): 7.71 ms
Speedup (CPU time)/(GPU time): 5.397

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

adsValidationGPU = transform(adsValidation,@(x)gpuArray(x));
adsValidationGPU = transform(adsValidationGPU,@(x){log10(extract(afe,x)+offset)});
adsValidationCPU = transform(adsValidation,@(x){log10(extract(afe,x)+offset)});

gpuFeatureExtraction = gputimeit(@()predict(net,adsValidationGPU,'ExecutionEnvironment','multi-gpu'));
cpuFeatureExtraction = gputimeit(@()predict(net,adsValidationCPU,'ExecutionEnvironment','multi-gpu'));

fprintf(['Prediction time for validation set (feature extraction on CPU): %0.2f s\n' ...
    'Prediction time for validation set (feature extraction on GPU): %0.2f s\n' ...
    'Speedup (CPU time)/(GPU time): %0.3f\n\n'], ...
    cpuFeatureExtraction,gpuFeatureExtraction,cpuFeatureExtraction/gpuFeatureExtraction)
Prediction time for validation set (feature extraction on CPU): 34.11 s
Prediction time for validation set (feature extraction on GPU): 5.53 s
Speedup (CPU time)/(GPU time): 6.173

Заключение

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

Вспомогательные Функции

Путаница

Объект поддержки, Mixup, помещается в вашу текущую папку, когда вы открываете этот пример.

type Mixup
classdef Mixup < handle
    %MIXUP Mixup data augmentation
    %   mixer = Mixup(augDatastore) creates an object that can mix features
    %   at a randomly set ratio and then probabilistically set the output
    %   label as one of the two original signals.
    %
    %   Mixup Properties:
    %   MixProbability - Mix probability
    %   AugDatastore   - Augmentation datastore
    %
    %   Mixup Methods:
    %   mix            - Apply mixup
    %

    % Copyright 2021 The MathWorks, Inc.

    properties (SetAccess=public,GetAccess=public)
        %MixProbability Mix probability
        % Specify the probability that mixing is applied as a scalar in the
        % range [0,1]. If unspecified, MixProbability defaults to 1/3.
        MixProbability (1,1) {mustBeNumeric} = 1/3;
    end
    properties (SetAccess=immutable,GetAccess=public)
        %AUGDATASTORE Augmentation datastore
        % Specify a datastore from which to get the mixing signals. The
        % datastore must contain a label in the info returned from reading.
        % This property is immutable, meaning it cannot be changed after
        % construction.
        AugDatastore
    end

    methods
        function obj = Mixup(augDatastore)
            obj.AugDatastore = augDatastore;
        end

        function [dataOut,infoOut] = mix(obj,x,infoIn)
            %MIX Apply mixup
            % [dataOut,infoOut] = mix(mixer,x,infoIn) probabilistically mix
            % the input, x, and its associated label contained in infoIn
            % with a signal randomly drawn from the augmentation datastore.
            % The output, dataOut, is a cell array with two columns. The
            % first column contains the features and the second column
            % contains the label.

            if rand > obj.MixProbability % Only mix ~1/3 the dataset

                % Randomly set mixing coefficient. Draw from a normal
                % distribution with mean 0.5 and contained within [0,1].
                lambda = max(min((randn./10)+0.5,1),0);

                % Read one file from the augmentation datastore.
                subDS = subset(obj.AugDatastore,randi([1,numel(obj.AugDatastore.UnderlyingDatastores{1}.Files)]));
                [y,yInfo] = read(subDS);

                % Mix the features element-by-element according to lambda.
                dataOut = lambda*x + (1-lambda)*y;

                % Set the output label probabilistically based on the mixing coefficient.
                if lambda < rand
                    labelOut = yInfo.Label;
                    infoOut.Label = labelOut;
                else
                    labelOut = infoIn.Label;
                end
                infoOut.Label = labelOut;

                % Combine the output data and labels.
                dataOut = [{dataOut},{labelOut}];

            else % Do not apply mixing

                dataOut = [{x},{infoIn.Label}];
                infoOut = infoIn;

            end
        end

    end
end

Ссылки

[1] Verma, Нищел К., и др. "Интеллектуальный основанный на условии Контроль Используя Акустические Сигналы для Воздушных Компрессоров". Транзакции IEEE на Надежности, издании 65, № 1, март 2016, стр 291–309. DOI.org (Crossref), doi:10.1109/TR.2015.2459684.

[2] Huszar, Ференц. "Путаница: информационно-зависимое Увеличение Данных". InFERENCe. 03 ноября 2017. Полученный доступ 15 января 2019. https://www.inference.vc/mixup-data-dependent-data-augmentation/.