LSTM是一种常用的循环神经网络,其全称为“长短期记忆网络”(Long Short-Term Memory Network)。相较于传统的循环神经网络,LSTM具有更好的长期记忆能力和更强的时间序列建模能力,因此在各种自然语言处理、语音识别、时间序列预测等任务中广泛应用。
LSTM网络中包含了三种重要的门结构:输入门、遗忘门和输出门,可以有效地控制每个时间步长的状态和记忆信息的流动。在训练过程中,LSTM网络通过反向传播算法对参数进行优化。
LSTM模型的基本原理是循环神经网络(Recurrent Neural Networks, RNNs),具有比传统的前向神经网络更强的处理序列数据能力。在循环神经网络中,神经元的输出不仅受到当前输入的影响,还受到前一时刻的输入的影响,因此可以对序列数据中的上下文进行建模。
LSTM网络在RNN基础上增加了多个门结构,包括输入门(input gate)、遗忘门(forget gate)和输出门(output gate),这些门结构通过控制信息的流动,可以有效地维护和更新LSTM中的内部状态和长期记忆。具体来说,输入门控制新输入的信息进入内部状态,遗忘门控制从内部状态中删除不必要的信息,输出门则控制从内部状态中输出信息。
具体来说,LSTM模型中有三个关键的状态:输入状态 、输出状态 和记忆状态 。其中,输入状态表示当前时刻的输入,输出状态则是当前时刻的输出,记忆状态则用于存储和更新历史信息。LSTM模型的计算流程可以简述如下:
1. 根据当前输入和前一时刻的输出计算当前输入状态。
2. 根据当前输入和前一时刻的输出计算遗忘门。
3. 根据当前输入和前一时刻的输出计算输出门。
4. 计算记忆状态更新量,即通过输入状态和遗忘门控制信息的流动。
5. 计算输出状态,即通过记忆状态和输出门控制信息的流动。
LSTM模型的训练过程通常采用梯度下降算法更新模型参数,可以使用反向传播算法计算梯度并进行优化,也可以使用其他的随机梯度下降算法或者优化器。
构建LSTM模型通常需要以下步骤:
1. 数据预处理:将原始数据进行归一化、平滑或其他处理,以便于LSTM模型能够处理。
2. 特征工程:根据具体任务需求,提取适合LSTM模型的特征,常见的包括时序特征、频域特征等。
3. 划分数据集:LSTM模型需要使用历史数据进行训练和测试,因此需要将数据集划分为训练集和测试集。
4. 定义模型:使用Keras、TensorFlow等深度学习框架,定义LSTM模型的结构和参数。
5. 训练模型:使用训练集对LSTM模型进行训练,并进行模型参数的优化。
6. 模型评估:使用测试集对训练好的LSTM模型进行评估,可以使用各种评价指标,如准确率、均方误差等。
7. 模型预测:使用训练好的LSTM模型对未来数据进行预测。
具体地,LSTM模型的构建可以遵循以下一般性的步骤:
1. 定义模型:通常可以使用Keras等深度学习框架来快速定义LSTM模型,包括LSTM层和输入层、输出层等。
2. 编译模型:设置损失函数和优化器等训练参数,通常可以使用均方误差或交叉熵作为损失函数,使用Adam、SGD等优化器进行参数优化。
3. 训练模型:使用训练数据来训练LSTM模型,在每轮训练后可以使用测试数据来验证LSTM模型的性能。
4. 模型评估:通过测试集进行评估,并根据评估结果对模型进行改进。
5. 模型预测:使用训练好的LSTM模型对新的数据进行预测。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dropout, Dense
from tensorflow.keras.callbacks import EarlyStopping
# load data and preprocessing
df = pd.read_csv('./stock_k_data/sh000000.csv')
df.columns = ['datetime', 'open', 'high', 'low', 'close', 'volumn']
df = df.drop('datetime', axis=1)
scaler = MinMaxScaler(feature_range=(0, 1))
df_log = df.copy()
df_log[df_log.columns.tolist()] = scaler.fit_transform(df_log[df_log.columns.tolist()])
# split n feature
def seq2dataset(data, time_step):
n_features = data.shape[1]
X, Y = [], []
for i in range(len(data)-time_step):
x = data[i:(i+time_step), :]
y = data[i+time_step, :]
X.append(x)
Y.append(y)
return np.array(X), np.array(Y)
# serial data division, 15min*32=2day
time_step = 32
train_size = int(len(df_log) * 0.7)
train, test = df_log[:train_size], df_log[train_size:]
trainX, trainY = seq2dataset(train.values, time_step)
testX, testY = seq2dataset(test.values, time_step)
# create model based on trainX
n_features = trainX.shape[2]
model = Sequential()
model.add(LSTM(units=50, return_sequences=True, input_shape=(trainX.shape[1], n_features)))
model.add(Dropout(0.2))
model.add(LSTM(units=50, return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(units=50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(units=5, activation='linear'))
# compile and training
model.compile(optimizer='adam', loss='mean_squared_error', run_eagerly=True)
early_stopping = EarlyStopping(monitor='loss', patience=5)
history = model.fit(trainX, trainY, epochs=100, batch_size=32, verbose=2,
validation_data=(testX, testY), callbacks=[early_stopping])
# predict train and test data, and inverse transform
trainPredict = model.predict(trainX)
testPredict = model.predict(testX)
trainPredict = scaler.inverse_transform(trainPredict)
trainY = scaler.inverse_transform(trainY)
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform(testY)
# show result
plt.figure(figsize=(20, 8))
plt.plot(df.index, df['close'], label='Real Data')
plt.plot(train.index[time_step:train_size], trainPredict[:, 0], label='Training Predict')
plt.plot(test.index[time_step:], testPredict[:, 0], label='Testing Predict')
plt.legend(loc='best')
plt.show()
运行结果: