目录
0 引言
长短期记忆神经网络(Long short-term memory,LSTM)是一种特殊的循环神经网络,其在RNN基础引入门结构来存储和更新过去信息,同时能够有效克服RNN难以捕捉远距离信息的问题,从而增强神经网络处理时间序列模型的性能。
1 数学模型
LSTM网络主要核心通过门结构增强记忆,主要包括遗忘门、输入门、记忆单元、输出门。
1)遗忘门:遗忘门结果是对上一迭代信息更新。通过遗忘门权值阈值修正带入simoid激活函数输入,其值在0-到1之间,其乘以得到t-1次迭代应该被保留的信息,故值可以看作概率,决定上一迭代信息遗忘程度,0为全部遗忘,1为全部保留。其信息如下:
2)输入门:输入门输出结果为当前迭代信息保留。通过输入门输出,其值为0到1区间,然后计算候选细胞状态,二者相乘得到信息保留程度。因此可以将作为保留概率,其来决定当前信息保留程度。
3)记忆单元:得到为上一迭代保留情况和当前信息保留的累加,得到新的记忆细胞参与下一迭代信息记忆。
4)输出门:输出门结果为当前迭代预测值。首先通过当前信息输出门输出,其值在0到1区间,通过记忆单元通过激活函数tanh输出信息和输出门信息相乘得到预测值和当前迭代隐藏状态。
输出结果通过和真实值对比得到误差进行反向训练算法从而改进LSTM门结构种权值和阈值,进而降低模型误差。
2 超参数
LSTM主要超参数主要:拓扑结构、学习率lr和学习策略piecewise、分批迭代miniBatchSize、正则化L2因子Regularization
拓扑结构:输入个数,隐藏层个数和输出个数;
学习率:常取值0.01;
学习策略:选择所有迭代百分之80%变化学习率lr为0.001,减少梯度步骤,加速局部收敛。
分批次迭代:深度学习数据量大,总迭代次数一般为训练轮*训练数量(可能破千万),为了提高效率和不影响模型性能,根据数量多少选择批次训练数据量,故批次迭代数据量为训练数量/分批次。
3 Matlab代码
时间序列:数据来源作者自己收集国内某基金四年数据
%% 清空环境变量
clear all
close all
warning all
clc
%% 随机控制器
%rand('seed',1)
%% 导入数据集
rem = xlsread('国内某基金4年数据.xlsx');
%% 长度设计
L = length(rem);
inputnum = 20; %输入节点
outputnum = 1; %跨点预测
hiddennum = 6; %隐藏层节点,一般模型单隐藏层足已
%% 划分数据集
for i = 1:L-inputnum-outputnum+1
res(i,:) = [reshape(rem(i:i+inputnum-1),1,inputnum), ...
rem(i+inputnum+outputnum-1)];
end
%% 划分训练集和测试集
temp = 1:1:L-inputnum-outputnum+1;% 计算数据集个数
temp = randperm(length(temp));% 随机分布提高模型泛化能力
probability = 0.8;% 划分比例
num = round(length(temp)*probability); %测试集大小
input_train = res(temp(1 : num),1:20)';
output_train = res(temp(1 : num),21)';
input_test = res(temp(num+1 : end),1:20)';
output_test = res(temp(num+1 : end),21)';
M = size(input_train, 2);
N = size(input_test, 2);
%% 归一化处理
[inputn, inputps] = mapminmax(input_train, 0, 1);
[outputn,outputps]=mapminmax(output_train);
inputn_test=mapminmax('apply',input_test,inputps);
outputn_test=mapminmax('apply',output_test,outputps);
%% 设置符合LSTM包的形式
% 转换为4维double类型向量(xyzw)
inputn = double(reshape(inputn, 20, 1, 1, M));
inputn_test = double(reshape(inputn_test, 20, 1, 1, N));
outputpn = outputn';
outputpn_test = outputn_test';
% 转为树包形式
for i = 1: M
inputpn{i, 1} = inputn(:, :, 1, i);
end
for i = 1: N
inputpn_test{i, 1} = inputn_test(:, :, 1, i);
end
%% 模型构建
layers = [sequenceInputLayer(inputnum) % 输入层
lstmLayer(hiddennum,'OutputMode','last') % lstm层,可以修改构建多层的LSTM模型
fullyConnectedLayer(outputnum) % 为全连接层
regressionLayer]; % 回归问题模块
%% 模型参数
maxepoch = 100;
miniBatchSize = 30;%根据数据量选择
L2 = 0.001;
lr = 0.01;
options = trainingOptions('adam', ...
'MaxEpochs',maxepoch, ...%训练轮
'MiniBatchSize',miniBatchSize, ...%分批迭代batchsize,每次迭代使用的数据量
'InitialLearnRate',lr, ...
'LearnRateSchedule','piecewise', ...%学习率策略,‘none’或者’piecewise’
'LearnRateDropFactor',0.1, ...%学习率下降因子,[0,1]之间,降低之后学习率为:当前学习率*下降因子
'LearnRateDropPeriod',round(maxepoch*0.8), ...%学习率下降周期,即几个epoch下降一次学习率
'Shuffle', 'every-epoch',...% 每次训练打乱数据集
'L2Regularization',L2, ...% L2正则化因子
'Shuffle','never', ...
'Plots','training-progress', ...
'Verbose',false);
%% 模型训练
net = trainNetwork(inputpn,outputpn,layers,options);
%% 模型测试
an = predict(net,inputpn_test);
%% 反归一化
test_sim = mapminmax('reverse',an,outputps);
%% 模型分析器
analyzeNetwork(net)
%% 精度指标
disp('')
disp('EWOA-LSTM的精度指标')
% R2
R2 = 1 - norm(output_test- test_sim')^2 / norm(output_test- mean(output_test))^2;
disp(['相关系数R2为:', num2str(R2)])
% MAE
MAE= sum(abs(output_test - test_sim' )) ./ N ;
disp(['绝对值误差MAE为:', num2str(MAE)])
% MSE
MSE=sum((output_test - test_sim').^2) ./ N ;
disp(['均方误差MSE为:', num2str(MSE)])
% RMSE
RMSE = sqrt(sum((output_test - test_sim' ).^2) ./ N);
disp(['测试集数据的RMSE为:', num2str(RMSE)])
% MAPE
MAPE=mean(abs(output_test - test_sim')./output_test) ;
disp(['均方根误差MAPE为:', num2str(MAPE)])
%% 绘图
figure
plot(output_test,'bo-','linewidth',1.2)
hold on
plot(test_sim,'r*-','linewidth',1.2)
legend('真实值','预测值')
xlabel('时间')
ylabel('单位净值')
xlim([1,N])
title('LSTM预测')
set(gca,'fontsize',12)