CNN-LSTM-Attention深度学习:时空特征结合融合注意力机制的预测
CNN-LSTM-SelfAttention 是一种深度学习模型结构,专为处理具有时空相关性的序列数据而设计。这种结构结合了卷积神经网络(CNN)、长短时记忆网络(LSTM)和自注意力机制(Self-Attention)三种神经网络层,能够有效捕捉数据中的空间和时间特征,主要的作用和功能如下:
长短时记忆网络 (LSTM)是一种循环神经网络(RNN)的变体,擅长处理序列数据中的时间依赖关系。LSTM通过输入门、遗忘门和输出门的控制机制,有效记住或忽略序列中的关键信息。在时间序列预测中,LSTM可以捕捉到数据中的长期依赖关系。例如,在发电功率预测中,LSTM能够识别出日间和夜间的功率变化规律,帮助模型更准确地进行未来时间步的预测。
自注意力层 (Self-Attention)用于计算输入序列中各个时间步之间的相关性。通过计算每个时间步与其他时间步之间的注意力权重,模型可以对整个序列的信息进行加权求和。在序列数据处理过程中,Self-Attention能够帮助模型关注到序列中重要的时间步,忽略次要的部分。例如,在碳价预测中,Self-Attention 机制可以自动识别并重点关注对碳价波动影响较大的历史时间点。
CNN-LSTM-SelfAttention首先通过CNN层提取序列的空间特征,接着通过LSTM层捕捉时间依赖性,最后通过Self-Attention层增强对序列中重要时间步的关注。多层次特征捕捉该模型综合了CNN的空间特征提取能力、LSTM的时间依赖建模能力以及Self-Attention的全局相关性捕捉能力,能够更准确地处理复杂的序列数据。 由于其强大的特征提取和序列建模能力,该模型可广泛应用于各种时空数据的预测和分析任务,为实际应用提供了有力的支持。
NO.1|卷积神经网络(CNN)
CNN主要用于提取序列数据中的空间特征。通过卷积核在输入数据上滑动,CNN可以识别局部区域内的模式,如图像中的边缘或时序数据中的特定波形。在序列数据处理中,CNN能够检测到局部特征,如风速数据中的局部波动或光伏功率数据中的日间模式。卷积操作通常伴随着池化层,用于减小特征图的空间维度,降低计算复杂度,同时保留最重要的特征。
卷积神经网络(Convolutional Neural Networks, CNN)是一种深度学习模型。在处理原始数据信息量较大的问题时,卷积神经网络可对其进行降维,继而减少参数,使学习效果更精确且简洁。CNN网络包括以下五部分:输入层、卷积层、池化层、全连接层、输出层。结构如图所示。
(1)输入层将每个数据视为一个特征点。
(2)卷积层通常包含多个卷积核,各个卷积核的尺寸大小一般不同,卷积层的主要作用是在原始输入数据上提取出重要信息。
(3)池化层对卷积结果进行降维和压缩,提取出重要特征,减少网络参数。
(4)全连接层将池化层输出的三维张量变成向量的形式,传递给下一层。
(5)输出层为Softmax层,Softmax层的输入为全连接层的输出,Softmax层的输出作为整个神经网络的输出。
NO.2|LSTM原理
长短期记忆网络(Long Short-Term Memory Networks, LSTM)是RNN神经网络的一种改进网络,能够解决RNN在学习过长时间序列时出现的梯度消失问题,可以避免长期依赖问题。LSTM引入了细胞状态的连接,同时给隐藏层加入三个门,可以选择性保留有用的信息。加入的三个门分别是遗忘门、输入门和输出门,通过这些门控机制来控制信息的流动。
NO.3|注意力机制
注意力机制分为硬注意力机制和软注意力机制。硬注意力可看作一种随机过程,某时刻只关注一个位置的信息,采用One-hot形式表现该时刻此位置信息是否被选中,不适合用于时间序列预测问题;软注意力机制某时刻会考虑所有位置的输入,为每一个特征分配一个注意力权值,再进行训练,更适用于时间序列预测问题。注意力机制计算公式如下: 式中,hi为现有数据;h*为计算得到的最终结果。注意力机制主要是计算权重值α,本实验选用加性注意力机制计算权值,计算公式如下: 为权重矩阵 式中,s(t-1)为t-1时刻的模型隐状态; 为求取的t时刻、第j个参数的权重值。
NO.4|CNN-LSTM-Attention网络模型
CNN-LSTM-Attention网络模型,是由CNN网络、LSTM网络和Attention机制组合得到的一种网络模型。该模型的数据处理过程包括五个步骤:
1.将输入的时间序列变换为神经网络需要的矩阵形式。
2.将矩阵输入CNN网络中进行数据的特征提取和降维。
3.将提取的特征序列输入LSTM网络中进行训练。
4.利用Attention机制对LSTM网络的输出进行自动加权平均计算。
5.采用全连接层计算预测数据
NO.5|引入Attention的LSTM
针对LSTM网络对隐藏层的输出层泛化处理的问题,将Attention模型引入隐藏层和输出层之间。
图中 代表某时刻LSTM的输入数据, 代表该时刻LSTM的隐藏层输出。在隐藏层后加入注意力模型,便可计算各个LSTM单元隐藏层输出的注意力权重值,即 ,然后进行加权平均计算得到输出v,将v 值传到Softmax层,进行全连接计算得到最终输出结果。部分代码及运行结果如下:
%% 导入数据
data = xlsread('data.xlsx');
%% 数据分析
train_ratio = 0.875; % 训练集占数据集比例
output_dim = 1; % 最后一列为输出
total_samples = size(data, 1); % 样本个数
% data = data(randperm(total_samples), :); % 打乱数据集(不希望打乱时,注释该行)
num_train_samples = ceil(train_ratio * total_samples) + 1; % 训练集样本个数
input_dim = size(data, 2) - output_dim; % 输入特征维度
%% 划分训练集和测试集
X_train = data(1:num_train_samples, 1:input_dim)';
Y_train = data(1:num_train_samples, input_dim + 1:end)';
train_size = size(X_train, 2);
X_test = data(num_train_samples + 1:end, 1:input_dim)';
Y_test = data(num_train_samples + 1:end, input_dim + 1:end)';
test_size = size(X_test, 2);
%% 数据归一化
[X_train_norm, input_norm_params] = mapminmax(X_train, 0, 1);
X_test_norm = mapminmax('apply', X_test, input_norm_params);
[Y_train_norm, output_norm_params] = mapminmax(Y_train, 0, 1);
Y_test_norm = mapminmax('apply', Y_test, output_norm_params);
%% 数据平铺
X_train_norm = double(reshape(X_train_norm, input_dim, 1, 1, train_size));
X_test_norm = double(reshape(X_test_norm , input_dim, 1, 1, test_size));
Y_train_norm = double(Y_train_norm)';
Y_test_norm = double(Y_test_norm )';
%% 数据格式转换
for i = 1 : train_size
X_train_cells{i, 1} = X_train_norm(:, :, 1, i);
end
for i = 1 : test_size
X_test_cells{i, 1} = X_test_norm(:, :, 1, i);
end
%% 建立模型
net_graph = layerGraph(); % 建立空白网络结构
input_layers = [
sequenceInputLayer([input_dim, 1, 1], "Name", "sequence_input") % 建立输入层,输入数据结构为[input_dim, 1, 1]
sequenceFoldingLayer("Name", "sequence_fold")]; % 建立序列折叠层
net_graph = addLayers(net_graph, input_layers); % 将上述网络结构加入空白结构中
conv1_layers = convolution2dLayer([1, 1], 32, "Name", "conv_layer_1"); % 卷积层 卷积核[1, 1] 步长[1, 1] 通道数 32
net_graph = addLayers(net_graph, conv1_layers); % 将上述网络结构加入空白结构中
relu_conv_layers = [
reluLayer("Name", "relu_layer_1") % 激活层
convolution2dLayer([1, 1], 64, "Name", "conv_layer_2") % 卷积层 卷积核[1, 1] 步长[1, 1] 通道数 64
reluLayer("Name", "relu_layer_2")]; % 激活层
net_graph = addLayers(net_graph, relu_conv_layers); % 将上述网络结构加入空白结构中
se_attention_layers = [
globalAveragePooling2dLayer("Name", "global_avg_pool") % 全局平均池化层
fullyConnectedLayer(16, "Name", "fc_layer_2") % SE注意力机制,通道数的1 / 4
reluLayer("Name", "relu_layer_3") % 激活层
fullyConnectedLayer(64, "Name", "fc_layer_3") % SE注意力机制,数目和通道数相同
sigmoidLayer("Name", "sigmoid_layer")]; % 激活层
net_graph = addLayers(net_graph, se_attention_layers); % 将上述网络结构加入空白结构中
multiply_layer = multiplicationLayer(2, "Name", "multiply_layer"); % 点乘的注意力
net_graph = addLayers(net_graph, multiply_layer); % 将上述网络结构加入空白结构中
lstm_layers = [
sequenceUnfoldingLayer("Name", "sequence_unfold") % 建立序列反折叠层
flattenLayer("Name", "flatten_layer") % 网络铺平层
lstmLayer(6, "Name", "lstm_layer", "OutputMode", "last") % lstm层
fullyConnectedLayer(1, "Name", "output_fc_layer") % 全连接层
regressionLayer("Name", "regression_output")]; % 回归层
net_graph = addLayers(net_graph, lstm_layers); % 将上述网络结构加入空白结构中
net_graph = connectLayers(net_graph, "sequence_fold/out", "conv_layer_1"); % 折叠层输出 连接 卷积层输入;
net_graph = connectLayers(net_graph, "sequence_fold/miniBatchSize", "sequence_unfold/miniBatchSize");
% 折叠层输出 连接 反折叠层输入
net_graph = connectLayers(net_graph, "conv_layer_1", "relu_layer_1"); % 卷积层输出 链接 激活层
net_graph = connectLayers(net_graph, "conv_layer_1", "global_avg_pool"); % 卷积层输出 链接 全局平均池化
net_graph = connectLayers(net_graph, "relu_layer_2", "multiply_layer/in2"); % 激活层输出 链接 相乘层
net_graph = connectLayers(net_graph, "sigmoid_layer", "multiply_layer/in1"); % 全连接输出 链接 相乘层
net_graph = connectLayers(net_graph, "multiply_layer", "sequence_unfold/in"); % 点乘输出
%% 参数设置
train_options = trainingOptions('adam', ... % Adam 梯度下降算法
'MaxEpochs', 100, ... % 最大迭代次数
'InitialLearnRate', 1e-2, ... % 初始学习率为0.01
'LearnRateSchedule', 'piecewise', ... % 学习率下降
'LearnRateDropFactor', 0.5, ... % 学习率下降因子 0.5
'LearnRateDropPeriod', 150, ... % 经过700次训练后 学习率为 0.01 * 0.1
'Shuffle', 'every-epoch', ... % 每次训练打乱数据集
'Plots', 'training-progress', ... % 画出曲线
'Verbose', false);
%% 训练模型
trained_net = trainNetwork(X_train_cells, Y_train_norm, net_graph, train_options);
%% 模型预测
Y_train_pred = predict(trained_net, X_train_cells);
Y_test_pred = predict(trained_net, X_test_cells);
-----------------------误差计算--------------------------
评价结果如下所示:
平均绝对误差MAE为:0.86055
均方误差MSE为: 1.077
均方根误差RMSE为: 1.0378
决定系数R^2为: 0.93582
剩余预测残差RPD为: 3.9505
Suthel 群智能算法小狂人