本示例说明如何使用长短期记忆LSTM网络对序列数据的每个时间步进行分类。
要训练深度神经网络对序列数据的每个时间步进行分类,可以使用序列到序列LSTM网络。序列到序列LSTM网络可以使得对序列数据的每个单独时间步进行不同的预测。
本示例使用了从佩戴在身上的智能手机获得的传感器数据,该示例训练了一个LSTM网络,在给定时间序列数据的情况下识别佩戴者的活动,该时间序列数据表示在三个不同方向上的加速度计的读数。训练数据包含其个人的时间序列数据。每个序列具有三个特征,并且长度不同,数据集包含6个训练观察结果和一个测试观察结果。
加载序列数据
加载人类活动识别数据。数据包含七个时间序列的传感器数据,这些数据是从穿戴在身上的智能手机获得的。每个序列有三个特征,并且特征不同。这三个功能分别对应三个方向上的加速度计数器。
load HumanActivityTrain
XTrain
XTrain=6×1 cell array {3×64480 double} {3×53696 double} {3×56416 double} {3×50688 double} {3×51888 double} {3×54256 double}
画一幅图来可视化一下训练过程,画出第一个训练序列的第一个特征,然后标注出相关的活动。
X = XTrain{1}(1,:);
classes = categories(YTrain{1});
figure
for j = 1:numel(classes)
label = classes(j);
idx = find(YTrain{1} == label);
hold on
plot(idx,X(idx))
end
hold off
xlabel("Time Step")
ylabel("Acceleration")
title("Training Sequence 1, Feature 1")
legend(classes,'Location','northwest')
定义LSTM网络架构
定义一下LSTM网络架构,确定LSTM的输入的大小为3(因为这是输入数据的特征个数),确定LSTM的隐藏层个数为200,输出整个序列。最后,通过设定全连接层的个数为5能够分辨出5个类来,然后紧跟着一个softmax层和一个分类层。(大小为3的输入层->大小为200的隐藏层->大小为5的全阶层->softmax层->分类层)。
numFeatures = 3;
numHiddenUnits = 200;
numClasses = 5;
layers = [...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits, 'OutputMode', 'sequence')
fullyConnectedLayer(numClasses)
softmaxLayer
classificationLayer
];
确定一下网络层的参数,设定解决方法为 ‘adam’,训练60个epochs。为了防止梯度爆炸,设定梯度阈值为2
options = trainingOptions('adam', ...
'MaxEpochs',60, ...
'GradientThreshold',2, ...
'Verbose',0, ...
'Plots','training-progress');
使用 trainNetwork
函数来训练LSTM网络,每个小批量都包含整个训练集,所以每个epoch都会更新一次,因为序列很长,所以在处理每个批量和更新画图的时候都要花很长时间。
net = trainNetwork(XTrain, YTrain, layers, options);
测试LSTM网络
加载测试集然后对每个时间步长的活动进行分类。
加载人类活动的测试集,其中XTest
包含了3维的序列,YTest
包含了序列所对应的步长所属的标签。
load HumanActivityTest
figure
plot(XTest{1}')
xlabel("Time Step")
legend("Feature " + (1:numFeatures))
title("Test Data")
图3. 验证集
使用classify
函数对测试集数据进行分类
YPred = classify(net, XTest{1});
另外,也可以使用函数classifyAndUpdateState
然后来一次预测一个时间步长。通常,与一次一次的与预测相比,对全序列预测会更快。
计算预测的准确性
acc = sum(YPred == YTest{1})./numel(YTest{1})
acc = 0.9998
画图来看一下预测数据和真实数据的差别
figure
plot(YPred,'.-')
hold on
plot(YTest{1})
hold off
xlabel("Time Step")
ylabel("Activity")
title("Predicted Activities")
legend(["Predicted" "Test Data"])
图5. 预测数据和真实数据的差别