使用深度学习进行“序列到序列”分类
此示例说明如何使用长短期记忆 (LSTM) 网络对序列数据的每个时间步进行分类。
要训练深度神经网络以对序列数据的每个时间步进行分类,可以使用“序列到序列”的 LSTM 网络。通过“序列到序列”的 LSTM 网络,您可以对序列数据的每个时间步进行不同预测。
此示例使用从佩戴在身体上的智能手机获得的传感器数据。该示例训练一个 LSTM 网络,旨在根据表示三个不同方向上的加速度计读数的时间序列数据来识别佩戴者的活动。
加载序列数据
加载人体活动识别数据。训练数据包含六个人的时间序列数据。测试数据包含第七个人的单个时间序列。每个序列有三个特征,且长度不同。这三个特征对应于三个不同方向上的加速度计读数。
load HumanActivityTrain
XTrainXTrain=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 网络架构。将输入指定为大小为 3(输入数据的特征数量)的序列。指定包含 200 个隐藏单元的 LSTM 层,并输出完整序列。最后,在网络中包含一个大小为 5 的全连接层,后跟 softmax 层,以此来指定五个类。
numFeatures = 3; numHiddenUnits = 200; numClasses = 5; layers = [ ... sequenceInputLayer(numFeatures) lstmLayer(numHiddenUnits,OutputMode="sequence") fullyConnectedLayer(numClasses) softmaxLayer];
指定训练选项。
使用 Adam 求解器进行训练。
进行 60 轮训练。
由于训练数据具有行和列分别对应于通道和时间步的序列,请指定输入数据格式
"CTB"(通道、时间、批量)。要防止梯度爆炸,请将梯度阈值设置为 2。
在图中显示训练进度并隐藏详尽输出。
在训练过程中监控网络的准确度。
options = trainingOptions("adam", ... MaxEpochs=60, ... InputDataFormats="CTB", ... GradientThreshold=2, ... Plots="training-progress", ... Verbose=false, ... Metrics="accuracy");
使用 trainnet 函数训练 LSTM 网络。对于分类,使用交叉熵损失。默认情况下,trainnet 函数使用 GPU(如果有)。在 GPU 上进行训练需要 Parallel Computing Toolbox™ 许可证和受支持的 GPU 设备。有关受支持设备的信息,请参阅 GPU 计算要求。否则,trainnet 函数使用 CPU。要手动选择执行环境,请使用 ExecutionEnvironment 训练选项。每个小批量都包含整个训练集,因此每训练一轮便更新一次绘图。序列非常长,因此处理每个小批量并更新绘图可能需要一些时间。
net = trainnet(XTrain,YTrain,layers,"crossentropy",options);
测试 LSTM 网络
加载测试数据并对每个时间步的活动进行分类。
加载人体活动测试数据。XTest 包含一个维度为 3 的序列。YTest 包含对应于每个时间步的活动的分类标签序列。
load HumanActivityTest figure XTest = XTest{1}'; plot(XTest) xlabel("Time Step") ylabel("Acceleration") legend("Feature " + (1:numFeatures)) title("Test Data")

对于单个观测值输入,请使用 predict 函数进行预测。要使用 GPU 进行预测,请先将数据转换为 gpuArray。
if canUseGPU XTest = gpuArray(XTest); end scores = predict(net,XTest);
要将预测分数转换为标签,请使用 scores2label 函数。
Y = scores2label(scores,classes);
您也可以使用 predict 并返回更新后的网络状态作为输出,一次对一个时间步进行预测。然后,您可以使用该状态输出来更新网络的 State 属性。这在时间步的值以流的方式到达时非常有用。通常,对完整序列进行预测比一次对一个时间步进行预测更快。有关如何通过在相邻的单个时间步预测之间更新网络来预测将来时间步的示例,请参阅使用深度学习进行时间序列预测。
计算预测的准确度。
acc = sum(Y == YTest{1}')./numel(YTest{1})acc = 0.9983
通过绘图将预测值与测试数据进行比较。
figure plot(Y,".-") hold on plot(YTest{1}) hold off xlabel("Time Step") ylabel("Activity") title("Predicted Activities") legend(["Predicted" "Test Data"])

另请参阅
trainnet | trainingOptions | dlnetwork | lstmLayer | sequenceInputLayer