用Grad-CAM解释深度学习时间序列分类
这个例子展示了如何使用梯度加权类激活映射(Grad-CAM)技术来理解训练时间序列数据的一维卷积神经网络的分类决策。
Grad-CAM[1]使用分类分数相对于网络确定的卷积特征的梯度来理解数据的哪些部分对分类最重要。对于时间序列数据,Grad-CAM计算网络分类决策最重要的时间步长。
这张图片显示了一个带有Grad-CAM重要性色彩图的例子序列。该地图突出显示了网络用于做出分类决策的区域。
本示例使用对标记数据的监督学习将时间序列数据分类为“正常”或“传感器故障”。还可以使用自动编码器网络对未标记的数据执行时间序列异常检测。有关更多信息,请参见基于深度学习的时间序列异常检测.
负载波形数据
加载波形数据集WaveformData.mat
.这个数据集包含了合成的不同长度的波形。每个波形有三个通道。
rng (“默认”)加载WaveformDatanumChannels = size(data{1},1);numObservations = numel(数据);
想象一个情节的前几个序列。
图tiledlayout (2, 2)为i = 1:4 nexttile stackedplot(data{i}',DisplayLabels=“通道”+ (1: numChannels));标题(“观察”+ i)包含(“时间步”)结束
模拟传感器故障
通过手动编辑一些序列来创建一组新的数据,以模拟传感器故障。
创建未修改数据的副本。
dataUnmodified =数据;
随机选择10%的序列进行修改。
failureFraction = 0.1;numFailures = round(numObservations*failureFraction);failureIdx = randperm(numel(data),numFailures);
为了模拟传感器故障,引入一个高度介于0.25到2之间的小附加异常。每个异常都发生在序列中的随机位置,发生时间步长在4到20之间。
anomaly:异常exception ypatchsize = [4 20];anomaly (2) - anomaly (1);
修改序列。
failureLocation = cell(size(data));为i = 1:numFailures X = data{failureIdx(i)};生成传感器故障位置。patchLength = randi(alarmypatchsize,1);patchStart = randi(长度(X)-patchLength);idxPatch = patchStart:(patchStart+patchLength);%生成异常高度。patchExtraHeight = anomaly (1) + anomaly (1,1) *rand;X(:,idxPatch) = X(:,idxPatch) + patchExtraHeight;%保存修改的序列。data{failureIdx(i)} = X;%保存失败位置。failureLocation{failureIdx(i)} = idxPatch;结束
对于未修改的序列,将类标签设置为正常的
.对于修改的序列,将类标签设置为传感器故障
.
标签= repmat(“正常”numObservations 1);标签(failureIdx) =“传感器失败”;标签=类别(标签);
使用直方图可视化类标签分布。
图直方图(标签)
可视化传感器故障
将修改后的序列与原始序列进行比较。虚线表示传感器故障的区域。
numFailuresToShow = 2;为i=1:numFailuresToShow图t = tiledlayout(numChannels,1);idx = failureIdx(i);modifiedSignal = data{idx};originalSignal = dataUnmodified{idx};为j = 1:numChannels nexttile plot(modifiedSignal(j,:))保持在情节(originalSignal (j,:)) ylabel (“通道”+ j)包含(“时间步”)参照线(failureLocation {idx} (1),”:“)参照线(failureLocation {idx}(结束),”:“)举行从结束标题(t)“观察”+ failureIdx(我))传说(“修改”,“原始”,…位置=“southoutside”,…NumColumns = 2)结束
除了传感器故障对应的异常补丁外,修改后的信号与原始信号匹配。
准备数据
通过将数据分割为训练集和验证集,为训练准备数据。使用90%的数据进行训练,使用10%的数据进行验证。
trainFraction = 0.9;idxTrain = 1:地板(trainFraction*numObservations);idxValidation = (idxTrain(end)+1):numObservations;XTrain = data(idxTrain);TTrain = labels(idxTrain);XValidation = data(idxValidation);TValidation = labels(idxValidation);failureLocationValidation = failureLocation(idxValidation);
定义网络架构
定义1-D卷积神经网络体系结构。
使用序列输入层,其输入大小与输入数据的通道数量相匹配。
指定一维卷积、ReLU和层归一化层的两个块,其中卷积层的过滤器大小为3。分别为第一和第二卷积层指定32和64个过滤器。对于两个卷积层,左填充输入,使输出具有相同的长度(因果填充)。
为了将卷积层的输出减少到单个向量,可以使用1-D全局平均池化层。
要将输出映射到概率向量,请指定一个输出大小与类数量匹配的完全连接层,然后是一个softmax层和一个分类层。
类=类别(TTrain);numClasses = numel(classes);filterSize = 3;numFilters = 32;图层= […sequenceInputLayer numChannels convolution1dLayer (filterSize numFilters,填充=“因果”reluLayer layerNormalizationLayer convolution1dLayer(filterSize,2*numFilters,Padding= .“因果”) reluLayer layerNormalizationLayer globalAveragePooling1dLayer fullyConnectedLayer(numClasses) softmaxLayer classificationLayer];
指定培训选项
使用自适应动量(ADAM)训练网络。将最大的epoch数设置为15,并使用27的迷你批处理大小。在一个小批处理中,将所有的序列保持相同的长度。在训练过程中使用验证数据验证网络。在一个图形中监视训练进度并抑制冗长的输出。
miniBatchSize = 27;options = trainingOptions(“亚当”,…MiniBatchSize = MiniBatchSize,…MaxEpochs = 15,…SequencePaddingDirection =“左”,…ValidationData = {XValidation, TValidation},…情节=“训练进步”,…Verbose = false);
列车网络的
方法使用指定选项训练卷积网络trainNetwork
函数。
net = trainNetwork(XTrain,TTrain,layers,options);
测试网络
使用训练时使用的相同的小批大小和序列填充选项对验证数据进行分类。
YValidation = class (net,XValidation,…MiniBatchSize = MiniBatchSize,…SequencePaddingDirection =“左”);
计算预测的分类精度。
精度=平均值(YValidation == TValidation)
准确度= 0.9500
在混淆矩阵中可视化预测。
图confusionchart (TValidation YValidation)
使用Grad-CAM解释分类结果
使用Grad-CAM来可视化网络用于做出分类决策的序列的各个部分。
找到一个被网络正确归类为“传感器故障”的序列子集。
numFailuresToShow = 2;isCorrect = TValidation ==“传感器失败”& YValidation ==“传感器失败”;idxValidationFailure = find(isCorrect,numFailuresToShow);
对于每个观察,计算和可视化的Grad-CAM地图。要计算Grad-CAM重要性图,请使用gradCAM
.控件显示表示Grad-CAM重要性的色彩图plotWithColorGradient
Helper函数,在本例末尾定义。添加虚线以显示传感器故障的真实位置。
为i = 1:numFailuresToShow图t = tiledlayout(numChannels,1);idx = idxValidationFailure(i);modifiedSignal = XValidation{idx};important = gradCAM(net,modifiedSignal,“传感器失败”);为j = 1:numChannels nexttile plotWithColorGradient(modifiedSignal(j,:)', important ');ylabel (“通道”+ j)包含(“时间步骤”)如果~ isempty (failureLocationValidation {idx})参照线(failureLocationValidation {idx} (1),”:“)参照线(failureLocationValidation {idx}(结束),”:“)结束结束标题(t)“Grad-CAM:验证观察”+idx) c = colorbar;c.Layout.Tile =“东”;c.Label.String =“Grad-CAM重要性”;结束
从Grad-CAM图可以看出,该网络正确地利用序列的传感器故障区域进行分类决策。使用正确的区域表明网络正在学习如何区分正常和失败的数据。网络是利用失败来决定的,而不是虚假的背景特征。
使用Grad-CAM来调查错误分类
你也可以使用Grad-CAM来调查错误分类的序列。
找出网络错误分类为“正常”的传感器故障序列的子集。
numFailuresToShow = 2;isIncorrect = TValidation ==“传感器失败”& YValidation ==“正常”;idxValidationFailure = find(isIncorrect,numFailuresToShow);
对于每一个错误的分类,计算和可视化的Grad-CAM地图。对于分类错误的传感器故障序列,Grad-CAM映射图显示网络确实找到了故障区域。然而,与正确分类的序列不同,网络不使用整个故障区域来进行分类决策。
为i = 1:length(idxValidationFailure) figure t = tiledlayout(numChannels,1);idx = idxValidationFailure(i);modifiedSignal = XValidation{idx};important = gradCAM(net,modifiedSignal,“传感器失败”);为j = 1:numChannels nexttile plotWithColorGradient(modifiedSignal(j,:)', important ');ylabel (“通道”+ j)包含(“时间步骤”)如果~ isempty (failureLocationValidation {idx})参照线(failureLocationValidation {idx} (1),”:“)参照线(failureLocationValidation {idx}(结束),”:“)结束结束标题(t)“Grad-CAM:验证观察”+idx) c = colorbar;c.Layout.Tile =“东”;c.Label.String =“Grad-CAM重要性”;结束
Helper函数
的plotWithColorGradient
函数将具有单一通道的序列和具有与该序列相同时间步数的重要映射作为输入。该函数使用重要性映射为序列的分段着色。
设置的最后一个条目y
而且c
来南
所以这个补丁创建了一条直线,而不是一个闭合的多边形。
函数plotWithColorGradient(sequence,importance) x = 1:size(sequence,1) + 1;Y =[序列;南);C =[重要性;南);补丁(x, y, c, EdgeColor =“插值函数”);结束
[1] Selvaraju, Ramprasaath R., Michael Cogswell, Abhishek Das, Ramakrishna Vedantam, Devi Parikh和Dhruv Batra。“Grad-CAM:基于梯度定位的深度网络视觉解释。”国际计算机视觉杂志,第128期。2(2020年2月):336-59。https://doi.org/10.1007/s11263 - 019 - 01228 - 7。
另请参阅
gradCAM
|imageLIME
|occlusionSensitivity
|deepDreamImage