目录
项目背景
加载序列数据
定义 LSTM 网络架构
训练LSTM网络
测试 LSTM 网络
使用 classify 对测试数据进行分类。
计算预测的准确度。
全部源代码
参考文献
重点:对于LSTM网络的两种工作模式,
加载人体活动识别数据。该数据包含从佩戴在身体上的智能手机获得的七个时间序列的传感器数据。每个序列有三个特征,且长度不同。这三个特征对应于三个不同方向上的加速度计读数。该例子来源mathwork,直接输入下列代码即可得到数据。
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 网络架构。将输入指定为大小为 3(输入数据的特征数量)的序列。指定包含 200 个隐含单元的 LSTM 层,并输出完整序列。最后,在网络中包含一个大小为 5 的全连接层,后跟 softmax 层和分类层,以此来指定五个类。
numFeatures = 3;
numHiddenUnits = 200;
numClasses = 5;
layers = [ ...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits,'OutputMode','sequence')
fullyConnectedLayer(numClasses)
softmaxLayer
classificationLayer];
%指定训练选项。将求解器设置为 'adam'。进行 60 轮训练。要防止梯度爆炸,请将梯度阈值设置为 2。
options = trainingOptions('adam', ...
'MaxEpochs',60, ...
'GradientThreshold',2, ...
'Verbose',0, ...
'Plots','training-progress');
%使用 trainNetwork 以指定的训练选项训练 LSTM 网络。每个小批量都包含整个训练集,因此每训练一轮便更新一次绘图。序列非常长,因此处理每个小批量并更新绘图可能需要一些时间。
net = trainNetwork(XTrain,YTrain,layers,options);
加载测试数据并对每个时间步的活动进行分类。
加载人体活动测试数据。XTest 包含一个维度为 3 的序列。YTest 包含对应于每个时间步的活动的分类标签序列。
load HumanActivityTest
figure
plot(XTest{1}')
xlabel("Time Step")
legend("Feature " + (1:numFeatures))
title("Test Data")
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"])
load HumanActivityTrain
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')
numFeatures = 3;
numHiddenUnits = 200;
numClasses = 5;
layers = [ ...
sequenceInputLayer(numFeatures)
lstmLayer(numHiddenUnits,'OutputMode','sequence')
fullyConnectedLayer(numClasses)
softmaxLayer
classificationLayer];
%指定训练选项。将求解器设置为 'adam'。进行 60 轮训练。要防止梯度爆炸,请将梯度阈值设置为 2。
options = trainingOptions('adam', ...
'MaxEpochs',60, ...
'GradientThreshold',2, ...
'Verbose',0, ...
'Plots','training-progress');
%使用 trainNetwork 以指定的训练选项训练 LSTM 网络。每个小批量都包含整个训练集,因此每训练一轮便更新一次绘图。序列非常长,因此处理每个小批量并更新绘图可能需要一些时间。
net = trainNetwork(XTrain,YTrain,layers,options);
load HumanActivityTest
figure
plot(XTest{1}')
xlabel("Time Step")
legend("Feature " + (1:numFeatures))
title("Test Data")
YPred = classify(net,XTest{1});
acc = sum(YPred == YTest{1})./numel(YTest{1})
%通过绘图将预测值与测试数据进行比较。
figure
plot(YPred,'.-')
hold on
plot(YTest{1})
hold off
xlabel("Time Step")
ylabel("Activity")
title("Predicted Activities")
legend(["Predicted" "Test Data"])
[1]Mathwork:Sequence-to-Sequence Classification Using Deep Learning