加入深度实战社区:www.zzgcz.com,免费学习所有深度学习实战项目。
1. 项目简介
本项目旨在利用深度学习中的长短期记忆网络(LSTM)来预测未来30天的销售额。LSTM模型能够处理时序数据中的长期依赖问题,因此在销售额预测这类涉及时间序列的场景中表现出色。通过分析历史销售数据以及相关影响因素(如温度、周数等),模型可以有效捕捉到销售趋势及其波动规律,为未来的销售决策提供参考依据。
项目首先通过对原始数据进行预处理,包括日期格式的转换、特征工程(如添加周数和上一周的销售额特征)以及特征的归一化处理。随后,项目采用LSTM模型进行多步预测,输入过去30天的数据序列,输出未来30天的预测结果。训练过程中,数据被分为训练集和测试集,并通过均方误差(MSE)和平均绝对误差(MAE)等指标来评估模型的性能。此外,项目通过可视化方式展示了模型的训练过程及预测结果,直观展示销售额的实际值与预测值的对比。
2.技术创新点摘要
- 多特征输入与特征工程:代码在模型输入中不仅使用了销售额历史数据,还引入了温度和周数等辅助特征,并通过创建上周销售额的特征来增强模型的预测能力。这种多特征的方式增强了LSTM模型的表现,有效捕捉到了与销售额波动相关的多重因素。这种做法在处理复杂的时间序列预测任务时,能够更好地挖掘潜在的影响因子,提升预测精度。
- 多步预测与序列化数据生成:项目中采用了多步序列预测,即通过过去30天的数据预测未来30天的销售额,而不仅仅是单步预测。这种多步预测使得模型能够在更长的时间范围内提供预测结果,增加了实际应用的价值。此外,代码通过定制的
create_sequences
函数,将原始数据转化为适合LSTM模型训练的输入序列和目标序列,确保数据结构与模型需求匹配。 - PyTorch自定义数据集和数据加载器的实现:在数据预处理中,项目自定义了一个
SalesDataset
类,利用PyTorch的Dataset
和DataLoader
模块,将数据转换为张量形式并进行批量化处理。通过自定义的数据集和加载器,项目可以高效地处理大规模数据集,提升训练和测试效率,减少内存占用。 - LSTM模型结构的设计与优化:项目中的LSTM模型采用了两层LSTM网络,并结合了Dropout层防止过拟合,进一步提升模型的泛化能力。同时,模型的输出层使用全连接层将LSTM的隐藏状态转化为最终的预测结果。该设计不仅可以有效捕捉时间序列中的长期依赖关系,还通过适当的参数(如隐藏层大小、层数和Dropout率)的调整,提升了模型的表现。
- 预测结果的反缩放与可视化:在模型预测结束后,项目通过MinMaxScaler进行反缩放处理,将标准化后的预测结果还原至原始的销售额尺度。这种反缩放步骤确保了模型的预测结果能够直观地反映真实销售额的变化。最后,项目通过绘图工具可视化了模型的预测效果,并展示了未来30天的销售趋势,方便用户对模型预测结果进行分析和理解。
3. 数据集与预处理
本项目所使用的数据集来自某商品的历史销售记录,包含多个特征字段,例如销售日期、销售额、温度等外部因素。数据集中最为核心的目标变量是商品的每日销售额,辅助特征包括温度和日期相关的周数信息。通过这些特征,项目能够分析和捕捉销售额的周期性趋势以及受到外部因素影响的波动性。
- 在数据预处理环节,首先对数据集进行了日期格式的标准化,将日期列转换为
datetime
格式,并按照时间顺序对数据进行了排序,确保后续模型能够捕捉到时间序列的顺序关系。此外,添加了周数作为新的特征,帮助模型捕捉到销售额的季节性和周期性模式。项目还引入了“上一周销售额”这一特征,使得模型在预测时能够参考历史数据,增加了时间序列的上下文信息。 - 为了处理缺失值,项目采用了向前填充的方式(
bfill
),确保特征值的完整性,避免数据不完整导致的模型训练问题。接下来,对选定的特征(如温度、周数、上一周销售额)进行了归一化处理。归一化使用了MinMaxScaler
方法,将所有特征值缩放至0到1之间,确保特征的数值范围相近,从而避免某些特征因数值较大而对模型产生过度影响。 - 项目还对时间序列数据进行了序列化处理,通过自定义函数将原始数据转换为适合LSTM模型的序列输入形式。每个输入序列包含过去30天的特征值,而对应的目标是预测未来30天的销售额。这种序列化处理不仅保留了原始时间序列的顺序信息,还为模型提供了充足的上下文。
- 通过这些预处理步骤,数据集被整理为适合深度学习模型训练的形式,为后续的LSTM模型训练和预测提供了良好的数据基础。
4. 模型架构
本项目采用的是长短期记忆网络(LSTM)来进行未来30天销售额的预测。LSTM是一种能够捕捉时间序列中长期依赖关系的循环神经网络(RNN)变种,能够有效解决序列数据中的梯度消失问题。项目中的LSTM模型由以下几部分组成:
LSTM层
LSTM的核心是其记忆单元和门机制,通过这些机制,它能够决定在每个时间步保留、更新或丢弃哪些信息。
输入门(Input Gate):决定当前时间步的输入对记忆状态的影响。其数学公式为:
i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) it=σ(Wi⋅[ht−1,xt]+bi)
其中,it表示输入门的输出,σ是sigmoid激活函数,Wi 和 bi 是输入门的权重和偏置,ht−1 是前一个时间步的隐藏状态,xt 是当前时间步的输入。
遗忘门(Forget Gate):决定从记忆单元中遗忘多少信息,公式为:
f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) ft=σ(Wf⋅[ht−1,xt]+bf)
其中,ft表示遗忘门的输出,Wf 和 bf 是遗忘门的权重和偏置。
候选记忆单元(Cell Candidate):生成候选记忆状态,用于更新当前的记忆单元,公式为:
C ~ t = tanh ( W C ⋅ [ h t − 1 , x t ] + b C ) \tilde{C}_t = \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) C~t=tanh(WC⋅[ht−1,xt]+bC)
其中,C~t 是候选的记忆单元状态,tanh 是双曲正切激活函数。
输出门(Output Gate):控制记忆状态如何影响输出,公式为:
o t = σ ( W o ⋅ [ h t − 1 , x t ] + b o ) o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) ot=σ(Wo⋅[ht−1,xt]+bo)
记忆单元更新(Cell State Update):通过遗忘门和输入门来更新记忆单元,公式为:
C t = f t ∗ C t − 1 + i t ∗ C ~ t C_t = f_t * C_{t-1} + i_t * \tilde{C}_t Ct=ft∗Ct−1+it∗C~t
隐藏状态更新(Hidden State Update):通过输出门和当前的记忆单元状态来更新隐藏状态,公式为:
h t = o t ∗ tanh ( C t ) h_t = o_t * \tanh(C_t) ht=ot∗tanh(Ct)
LSTM前向传播公式:
h t , C t = LSTM ( x t , h t − 1 , C t − 1 ) h_t, C_t = \text{LSTM}(x_t, h_{t-1}, C_{t-1}) ht,Ct=LSTM(xt,ht−1,Ct−1)
全连接层
LSTM的输出通过全连接层(fully connected layer)进行映射,得到最终的预测值。全连接层的公式为:
y = W f c ⋅ h t + b f c y = W_{fc} \cdot h_t + b_{fc} y=Wfc⋅ht+bfc
其中,Wfc 和 bfc 分别是全连接层的权重和偏置,ht 是LSTM输出的隐藏状态。
Dropout层
为了防止过拟合,模型中还使用了Dropout层,在训练过程中随机屏蔽掉部分神经元,Dropout的公式为:
h ′ = Dropout ( h , p ) h' = \text{Dropout}(h, p) h′=Dropout(h,p)
其中,p 是保留的神经元概率。
模型的整体训练流程
数据加载与处理:首先将时间序列数据按30天作为一个输入序列,构建训练和测试集。每个输入序列对应未来30天的销售额预测。
模型训练:在训练阶段,模型使用均方误差(MSE)作为损失函数。MSE的公式为:
MSE = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 \text{MSE} = \frac{1}{n} \sum_{i=1}^{n}(y_i - \hat{y}_i)^2 MSE=n1i=1∑n(yi−y^i)2
其中,yi是实际值,y^i是模型预测值,n 是样本数量。优化器选择Adam算法,基于反向传播更新模型参数。
评估指标:在评估阶段,除了MSE外,还使用了平均绝对误差(MAE)作为评估指标。MAE的公式为:
MAE = 1 n ∑ i = 1 n ∣ y i − y ^ i ∣ \text{MAE} = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i| MAE=n1i=1∑n∣yi−y^i∣
评估过程中,测试集的预测结果通过这些指标进行比较,最后输出模型的误差情况。
可视化与结果分析:训练完成后,模型的损失曲线和预测结果通过图表进行可视化,便于直观了解模型的收敛情况以及预测性能。
5. 核心代码详细讲解
1. 数据预处理与特征工程
df = pd.read_csv('smoothed_ES_sku023.csv')
解释: 读取销售数据的CSV文件。这里使用的是pandas
库的read_csv
函数,将原始数据加载为DataFrame格式。
df['date'] = pd.to_datetime(df['date'], format='%Y/%m/%d')
解释: 将date
列转换为datetime
格式,方便后续的时间序列操作和按日期排序。
df = df.sort_values('date')
df.reset_index(drop=True, inplace=True)
解释: 对数据集按日期升序排序,确保时间序列的顺序一致。同时重置索引,删除旧索引并更新为新顺序。
df['week_number'] = df['date'].dt.isocalendar().week
解释: 提取每条数据所属的周数,并将其作为新的特征添加到数据集中,捕捉销售额的周期性特征。
df['last_week_sale'] = df['sale'].shift(7)
解释: 创建“上一周销售额”这一特征,用于捕捉前一周销售额对当前销售额的影响。shift(7)
表示将销售额向前平移7天。
df.fillna(method='bfill', inplace=True)
解释: 处理缺失值。这里使用向后填充的方法(backward fill),用之后的有效值填补缺失数据,确保数据的完整性。
features = ['temperature', 'week_number', 'last_week_sale']
target = 'sale'
解释: 定义模型的特征列和目标变量。其中,特征列包含温度、周数和上一周的销售额,目标变量为每日的销售额。
scaler = MinMaxScaler()
scaled_features = scaler.fit_transform(data)
解释: 使用MinMaxScaler
将特征和目标变量缩放到0到1之间的范围。这样做可以避免不同特征数值范围差异太大,防止某些特征对模型的影响过大。
2. 创建多步序列数据
def create_sequences(data, seq_length, forecast_steps, feature_cols, target_col):
xs = []
ys = []for i in range(len(data) - seq_length - forecast_steps + 1):
x = data.iloc[i:i + seq_length][feature_cols].values
y = data.iloc[i + seq_length:i + seq_length + forecast_steps][target_col].values
xs.append(x)
ys.append(y)return np.array(xs), np.array(ys)
-
解释: 这是创建多步序列数据的核心函数。它通过滑动窗口的方式将输入数据分割成固定长度的序列,用于训练LSTM模型。
data
: 输入的已预处理数据。seq_length
: 输入序列的长度,这里为过去30天。forecast_steps
: 预测步长,这里为未来30天。feature_cols
: 使用的特征列。target_col
: 目标列。- 函数返回两个数组:
xs
为输入特征序列,ys
为对应的目标序列。
X, y = create_sequences(scaled_data, SEQ_LENGTH, FORECAST_STEPS, features, target)
- 解释: 使用上面的
create_sequences
函数生成训练和测试数据,X
是特征序列,y
是目标值序列。
3. 模型架构构建
class LSTMModel(nn.Module):def init(self, input_size, hidden_size, num_layers, output_size, dropout=0.2):super(LSTMModel, self).
__init__
()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, dropout=dropout)
self.fc = nn.Linear(hidden_size, output_size)
-
解释: 这是模型的构建部分,定义了LSTM模型的结构。
input_size
: 输入特征的数量。hidden_size
: LSTM层的隐藏单元数量,决定了每层输出的维度。num_layers
: LSTM层的数量,这里使用了2层。dropout
: Dropout的比例,用于防止过拟合。lstm
: 定义了一个LSTM层,带有batch_first=True
,即输入的batch维度为第一维。fc
: 全连接层,将LSTM的输出映射到最终的预测值(未来30天的销售额)。
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 = out[:, -1, :]
out = self.fc(out)return out
- 解释: 前向传播函数。初始化LSTM的隐藏状态和细胞状态为全零向量,然后通过LSTM层获取输出,并仅保留最后一个时间步的输出。最终通过全连接层生成预测结果。
4. 模型训练与评估
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
- 解释: 定义损失函数和优化器。损失函数为均方误差(MSE),优化器为Adam算法,它通过梯度下降优化模型的参数。
for epoch in range(EPOCHS):
model.train()
epoch_train_loss = 0for X_batch, y_batch in train_loader:
X_batch = X_batch.to(device)
y_batch = y_batch.to(device)
outputs = model(X_batch)
loss = criterion(outputs, y_batch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
epoch_train_loss += loss.item() * X_batch.size(0)
- 解释: 训练循环。每个epoch中,模型首先进入训练模式,并循环遍历训练数据进行前向传播、计算损失、反向传播和优化更新权重。每个batch训练完成后,累积损失用于后续的模型评估。
model.eval()
epoch_test_loss = 0with torch.no_grad():for X_batch, y_batch in test_loader:
X_batch = X_batch.to(device)
y_batch = y_batch.to(device)
outputs = model(X_batch)
loss = criterion(outputs, y_batch)
epoch_test_loss += loss.item() * X_batch.size(0)
- 解释: 测试循环。在评估阶段,模型切换为评估模式,不进行梯度更新。通过前向传播计算测试集的损失,以评估模型的泛化能力。
mse = mean_squared_error(y_test_unscaled, y_pred_unscaled)
mae = mean_absolute_error(y_test_unscaled, y_pred_unscaled)
- 解释: 计算均方误差(MSE)和平均绝对误差(MAE),作为模型的评估指标,评估预测值与真实值之间的偏差。
6. 模型优缺点评价
模型优点:
- 时序特征捕捉:LSTM模型擅长处理时间序列数据,其记忆单元能够有效捕捉长期依赖关系,在销售额预测中可以很好地捕捉历史数据对未来的影响。
- 多特征输入:模型不仅使用了历史销售数据,还添加了温度、周数等额外特征,有助于增强对外部因素的敏感度,提升预测精度。
- 多步预测能力:模型能够同时预测未来30天的销售额,而不是逐步预测,这提升了预测的效率和实用性。
- 防止过拟合:通过Dropout层减少过拟合的可能性,增强了模型的泛化能力,特别是当训练数据有限时,这种机制尤为有效。
模型缺点:
- 长序列数据依赖问题:尽管LSTM适合捕捉长期依赖,但随着序列长度增加,模型在训练时可能会遇到梯度消失或梯度爆炸问题,导致模型难以学习非常长的序列信息。
- 对非线性特征的表达能力有限:虽然LSTM能够处理时间序列,但在对复杂的非线性特征的捕捉能力上有限,可能无法充分挖掘某些潜在的复杂模式。
- 计算资源消耗较大:LSTM的训练通常需要较大的计算资源,尤其在多层LSTM结构中,训练时间会显著增加。
改进方向:
- 模型结构优化:可以考虑使用更复杂的时序模型,如Transformer或Attention机制,这类模型在捕捉长距离依赖关系上更有效,且计算效率较高。
- 超参数调整:当前的超参数如隐藏单元数量、层数和学习率等可以通过网格搜索或随机搜索进行调优,从而找到最佳参数配置,进一步提升模型表现。
- 数据增强:可以考虑引入更多的数据增强方法,如滑动窗口增强、时间序列的噪声扰动等,以增强模型的鲁棒性。
- 特征工程:加入更多与销售相关的外部特征,如节假日、促销活动、竞争对手的动态等,进一步丰富特征空间,提升模型的预测精度。
↓↓↓更多热门推荐:
查看全部项目数据集、代码、教程进入官网https://zzgcz.com/