LeNet分类单变量时间序列报错:数据格式化问题排查求助
单变量时间序列分类:LeNet维度匹配问题修复
问题描述
尝试用LeNet对含300时间步的单变量时间序列做分类,遇到预测与标签维度不匹配的错误,先后试过矩阵格式和单元格数组格式的输入,均报错。对channel和feature的概念混淆,不确定序列输入层的参数设置是否正确。
原代码
num_channels = 1; num_classes = 3; filterSize = 5; numFilters = 32; num_of_features = size(X_train(1, :), 2); assert(num_of_features==300); net = dlnetwork; LeNeT = [ % featureInputLayer(num_of_features, "Name", "input") sequenceInputLayer(num_of_features, "Name", "input", "MinLength", num_of_features) convolution1dLayer( 5, 6,"Name","conv1") tanhLayer("Name","tanh1") averagePooling1dLayer( 2, "Name","pool1","Stride", 2) tanhLayer("Name","tanh2") convolution1dLayer( 5, 16,"Name","conv2") tanhLayer("Name","tanh3") averagePooling1dLayer( 2,"Name","pool2","Stride", 2) tanhLayer("Name","tanh4") convolution1dLayer( 5, 120,"Name","conv3") tanhLayer("Name","tanh5") fullyConnectedLayer( 84, "Name","fc1") tanhLayer("Name","tanh6") fullyConnectedLayer( num_classes, "Name","new_fc") softmaxLayer("Name","prob")]; net = addLayers(net,LeNeT); net = initialize(net); train_opts = trainingOptions("adam", ... MaxEpochs=20, ... MiniBatchSize=128, ... InitialLearnRate=0.01, ... Shuffle="once", ... ValidationData={X_val,Y_val}, ... Plots="none", ... Metrics="accuracy", ... Verbose=true); %% Train the network. net = trainnet(X_train, Y_train, net, "crossentropy", train_opts); %% Test the network. accuracy = testnet(net, X_test, Y_test, "accuracy"); scores = minibatchpredict(net, X_test); predicted_labels = scores2label(scores, categories(Y)); figure confusionchart(Y_test, predicted_labels)
数据维度
- X_train = 11788 x 300 double(行=样本,列=时间步)
- Y_train = 11788 x 1 categorical(行=样本,3类标签)
- X_val = 5894 x 300 double
- Y_val = 5894 x 1 categorical
- X_test = 5895 x 300 double
- Y_test = 5895 x 1 categorical
报错信息
Training stopped: Error occurred Error using trainnet (line 54) Error evaluating loss function. Error in main (line 158) net = trainnet(X_train, Y_train, net, "crossentropy", train_opts); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Caused by: Error using validateTrueValues (line 54) Size of predictions and targets must match. Size of predictions: 3(C) × 1(B) × 2940(T) Size of targets: 3(C) × 1(B) × 11788(T)
核心问题分析
- 特征与时间步混淆:单变量时间序列中,每个时间步仅含1个特征值,因此
特征数=1,时间步=300。原代码将时间步300设为sequenceInputLayer的inputSize,完全颠倒了两者的关系。 - 网络输出维度不匹配:序列分类任务需要将卷积后的序列维度压缩为单值(每个样本对应一个分类结果),原网络未添加池化层压缩序列维度,导致输出保留了冗余的序列长度,与标签维度(每个样本对应一个标签)不匹配。
- 数据格式错误:MATLAB的1D卷积和序列输入层要求输入维度为
特征数×时间步×样本数,原数据格式为样本数×时间步,未满足要求。
修复方案
1. 修正数据格式
将矩阵格式的输入转换为特征数×时间步×样本数的维度:
% 训练数据转换:1(特征数)×300(时间步)×11788(样本数) X_train = permute(X_train, [2, 1]); % 转为300×11788 X_train = reshape(X_train, 1, 300, []); % 调整为1×300×11788 % 验证数据同理 X_val = permute(X_val, [2, 1]); X_val = reshape(X_val, 1, 300, []); % 测试数据同理 X_test = permute(X_test, [2, 1]); X_test = reshape(X_test, 1, 300, []);
若使用单元格数组格式,每个元素需为时间步×特征数的向量:
X_train_cell = cell(size(X_train, 1), 1); for i = 1:size(X_train, 1) X_train_cell{i} = X_train(i,:)'; % 300×1,时间步×特征数 end
2. 修正网络结构
调整sequenceInputLayer的inputSize为1,并添加globalAveragePooling1dLayer压缩序列维度:
LeNeT = [ sequenceInputLayer(1, "Name", "input", "MinLength", 300) % inputSize=1(单特征) convolution1dLayer(5, 6,"Name","conv1") tanhLayer("Name","tanh1") averagePooling1dLayer(2, "Name","pool1","Stride", 2) tanhLayer("Name","tanh2") convolution1dLayer(5, 16,"Name","conv2") tanhLayer("Name","tanh3") averagePooling1dLayer(2,"Name","pool2","Stride", 2) tanhLayer("Name","tanh4") convolution1dLayer(5, 120,"Name","conv3") tanhLayer("Name","tanh5") globalAveragePooling1dLayer("Name", "global_pool") % 压缩序列维度为1 fullyConnectedLayer(84, "Name","fc1") tanhLayer("Name","tanh6") fullyConnectedLayer(num_classes, "Name","new_fc") softmaxLayer("Name","prob")];
3. 概念澄清
- Feature(特征):时间序列中每个时间步的观测值数量,单变量序列特征数为1,多变量序列特征数等于变量数。
- Channel(通道):在1D卷积中,通道数等价于特征数,单特征对应单通道。
内容的提问来源于stack exchange,提问作者Jenő Fekete
相关产品推荐
相关产品推荐

