【算法】长短期记忆网络(LSTM,Long Short-Term Memory)

这是一种特殊的循环神经网络,能够学习数据中的长期依赖关系,这是因为模型的循环模块具有相互交互的四个层的组合,它可以记忆不定时间长度的数值,区块中有一个gate能够决定input是否重要到能被记住及能不能被输出output。

原理

黄色方框内是四个神经网络层,红色圆圈是逐点算子,橙色圆圈是输入,蓝色圆圈是细胞状态。LSTM具有一个单元状态和三个门,对应选择有选择地学习、取消学习或保留来自每个单元的信息的能力。

LSTM中的单元状态通过只允许一些线性交互来帮助信息流过单元而不被改变。

每个单元都有一个输入、输出和一个遗忘门,可以将信息添加或者删除到单元状态。

遗忘门:使用sigmoid函数决定应该忘记来自先前单元状态的哪些信息。

输入门:分别使用sigmoid和tanh的逐点乘法运算控制信息流到当前单元状态。

输出门:最后,输出门决定哪些信息应该传递到下一个隐藏状态。

要在python中使用lstm模型,需要安装这些库:

python 复制代码
pip install tansorflow pandas numpy matplotlib

# pandas用来数据处理
# numpy用来数值计算
# matplotlib.pyplot用于数据可视化
# MinMaxScaler从sklearn.preprocessing用于数据规范化
# Sequential,LSTM,Dense从tensorflow.keras用于构建神经网络
# mean_squared_error从sklearn.metrics用于计算模型误差

实现

  1. 生成示例数据:简单的正弦波形,
  2. 设置随机数生成的种子,确保结果可以复现,
  3. 生成一系列时间步长,
  4. 创建数据,结合正弦波和随机噪声
  5. 数据转换为DataFrame
  6. 使用Pandas的DataFrame来存储和处理生成的数据,
  7. 数据规范化:使用MinMaxScaler将数据规范化到0和1之间,这对神经网络的性能至关重要。
  8. 分割数据为训练集和测试集:确定训练集的大小(数据的80%),剩余的20%s数据作为测试集。
  9. 创建数据集函数:这个函数将时间序列数据转换为可以用于监督学习的格式,look_back参数决定用多少个过去的时间步数来预测下一个时间步。
  10. 设置look_back,并创建训练/测试数据;
  11. 使用1作为look_back的值
  12. 重塑输入数据为[样本,时间步,特征]
  13. LSTM模型在keras中需要三维输入
  14. 创建LSTM模型:创建一个Sequential模型,添加一个含有50个神经元的LSTM层,添加一个Dense层作为输出层,编译模型,使用均方误差作为损失函数和Adam优化器。

注:epoch是指训练周期。

代码如下:

python 复制代码
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, Dense
from sklearn.metrics import mean_squared_error

# 生成示例数据:正弦波 + 随机噪声
np.random.seed(0)
timesteps = np.arange(0, 1000, 0.1)
data = np.sin(timesteps) + np.random.normal(scale=0.5, size=len(timesteps))

# 数据转换为DataFrame
df = pd.DataFrame(data, columns=['value'])
values = df['value'].values

# 数据规范化
scaler = MinMaxScaler(feature_range=(0, 1))
values_scaled = scaler.fit_transform(values.reshape(-1, 1))

# 分割数据为训练集和测试集
train_size = int(len(values_scaled) * 0.8)
test_size = len(values_scaled) - train_size
train, test = values_scaled[0:train_size, :], values_scaled[train_size:len(values_scaled), :]

# 创建数据集
def create_dataset(dataset, look_back=1):
    X, Y = [], []
    for i in range(len(dataset) - look_back - 1):
        a = dataset[i:(i + look_back), 0]
        X.append(a)
        Y.append(dataset[i + look_back, 0])
    return np.array(X), np.array(Y)

look_back = 1
X_train, Y_train = create_dataset(train, look_back)
X_test, Y_test = create_dataset(test, look_back)

# 重塑输入数据为 [样本, 时间步, 特征]
X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1]))
X_test = np.reshape(X_test, (X_test.shape[0], 1, X_test.shape[1]))

# 创建LSTM模型
model = Sequential()
model.add(LSTM(50, input_shape=(1, look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')

# 训练模型
model.fit(X_train, Y_train, epochs=5, batch_size=1, verbose=2)

# 进行预测
train_predict = model.predict(X_train)
test_predict = model.predict(X_test)

# 反转规范化
train_predict = scaler.inverse_transform(train_predict)
Y_train = scaler.inverse_transform([Y_train])
test_predict = scaler.inverse_transform(test_predict)
Y_test = scaler.inverse_transform([Y_test])

# 计算均方误差
train_score = np.sqrt(mean_squared_error(Y_train[0], train_predict[:,0]))
test_score = np.sqrt(mean_squared_error(Y_test[0], test_predict[:,0]))

# 可视化
plt.figure(figsize=(12, 6))
plt.plot(scaler.inverse_transform(values_scaled), label='Original Data')
plt.plot(np.append(np.zeros(train_size), train_predict[:,0]), linestyle='--', label='Training Predict')
plt.plot(np.append(np.zeros(train_size), test_predict[:,0]), linestyle='--', label='Test Predict')
plt.legend()
plt.show()

运行图如下:

观测

训练损失逐渐降低并趋于稳定,意味着模型正在从训练数据中学习。

在训练集和测试集上的评估速度很快,意味着模型的推断(预测)效率很高。

如果损失在后续的epoch中没有显著下降,可能意味着模型需要更多的epoch来训练。或者可能需要调整模型的结构或超参数(例如增加神经元数量、改变学习率)以进一步提高性能。

训练集和测试集的RMSE非常接近,说明模型在两者上的性能是一致的。

没有出现过拟合/欠拟合的迹象,则说明模型的泛化能力良好。

考虑到数据生成时添加了随机噪声,这个RMSE值表明模型在捕捉数据的基本趋势方面表现的不错,相对较小的RMSE表示预测的准确。

如果要改进LSTM,可以从贝叶斯超参数调优、增加更多训练周期(EPOCH)、尝试不同网络架构,或者在数据预处理时更复杂一些。

事实上,在RMSE上,SARIMA比LSTM更小,但非线性模式/利用长期依赖性的复杂时间序列数据时,LSTM更好。

相关推荐
古希腊掌管学习的神2 分钟前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca3 分钟前
洛谷 P1706 全排列问题 C语言
算法
浊酒南街9 分钟前
决策树(理论知识1)
算法·决策树·机器学习
就爱学编程16 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
B站计算机毕业设计超人17 分钟前
计算机毕业设计PySpark+Hadoop中国城市交通分析与预测 Python交通预测 Python交通可视化 客流量预测 交通大数据 机器学习 深度学习
大数据·人工智能·爬虫·python·机器学习·课程设计·数据可视化
学术头条21 分钟前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
18号房客25 分钟前
一个简单的机器学习实战例程,使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集(Iris Dataset)**的分类
人工智能·深度学习·神经网络·机器学习·语言模型·自然语言处理·sklearn
feifeikon28 分钟前
机器学习DAY3 : 线性回归与最小二乘法与sklearn实现 (线性回归完)
人工智能·机器学习·线性回归
游客52031 分钟前
opencv中的常用的100个API
图像处理·人工智能·python·opencv·计算机视觉
古希腊掌管学习的神32 分钟前
[机器学习]sklearn入门指南(2)
人工智能·机器学习·sklearn