最强总结,LSTM 时间序列预测!!

文摘   2024-11-18 11:16   北京  

哈喽,我是小白~

今儿和大家聊聊LSTM在时间序列预测方面的应用。

如果需要本文PDF版本的同学,文末获取~

另外,文末有总结性的干货~

一起来看下具体细化内容~

LSTM 是什么?

LSTM(Long Short-Term Memory,长短期记忆)是一种时间序列算法,常用于处理和预测基于时间的序列数据,比如天气预测、股价变化、自然语言处理等。它是递归神经网络(RNN)的一种特殊类型,能够记住长期依赖关系,解决了传统 RNN 在处理长序列时容易出现“长期依赖问题”的缺陷。

简单来说,传统 RNN 在处理长时间序列时,由于信息逐渐丢失,无法有效记住较早的数据。而 LSTM 引入了“记忆单元”和“门机制”,可以控制哪些信息保留、哪些信息遗忘,因此能更好地应对长时间间隔的数据关系。


LSTM 工作原理

LSTM 的核心在于“门机制”,主要包括三个重要的门:

1. 遗忘门(Forget Gate): 决定哪些信息需要遗忘。

2. 输入门(Input Gate): 决定哪些新信息需要存储到记忆中。

3. 输出门(Output Gate): 决定哪些信息要输出到下一时刻。

这些门会根据当前输入和之前的隐藏状态(即记忆)来进行计算。


一个简单案例:预测每天的温度

假设你想根据前几天的温度来预测今天的温度。假设过去 7 天的温度如下:

日期温度(°C)
第一天20
第二天21
第三天19
第四天18
第五天22
第六天23
第七天21

你想通过这些天的温度,预测第八天的温度。

LSTM 就像是一个有记忆的人,它不仅记得最近几天的温度,还能根据之前的信息做出相应的调整,决定哪些温度数据重要,哪些可以忽略。

遗忘门: 检查过去 7 天的温度,可能决定“忽略”不重要的温度变化(例如波动不大的天数)。

输入门: 决定从新的温度数据中,选择哪些重要信息存入记忆单元。

输出门: 最后根据遗忘和输入门的结果,输出预测结果,即第八天的温度。


LSTM 计算示例

为了简单说明计算过程,我们简化 LSTM 的门结构,假设只有两个输入(温度序列和前一天的预测)和一个隐藏层,LSTM 的门公式如下:

1. 遗忘门:

这里的  是遗忘门的输出,决定了上一个时刻的记忆有多少部分需要保留。  是 sigmoid 激活函数,其输出在 0 到 1 之间。

2. 输入门:

输入门决定当前输入  的哪些部分需要加入到记忆中。

3. 记忆更新:

这个公式更新新的候选记忆 ,使用的是 tanh 激活函数,其输出范围在 -1 到 1 之间。

4. 当前记忆:

当前时刻的记忆是上一时刻记忆的部分保留,再加上本时刻新的记忆。

5. 输出门:

输出门控制将记忆单元中哪些部分作为输出。

6. 最终输出:

最终的输出  是当前记忆经过 tanh 激活函数后,乘上输出门的结果。


具体例子

假设我们现在有 7 天的温度序列(如上表),并希望预测第 8 天的温度。我们手动进行一次计算简化后的 LSTM 操作。

假设初始参数为:

  • 初始记忆 , 初始隐藏状态 
  • 假设偏置 

1. 以第 7 天的温度为输入(21°C)

当前输入 ,上一时刻的输出为 (假设初始输出为 0)

遗忘门:

遗忘门几乎为 1,表示我们保留之前的记忆。

输入门:

输入门也接近 1,表示当前输入的重要性很大。

记忆更新:

候选记忆几乎为 1。

当前记忆:

输出门:

最终输出:

根据这个简单的计算过程,LSTM 输出了一个值约为 0.76,这个值可以被用于下一步预测。

公式解析

1. 变量定义

首先,我们定义 LSTM 的一些关键变量:

输入向量:  表示在时间步  的输入数据(如某时刻的温度、股价等)。

隐藏状态:  表示时间步  的隐藏状态,也可以看作是 LSTM 的输出,用来传递到下一时间步。

记忆单元:  表示 LSTM 在时间步  的记忆内容。

遗忘门: ,表示在时间步  遗忘多少之前的记忆。

输入门: ,决定当前的输入有多少需要存储到记忆单元中。

输出门: ,决定当前的隐藏状态和记忆单元有多少内容输出。

此外,LSTM 中有一系列权重矩阵和偏置项:

权重矩阵:

  • (遗忘门)、(输入门)、(输出门)、(候选记忆)
  • 这些矩阵作用于当前输入  和上一个隐藏状态 

偏置项:

  •  是各个门和记忆单元对应的偏置项。

2. LSTM 公式推导

遗忘门(Forget Gate)

遗忘门决定哪些记忆内容应该被保留,哪些应该被丢弃。它通过输入当前时刻的输入  和上一时刻的隐藏状态  来计算,最终输出值介于 0 到 1 之间。

遗忘门的公式为:

  •  是 sigmoid 激活函数,其输出为 0 到 1 之间的值。接近 0 时表示遗忘,接近 1 时表示保留。
  •  是遗忘门的权重矩阵, 是遗忘门的偏置。
  •  表示将隐藏状态  和输入  拼接在一起形成新的输入。

输入门(Input Gate)

输入门决定哪些当前的输入信息要被存入记忆单元。同样,输入门也依赖当前输入  和上一时刻的隐藏状态 

输入门的公式为:

  •  是输入门的权重矩阵, 是输入门的偏置。
  •  的值控制当前输入信息存入多少到记忆单元中,0 表示完全忽略,1 表示完全保留。

候选记忆单元(Cell Candidate)

接下来,我们要生成候选记忆单元,也就是当前时刻的潜在记忆更新,它是通过输入门和输入数据的一个候选更新值,决定了可以加入到记忆单元中的信息。

候选记忆的公式为:

  •  是双曲正切函数,其输出范围是  到 ,用于控制候选记忆单元的输出范围。
  •  是候选记忆单元的权重矩阵, 是其偏置。

更新记忆单元(Cell State)

记忆单元  的更新是通过遗忘上一个时刻的一部分记忆,再结合当前时刻新输入的信息。

记忆单元的更新公式为:

  •  表示用遗忘门控制上一时刻的记忆  保留多少。
  •  表示用输入门控制当前时刻的候选记忆  要更新多少。

输出门(Output Gate)

输出门决定了记忆单元中的哪些部分要作为当前时刻的输出,也就是 LSTM 的隐藏状态。

输出门的公式为:

  •  是输出门的权重矩阵, 是其偏置。
  •  的值决定了当前时刻哪些信息需要输出。

最终输出(Hidden State)

最后,当前时刻的隐藏状态  通过输出门和当前的记忆单元计算得到。首先对当前记忆单元  使用 函数,之后与输出门  相乘,得到隐藏状态 

隐藏状态的公式为:

  •  将记忆单元的值限制在  到  之间。
  •  决定了从记忆中输出的部分。

3. 完整 LSTM 工作流程

综上所述,LSTM 的完整工作流程可以描述为:

1. 遗忘门计算:

  • 计算 ,决定遗忘多少上一个时间步的记忆。

2. 输入门计算:

  • 计算 ,决定输入多少当前时刻的信息。
  • 计算候选记忆 $ \tilde{C}t = \tanh(W_C \cdot [h{t-1}, x_t] + b_C) $,生成当前时刻的潜在记忆。

3. 更新记忆单元:

  • 通过  更新当前记忆单元。

4. 输出门计算:

  • 计算 ,决定输出多少信息。

5. 最终输出:

  • 通过  计算当前时刻的隐藏状态,即 LSTM 的最终输出。

LSTM 的关键在于它的“门机制”,通过遗忘门、输入门和输出门对记忆的管理,能够有效解决长时间序列中信息丢失的问题。

优缺点和适用场景

优点

1. 解决长期依赖问题:LSTM 通过引入遗忘门输入门输出门,能够有效保留或遗忘历史信息,避免了传统 RNN(递归神经网络)中梯度消失或梯度爆炸的问题,从而擅长处理长时间跨度的依赖关系。

2. 记忆能力强:LSTM 通过其内在的记忆单元可以保存信息更长时间,适用于需要长时间记忆的时间序列任务。

3. 灵活性高:LSTM 能够灵活地通过门控机制选择哪些信息应该保留,哪些信息应该忽略,因此在非线性、复杂的时间序列数据上表现良好。

4. 较好的泛化能力:由于可以学习到更复杂的时间依赖结构,LSTM 通常在训练数据和测试数据上表现出较好的泛化能力。

缺点

1. 计算复杂度高: LSTM 结构复杂,包含多个门控机制,参数较多,因此计算量大,训练时间较长,尤其在面对大规模数据时效率较低。

2. 难以解释:虽然 LSTM 在捕捉时间序列中的长短期依赖关系上表现良好,但它内部的门控机制较为复杂,难以解释为什么网络会做出特定的决策。

3. 对长时间序列的捕捉仍然有限: 虽然 LSTM 比传统 RNN 更好地处理长时间依赖问题,但在非常长的序列(如成千上万步的序列)上依然可能失效。

4. 需要大量数据:LSTM 需要大量标记数据才能训练出高质量的模型,数据量不足时可能导致模型过拟合或表现不佳。

适用场景

LSTM 主要适用于处理时间依赖性强、数据序列较长的任务。

1. 时间序列预测: LSTM 常用于处理如股票价格、天气、商品需求量等时间序列数据,能够有效预测未来的趋势。

2. 自然语言处理(NLP):LSTM 广泛应用于自然语言处理任务,尤其是处理长文本、翻译、问答等需要捕捉上下文信息的任务。

3. 语音识别:语音信号是典型的时间序列数据,LSTM 在语音识别中可以有效提取信号中的时序特征。

4. 视频分析: 视频可以看作是一系列连续帧的时间序列数据,LSTM 能够在视频分析中捕捉帧间的动态变化,进行行为识别、事件检测等。

完整案例

使用LSTM对股票价格的时间序列数据进行预测,这里假设使用的是一个股票市场的开盘价格数据。

仅仅作为算法学习使用,数据集为虚拟数据集。

代码会涉及数据预处理、LSTM模型构建、训练、以及数据可视化。可视化部分会使用MatplotlibSeaborn等工具展示。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout

# 1. 生成模拟的股票价格数据
np.random.seed(42)
dates = pd.date_range('2020-01-01', periods=1000)
prices = np.sin(np.linspace(0201000)) * 100 + np.random.normal(051000) + 100

# 创建 DataFrame
data = pd.DataFrame(data={'Date': dates, 'Open': prices})
data.set_index('Date', inplace=True)

# 可视化股票价格的初始走势
plt.figure(figsize=(126))
sns.lineplot(x=data.index, y=data['Open'], color='blue', lw=2)
plt.title('Stock Open Prices Over Time', fontsize=16)
plt.xlabel('Date')
plt.ylabel('Open Price')
plt.grid(True)
plt.show()

# 2. 数据预处理 - 归一化处理
scaler = MinMaxScaler(feature_range=(01))
scaled_data = scaler.fit_transform(data[['Open']])

# 创建时间序列数据集
def create_dataset(dataset, time_step=60):
    X, y = [], []
    for i in range(len(dataset)-time_step-1):
        X.append(dataset[i:(i+time_step), 0])
        y.append(dataset[i + time_step, 0])
    return np.array(X), np.array(y)

# 生成训练集
time_step = 60
X, y = create_dataset(scaled_data, time_step)

# Reshape输入为LSTM模型的格式 [样本数, 时间步长, 特征数]
X = X.reshape(X.shape[0], X.shape[1], 1)

# 3. 创建LSTM模型
model = Sequential()
model.add(LSTM(units=100, return_sequences=True, input_shape=(time_step, 1)))
model.add(Dropout(0.2))
model.add(LSTM(units=100, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(units=1))  # 输出层

model.compile(optimizer='adam', loss='mean_squared_error')

# 4. 训练模型
model.fit(X, y, epochs=10, batch_size=32, verbose=1)

# 5. 预测
train_predict = model.predict(X)

# 将预测值反归一化
train_predict = scaler.inverse_transform(train_predict)

# 创建一个新的DataFrame用于展示
train_data = data.iloc[time_step+1:]
train_data['Predicted'] = train_predict

# 6. 可视化真实值和预测值
plt.figure(figsize=(147))
plt.plot(train_data.index, train_data['Open'], label='True Open Prices', color='blue', lw=2)
plt.plot(train_data.index, train_data['Predicted'], label='Predicted Open Prices', color='orange', lw=2)
plt.fill_between(train_data.index, train_data['Open'], train_data['Predicted'], color='lightgreen', alpha=0.5)
plt.title('True vs Predicted Stock Prices', fontsize=18)
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend(loc='best')
plt.grid(True)
plt.show()

# 7. 复杂可视化: 热力图分析误差
error = train_data['Open'] - train_data['Predicted']
plt.figure(figsize=(126))
sns.heatmap(np.reshape(error.values, (1094)), cmap="YlGnBu", annot=False, cbar=True)
plt.title('Error Heatmap between True and Predicted Prices', fontsize=16)
plt.show()

# 8. 复杂可视化: 预测值与真实值的差异柱状图
plt.figure(figsize=(146))
sns.barplot(x=train_data.index[::10], y=(train_data['Open'] - train_data['Predicted'])[::10], palette='coolwarm')
plt.xticks(rotation=45)
plt.title('Differences between True and Predicted Prices', fontsize=18)
plt.ylabel('Difference')
plt.grid(True)
plt.show()

代码说明:

1. 生成模拟的股票价格数据:这里通过 sin 函数加噪声生成股票的开盘价格数据。

2. 数据预处理:使用MinMaxScaler对数据进行归一化,将股票价格数据压缩到0-1之间;然后创建时间序列数据集。

3. 构建LSTM模型:使用两层LSTM和Dropout进行正则化,最后用一个全连接层输出预测值。

4. 模型训练:使用Adam优化器,损失函数为均方误差(MSE)。

5. 预测并反归一化:使用训练好的LSTM模型对训练集进行预测,然后将预测值反归一化回原来的价格范围。

真实值和预测值的折线图,并在图中填充真实值与预测值之间的区域,形成复杂的可视化效果。

其他图形效果,大家自行跑代码,上面代码是完整的。

最后

以上就是今天所有的内容了。
获取本文PDF,点击名片回复「基础算法模型」即可~
 
另外, 我们整理了机器学习算法册子,总共16大块的内容,124个问题的总结点击领取!
如果对你来说比较有用,记得点赞、转发,收藏起来慢慢学习~
下期会有更多干货等着你!~

Python和机器学习初学者
Python和机器学习分享,只写干货,一起学习~
 最新文章