主要内容

使用基于gpu的特征提取加速音频深度学习

在这个例子中,你利用gpu进行特征提取和增强,以减少训练深度学习模型所需的时间。你训练的模型是一个用于声学故障识别的卷积神经网络(CNN)。

音频工具箱™包括gpuArray(并行计算工具箱)支持大多数特征提取器,包括流行的,如melSpectrogram(音频工具箱)mfcc(音频工具箱)。关于GPU支持的概述,请参见代码生成和GPU支持(音频工具箱)

负荷训练数据

下载并解压空压机数据集[1]。该数据集由空气压缩机在健康状态或七个故障状态之一的记录组成。

downloadFolder = matlab.internal.examples.downloadSupportFile (“音频”,“AirCompressorDataset / AirCompressorDataset.zip”);dataFolder = tempdir;unzip(downloadFolder,dataFolder) dataset = fullfile(dataFolder,“AirCompressorDataset”);

创建一个audioDatastore(音频工具箱)对象来管理数据,并将其划分为训练集和验证集。

广告= audioDatastore(数据集,IncludeSubfolders = true, LabelSource =“foldernames”);rng默认的[adsTrain, adsValidation] = splitEachLabel(广告,0.8);

可视化训练集和验证集中的文件数量。

uniqueLabels =独特(adsTrain.Labels);tblTrain = countEachLabel (adsTrain);tblValidation = countEachLabel (adsValidation);H =酒吧(uniqueLabels, [tblTrain。计数,tblValidation。数),“堆叠”);传奇(H, [“训练集”,“验证”),位置=“NorthEastOutside”)

从训练集中随机选取样本进行绘图。每段录音都有5万个采样频率为16千赫的样本。

t = (0:5e4-1) / 16 e3;tiledlayout (4,2 TileSpacing =“紧凑”填充=“紧凑”)n = 1:numel(uniqueLabels) idx = find(adsTrain.Labels==uniqueLabels(n));[x, fs] = audioread (adsTrain.Files {idx (randperm(元素个数(idx), 1))});nexttile plotHandle = plot(t,x);如果N == 7 ||“秒”);其他的甘氨胆酸集(xtick = [])结束标题(string (uniqueLabels (n)));结束

CPU和GPU的预处理数据

在本例中,您在训练网络的同时执行特征提取和数据增强。在本节中,您将定义特征提取和增强管道,并将在CPU上执行的管道速度与在GPU上执行的管道速度进行比较。这个管道的输出就是你训练的CNN的输入。

创建一个audioFeatureExtractor(音频工具箱)对象使用200 ms MEL Windows和5 ms跳转提取MEL光谱。的输出提取是一个numHops- 128 - 1阵列。

afe = audioFeatureExtractor (SampleRate = fs,FFTLength = 4096,窗口=损害(圆(fs * 0.2),“周期”),OverlapLength =圆(fs * 0.195),melSpectrum = true);setExtractorParameters (afe“melSpectrum”NumBands = 128);featureVector =提取(afe x);[numHops, numFeatures numChannels] =大小(featureVector)
numHops = 586
numFeatures = 128
numChannels = 1

深度学习方法需要大量数据,本例中的训练数据集相对较小。使用混合[2],有效放大训练集的增强技术在mixup中,你合并从两个音频信号提取的特征作为加权和。这两个信号有不同的标签,分配给合并的特征矩阵的标签是基于混合系数概率分配的。mixup增强在支撑对象中实现,混合

创建管道,执行以下步骤:

  1. 提取log-mel谱图。

  2. 对特征矩阵应用mixup。的混合支持对象输出包含特征和标签的单元格数组。

创建两个版本的管道进行比较:一个在你的CPU上执行管道,一个将原始音频信号转换为gpuArray以便管道在你的GPU上执行。

抵消=每股收益;adsTrainCPU =变换(adsTrain @ (x) log10(提取(afe x) +偏移量));mixerCPU =混合物(adsTrainCPU);adsTrainCPU =变换(adsTrainCPU @ (x,信息)混合(mixerCPU x,信息),IncludeInfo = true);adsTrainGPU =变换(adsTrain @gpuArray);adsTrainGPU =变换(adsTrainGPU @ (x) log10(提取(afe x) +偏移量));mixerGPU =混合物(adsTrainGPU);adsTrainGPU =变换(adsTrainGPU @ (x,信息)混合(mixerGPU x,信息),IncludeInfo = true);

对于验证集,应用特征提取管道,而不是增强。因为您没有应用mixup,所以创建一个组合数据存储来输出包含特征和标签的单元格数组。同样,创建一个在GPU上执行的验证管道和一个在CPU上执行的验证管道。

adsValidationGPU =变换(adsValidation @gpuArray);adsValidationGPU =变换(adsValidationGPU @ (x) {log10(提取(afe x) +偏移量)});adsValidationGPU =结合(adsValidationGPU arrayDatastore (adsValidation.Labels));adsValidationCPU =变换(adsValidation @ (x) {log10(提取(afe x) +偏移量)});adsValidationCPU =结合(adsValidationCPU arrayDatastore (adsValidation.Labels));

比较CPU和单个GPU提取特征和执行数据扩充所需的时间。

抽搐ii = 1:numel(adsTrain.Files) x = read(adsTrainCPU);结束cpuPipeline = toc;重置(adsTrainCPU)抽搐ii = 1:numel(adsTrain.Files) x = read(adsTrainGPU);结束等待(gpuDevice)%确保所有计算都已完成gpuPipeline = toc;重置(adsTrainGPU) disp ([“读取、提取和扩充训练集(CPU):”+ cpuPipeline +“秒”;“读取、提取和扩充列车集(GPU):”+ gpuPipeline +“秒”;“Speedup (CPU时间)/(GPU时间):”+ cpuPipeline / gpuPipeline]);
“读取,提取,并增强训练集(CPU): 117.0887秒”“读取,提取,并增强训练集(GPU): 34.8972秒”“加速(CPU时间)/(GPU时间):3.3552”

从数据存储中读取数据占管道总时间的很大一部分。仅仅是提取和增强的比较显示了更大的加速。对比GPU和CPU上的特征提取。

x =阅读(广告);提取(afe x);%在计时循环之外产生初始化成本抽搐ii = 1:numel(adsTrain.Files) features = log10(extract(afe,x)+offset);结束cpuFeatureExtraction = toc;x = gpuArray (x);%在计时循环之外产生初始化成本提取(afe x);抽搐ii = 1:numel(adsTrain.Files) features = log10(extract(afe,x)+offset);结束等待(gpuDevice)%确保所有计算都已完成gpuFeatureExtraction = toc;disp ([“从训练集(CPU)中提取特征:”+ cpuFeatureExtraction +“秒”;“从训练集(GPU)中提取特征:”+ gpuFeatureExtraction +“秒”;“Speedup (CPU时间)/(GPU时间):”+ cpuFeatureExtraction / gpuFeatureExtraction]);
“从火车集(CPU)中提取特征:52.7254秒”“从火车集(GPU)中提取特征:1.2611秒”“加速(CPU时间)/(GPU时间):41.8096”

定义网络

定义一个以增广mel谱图为输入的卷积神经网络。该网络应用了一个由48个3乘3核滤波器组成的单一卷积层,然后是一个批处理归一化层和一个ReLU激活层。然后使用最大池化层对时间维度进行折叠。最后,使用一个全连接层然后是softmax和分类层来减少池化层的输出。看到深度学习层列表为更多的信息。

numClasses =元素个数(类别(adsTrain.Labels));图象尺寸= [numHops, afe.FeatureVectorLength];layers = [imageInputLayer(imageSize,Normalization= .“没有”现年48岁的)convolution2dLayer(3填充=“相同”) batchNormalizationLayer reluLayer maxPooling2dLayer([numHops,1]) fullyConnectedLayer(numClasses) softmaxLayer classificationLayer(Classes=categories(adsTrain.Labels));];

要定义培训选项,请使用trainingOptions。设置ExecutionEnvironmentmulti-gpu使用多个gpu,如果有的话。否则,您可以设置ExecutionEnvironmentgpu。本例中使用的计算机可以访问四个Titan V GPU设备。在本例中,网络训练始终利用gpu。

miniBatchSize = 128;选择= trainingOptions (“亚当”,洗牌=“every-epoch”,MaxEpochs = 40,LearnRateSchedule =“分段”,LearnRateDropPeriod = 15,LearnRateDropFactor = 0.2,MiniBatchSize = MiniBatchSize,情节=“训练进步”,Verbose = false,ValidationData = adsValidationCPU,ValidationFrequency =装天花板(元素个数(adsTrain.Files) / miniBatchSize),ExecutionEnvironment =“multi-gpu”);

列车网络的

使用基于cpu的预处理训练网络

调用trainNetwork使用你的CPU来训练网络进行特征提取管道。网络训练的执行环境是你的GPU。

tic net = trainNetwork(adsTrainCPU,layers,options);
使用“本地”配置文件启动平行池(parpool)…连接到平行池(工人人数:4)。

cpuTrainTime = toc;

使用基于gpu的预处理训练网络

,将训练选项中的验证数据替换为基于gpu的管道。使用你的GPU(s)为特征提取管道训练网络。网络训练的执行环境是你的GPU。

选项。ValidationData = adsValidationGPU;tic net = trainNetwork(adsTrainGPU,layers,options);

gpuTrainTime = toc;

比较基于CPU和gpu的预处理

打印使用CPU进行特征提取和增强的训练的计时结果,以及使用GPU(s)进行特征提取和增强的训练。

disp (["训练时间(CPU): "+ cpuTrainTime +“秒”;“训练时间(GPU):”+ gpuTrainTime +“秒”;“Speedup (CPU时间)/(GPU时间):”+ cpuTrainTime / gpuTrainTime])
“训练时间(CPU): 4650.3639秒”“训练时间(GPU): 599.1963秒”“Speedup (CPU时间)/(GPU时间):7.761”

比较CPU和GPU Inference Performance

比较在GPU和CPU上进行特征提取时,对单个3秒剪辑进行预测所需的时间。在这两种情况下,网络预测都发生在GPU上。

signalToClassify =阅读(广告);gpuFeatureExtraction = gputimeit(@()预测(净,log10(提取(afe, gpuArray (signalToClassify)) +偏移量)));cpuFeatureExtraction = gputimeit(@()预测(净,log10(提取(afe (signalToClassify)) +偏移量)));disp ([“3秒数据的预测时间(CPU上的特征提取):”e3 + + cpuFeatureExtraction * 1“女士”;“3 s数据的预测时间(GPU上的特征提取):”e3 + + gpuFeatureExtraction * 1“女士”;“Speedup (CPU时间)/(GPU时间):”+ cpuFeatureExtraction / gpuFeatureExtraction])
“3秒数据预测时间(CPU上的特征提取):42.8014 ms”“3秒数据预测时间(GPU上的特征提取):4.0693 ms”“加速(CPU时间)/(GPU时间):10.5182”

比较在GPU(s)和CPU上进行特征提取时,对一组3秒剪辑进行预测所需的时间。在这两种情况下,网络预测都发生在你的GPU上。

adsValidationGPU =变换(adsValidation @ (x) gpuArray (x));adsValidationGPU =变换(adsValidationGPU @ (x) {log10(提取(afe x) +偏移量)});adsValidationCPU =变换(adsValidation @ (x) {log10(提取(afe x) +偏移量)});gpuFeatureExtraction = gputimeit(@()预测(净、adsValidationGPU ExecutionEnvironment =“multi-gpu”));cpuFeatureExtraction = gputimeit(@()预测(净、adsValidationCPU ExecutionEnvironment =“multi-gpu”));disp ([“验证集预测时间(CPU上的特征提取):”+ cpuFeatureExtraction +“秒”;“验证集的预测时间(GPU上的特征提取):”+ gpuFeatureExtraction +“秒”;“Speedup (CPU时间)/(GPU时间):”+ cpuFeatureExtraction / gpuFeatureExtraction])
“验证集预测时间(CPU上特征提取):36.2089秒”“验证集预测时间(GPU上特征提取):4.1345秒”“Speedup (CPU时间)/(GPU时间):8.7578”

结论

众所周知,利用GPU设备可以减少训练网络所需的时间。这使你能够更快速地迭代和开发你的最终系统。在许多训练设置中,你可以通过利用GPU设备进行特征提取和数据增强来获得额外的性能收益。这个例子显示,当利用GPU设备进行特征提取和数据增强时,训练CNN所需的总时间显著减少。此外,在推理时利用GPU设备进行特征提取,对于单次观测和数据集,都能获得显著的性能收益。

支持功能

混合

支持对象,混合,在您打开此示例时被放在您的当前文件夹中。

类型混合
classdef Mixup < handle % Mixup Mixup数据增强% mixer = Mixup(augDatastore)创建一个对象,可以以随机设置的比例混合特征%,然后概率地将输出的%标签设置为两个原始信号之一。% % Mixup属性:%MixProbability -混合概率% AugDatastore -增强数据存储% % Mixup方法:%Mix - Apply Mixup % % Copyright 2021 The MathWorks, Inc.属性(SetAccess=public,GetAccess=public) %MixProbability混合概率%指定混合作为%范围[0,1]中的标量应用的概率。如果未指定,MixProbability默认为1/3。MixProbability (1,1) {mustBeNumeric} = 1/3;end properties (SetAccess=immutable,GetAccess=public) %AUGDATASTORE增强数据存储%指定获取混合信号的数据存储。%数据存储必须在读取返回的信息中包含一个标签。此属性是不可变的,这意味着它在%构造后不能被更改。AugDatastore结束方法函数obj = Mixup(AugDatastore) obj。AugDatastore = AugDatastore;end function [dataOut,infoOut] = mix(obj,x,infoIn) % mix应用mixup % [dataOut,infoOut] = mix(mixer,x,infoIn)概率地将%包含在infoIn %中的输入x及其相关标签与从增强数据存储中随机抽取的信号混合。%输出dataOut是一个有两列的单元格数组。 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, Nishchal K.等。“利用声学信号对空压机进行基于智能状态的监测。”《IEEE可靠性汇刊》,第65卷,第。2016年3月1日,291-309页。DOI.org (Crossref), doi: 10.1109 / TR.2015.2459684。

[2] Huszar,费伦茨。《Mixup: Data- dependent Data Augmentation》。推理。2017年11月3日。2019年1月15日访问。https://www.inference.vc/mixup-data-dependent-data-augmentation/

Baidu
map