上一篇文章有提到线性回归方程。
时间序列预测(二)——前馈神经网络(Feedforward Neural Network, FNN)-CSDN博客
与线性回归相比:
线性回归只有一个线性层,输入直接映射到输出,不包含隐藏层和激活函数。而前馈神经网络通常包含多个隐藏层和非线性激活函数,可以学习更复杂的模式和非线性关系。当前馈神经网络只有一个输入层和一个输出层,且没有激活函数时,它实际上等价于线性回归。
接下来,讲前馈神经网络。
参考文章:
前馈神经网络(Feed-Forward Neural Network) - JackYang - 博客园 (cnblogs.com)
深度学习神经网络基础知识(三)前向传播,反向传播和计算图_前向传播公式-CSDN博客
优化器(Optimizer)(SGD、Momentum、AdaGrad、RMSProp、Adam) - CSDN
前馈神经网络(Feedforward Neural Networks)是最基础的神经网络类型,信号单向流动,从输入层到隐藏层再到输出层,没有反馈循环,它适用于非时间序列的预测问题。在时间序列预测中,前馈神经网络(FNN) 虽然没有时间依赖性,但可以通过适当的数据预处理来实现时间序列预测的功能。它的核心思路是将时间序列的历史数据转换为独立特征,然后通过 FNN 进行预测。这种方法称为 滞后输入法(Lagged Input Method) 或 窗口法。
一、基本结构和工作原理
1、基本结构
前馈神经网络(Feed-Forward Neural Network,简称FNN)是一种基本且广泛应用的人工神经网络结构。其结构由多个层次组成,主要包括:
- 输入层:接收外部输入的数据,并将其传递给下一层。
- 隐藏层:位于输入层和输出层之间,可以有一层或多层,负责对输入数据进行非线性变换和特征提取。
- 输出层:接收隐藏层的输出,并将最终的结果输出
2、工作原理
前馈神经网络的工作原理主要包括前向传播和反向传播两个过程。
(1)前向传播(Forward Propagation)
首先,输入数据首先进入输入层,然后依次经过每个隐藏层的神经元,每个神经元通过权重和偏置对输入进行线性组合,并经过激活函数处理。每层的输出成为下一层的输入。最后,隐藏层的最终输出通过输出层,生成预测结果。
如果是回归问题,输出可以是连续值;如果是分类问题,输出可以是概率分布或类别标签。
其中每个隐藏层的具体计算过程如下:
涉及到激活函数后面介绍。
在前向传播中,网络的参数(权重和偏置)保持不变,网络对输入数据生成初始预测结果。
(2)反向传播(Backward Propagation)
反向传播是神经网络在训练过程中使用的,其实思路是和上一篇文章讲的线性回归一样的,也是如下两步:
a、先计算计算损失函数;
b、更新权重和偏置。从输出层开始,逐层计算误差的梯度,并沿着网络向输入层传播。每层的梯度用于更新更新各层的权重和偏置,使得模型的损失逐步减小。(即梯度下降,这只是优化器的一种,后面介绍)。
这里的损失函数要丰富一些,常见的损失函数包括均方误差(MSE)、交叉熵损失等,后面介绍。
总得来说,前向传播用来计算预测结果。反向传播用来计算误差并更新参数。这两个过程相互交替,逐步优化模型,使其对输入数据的预测越来越准确。
值得注意的是,这里的“反馈”仅用于权重的调整,并不构成循环反馈,即网络整体仍然是前馈的。网络接收新信息后,改变连接权值,调节最终输出,直至网络输出误差满足精度要求,结束训练。
二、补充的几个概念
1、激活函数(Activation Function)
激活函数是神经网络中每个神经元的输出函数,用于引入非线性,从而使神经网络能够逼近复杂的非线性关系。没有激活函数的网络只能表示线性变换(如上一篇的线性回归不需要激活函数),因此不能解决实际中的非线性问题。激活函数的输入是该神经元的加权和,输出则是处理后的值,通过激活函数的输出可以决定是否激活一个神经元,或者说一个神经元的输出程度。
具体请看下面这篇文章:
时间序列预测(三)——激活函数(Activation Function)-CSDN博客
2、损失函数(Loss Function)
损失函数是衡量模型预测值与真实值之间差异的函数,指导模型在训练过程中不断优化。根据任务类型和数据分布不同,常用的损失函数分为回归损失函数(如线性回归模型用到的)和分类损失函数两大类。
具体请看下面这篇文章:
3、优化器(Optimizer)
优化器用于更新神经网络的权重,以减少或最小化损失函数(loss function)的值以提高模型准确性,同时,优化器还能根据损失函数的梯度调整学习速率,帮助模型更好地学习,避免在训练过程中陷入局部最小值。常见的有BGD、SGD、Adam和RMSProp。
具体请看下面这篇文章:
‘
三、前馈神经网络(FNN)与多层感知器(MLP)的关系
看其他文章又看到了多层感知器,说是和前馈神经网络很像,查了一下:
多层感知器是一种经典的前馈人工神经网络,是前馈人工神经网络的一个子集,通常专指由多个隐藏层组成的网络。所有的多层感知器都是前馈神经网络,但并非所有的前馈神经网络都是多层感知器。前馈神经网络可以包含更复杂的结构,如卷积层、池化层等,而多层感知器则主要由全连接层组成。
四、代码实现
同前一篇文章一样,根据一个包含道路曲率(Curvature)、车速(Velocity)、侧向加速度(Ay)和方向盘转角(Steering_Angle)真实的数据集,去预测未来的方向盘转角。
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error as mae
import matplotlib.pyplot as plt
# 1. 数据预处理
# 读取数据
data = pd.read_excel('input_data_20241010160240.xlsx') # 替换为你的数据文件路径
# 提取特征和标签
labels = data['Steering_Angle'].values
features = data[['Curvature', 'Ay', 'Velocity']].values # 使用 NumPy 数组
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(features, labels, test_size=0.2)
# 转换为 PyTorch 张量
x_train_tensor = torch.tensor(x_train, dtype=torch.float32)
y_train_tensor = torch.tensor(y_train, dtype=torch.float32).view(-1, 1)
x_test_tensor = torch.tensor(x_test, dtype=torch.float32)
y_test_tensor = torch.tensor(y_test, dtype=torch.float32).view(-1, 1)
# 2. 创建神经网络模型
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(3, 64) # 输入层到隐藏层
self.fc2 = nn.Linear(64, 32) # 隐藏层到隐藏层
self.fc3 = nn.Linear(32, 1) # 隐藏层到输出层
def forward(self, x):
x = torch.relu(self.fc1(x)) # 激活函数
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x
# 实例化模型
model = SimpleNN()
# 3. 设置损失函数和优化器
criterion = nn.MSELoss() # 均方误差损失
optimizer = optim.Adam(model.parameters(), lr=0.001) # Adam 优化器
# 4. 训练模型
num_epochs = 1000
for epoch in range(num_epochs):
model.train()
# 前向传播
outputs = model(x_train_tensor)
loss = criterion(outputs, y_train_tensor)
# 后向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch + 1) % 100 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')
# 5. 预测
model.eval()
with torch.no_grad():
y_pred_tensor = model(x_test_tensor)
y_pred = y_pred_tensor.numpy()
# 评估指标
score = 1 - (mae(y_test, y_pred) / (y_test.mean() if y_test.mean() != 0 else 1))
print(f"R^2 score: {score}")
# 绘制实际值和预测值的对比图
plt.figure(figsize=(10, 6))
plt.plot(range(len(y_test)), y_test, label='实际值', color='blue')
plt.plot(range(len(y_pred)), y_pred, label='预测值', color='red')
plt.xlabel('样本索引')
plt.ylabel('Steering Angle')
plt.title('实际值与预测值对比图')
plt.legend()
plt.grid(True)
plt.show()
输出结果:
别忘了给这篇文章点个赞哦,非常感谢。我也正处于学习的过程,可能会有错,如果有问题,欢迎在评论区留言讨论,一起学习!