基于Levenberg-Marquardt算法改进的BP神经网络-公式推导及应用

2023-12-19 00:04:01

Levenberg-Marquardt算法是一种用于非线性最小化问题的优化算法,通常用于训练神经网络。它结合了梯度下降和高斯-牛顿方法的特点,旨在提高收敛速度和稳定性。下面是基于Levenberg-Marquardt算法改进的反向传播(BP)神经网络的详细推导过程。

考虑一个具有L层的前馈神经网络,其中第l层(l=1,2,...,L)有nl个神经元。令θ表示所有权重和偏置参数的集合。网络的输入为x,输出为y,训练数据集包含N个样本{(xi, yi)}。

1. 网络结构和符号定义:

? ?- 输入层:$a^{(1)} = x$
? ?- 第l层的激活:$z^{(l+1)} = \theta^{(l)}a^{(l)}$
? ?- 第l层的输出:$a^{(l+1)} = g(z^{(l+1)})$
? ?- 损失函数:$J(\theta) = \frac{1}{2}\sum_{i=1}^{N}\|y_i - a^{(L)}_i\|^2$

2. 反向传播:

? ?对于Levenberg-Marquardt算法,我们需要计算损失函数对参数的梯度。首先,使用反向传播计算梯度。

? ?- 计算输出层的误差项:
? ? ?$\delta^{(L)} = \nabla_{a^{(L)}}J \odot g'(z^{(L+1)})$

? ?- 计算隐藏层的误差项:
? ? ?$\delta^{(l)} = (\theta^{(l)})^T \delta^{(l+1)} \odot g'(z^{(l+1)})$

3. Levenberg-Marquardt算法的更新规则:

? ?Levenberg-Marquardt算法的更新规则基于牛顿方法,但引入了一个调整因子(damping parameter)λ。

? ?- 计算Hessian矩阵H(二阶偏导数):
? ? ?$H = \nabla_{\theta}\nabla_{\theta}J = \sum_{i=1}^{N}\nabla_{\theta}\delta_i \nabla_{\theta}\delta_i^T$

? ?- 计算梯度g:
? ? ?$g = \nabla_{\theta}J = \sum_{i=1}^{N}\nabla_{\theta}\delta_i$

? ?- 计算Levenberg-Marquardt矩阵:
? ? ?$L = H + \lambda I$

? ?- 使用Levenberg-Marquardt矩阵求解参数更新:
? ? ?$\Delta\theta = -L^{-1}g$

? ?- 更新参数:
? ? ?$\theta \leftarrow \theta + \Delta\theta$

? ?- 更新λ:
? ? ?$\lambda \leftarrow \lambda \times \text{adjustment factor}$

? ?这里,调整因子通常根据网络性能进行动态调整,以确保算法的稳定性和收敛性。

4. 迭代更新:

? ?通过反复执行步骤2和步骤3,直到满足停止条件(如达到最大迭代次数或达到一定的精度)为止。

5. 代码实现:

下面是一个使用PyTorch实现基于Levenberg-Marquardt算法改进的BP神经网络的简单示例:

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

# 生成模拟数据
np.random.seed(42)
X = np.random.rand(100, 1).astype(np.float32)
Y = 3 * X + 1 + 0.1 * np.random.randn(100, 1).astype(np.float32)

# 转换为PyTorch张量
X_tensor = torch.from_numpy(X)
Y_tensor = torch.from_numpy(Y)

# 定义神经网络模型
class LinearRegression(nn.Module):
? ? def __init__(self):
? ? ? ? super(LinearRegression, self).__init__()
? ? ? ? self.linear = nn.Linear(1, 1, bias=True)

? ? def forward(self, x):
? ? ? ? return self.linear(x)

# 初始化模型、损失函数和优化器
model = LinearRegression()
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 定义Levenberg-Marquardt算法的训练步骤
def train_step(X, Y, model, criterion, optimizer):
? ? model.train()
? ? optimizer.zero_grad()
? ? predictions = model(X)
? ? loss = criterion(predictions, Y)

? ? # 计算梯度和Hessian矩阵
? ? gradients = torch.autograd.grad(loss, model.parameters(), create_graph=True)
? ? hessian = torch.autograd.grad(gradients, model.parameters(), create_graph=True)

? ? # 调整因子
? ? damping = 0.01
? ? l_matrix = [h + damping * torch.eye(h.size(0), device=h.device) for h in hessian]

? ? # 使用Levenberg-Marquardt矩阵求解参数更新
? ? update_direction = torch.linalg.solve(l_matrix, gradients)

? ? # 更新参数
? ? for param, update in zip(model.parameters(), update_direction):
? ? ? ? param.data -= update.data

? ? return loss.item()

# 训练模型
epochs = 100
for epoch in range(epochs):
? ? loss = train_step(X_tensor, Y_tensor, model, criterion, optimizer)
? ? print(f'Epoch {epoch+1}/{epochs}, Loss: {loss}')

# 打印训练后的权重和偏置
print('Trained weights:', model.linear.weight.data.item())
print('Trained bias:', model.linear.bias.data.item())

这个示例中,我们首先定义了一个简单的线性回归模型,并使用均方误差作为损失函数。在`train_step`函数中,我们计算了梯度和Hessian矩阵,并使用Levenberg-Marquardt算法进行参数更新。在每个训练步骤中,通过反复执行`train_step`函数,模型的参数将逐渐收敛到最优值。

在实际情况中,基于Levenberg-Marquardt算法的神经网络训练可能不是最佳选择,因为该算法相对较复杂,而深度学习框架通常使用更适合大规模数据集的优化算法。不过,为了演示,你可以使用基于Levenberg-Marquardt算法的训练方法来训练一个简单的神经网络模型以在MNIST数据集上进行数字识别。以下是一个PyTorch示例:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
import matplotlib.pyplot as plt

# 加载MNIST数据集
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)

# 定义神经网络模型
class SimpleNN(nn.Module):
? ? def __init__(self):
? ? ? ? super(SimpleNN, self).__init__()
? ? ? ? self.flatten = nn.Flatten()
? ? ? ? self.linear1 = nn.Linear(28 * 28, 128)
? ? ? ? self.relu = nn.ReLU()
? ? ? ? self.linear2 = nn.Linear(128, 10)

? ? def forward(self, x):
? ? ? ? x = self.flatten(x)
? ? ? ? x = self.linear1(x)
? ? ? ? x = self.relu(x)
? ? ? ? x = self.linear2(x)
? ? ? ? return x

# 定义Levenberg-Marquardt算法的训练步骤
def train_step(X, Y, model, criterion, optimizer):
? ? model.train()
? ? optimizer.zero_grad()
? ? predictions = model(X)
? ? loss = criterion(predictions, Y)

? ? # 计算梯度和Hessian矩阵
? ? gradients = torch.autograd.grad(loss, model.parameters(), create_graph=True)
? ? hessian = torch.autograd.grad(gradients, model.parameters(), create_graph=True)

? ? # 调整因子
? ? damping = 0.01
? ? l_matrix = [h + damping * torch.eye(h.size(0), device=h.device) for h in hessian]

? ? # 使用Levenberg-Marquardt矩阵求解参数更新
? ? update_direction = torch.linalg.solve(l_matrix, gradients)

? ? # 更新参数
? ? for param, update in zip(model.parameters(), update_direction):
? ? ? ? param.data -= update.data

? ? return loss.item()

# 初始化模型、损失函数和优化器
model = SimpleNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模型
epochs = 5
for epoch in range(epochs):
? ? for data, target in train_loader:
? ? ? ? optimizer.zero_grad()
? ? ? ? output = model(data)
? ? ? ? loss = criterion(output, target)
? ? ? ? loss.backward()
? ? ? ? optimizer.step()

? ? print(f'Epoch {epoch+1}/{epochs}, Loss: {loss.item()}')

# 可视化模型预测结果
with torch.no_grad():
? ? model.eval()
? ? test_loader = torch.utils.data.DataLoader(datasets.MNIST('./data', train=False, download=True, transform=transform), batch_size=1000, shuffle=True)
? ? images, labels = next(iter(test_loader))
? ? predictions = model(images)
? ? predicted_labels = torch.argmax(predictions, dim=1)

? ? # 显示前25个测试样本及其预测标签
? ? plt.figure(figsize=(10, 10))
? ? for i in range(25):
? ? ? ? plt.subplot(5, 5, i + 1)
? ? ? ? plt.imshow(images[i].squeeze(), cmap='gray')
? ? ? ? plt.title(f'Predicted: {predicted_labels[i]}, Actual: {labels[i]}')
? ? ? ? plt.axis('off')
? ? plt.show()

请注意,这只是一个演示性质的例子,使用Levenberg-Marquardt算法来训练神经网络可能不如其他现代优化算法(如Adam、SGD等)效果好。深度学习领域通常使用梯度下降的变体来训练神经网络。

文章来源:https://blog.csdn.net/m0_61789994/article/details/135073242
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。