В этом примере показано, как можно ускорить scalogram расчет с помощью графических процессоров. Вычисленные scalograms используются в качестве входных функций к глубоким нейронным сетям свертки (CNN) для ECG и разговорной классификации цифр.
Используя графический процессор требует Parallel Computing Toolbox™. Чтобы видеть, который поддерживаются графические процессоры, смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox). Аудио раздел этого примера требует, чтобы Audio Toolbox™ использовал аудио datastore и преобразованный datastore.
Самый эффективный способ вычислить scalograms на графическом процессоре состоит в том, чтобы использовать cwtfilterbank
. Шаги, чтобы вычислить scalograms на графическом процессоре:
Создайте cwtfilterbank
с желаемыми настройками свойства.
Переместите сигнал в графический процессор с помощью gpuArray
.
Используйте набор фильтров WT
метод, чтобы вычислить непрерывный вейвлет преобразовывает (CWT).
В первый раз вы используете WT
метод, cwtfilterbank
кэширует фильтры вейвлета на графическом процессоре. В результате существенная экономия времени в расчете понята, когда вы получаете scalograms нескольких сигналов с помощью того же набора фильтров и того же типа данных. Следующее демонстрирует рекомендуемый рабочий процесс. Как пример, используйте выборку музыки гитары, содержащей 661 500 выборок.
[y,fs] = audioread('guitartune.wav'); plot(y) grid on
Поскольку большая часть NVIDIA, графические процессоры значительно более эффективны с одними а не данными с двойной точностью, бросает сигнал к одинарной точности.
y = single(y);
Создайте набор фильтров, чтобы совпадать с длиной сигнала и частотой дискретизации. Для глубокого обучения частота дискретизации обычно не необходима и поэтому может быть исключена.
fb = cwtfilterbank('SignalLength',length(y),'SamplingFrequency',fs);
Наконец переместите сигнал в графический процессор с помощью gpuArray
и вычислите CWT данных. Постройте получившийся scalogram.
[cfs,f] = fb.wt(gpuArray(y)); t = 0:1/fs:(length(y)*1/fs)-1/fs; imagesc(t,f,abs(cfs)) axis xy ylabel('Hz') xlabel('Seconds')
Используйте gather
принести коэффициенты CWT и любые другие выходные параметры назад к центральному процессору.
cfs = gather(cfs); f = gather(f);
Продемонстрировать КПД, полученный в использовании графического процессора, время расчет CWT на графическом процессоре и центральном процессоре для того же сигнала. Графический процессор вычисляет времена, о которых сообщают, здесь получены с помощью Титана NVIDIA V с вычислить возможностью 7,0.
ygpu = gpuArray(y); fgpu = @()fb.wt(ygpu); Tgpu = gputimeit(fgpu)
Tgpu = 0.2658
Повторите то же измерение на центральном процессоре и исследуйте отношение графического процессора к процессорному времени, чтобы видеть сокращение во время вычисления.
fcpu = @()fb.wt(y); Tcpu = timeit(fcpu)
Tcpu = 3.7088
Tcpu/Tgpu
ans = 13.9533
Распространенное приложение CWT в глубоком обучении должно использовать scalogram сигнала как вход "изображение" к глубокому CNN. Это обязательно передает под мандат расчет нескольких scalograms, один для каждого сигнала в обучении, валидации и наборах тестов. В то время как графические процессоры часто используются, чтобы ускорить обучение и вывод в глубокой сети, это также выгодно, чтобы использовать графические процессоры, чтобы ускорить любое извлечение признаков, или предварительная обработка данных должна была сделать глубокую сеть более устойчивой.
Чтобы проиллюстрировать это, следующий раздел применяет вейвлет scalograms к человеческой электрокардиограмме (ECG) классификация. Scalograms используются с теми же данными, обработанными в, Классифицируют Временные ряды Используя Анализ Вейвлета и Глубокое обучение. В том примере передача обучения с GoogLeNet и SqueezeNet использовалась, чтобы классифицировать формы волны ECG в одну из трех категорий. Описание данных и как получить, это повторяется здесь для удобства.
Данные о ECG получены из трех групп людей: люди с сердечной аритмией (ARR), люди с застойной сердечной недостаточностью (CHF) и люди с нормальными ритмами пазухи (NSR). Всего от трех Физиосетевых баз данных существует 162 записи ECG: База данных Аритмии MIT-BIH [2] [3], MIT-BIH Нормальная База данных Ритма Пазухи [3] и База данных Застойной сердечной недостаточности BIDMC [1] [3]. А именно, 96 записей от людей с аритмией, 30 записей от людей с застойной сердечной недостаточностью и 36 записей от людей с нормальными ритмами пазухи. Цель состоит в том, чтобы обучить модель различать ARR, швейцарский франк и NSR.
Можно получить эти данные из репозитория MathWorks GitHub. Чтобы загрузить данные из веб-сайта, нажмите Code
и выберите Download ZIP
. Сохраните файл physionet_ECG_data-main.zip
в папке, где у вас есть разрешение записи. Инструкции для этого примера принимают, что вы загрузили файл на свою временную директорию, tempdir
, в MATLAB. Измените последующие инструкции для того, чтобы разархивировать и загрузить данные, если вы принимаете решение загрузить данные в папке, отличающейся от tempdir
.
После загрузки данных GitHub разархивируйте файл в своей временной директории.
unzip(fullfile(tempdir,'physionet_ECG_data-main.zip'),tempdir)
Разархивация создает папку physionet-ECG_data-main
в вашей временной директории. Эта папка содержит текстовый файл README.md
и ECGData.zip
. ECGData.zip
файл содержит
ECGData.mat
Modified_physionet_data.txt
License.txt
ECGData.mat
содержит данные, используемые в этом примере. Текстовый файл, Modified_physionet_data.txt
, требуется копированием PhysioNet политики и обеспечивает исходные приписывания для данных, а также описание шагов предварительной обработки применилось к каждой записи ECG.
Разархивируйте ECGData.zip
в physionet-ECG_data-main
. Загрузите файл данных в свое рабочее пространство MATLAB.
unzip(fullfile(tempdir,'physionet_ECG_data-main','ECGData.zip'),... fullfile(tempdir,'physionet_ECG_data-main')) load(fullfile(tempdir,'physionet_ECG_data-main','ECGData.mat'))
ECGData
массив структур с двумя полями: Data
и Labels
. Data
поле 162 65536 матрица, где каждая строка является записью ECG, произведенной на уровне 128 герц. Labels
162 1 массив ячеек диагностических меток, один для каждой строки Data
. Три диагностических категории: 'ARR'
, 'CHF'
, и 'NSR'
. Используйте функцию помощника, helperRandomSplit
, разделять данные в обучение и валидацию устанавливает с 80% данных, выделенных для обучения и 20% для валидации. Преобразуйте метки диагностики ECG в categoricals.
[trainData, validationData, trainLabels, validationLabels] = helperRandomSplit(80,ECGData); trainLabels = categorical(trainLabels); validationLabels = categorical(validationLabels);
В trainData
существует 130 записей установите и 32 записи в validation
Data
. Проектом обучающие данные содержат 80,25% (130/162) данных. Вспомните, что класс ARR представляет 59,26% данных (96/162), класс швейцарского франка представляет 18,52% (30/162), и класс NSR представляет 22,22% (36/162). Исследуйте процент каждого класса в наборах обучающих данных и наборах тестов. Проценты в каждом сопоставимы с полными процентами класса в наборе данных.
Ctrain = countcats(trainLabels)./numel(trainLabels).*100
Ctrain = 3×1
59.2308
18.4615
22.3077
Cvalid = countcats(validationLabels)./numel(validationLabels).*100
Cvalid = 3×1
59.3750
18.7500
21.8750
Вычислите scalograms и для наборов обучения и для валидации. Установите useGPU
к true
использовать графический процессор и false
вычислить scalograms на центральном процессоре. Смягчить последствие больших входных матриц на CNN и создать больше примеров обучения и валидации, helperECGScalograms
разделения каждая форма волны ECG в четыре неперекрывающихся сегмента 16 384 выборок каждый и вычисляют scalograms для всех четырех сегментов. Реплицируйте метки, чтобы совпадать с расширенным набором данных. В этом случае получите оценку израсходованного времени вычисления.
frameLength = 16384; useGPU = true; tic; Xtrain = helperECGScalograms(trainData,frameLength,useGPU);
Computing scalograms... Processed 50 files out of 130 Processed 100 files out of 130 ...done
T = toc;
sprintf('Elapsed time is %1.2f seconds',T)
ans = 'Elapsed time is 4.22 seconds'
trainLabels = repelem(trainLabels,4);
С Титаном V графических процессоров 502 scalograms были вычислены приблизительно за 4,2 секунды. Установка useGPU
к false
и повторение вышеупомянутого расчета демонстрирует скорость, полученную при помощи графического процессора. В этом случае использование центрального процессора потребовало, чтобы 33,3 секунды вычислили scalograms. Расчет графического процессора был больше чем в 7 раз быстрее.
Повторите тот же процесс для данных о валидации.
useGPU = true; Xvalid = helperECGScalograms(validationData,frameLength,useGPU);
Computing scalograms... ...done
validationLabels = repelem(validationLabels,4);
Затем настройте глубокий CNN, чтобы обработать и наборы обучения и валидации. Простая сеть, используемая здесь, не оптимизирована. Этот CNN только используется, чтобы проиллюстрировать сквозной рабочий процесс для случаев, где scalograms умещаются в памяти.
sz = size(Xtrain); specSize = sz(1:2); imageSize = [specSize 1]; dropoutProb = 0.3; layers = [ imageInputLayer(imageSize) convolution2dLayer(3,12,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) convolution2dLayer(3,20,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(2,'Stride',2) convolution2dLayer(3,32,'Padding','same') batchNormalizationLayer reluLayer dropoutLayer(dropoutProb) fullyConnectedLayer(3) softmaxLayer classificationLayer];
Используйте следующие опции обучения.
options = trainingOptions('sgdm',... 'InitialLearnRate', 1e-4,... 'LearnRateDropPeriod',18,... 'MiniBatchSize', 20,... 'MaxEpochs',25,... 'L2Regularization',1e-1,... 'Plots', 'training-progress',... 'Verbose',false,... 'Shuffle','every-epoch',... 'ExecutionEnvironment','auto',... 'ValidationData',{Xvalid,validationLabels});
Обучите сеть и измерьте ошибку валидации.
trainNetwork(Xtrain,trainLabels,layers,options);
Даже при том, что простой CNN, используемый здесь, не оптимизирован, точность валидации последовательно находится в высоких 80 к низкой 90-процентной области значений. Это сопоставимо с точностью валидации, достигнутой с более мощным и оптимизированным SqueezeNet, показанным в, Классифицируют Временные ряды Используя пример Анализа и Глубокого обучения Вейвлета. Далее, это - намного более эффективное использование scalogram, потому что в том примере scalograms должен был быть перемасштабирован, когда RGB отображает совместимый с SqueezeNet, сохраненным на диск в соответствующем формате изображения, и затем питаемым глубокую сеть с помощью imageDatastore
.
Этот раздел показывает, как ускорить scalogram расчет с помощью графического процессора в преобразованном рабочем процессе datastore.
Клонируйте или загрузите Свободный разговорный набор данных цифры (FSDD), доступный в https://github.com/Jakobovski/free-spoken-digit-dataset. FSDD является открытым набором данных, что означает, что это может расти в зависимости от времени. Этот пример использует версию, фиксировавшую 01/29/2019, который состоит из 2 000 записей английских цифр 0 через 9 полученных от четырех докладчиков. Два из докладчиков в этой версии являются носителями американского варианта английского языка, и два докладчика являются ненативными докладчиками английского языка с французским Бельгии и немецким диакритическим знаком. Данные производятся на уровне 8 000 Гц.
Для других подходов к этому набору данных включая рассеивание вейвлета смотрите Разговорное Распознавание Цифры с Рассеиванием Вейвлета и Глубоким обучением.
Используйте audioDatastore
управлять доступом к данным и гарантировать случайное деление записей в наборы обучающих данных и наборы тестов. Установите location
свойство к местоположению папки записей FSDD на вашем компьютере, например:
pathToRecordingsFolder = '/home/user/free-spoken-digit-dataset/recordings';
location = pathToRecordingsFolder;
Укажите audioDatastore
к тому местоположению.
ads = audioDatastore(location);
Функция помощника helpergenLabels
создает категориальный массив меток из файлов FSDD. Перечислите классы и количество примеров в каждом классе.
ads.Labels = helpergenLabels(ads); summary(ads.Labels)
0 200 1 200 2 200 3 200 4 200 5 200 6 200 7 200 8 200 9 200
Сначала разделите FSDD в наборы обучающих данных и наборы тестов. Выделите 80% данных к набору обучающих данных и сохраните 20% для набора тестов.
rng default;
ads = shuffle(ads);
[adsTrain,adsTest] = splitEachLabel(ads,0.8);
countEachLabel(adsTrain)
ans=10×2 table
Label Count
_____ _____
0 160
1 160
2 160
3 160
4 160
5 160
6 160
7 160
8 160
9 160
Затем создайте набор фильтров CWT и преобразованные хранилища данных и для обучения и для тестовых данных с помощью функции помощника, helperDigitScalogram
. Преобразованный datastore преобразует каждую запись в сигнал длины 8192, вычисляет scalogram на графическом процессоре и собирает данные назад на центральный процессор.
reset(gpuDevice(1)) fb = cwtfilterbank('SignalLength',8192); adsSCTrain = transform(adsTrain,@(audio,info)helperDigitScalogram(audio,info,fb),'IncludeInfo',true); adsSCTest = transform(adsTest,@(audio,info)helperDigitScalogram(audio,info,fb),'IncludeInfo',true);
Создайте глубокий CNN, чтобы обучаться с преобразованным datastore, adscTrain
. Как в первом примере, не оптимизирована сеть. Точка должна показать рабочий процесс с помощью scalograms вычисленный на графическом процессоре для данных, которые не помещаются в память.
numClasses = 10; dropoutProb = 0.2; numF = 12; layers = [ imageInputLayer([101 8192 1]) convolution2dLayer(5,numF,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(3,'Stride',2,'Padding','same') convolution2dLayer(3,2*numF,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(3,'Stride',2,'Padding','same') convolution2dLayer(3,4*numF,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(3,'Stride',2,'Padding','same') convolution2dLayer(3,4*numF,'Padding','same') batchNormalizationLayer reluLayer convolution2dLayer(3,4*numF,'Padding','same') batchNormalizationLayer reluLayer maxPooling2dLayer(2) dropoutLayer(dropoutProb) fullyConnectedLayer(numClasses) softmaxLayer classificationLayer('Classes',categories(ads.Labels)); ];
Установите опции обучения для сети.
miniBatchSize = 25; options = trainingOptions('adam', ... 'InitialLearnRate',1e-4, ... 'MaxEpochs',30, ... 'MiniBatchSize',miniBatchSize, ... 'Shuffle','every-epoch', ... 'Plots', 'training-progress',... 'Verbose',false,... 'ExecutionEnvironment','gpu');
Обучите сеть.
trainedNet = trainNetwork(adsSCTrain,layers,options);
В этом экземпляре обучение было завершено за 25 минут и 10 секунд. Если вы комментируете вызов gpuArray
in helperDigitScalogram
и используйте центральный процессор, чтобы получить scalograms, учебное время значительно увеличивается. В этом случае увеличение с 25 минут и 10 секунд к 45 минутам и 38 секунд наблюдалось.
Используйте обучивший сеть, чтобы предсказать метки цифры для набора тестов.
Ypredicted = classify(trainedNet,adsSCTest,'ExecutionEnvironment','CPU'); cnnAccuracy = sum(Ypredicted == adsTest.Labels)/numel(Ypredicted)*100
cnnAccuracy = 96.2500
Время вывода с помощью графического процессора составляло приблизительно 22 секунды. Используя центральный процессор, заключите время, удвоенное до 45 секунд.
Эффективность обучивших сеть на тестовых данных близко к 96%. Это сопоставимо с эффективностью в Разговорном Распознавании Цифры с Рассеиванием Вейвлета и Глубоким обучением.
Этот пример продемонстрировал, как использовать графический процессор, чтобы ускорить scalogram расчет. Пример представил оптимальный рабочий процесс для того, чтобы эффективно вычислить scalograms и для данных в оперативной памяти и для данных, которые не помещаются в память, считанных из диска с помощью преобразованных хранилищ данных.
Baim, D. S. В. С. Колуччи, Э. С. Монрэд, Х. С. Смит, Р. Ф. Райт, А. Лэноу, Д. Ф. Готье, Б. Дж. Рэнсил, В. Гроссман и Э. Бронвалд. "Выживание пациентов с тяжелой застойной сердечной недостаточностью отнеслось с устным milrinone". Журнал американского Колледжа Кардиологии. Издание 7, Номер 3, 1986, стр 661–670.
Голдбергер А. Л., Л. А. Н. Амарал, L. Стекло, Дж. М. Гаусдорф, P. Ch. Иванов, Р. Г. Марк, Дж. Э. Митус, Г. Б. Муди, C.-K. Пенг и Х. Э. Стэнли. "PhysioBank, PhysioToolkit и PhysioNet: Компоненты Нового Ресурса Исследования для Комплексных Физиологических Сигналов". Циркуляция. Издание 101, Номер 23: e215–e220. [Циркуляция Электронные Страницы; http://circ.ahajournals.org/content/101/23/e215.full
]; 2000 (13 июня). doi: 10.1161/01. CIR.101.23.e215.
Капризный, G. B. и Р. Г. Марк. "Удар Базы данных Аритмии MIT-BIH". Разработка IEEE в Журнале Медицины и Биологии. Издание 20. Номер 3, мочь-июнь 2001, стр 45–50. (PMID: 11446209)
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
function X = helperECGScalograms(data,window,useGPU) disp("Computing scalograms..."); Nsig = size(data,1); Nsamp = size(data,2); Nsegment = Nsamp/window; fb = cwtfilterbank('SignalLength',window,'Voices',10); Ns = length(fb.Scales); X = zeros([Ns,window,1,Nsig*Nsegment],'single'); start = 0; if useGPU data = gpuArray(single(data')); else data = single(data'); end for ii = 1:Nsig ts = data(:,ii); ts = reshape(ts,window,Nsegment); ts = (ts-mean(ts))./max(abs(ts)); for kk = 1:size(ts,2) cfs = fb.wt(ts(:,kk)); X(:,:,1,kk+start) = gather(abs(cfs)); end start = start+Nsegment; if mod(ii,50) == 0 disp("Processed " + ii + " files out of " + Nsig) end end disp("...done"); data = gather(data); end
function [x,info] = helperReadSPData(x,info) % 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 = x./max(abs(x)); end
function [dataout,info] = helperDigitScalogram(audioin,info,fb) audioin = single(audioin); audioin = gpuArray(audioin); audioin = helperReadSPData(audioin); cfs = gather(abs(fb.wt(audioin))); audioin = gather(audioin); dataout = {cfs,info.Label}; end