使用LSTM模型进行时序数据预测
创作时间:
作者:
@小白创作中心
使用LSTM模型进行时序数据预测
引用
CSDN
1.
https://blog.csdn.net/qq_42035021/article/details/141132537
LSTM模型简介
LSTM(Long Short-Term Memory)是一种循环神经网络(RNN)的变体,主要用于解决序列数据处理中的长期依赖问题。LSTM通过引入记忆单元和门控机制,能够有效地捕捉序列中的长期依赖关系,因此在时序数据预测、自然语言处理等领域得到了广泛应用。
研究目标
本项目的目标是使用临近若干时刻的气象观测数据,预测未来3个时刻的能见度。具体来说,我们将使用温度、露点温度、相对湿度、饱和水汽压差和能见度等气象要素作为输入特征,预测未来的能见度变化。
准备工作
环境准备
本项目需要Python 3.x环境,并安装以下必要库:
- PyTorch
- NumPy
- Pandas
- Scikit-learn
数据准备
数据来源为全国气象站逐小时观测数据,包含以下要素:
- 温度(TEM)
- 露点温度(DPT)
- 相对湿度(RHU)
- 饱和水汽压差(VAP)
- 能见度(VIS)
每个时刻的观测数据存储在一个CSV文件中,文件中的行代表不同的站点观测值,列代表不同的要素属性。
数据预处理
读取数据
首先需要从文件中读取数据。代码如下:
import pandas as pd
import os
import numpy as np
indir = r'./filepath' # 保存所有数据文件的文件夹
file_list = os.listdir(indir) # 获得所有数据文件的文件名
feature_vars = ['TEM', 'DPT', 'RHU', 'VAP', 'VIS']
label_vars = 'VIS'
dataset = []
for f in range(len(file_list)):
df = pd.read_csv(os.path.join(indir, f), na_values=[999999, 999107], usecols=['Station_Id_C', 'Lat', 'Lon', 'TEM', 'DPT', 'RHU', 'VAP', 'VIS'])
df = df.dropna(axis=0, how='any').query('Lat>17 & Lat<29 & Lon>108 & Lon<123') # 剔除所有存在空值的行,并提取目标空间范围内的数据
dataset.append(df.loc[:, feature_vars].values)
dataset = np.array(dataset, dtype=np.float32) # (times, stations, features)
创建样本集
什么是样本?
在时序预测中,一个样本通常包含两部分:特征数据和标签数据。特征数据用于预测目标,标签数据则是预测的目标值。例如,如果我们想用当前时刻的温度和气压预测风速,那么温度和气压组成特征数据,风速则是标签数据。
构造样本集
假设我们需要用最近5个时刻的温度和气压数据,去预测未来3个时刻的风速数据。在这种情况下,我们有三个时间维度:
time_step
:用于预测的时间窗口长度pred_step
:预测的目标时间长度times
:原始观测数据的时间长度
代码实现如下:
time_step = 5
pred_step = 3
samples = []
X = []
Y = []
for i in range(dataset.shape[0] - time_step - pred_step + 1):
X.append(dataset[i:i+time_step, :, :-1]) # (time_step, stations, features)
Y.append(dataset[i+time_step:i+time_step+pred_step, :, -1]) # (pred_step, stations)
X = np.array(X).transpose(0, 2, 1, 3) # (new_times, stations, time_step, features)
Y = np.array(Y).transpose(0, 2, 1) # (new_times, stations, pred_step)
samples_x = X.reshape(-1, time_step, features) # 形状为(samples, time_step, features)
samples_y = Y.reshape(-1, pred_step) # 形状为(samples, pred_step)
拆分样本集
将样本集拆分成训练集、验证集和测试集:
from sklearn.model_selection import train_test_split
train_x, tmp_x, train_y, tmp_y = train_test_split(data_x, data_y, train_size=0.6, random_state=42, shuffle=True)
val_x, test_x, val_y, test_y = train_test_split(tmp_x, tmp_y, train_size=0.5, random_state=42, shuffle=True)
样本归一化
为了消除不同特征之间数值范围差异的影响,需要对数据进行归一化处理:
from sklearn.preprocessing import MinMaxScaler
scale_x = MinMaxScaler()
train_x = scale_x.fit_transform(train_x.reshape(-1, len(feature_vars)).reshape(-1, time_step, len(feature_vars))
val_x = scale_x.transform(val_x.reshape(-1, len(feature_vars))).reshape(-1, time_step, len(feature_vars))
test_x = scale_x.transform(test_x.reshape(-1, len(feature_vars))).reshape(-1, time_step, len(feature_vars))
scale_y = MinMaxScaler()
train_y = scale_y.fit_transform(train_y)
val_y = scale_y.transform(val_y)
test_y = scale_y.transform(test_y)
模型训练
定义LSTM模型
使用PyTorch定义LSTM模型:
import torch
import torch.nn as nn
import torch.optim as optim
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers=1, dropout_rate=0.2):
super(LSTMModel, self).__init__()
self.input_size = input_size
self.hidden_size = hidden_size
self.output_size = output_size
self.num_layers = num_layers
self.dropout_rate = dropout_rate
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.dropout = nn.Dropout(dropout_rate)
self.fc1 = nn.Linear(hidden_size, output_size)
self.relu = nn.ReLU()
def forward(self, x):
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
out, _ = self.lstm(x, (h0, c0))
out = self.dropout(out[:, -1, :])
out = self.fc1(out)
out = self.relu(out)
return out
模型训练
定义数据加载器和训练函数:
def set_loader(x, y, batch_size):
tensor_x = torch.from_numpy(x)
tensor_y = torch.from_numpy(y)
loader = DataLoader(TensorDataset(tensor_x, tensor_y), batch_size=batch_size, shuffle=True)
return loader
def lstm_train(model, epochs, train_loader, val_loader, learning_rate=0.01, plot_loss=False):
loss_function = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
train_losses = []
val_losses = []
for epoch in range(epochs):
model.train()
train_loss = 0.0
for x_batch, y_batch in train_loader:
optimizer.zero_grad()
outputs = model(x_batch)
loss = loss_function(outputs, y_batch)
loss.backward()
optimizer.step()
train_loss += loss.item() * x_batch.size(0)
train_loss /= len(train_loader.dataset)
train_losses.append(train_loss)
model.eval()
val_loss = 0.0
with torch.no_grad():
for x, y in val_loader:
outputs = model(x)
loss = loss_function(outputs, y)
val_loss += loss.item() * x.size(0)
val_loss /= len(val_loader.dataset)
val_losses.append(val_loss)
print(f'Epoch [{epoch+1}/{epochs}], Train Loss: {train_loss:.4f}, Val Loss: {val_loss:.4f}')
if plot_loss:
fig = plt.figure(figsize=[8,6])
ax = fig.add_subplot(111)
ax.plot(train_losses, 'b', label='train_losses')
ax.plot(val_losses, 'r', label='val_losses')
ax.legend()
ax.set_title(f'Epochs:{epochs} learning_rate:{learning_rate}')
plt.show()
return model
模型预测
使用训练好的模型进行预测:
hidden_size = 16
input_size = len(feature_vars)
output_size = pred_time
batch_size = 16
epochs = 500
train_loader = set_loader(train_x, train_y, batch_size)
val_loader = set_loader(val_x, val_y, batch_size)
model = LSTMModel(input_size, hidden_size, output_size, num_layers=1, dropout_rate=0.3)
model = lstm_train(model, epochs, train_loader, val_loader, learning_rate=0.001, plot_loss=False)
model.eval()
with torch.no_grad():
out = model(torch.from_numpy(test_x))
pred = scale_y.inverse_transform(out)
结果分析
模型预测结果如下图所示:
虽然原数据的变化范围较大,导致预测结果在极值处表现较差,但模型基本能够捕捉到能见度的变化趋势。
热门推荐
第87、88师最初是蒋介石警卫部队,抗战时在淞沪和南京与敌血战
工业设计作品集怎么准备
天下李,广东陈!源自北方的陈姓,“三迁”后如何成广东第一大姓
陈姓的起源与发展:华夏大姓的历史变迁与文化传承
茅茅虫论文写作:如何精炼论文结构
ENFJ型人格与什么人格最配?详解ENFJ的完美伴侣类型
内向话少最赚钱的工作
糖尿病患者可以吃青提吗?医生给出专业解答
汉服上的神话故事纹样
最新职级并行工资对照表:帮你了解法律行业薪资标准
网络状态监控:保障网络平稳运行的守护者
色差仪有哪些类型?企业怎么选择合适的色差仪?
心口窝正中间疼是怎么回事?挂什么科?
动态规划 — 最长递增子序列(从原理到实现详解)
动态规划 — 最长递增子序列(从原理到实现详解)
SSD SLC缓存设计原理与优化方案
猫咪玩具盘点:猫咪常见绳索类玩具竟有5大类
一文看懂散热风扇的2PIN、3PIN、4PIN!
机械电子工程就业方向及前景(关于机械电子工程最好的出路)
雨前茶和明前茶区别?你喝过哪一种?
正确呼吸,减少跑步时的能量消耗
建立高效的跨部门合作机制
自由泳腿部动作要领详解(掌握正确技巧)
线性预测编码(LPC)压缩技术在信号处理中的实用指南
《一念逍遥》灵兽选择攻略:五种灵兽技能详解与推荐顺序
历史文化名城泉州:海上丝绸之路的璀璨明珠
有什么适合提高 C/C++ 网络编程能力的开源项目推荐
青蛙种群密度调查方法揭秘:从传统到新兴技术的全面探讨
英冠关键对决:米堡与伯恩利近期状态深度剖析
通缩、通胀和滞胀:这些经济术语与我们的生活息息相关