在本篇文章中,我们将使用时间序列数据分析技术,基于美国联邦储备经济数据库(FRED)中的酒类销售数据,使用LSTM(长短期记忆网络)进行未来销售量的预测。本案例展示了如何构建LSTM模型,训练模型进行时间序列预测,并使用历史数据进行模型的评估与未来预测。
1. 加载数据
首先,我们加载酒类销售数据,该数据集包含了从1992年到2019年的月度销售记录。
python
import pandas as pd
# 加载数据集
df = pd.read_csv('../data/Alcohol_Sales.csv', index_col=0, parse_dates=True)
# 查看数据长度
len(df)
# 清理数据,移除空值
df.dropna(inplace=True)
len(df)
# 查看前5行数据
df.head()
# 查看最后5行数据
df.tail()
2. EDA:时间序列数据可视化
接下来,我们将数据进行可视化,以便更好地理解时间序列趋势。
python
import matplotlib.pyplot as plt
plt.figure(figsize=(12,4))
plt.title('Beer, Wine, and Alcohol Sales')
plt.ylabel('Sales (millions of dollars)')
plt.grid(True)
plt.autoscale(axis='x',tight=True)
plt.plot(df['S4248SM144NCEN'])
plt.show()
3. 特征提取与数据准备
我们将数据分为训练集和测试集,分别用于模型训练和评估。训练集将被归一化为-1到1之间的值,以提高训练效率。
python
import numpy as np
from sklearn.preprocessing import MinMaxScaler
# 提取数据
y = df['S4248SM144NCEN'].values.astype(float)
# 定义测试集大小
test_size = 12
# 划分训练集和测试集
train_set = y[:-test_size]
test_set = y[-test_size:]
# 实例化归一化工具
scaler = MinMaxScaler(feature_range=(-1, 1))
# 归一化训练集
train_norm = scaler.fit_transform(train_set.reshape(-1, 1))
# 转换为张量
import torch
train_norm = torch.FloatTensor(train_norm).view(-1)
# 定义窗口大小
window_size = 12
# 创建输入数据
def input_data(seq,ws):
out = []
L = len(seq)
for i in range(L-ws):
window = seq[i:i+ws]
label = seq[i+ws:i+ws+1]
out.append((window,label))
return out
train_data = input_data(train_norm, window_size)
4. 构建LSTM模型
接下来,我们定义一个包含LSTM层的神经网络模型。
python
import torch.nn as nn
class LSTMnetwork(nn.Module):
def __init__(self, input_size=1, hidden_size=100, output_size=1):
super().__init__()
self.hidden_size = hidden_size
self.lstm = nn.LSTM(input_size, hidden_size)
self.linear = nn.Linear(hidden_size, output_size)
self.hidden = (torch.zeros(1, 1, self.hidden_size),
torch.zeros(1, 1, self.hidden_size))
def forward(self, seq):
lstm_out, self.hidden = self.lstm(seq.view(len(seq), 1, -1), self.hidden)
pred = self.linear(lstm_out.view(len(seq), -1))
return pred[-1] # 我们只需要最后一个预测值
5. 训练模型
我们将使用均方误差损失函数(MSE)和Adam优化器来训练模型。
python
torch.manual_seed(101)
model = LSTMnetwork()
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练模型
epochs = 100
for epoch in range(epochs):
for seq, y_train in train_data:
optimizer.zero_grad()
model.hidden = (torch.zeros(1, 1, model.hidden_size),
torch.zeros(1, 1, model.hidden_size))
y_pred = model(seq)
loss = criterion(y_pred, y_train)
loss.backward()
optimizer.step()
print(f'Epoch: {epoch+1:2} Loss: {loss.item():10.8f}')
6. 进行预测并与测试集比较
模型训练完毕后,我们使用模型对未来12个月的数据进行预测,并与测试集进行对比。
python
future = 12
# 使用最后一个训练窗口的值进行预测
preds = train_norm[-window_size:].tolist()
model.eval()
for i in range(future):
seq = torch.FloatTensor(preds[-window_size:])
with torch.no_grad():
model.hidden = (torch.zeros(1, 1, model.hidden_size),
torch.zeros(1, 1, model.hidden_size))
preds.append(model(seq).item())
# 反归一化预测结果
true_predictions = scaler.inverse_transform(np.array(preds[window_size:]).reshape(-1, 1))
# 可视化预测结果
import numpy as np
x = np.arange('2018-02-01', '2019-02-01', dtype='datetime64[M]').astype('datetime64[D]')
plt.figure(figsize=(12,4))
plt.title('Beer, Wine, and Alcohol Sales')
plt.ylabel('Sales (millions of dollars)')
plt.grid(True)
plt.plot(df['S4248SM144NCEN'])
plt.plot(x,true_predictions)
plt.show()
7. 预测未来数据
我们将模型应用于整个数据集,并预测未来12个月的销售数据。
python
# 训练整个数据集并预测未来
epochs = 100
# 归一化整个数据集
y_norm = scaler.fit_transform(y.reshape(-1, 1))
y_norm = torch.FloatTensor(y_norm).view(-1)
all_data = input_data(y_norm, window_size)
for epoch in range(epochs):
for seq, y_train in all_data:
optimizer.zero_grad()
model.hidden = (torch.zeros(1, 1, model.hidden_size),
torch.zeros(1, 1, model.hidden_size))
y_pred = model(seq)
loss = criterion(y_pred, y_train)
loss.backward()
optimizer.step()
# 预测未来12个月数据
future = 12
preds = y_norm[-window_size:].tolist()
model.eval()
for i in range(future):
seq = torch.FloatTensor(preds[-window_size:])
with torch.no_grad():
model.hidden = (torch.zeros(1, 1, model.hidden_size),
torch.zeros(1, 1, model.hidden_size))
preds.append(model(seq).item())
# 反归一化预测值并可视化
true_predictions = scaler.inverse_transform(np.array(preds).reshape(-1, 1))
x = np.arange('2019-02-01', '2020-02-01', dtype='datetime64[M]').astype('datetime64[D]')
plt.figure(figsize=(12,4))
plt.title('Beer, Wine, and Alcohol Sales')
plt.ylabel('Sales (millions of dollars)')
plt.grid(True)
plt.plot(df['S4248SM144NCEN'])
plt.plot(x,true_predictions[window_size:])
plt.show()
结语
在本篇案例中,我们通过LSTM模型对美国酒类销售的时间序列数据进行了分析和预测。通过归一化处理、模型训练、测试集验证以及未来趋势预测,我们可以看到LSTM模型能够有效捕捉数据的时间依赖性,进而在一定程度上准确预测未来的销售趋势。虽然我们的模型表现较好,但仍有一些误差,可以通过调整模型参数、增加训练数据或采用其他高级算法进一步优化。
本案例展示了LSTM在时间序列预测中的应用,证明了其在捕捉长期依赖性和模式识别中的强大能力。对于需要预测趋势、销售额、库存等的商业决策场景,LSTM提供了可靠的解决方案。未来的工作中,我们可以探索更多模型的改进和应用场景,以提升预测的准确性和实用性。
通过本案例的学习,希望您对时间序列预测和LSTM网络有了更深入的理解,并能将其应用到更多实际问题中。
如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!
欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。
谢谢大家的支持!