主要内容

基于后期融合的声场景识别

这个例子展示了如何创建一个多模型的声学场景识别后期融合系统。该示例使用mel谱图训练卷积神经网络(CNN),使用小波散射训练集成分类器。该示例使用TUT数据集进行训练和评估[1]

简介

声场景分类(ASC)是根据环境产生的声音对环境进行分类的任务。ASC是一个通用的分类问题,是设备、机器人和许多其他应用中的上下文感知的基础[1].早期的ASC尝试使用mel频率倒谱系数(mfcc(音频工具箱))和高斯混合模型(GMMs)来描述它们的统计分布。其他常用的ASC特征包括过零率、光谱质心(spectralCentroid(音频工具箱)),光谱滚转(spectralRolloffPoint(音频工具箱))、光谱通量(spectralFlux(音频工具箱))和线性预测系数(lpc的(信号处理工具箱)[5].隐马尔可夫模型(hmm)被训练来描述GMMs的时间演化。最近,表现最好的系统已经使用了深度学习(通常是cnn)和多个模型的融合。在DCASE 2017竞赛中,排名靠前的系统最受欢迎的功能是mel谱图(melSpectrogram(音频工具箱)).在挑战中排名靠前的系统使用后期融合和数据增强来帮助他们的系统泛化。

为了说明一种产生合理结果的简单方法,本例使用mel谱图训练CNN,使用小波散射训练集成分类器。CNN和集成分类器产生大致相当的总体精度,但在区分不同的声学场景方面表现更好。为了提高整体精度,您可以使用后期融合来合并CNN和集成分类器结果。

加载声场景识别数据集

要运行该示例,必须首先下载数据集[1].完整的数据集大约为15.5 GB。根据您的机器和互联网连接,下载数据可能需要大约4个小时。

downloadFolder = tempdir;数据集= fullfile(下载文件夹,“啧声-情景- 2017”);如果~ datasetExists(集)disp (下载TUT-acoustic-scenes-2017 (15.5 GB)…) HelperDownload_TUT_acoustic_scenes_2017(数据集);结束

将开发集元数据作为表读入。为表变量命名文件名AcousticScene,SpecificLocation

trainMetaData = readtable(fullfile(dataset,”图坦卡蒙-声场景- 2017 -发展”“元”),...分隔符= {' \ t '},...ReadVariableNames = false);trainMetaData.Properties.VariableNames = [“文件名”“AcousticScene”“SpecificLocation”];头(trainMetaData)
ans =8×3表文件名AcousticScene SpecificLocation  __________________________ _____________ ________________ {' 音频/ b020_90_100.wav '}{“海滩”}{‘b020}{的音频/ b020_110_120.wav}{“海滩”}{‘b020}{的音频/ b020_100_110.wav}{“海滩”}{‘b020}{的音频/ b020_40_50.wav}{“海滩”}{‘b020}{的音频/ b020_50_60.wav}{“海滩”}{‘b020}{的音频/ b020_30_40.wav}{“海滩”}{‘b020}{的音频/ b020_160_170.wav}{“海滩”}{‘b020}{的音频/ b020_170_180.wav}{“海滩”}{' b020 '}
testMetaData = readtable(fullfile(数据集)”图坦卡蒙-声场景- 2017 -评价”“元”),...分隔符= {' \ t '},...ReadVariableNames = false);testMetaData.Properties.VariableNames = [“文件名”“AcousticScene”“SpecificLocation”];头(testMetaData)
ans =8×3表文件名AcousticScene SpecificLocation  __________________ _____________ ________________ {' 音频/ 1245. wav}{“海滩”}{‘b174}{“音频/ 1456. wav”}{“海滩”}{‘b174}{“音频/ 1318. wav”}{“海滩”}{‘b174}{“音频/ 967. wav”}{“海滩”}{‘b174}{“音频/ 203. wav”}{“海滩”}{‘b174}{“音频/ 777. wav”}{“海滩”}{‘b174}{“音频/ 231. wav”}{“海滩”}{‘b174}{“音频/ 768. wav”}{“海滩”}{' b174 '}

注意,测试集中的特定记录位置不会与开发集中的特定记录位置相交。这使得验证训练过的模型是否可以推广到现实场景变得更容易。

sharedRecordingLocations = intersect(testMetaData.SpecificLocation,trainMetaData.SpecificLocation);disp ("列车和测试集中的特定记录位置数= "+元素个数(sharedRecordingLocations))
列和测试集中的特定记录位置数均为0

元数据表的第一个变量包含文件名。将文件名与文件路径连接起来。

trainfileppaths = fullfile(数据集,”图坦卡蒙-声场景- 2017 -发展”, trainMetaData.FileName);testfileppaths = fullfile(数据集,”图坦卡蒙-声场景- 2017 -评价”, testMetaData.FileName);

元数据中列出的文件可能不存在于数据集中。删除与缺失文件对应的文件路径和声学场景标签。

ads = audioDatastore(dataset, inclesubfolders =true);allFiles = ads.Files;trainIdxToRemove = ~ismember(trainfileppaths,allFiles);trainfileppaths (trainIdxToRemove) = [];trainLabels = categorical(trainMetaData.AcousticScene);trainLabels(trainIdxToRemove) = [];testdxtoremove = ~ismember(testfileppaths,allFiles);testfileppaths (testdxtoremove) = [];testLabels = categorical(testMetaData.AcousticScene);testLabels(testdxtoremove) = [];

为列车和测试集创建音频数据存储。设置标签的属性audioDatastore(音频工具箱)到声学现场。调用countEachLabel(音频工具箱)验证标签在训练集和测试集中的均匀分布。

adsTrain = audioDatastore(trainfilepath,...标签= trainLabels,...IncludeSubfolders = true);显示器(countEachLabel (adsTrain))
15×2表格标签计数________________ _____海滩312公共汽车312咖啡馆/餐厅312汽车312城市中心312森林路径312杂货店312家庭312图书馆312地铁站312办公室312公园312住宅区312火车312有轨电车312
adsTest = audioDatastore(testfileppaths,...标签=分类(testMetaData.AcousticScene),...IncludeSubfolders = true);显示器(countEachLabel (adsTest))
15×2表格标签计数________________ _____海滩108公共汽车108咖啡馆/餐厅108汽车108城市中心108森林路径108杂货店108家庭108图书馆108地铁站108办公室108公园108居民区108火车108有轨电车108

您可以减少本例中使用的数据集,以牺牲性能为代价来加快运行时。一般来说,减少数据集对于开发和调试是一种很好的实践。集speedupExample真正的减少数据集。

speedupExample =如果(adsTrain = splitEachLabel(adsTrain,20);adsTest = splitEachLabel(adsTest,10);结束

调用(音频工具箱)从集合中获取文件的数据和采样率。数据库中的音频具有一致的采样率和持续时间。将音频规范化,然后听一听。显示相应的标签。

[data,adsInfo] = read(adsTrain);Data = Data ./max(Data,[],“所有”);fs = adsInfo.SampleRate;声音(数据、fs) disp ("声学场景= "+字符串(adsTrain.Labels (1)))
声学场景=海滩

调用重置(音频工具箱)将数据存储返回到其初始状态。

重置(adsTrain)

CNN的特征提取

数据集中的每个音频剪辑由10秒的立体声(左右)音频组成。本例中的特征提取管道和CNN体系结构是基于[3].使用系统的超参数优化工作流程对特征提取的超参数、CNN架构和训练选项进行了修改。

首先,将音频转换为中间编码。[3]表明中端编码数据提供了更好的空间信息,CNN可以使用这些信息来识别移动的源(例如在声学场景中移动的火车)。

dataMidSide = [sum(data,2),data(:,1)-data(:,2)];

把信号分成重叠的一秒段。最后的系统使用一秒片段的概率加权平均值来预测测试集中每个10秒音频片段的场景。将音频片段分成一秒的片段可以使网络更容易训练,并有助于防止训练集中的特定声学事件过度拟合。重叠有助于确保训练数据捕获相对于其他特征的所有组合。它还为系统提供了额外的数据,可以在增强过程中唯一地混合。

segmentLength = 1;segmentOverlap = 0.5;[dataBufferedMid,~] = buffer(dataMidSide(:,1),round(segmentLength*fs),round(segmentOverlap*fs),“nodelay”);[dataBufferedSide,~] = buffer(dataMidSide(:,2),round(segmentLength*fs),round(segmentOverlap*fs),“nodelay”);dataBuffered = 0 (size(dataBufferedMid,1),size(dataBufferedMid,2)+size(dataBufferedSide,2));dataBuffered(:,1:2:end) = dataBufferedMid;dataBuffered(:,2:2:end) = dataBufferedSide;

使用melSpectrogram(音频工具箱)将数据转换为紧凑的频域表示。定义mel谱图的参数[3]

windowLength = 2048;samplesPerHop = 1024;samplesOverlap = windowLength - samplesPerHop;fftLength = 2*windowLength;numBands = 128;

melSpectrogram独立沿通道运行。要优化处理时间,请调用melSpectrogram整个缓冲信号。

spec = melSpectrogram(dataBuffered,fs,...窗口=汉明(windowLength,“周期”),...OverlapLength = samplesOverlap,...FFTLength = FFTLength,...NumBands = NumBands);

将mel谱图转换为对数刻度。

Spec = log10(Spec +eps);

将数组重塑为维度(频带数)-by-(跳数)-by-(通道数)-by-(段数)。当你将一张图像输入神经网络时,前两个维度是图像的高度和宽度,第三个维度是通道,第四个维度将单独的图像分开。

X =重塑(规格、尺寸(规范,1),大小(规范,2),大小(数据,2),[]);

调用melSpectrogram在没有输出参数的情况下,绘制中间通道的前六个一秒增量的MEL频谱图。

tiledlayout (2)nexttile melSpectrogram(dataBuffered(:,channel),fs,...窗口=汉明(windowLength,“周期”),...OverlapLength = samplesOverlap,...FFTLength = FFTLength,...NumBands = NumBands);标题(“段”+装天花板(频道/ 2))结束

辅助函数HelperSegmentedMelSpectrograms执行上面概述的特征提取步骤。

为了加快处理速度,在使用的数据存储中提取所有音频文件的mel谱图数组。与内存中数组不同,高数组在请求使用收集函数。这种延迟计算使您能够快速处理大型数据集。当您最终请求输出时使用收集, MATLAB在可能的情况下组合队列计算,并采用最少的数据遍历次数。如果您有并行计算工具箱™,您可以在本地MATLAB会话或本地并行池中使用高数组。如果安装了MATLAB®Parallel Server™,还可以在集群上运行高数组计算。

如果没有并行计算工具箱™,则此示例中的代码仍然可以运行。

train_set_tall = tall(adsTrain);xTrain = cellfun(@(x)HelperSegmentedMelSpectrograms(x,fs,...SegmentLength = SegmentLength,...SegmentOverlap = SegmentOverlap,...WindowLength = WindowLength,...HopLength = samplesPerHop,...NumBands = NumBands,...FFTLength = FFTLength),...train_set_tall,...UniformOutput = false);xTrain = gather(xTrain);
使用并行池“本地”评估tall表达式:-通过1:0%完成评估0%完成-通过1:1:在3分56秒内完成评估在3分56秒内完成
xTrain = cat(4,xTrain{:});test_set_tall = tall(adsTest);xTest = cellfun(@(x)HelperSegmentedMelSpectrograms(x,fs,...SegmentLength = SegmentLength,...SegmentOverlap = SegmentOverlap,...WindowLength = WindowLength,...HopLength = samplesPerHop,...NumBands = NumBands,...FFTLength = FFTLength),...test_set_tall,...UniformOutput = false);xTest = gather(xTest);
使用并行池“本地”评估tall表达式:-通过1 / 1:在1分26秒内完成评估
xTest = cat(4,xTest{:});

复制训练集和测试集的标签,使它们与片段一一对应。

numSegmentsPer10seconds = size(dataBuffered,2)/2;yTrain = repmat(adsTrain.Labels,1,numSegmentsPer10seconds)';yTrain = yTrain(:);yTest = repmat(adsTest.Labels,1,numSegmentsPer10seconds)';yTest = yTest(:);

CNN的数据增强

DCASE 2017数据集包含相对较少的任务声学记录,开发集和评估集是在不同的特定位置记录的。因此,在训练过程中很容易对数据进行过拟合。减少过拟合的一种流行方法是混合.在mixup中,通过混合两个不同类的特性来扩充数据集。当您混合这些特性时,您将以相等的比例混合标签。那就是:

x λ x + 1 - λ x j y λ y + 1 - λ y j

Mixup由[2]从概率分布中抽取标签,而不是混合标签。本例中mixup的实现是mixup的简化版本:每个谱图与不同标签的谱图混合,lambda设置为0.5。将原始数据集和混合数据集结合起来进行训练。

xTrainExtra = xTrain;yTrainExtra = yTrain;Lambda = 0.5;ii = 1:size(xTrain,4)找到所有可用的不同标签的频谱图。availablspectrograms = find(yTrain~=yTrain(ii));%随机选择一个不同标签的可用频谱图。numAvailableSpectrograms = numel(availableSpectrograms);idx = randi([1,numAvailableSpectrograms]);%的组合。xTrainExtra(:,:,:,(二)=λ* xTrain(:,:,:,(二)+(1λ)* xTrain (:,:,:, availableSpectrograms (idx));指定由lambda随机设置的标签。如果rand > lambda yTrainExtra(ii) = yTrain(availableSpectrograms(idx));结束结束xTrain = cat(4,xTrain,xTrainExtra);yTrain = [yTrain;yTrainExtra];

调用总结显示增强训练集的标签分布。

总结(yTrain)
海滩11769公共汽车11904咖啡馆/餐厅11873汽车11820城市中心11886森林路径11936杂货店11914家庭11923图书馆11817地铁站11804办公室11922公园11871住宅区11704火车11773有轨电车11924

定义和训练CNN

定义CNN体系结构。这个体系结构是基于[1]并通过反复试验进行修正。看到深度学习层列表(深度学习工具箱)了解更多关于MATLAB®中提供的深度学习层的信息。

imgSize = [size(xTrain,1),size(xTrain,2),size(xTrain,3)];numF = 32;层= [...imageInputLayer(imgSize) batchNormalizationLayer convolution2dLayer(3,numF,Padding=“相同”) batchNormalizationLayer relullayer convolution2dLayer(3,numF,Padding=“相同”) batchNormalizationLayer reluLayer maxPooling2dLayer(3,Stride=2,Padding=“相同”) convolution2dLayer (3 2 * numF填充=“相同”(3,2*numF,Padding= .“相同”) batchNormalizationLayer reluLayer maxPooling2dLayer(3,Stride=2,Padding=“相同”) convolution2dLayer(3、4 * numF填充=“相同”) batchNormalizationLayer reluLayer convolution2dLayer(3,4*numF,Padding=“相同”) batchNormalizationLayer reluLayer maxPooling2dLayer(3,Stride=2,Padding=“相同”) convolution2dLayer (3 8 * numF填充=“相同”) batchNormalizationLayer reluLayer convolution2dLayer(3,8*numF,Padding=“相同”) batchNormalizationLayer reluLayer globalAveragePooling2dLayer dropoutLayer(0.5) fullyConnectedLayer(15) softmaxLayer classificationLayer];

定义trainingOptions(深度学习工具箱)CNN报道。这些选项是基于[3]并通过系统的超参数优化工作流程进行了修改。

miniBatchSize = 128;Tuneme = 128;lr = 0.05*miniBatchSize/tuneme;选项= trainingOptions(...“个”...动量= 0.9,...L2Regularization = 0.005,......MiniBatchSize = MiniBatchSize,...MaxEpochs = 8,...洗牌=“every-epoch”......情节=“训练进步”...Verbose = false,......InitialLearnRate = lr,...LearnRateSchedule =“分段”...LearnRateDropPeriod = 2,...LearnRateDropFactor = 0.2,......ValidationData = {xTest,欧美},...ValidationFrequency =地板(大小(xTrain 4) / miniBatchSize));

调用trainNetwork(深度学习工具箱)训练网络。

trainedNet = trainNetwork(xTrain,yTrain,图层,选项);

评估美国有线电视新闻网

调用预测(深度学习工具箱)使用保留测试集预测训练网络的响应。

cnnResponsesPerSegment = predict(trainedNet,xTest);

平均每个10秒音频片段的回答。

classes = trainedNet.Layers(end).Classes;numFiles = nummel (adste . files);计数器= 1;cnnResponses = 0 (numFiles,numel(classes));cnnResponses(channel,:) = sum(cnnResponsesPerSegment(counter:counter+numSegmentsPer10seconds-1,:),1)/numSegmentsPer10seconds;counter = counter + numSegmentsPer10seconds;结束

对于每个10秒的音频剪辑,选择预测的最大值,然后将其映射到相应的预测位置。

[~, classsidx] = max(cnnResponses,[],2);cnnPredictedLabels = classes(classsidx);

调用confusionchart(深度学习工具箱)为了在测试集上显示准确性。

图(单位=“归一化”,Position=[0.2 0.2 0.5 0.5])标签,cnnPredictedLabels,...title = (“测试准确性- CNN”“平均准确度=”+的意思是(adsTest.Labels = = cnnPredictedLabels) * 100),...ColumnSummary =“column-normalized”RowSummary =“row-normalized”);

集成分类器的特征提取

小波散射在[4]提供一个良好的声音场景的表现。定义一个waveletScattering对象。通过试错确定不变性尺度和质量因子。

sf =小波散射(SignalLength=size(data,1),...SamplingFrequency = fs,...InvarianceScale = 0.75,...QualityFactors = 1 [4]);

将音频信号转换为单声道,然后呼叫featureMatrix为了返回散射分解框架的散射系数,科幻小说

dataMono = mean(数据,2);散射系数= featureMatrix(sf,dataMono,Transform=“日志”);

平均10秒音频片段的散射系数。

featureVector = mean(scatteringcoefficients,2);disp ("每10秒剪辑的小波特征数= "+元素个数(featureVector));
每10秒剪辑的小波特征数= 286

辅助函数HelperWaveletFeatureVector执行上述步骤。使用一个数组cellfun而且HelperWaveletFeatureVector使特征提取并行化。提取训练集和测试集的小波特征向量。

scatteringTrain = cellfun(@(x)HelperWaveletFeatureVector(x,sf),train_set_tall,UniformOutput=false);xTrain = gather(散射火车);xTrain = cell2mat(xTrain')';
scatteringTest = cellfun(@(x)HelperWaveletFeatureVector(x,sf),test_set_tall,UniformOutput=false);xTest = gather(scatteringTest);xTest = cell2mat(xTest')';

定义并训练集成分类器

使用fitcensemble要创建经过训练的分类集成模型(ClassificationEnsemble).

subspaceDimension = min(150,size(xTrain,2) - 1);numLearningCycles = 30;classificationEnsemble = fitcensemble(xTrain,adsTrain。标签,...方法=“子”...NumLearningCycles = NumLearningCycles,...学习者=“判别”...NPredToSample = subspaceDimension,...一会= removecats(独特(adsTrain.Labels)));

评估集成分类器

对于每一个10秒的音频剪辑,呼叫预测为了返回标签和权重,然后将其映射到相应的预测位置。调用confusionchart(深度学习工具箱)为了在测试集上显示准确性。

[wavetpredictedlabels, wavetresponses] = predict(classificationEnsemble,xTest);图(单位=“归一化”,Position=[0.2 0.2 0.5 0.5])标签,waveletPredictedLabels,...title = (《测试精度-小波散射》“平均准确度=”+的意思是(adsTest.Labels = = waveletPredictedLabels) * 100),...ColumnSummary =“column-normalized”RowSummary =“row-normalized”);

流('分类器平均准确率= %0.2f\n',意味着(adsTest.Labels = = waveletPredictedLabels) * 100)
分类器的平均准确率= 75.74

应用后期融合

每10秒,来电预测在小波分类器上,CNN返回一个向量,表明他们对决策的相对信心。乘以waveletResponsescnnResponses创造一个晚期聚变系统。

融合=小波响应。*cnnResponses;[~, classsidx] = max(fused,[],2);predictedLabels = classes(classsidx);

评估晚期融合

调用confusionchart可视化融合分类精度。

图(单位=“归一化”,Position=[0.2 0.2 0.5 0.5])标签,predictedLabels,...Title = (“测试精度-融合”“平均准确度=”+的意思是(adsTest.Labels = = predictedLabels) * 100),...ColumnSummary =“column-normalized”RowSummary =“row-normalized”);

万博1manbetx支持功能

HelperSegmentedMelSpectrograms

函数X = helpsegmentedmelspectrograms (X,fs,varargin)版权所有The MathWorks, Inc.p = inputParser;addParameter (p, WindowLength = 1024);addParameter (p, HopLength = 512);addParameter (p, NumBands = 128);addParameter (p, SegmentLength = 1);addParameter (p, SegmentOverlap = 0);addParameter (p, FFTLength = 1024);解析(p,varargin{:}) params = p. results;X = [sum(X,2), X (:,1)-x(:,2)];X = X /max(max(X)); [xb_m,~] = buffer(x(:,1),round(params.SegmentLength*fs),round(params.SegmentOverlap*fs),“nodelay”);[xb_s,~] = buffer(x(:,2),round(params.SegmentLength*fs),round(params.SegmentOverlap*fs),“nodelay”);xb = 0(大小(xb_m, 1),大小(xb_m 2) +大小(xb_s, 2));Xb (:,1:2:end) = xb_m;Xb (:,2:2:end) = xb_s;spec = melSpectrogram(xb,fs,...窗口=汉明(参数。WindowLength,“周期”),...OverlapLength =参数。WindowLength -参数。HopLength,...FFTLength =参数。FFTLength,...NumBands =参数。NumBands,...FrequencyRange =[0,地板(fs / 2)));Spec = log10(Spec +eps);X =重塑(规格、尺寸(规范,1),大小(规范,2),大小(X, 2), []);结束

HelperWaveletFeatureExtractor

函数features = helperwavetfeaturevector (x,sf)版权所有The MathWorks, Inc.X = mean(X,2);feature = featureMatrix(sf,x,Transform=“日志”);Features = mean(Features,2);结束

参考文献

A.梅萨罗斯,T.海托拉,T.维尔塔宁。声场景分类:DCASE 2017挑战赛参赛作品概述。国际声学信号增强研讨会,2018。

[2]胡萨尔,费伦茨。《混淆:依赖数据的数据增强》推理。2017年11月3日2019年1月15日访问。https://www.inference.vc/mixup-data-dependent-data-augmentation/

[3]韩允昌朴正秀李圭“用于声场景分类的双听觉表示和背景减法卷积神经网络”,《声场景和事件的检测与分类》(DCASE)(2017): 1-5。

洛斯坦伦,文森特,和约阿基姆·安登。基于小波散射的双耳场景分类。技术报告,DCASE2016挑战赛,2016。

[5] A. J. Eronen, V. T. Peltonen, J. T. Tuomi, A. P. Klapuri, S. Fagerlund, T. Sorsa, G. Lorho,和J. Huopaniemi,“基于音频的上下文识别”,IEEE Trans。关于音频,语音和语言处理,第14卷,no。1,页321-329,2006年1月。

[6]图坦卡蒙声学场景2017,开发数据集

[7]TUT声学场景2017,评估数据集

另请参阅

相关的例子

更多关于