前馈神经网络(Feedforward Neural Network, FNN) 是一种基本的人工神经网络类型,其结构简单,广泛应用于各种机器学习任务。它由多个层次组成,包括输入层、隐藏层和输出层。FNN 中的每一层与下一层的神经元之间是完全连接的,但不同层之间的神经元不相互连接。
FNN 以其数据流动方式来命名——前馈,意味着信息从输入层开始,经过一系列的隐藏层,最终输出结果,不存在任何循环或反馈连接。与递归神经网络(RNN)或卷积神经网络(CNN)相比,FNN 是最基础、最简单的神经网络结构。
FNN 的基本结构
- 输入层(Input Layer):接收外部数据,每个神经元代表一个特征。
- 隐藏层(Hidden Layers):通过多层神经元进行数据处理,学习特征之间的关系。每一层神经元通过权重和激活函数处理输入,并将结果传递到下一层。
- 输出层(Output Layer):生成最终结果,根据任务类型(分类、回归等)输出相应的预测值。
FNN 的特点
-
无反馈循环:
- FNN 是前馈型网络,信息从输入流向输出,没有反馈环路或递归连接。
-
层次结构:
- FNN 由多个层次构成,包括输入层、隐藏层和输出层。每个神经元与上一层的所有神经元相连接。
-
非线性激活函数:
- 每个神经元通过激活函数(如 ReLU、sigmoid、tanh)处理其输入,增加网络的非线性,使其能够学习更复杂的模式。
-
权重和偏置:
- 每一层的连接都有相应的权重和偏置,经过训练优化,以最小化预测误差。权重通过梯度下降算法(如 Adam、SGD)进行更新。
-
端到端训练:
- FNN 通过反向传播算法进行训练。输入数据通过前向传播进入输出层,计算误差后,反向传播梯度并更新参数。
-
适用于各种任务:
- FNN 可应用于分类、回归、特征提取、生成等多种任务,能够处理结构化数据、文本数据、时间序列等多种类型的数据。
-
过拟合的风险:
- 如果网络层数过多或参数过多,容易产生过拟合现象。为防止过拟合,常使用正则化技术,如 dropout、L2 正则化等。
-
训练过程较为直观:
FNN 的应用
- 分类问题:通过输入特征,预测所属类别,例如图像分类、文本分类、情感分析等。
- 回归问题:预测连续值,例如房价预测、股市趋势预测等。
- 函数逼近:FNN 可以近似任何连续函数,因此常用于预测问题。
- 数据降维:通过学习数据的低维表示,FNN 可用于数据压缩和特征提取。
例子:
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import matplotlib.pyplot as pltclass FeedforwardNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(FeedforwardNN, self).__init__()self.fc1 = nn.Linear(input_size, hidden_size)self.relu = nn.LeakyReLU(negative_slope=0.01) # 使用 LeakyReLUself.fc2 = nn.Linear(hidden_size, hidden_size) # 增加一个隐藏层self.fc3 = nn.Linear(hidden_size, output_size)self.dropout = nn.Dropout(p=0.5) # 加入 Dropout 防止过拟合def forward(self, x):x = self.fc1(x)x = self.relu(x)x = self.dropout(x) # Dropoutx = self.fc2(x)x = self.relu(x)x = self.fc3(x)return x# 重新初始化网络和优化器
input_size = 10
hidden_size = 64 # 更大的隐藏层
output_size = 2model = FeedforwardNN(input_size, hidden_size, output_size)# 使用 Adam 优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)# 使用 CrossEntropyLoss 作为损失函数
criterion = nn.CrossEntropyLoss()# 创建数据
X_train = torch.randn(100, input_size)
y_train = torch.randint(0, 2, (100,))train_dataset = TensorDataset(X_train, y_train)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)# 训练模型
num_epochs = 100
for epoch in range(num_epochs):for inputs, labels in train_loader:optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')# 测试模型
X_test = X_train[:10] # 选择前10个训练数据样本进行预测
y_test = y_train[:10] # 选择前10个训练数据标签作为真实标签
model.eval()
with torch.no_grad():predictions = model(X_test)predicted_labels = torch.argmax(predictions, dim=1)# 可视化结果
plt.figure(figsize=(10, 6))
plt.plot(y_test.numpy(), label='True Labels', marker='o', linestyle='--', color='b')
plt.plot(predicted_labels.numpy(), label='Predicted Labels', marker='x', linestyle='-', color='r')
plt.xlabel('Sample Index')
plt.ylabel('Label')
plt.title('True vs Predicted Labels')
plt.legend()
plt.show()