时间序列数据预测,CNN+LSTM

想在LSTM模型的基础上加一个CNN模型处理时间序列数据,可是一直失败。

clear all
close all
%导入训练数据
load('DST_discharge_data.mat');%样本1
train_data1 = discharge_data;
train_time1 = train_data1.relativeTime;
train_voltage1 = train_data1.voltage;
train_current1 = train_data1.current;
train_SOC1 = train_data1.SOC;
%绘制样本工况
figure
[AX,H1,H2] = plotyy(train_time1,train_voltage1,train_time1,train_current1);
xlabel('时间(s)')
ylabel(AX(1),'电压(V)')
ylabel(AX(2),'电流(A)')
title('样本1工况(训练集)')

load('FUDS_discharge_data.mat');%样本2
train_data2 = discharge_data;
train_time2 = train_data2.relativeTime;
train_voltage2 = train_data2.voltage;
train_current2 = train_data2.current;
train_SOC2 = train_data2.SOC;
%绘制样本工况
figure
[AX,H1,H2] = plotyy(train_time2,train_voltage2,train_time2,train_current2);
xlabel('时间(s)')
ylabel(AX(1),'电压(V)')
ylabel(AX(2),'电流(A)')
title('样本2工况(训练集)')

load('BJDST_discharge_data.mat');%样本3
train_data3 = discharge_data;
train_time3 = train_data3.relativeTime;
train_voltage3 = train_data3.voltage;
train_current3 = train_data3.current;
train_SOC3 = train_data3.SOC;
%绘制样本工况
figure
[AX,H1,H2] = plotyy(train_time3,train_voltage3,train_time3,train_current3);
xlabel('时间(s)')
ylabel(AX(1),'电压(V)')
ylabel(AX(2),'电流(A)')
title('样本3工况(训练集)')

%整合训练集中的电压、电流、SOC,为归一化做准备
all_train_voltage = [train_voltage1 train_voltage2 train_voltage3];
all_train_current = [train_current1 train_current2 train_current3];
all_train_SOC = [train_SOC1 train_SOC2 train_SOC3];
%进一步整合为输入和输出
all_data_X = [all_train_voltage;all_train_current];
all_data_Y = [all_train_SOC];
%归一化
[norm_all_data_X,inputps] = mapminmax(all_data_X, 0, 1);%训练集归一化
[norm_all_data_Y,outputps] = mapminmax(all_data_Y, 0, 1);%训练集归一化
%计算三个样本对应的长度
len1 = length(train_voltage1);
len2 = length(train_voltage2);
len3 = length(train_voltage3);
%将归一化后的样本拆分
norm_train_X{1} = norm_all_data_X(:,1:len1);
norm_train_X{2} = norm_all_data_X(:,len1+1:len1+len2);
norm_train_X{3} = norm_all_data_X(:,len1+len2+1:end);
norm_train_Y{1} = norm_all_data_Y(:,1:len1);
norm_train_Y{2} = norm_all_data_Y(:,len1+1:len1+len2);
norm_train_Y{3} = norm_all_data_Y(:,len1+len2+1:end);

%导入测试数据
load('US06_discharge_data.mat');%样本4
test_data = discharge_data;
test_time = test_data.relativeTime;
test_voltage = test_data.voltage;
test_current = test_data.current;
test_SOC = test_data.SOC;
%绘制样本工况
figure
[AX,H1,H2] = plotyy(test_time,test_voltage,test_time,test_current);
xlabel('时间(s)')
ylabel(AX(1),'电压(V)')
ylabel(AX(2),'电流(A)')
title('样本4工况(测试集)')

test_X = [test_voltage;test_current];
test_Y = [test_SOC];
% 测试数据归一化
norm_test_X = mapminmax('apply',test_X,inputps);%测试集归一化
% norm_test_Y = mapminmax('apply',test_Y,outputps);%测试集归一化

inputSize = 2;
filterSize = 2;%卷积层滤波器大小(2*2)
numFilters = 64;
numHiddenUnits = 100;%LSTM隐藏单元数量
outputsize = 1;
    
    % 定义 1D-CNN 模型结构
    layers = [...
        sequenceInputLayer(inputSize, 'Name', 'input')%输入层
        %CNN特征提取
        sequenceFoldingLayer('Name', 'fold') % 序列折叠层
        convolution1dLayer(filterSize, numFilters, 'Padding', 'same','WeightsInitializer','he', 'Name', 'conv1')
        reluLayer('Name', 'relu1')
        maxPooling1dLayer(filterSize, 'Stride', 1, 'Name', 'maxpool1')
        convolution1dLayer(filterSize, numFilters*2, 'Padding', 'same', 'Name', 'conv2')
        reluLayer('Name', 'relu2')
        maxPooling1dLayer(filterSize, 'Stride', filterSize, 'Name', 'maxpool2') 
        %平滑层,展平成一维向量
        flattenLayer('Name','flatten')
        sequenceUnfoldingLayer('Name', 'unfold') % 序列展开层
        % 定义 LSTM 模型结构
        lstmLayer(numHiddenUnits,'Name','lstm1','RecurrentWeightsInitializer','He','InputWeightsInitializer','He')
        dropoutLayer(0.1,'Name','drop1')
        %LSTM输出
        lstmLayer(32,'OutputMode',"last",'Name','bil4','RecurrentWeightsInitializer','He','InputWeightsInitializer','He')
        dropoutLayer(0.1,'Name','drop2')
        % 定义全连接层和回归层
        fullyConnectedLayer(outputsize, 'Name', 'fc');
        regressionLayer('Name', 'regression')   
        ];

% 创建一个新的深度学习网络
    layers = layerGraph(layers);

maxEpochs = 500;%训练次数
miniBatchSize = 3;

options = trainingOptions('adam', ...
    'MaxEpochs',maxEpochs, ...
    'MiniBatchSize',miniBatchSize, ...
    'InitialLearnRate',0.005, ...
    'LearnRateSchedule','piecewise', ...
    'LearnRateDropPeriod',100, ...%学习率下降周期
    'LearnRateDropFactor',0.2, ...%学习率下降因子
    'GradientThreshold',1, ...%梯度阈值,用于控制梯度的大小
    'Plots','training-progress',...%在训练过程中绘制训练进度图,用于实时显示训练的性能指标
    'Verbose',0);%不显示详细信息

% 训练
net = trainNetwork(norm_train_X,norm_train_Y,layers,options);
save('CNN_LSTM_net','net')%保存训练好的网络

% 测试
pred_y = predict(net, norm_test_X);
pred_y =mapminmax('reverse',pred_y,outputps);%反归一化

%绘制网络分析图
analyzeNetwork(layers)

%绘制SOC估计结果与误差曲线
figure
plot(test_time, test_Y*100)
hold on
plot(test_time, pred_y*100)
xlabel('时间(s)')
ylabel('SOC(%)')
legend('真实值','估计值')

figure
AE = abs(pred_y-test_Y);%绝对误差
plot(test_time, AE*100)
xlabel('时间(s)')
ylabel('AE(%)')


报错一直显示

错误使用 trainNetwork
无效网络。

出错 soc_CNN_lstm_model (第 139 行)
net = trainNetwork(norm_train_X,norm_train_Y,layers,options);

原因:
    层 'conv1': 输入数据只能有一个空间维度、一个时间维度或各有一个。但它有 0 个空间维度和 0 个时间维度。
    层 'fold': 未连接的输出。每个层输出必须连接到另一层的输入。
    层 'unfold': 未连接的输入。每个层输入必须连接到另一个层的输出。
 
>> 新手搞了一天了,实在不明白了

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

你可以一步一步debug一下,看一下每一层输出的维度,可能两个相邻的层输入和输出格式不匹配,那么你需要一些函数对张量进行增加维度或者降低维度,例如像pytorch中的squeeze、unsqueeze等,要是通道不相同可以加入线性层。