首页 > 编程语言 >基于 Levenberg - Marquardt 法的 BP 网络学习改进算法详解

基于 Levenberg - Marquardt 法的 BP 网络学习改进算法详解

时间:2024-11-19 09:48:11浏览次数:3  
标签:mathbf lambda self Marquardt BP output hidden Levenberg size

基于 Levenberg - Marquardt 法的 BP 网络学习改进算法详解

一、引言

BP(Back Propagation)神经网络在众多领域有着广泛应用,但传统 BP 算法存在收敛速度慢、易陷入局部最优等问题。Levenberg - Marquardt(LM)算法作为一种有效的优化算法,被应用于改进 BP 网络学习,能够显著提高训练效率和网络性能。本文将深入阐述基于 Levenberg - Marquardt 法的 BP 网络学习改进算法,包括其原理、实现步骤和详细的代码示例。

二、传统 BP 网络学习算法回顾

(一)网络结构与前向传播

BP 神经网络一般由输入层、隐藏层和输出层构成。设输入层有 n n n 个神经元,输入向量为 x = ( x 1 , x 2 , ⋯   , x n ) \mathbf{x}=(x_1,x_2,\cdots,x_n) x=(x1​,x2​,⋯,xn​);隐藏层有 m m m 个神经元,输出向量为 h = ( h 1 , h 2 , ⋯   , h m ) \mathbf{h}=(h_1,h_2,\cdots,h_m) h=(h1​,h2​,⋯,hm​);输出层有 p p p 个神经元,输出向量为 y = ( y 1 , y 2 , ⋯   , y p ) \mathbf{y}=(y_1,y_2,\cdots,y_p) y=(y1​,y2​,⋯,yp​)。

在前向传播过程中,对于输入层到隐藏层,隐藏层神经元的输入为:

n e t j = ∑ i = 1 n w i j 1 x i + b j 1 net_{j}=\sum_{i = 1}^{n}w_{ij}^{1}x_{i}+b_{j}^{1} netj​=∑i=1n​wij1​xi​+bj1​

其中, w i j 1 w_{ij}^{1} wij1​ 是输入层到隐藏层的连接权重, b j 1 b_{j}^{1} bj1​ 是隐藏层的偏置。隐藏层神经元的输出通常经过激活函数(如 Sigmoid 函数 h j = 1 1 + e − n e t j h_{j}=\frac{1}{1 + e^{-net_{j}}} hj​=1+e−netj​1​)处理。

从隐藏层到输出层,输出层神经元的输入为:

u k = ∑ j = 1 m w j k 2 h j + b k 2 u_{k}=\sum_{j = 1}^{m}w_{jk}^{2}h_{j}+b_{k}^{2} uk​=∑j=1m​wjk2​hj​+bk2​

输出层神经元的输出 y k = 1 1 + e − u k y_{k}=\frac{1}{1 + e^{-u_{k}}} yk​=1+e−uk​1​(这里以 Sigmoid 函数为例)。

(二)误差计算与反向传播

对于训练样本集 { ( x ( μ ) , t ( μ ) ) } μ = 1 N \{(\mathbf{x}^{(\mu)},\mathbf{t}^{(\mu)})\}_{\mu = 1}^{N} {(x(μ),t(μ))}μ=1N​,其中 x ( μ ) \mathbf{x}^{(\mu)} x(μ) 是第 μ \mu μ 个输入样本, t ( μ ) \mathbf{t}^{(\mu)} t(μ) 是对应的目标输出。常用的误差函数是均方误差:

E = 1 2 ∑ μ = 1 N ∑ k = 1 p ( y k ( μ ) − t k ( μ ) ) 2 E=\frac{1}{2}\sum_{\mu = 1}^{N}\sum_{k = 1}^{p}(y_{k}^{(\mu)}-t_{k}^{(\mu)})^{2} E=21​∑μ=1N​∑k=1p​(yk(μ)​−tk(μ)​)2

在反向传播过程中,根据误差函数对权重的梯度来更新权重。以输出层到隐藏层的权重 w j k 2 w_{jk}^{2} wjk2​ 为例,其梯度计算为:

∂ E ∂ w j k 2 = ∑ μ = 1 N ( y k ( μ ) − t k ( μ ) ) y k ( μ ) ( 1 − y k ( μ ) ) h j ( μ ) \frac{\partial E}{\partial w_{jk}^{2}}=\sum_{\mu = 1}^{N}(y_{k}^{(\mu)}-t_{k}^{(\mu)})y_{k}^{(\mu)}(1 - y_{k}^{(\mu)})h_{j}^{(\mu)} ∂wjk2​∂E​=∑μ=1N​(yk(μ)​−tk(μ)​)yk(μ)​(1−yk(μ)​)hj(μ)​

然后根据梯度下降法更新权重:

w j k 2 ( t + 1 ) = w j k 2 ( t ) − η ∂ E ∂ w j k 2 w_{jk}^{2}(t + 1)=w_{jk}^{2}(t)-\eta\frac{\partial E}{\partial w_{jk}^{2}} wjk2​(t+1)=wjk2​(t)−η∂wjk2​∂E​

其中, η \eta η 是学习率, t t t 表示训练次数。类似地,可以计算输入层到隐藏层的权重更新公式。

三、传统 BP 算法的问题分析

(一)收敛速度问题

  1. 学习率的影响
    在传统 BP 算法中,学习率的选择至关重要且困难。若学习率过大,权重更新可能会过度,导致网络在误差曲面上跳过最小值点,甚至使训练过程发散;若学习率过小,权重更新缓慢,需要大量的训练迭代才能使误差降低到可接受的水平,尤其在处理复杂的高维数据或复杂函数逼近问题时,收敛速度会非常慢。
  2. 梯度下降的局限性
    传统 BP 基于梯度下降方法,每次权重更新仅沿着当前梯度的负方向进行。在复杂的误差曲面中,如存在狭长的峡谷或平坦区域,梯度方向可能并不直接指向全局最小值,这会导致在这些区域收敛效率低下。

(二)局部最优问题

由于传统 BP 算法沿着梯度下降方向更新权重,容易陷入局部最优解。在误差曲面中,当达到局部最优点时,梯度为零或接近零,此时权重更新停止,但这个局部最优点可能并非全局最优解,使得网络的性能无法进一步提升。

四、Levenberg - Marquardt 法原理

(一)基本思想

Levenberg - Marquardt 法是一种结合了梯度下降法和牛顿法优点的优化算法。它在接近最优解时具有牛顿法的二次收敛速度,在远离最优解时表现得像梯度下降法一样稳定。

对于目标函数 E ( w ) E(\mathbf{w}) E(w)(这里 w \mathbf{w} w 表示网络的所有权重和偏置组成的向量),牛顿法的迭代公式为:

w t + 1 = w t − [ ∇ 2 E ( w t ) ] − 1 ∇ E ( w t ) \mathbf{w}^{t + 1}=\mathbf{w}^{t}-[\nabla^{2}E(\mathbf{w}^{t})]^{-1}\nabla E(\mathbf{w}^{t}) wt+1=wt−[∇2E(wt)]−1∇E(wt)

其中, ∇ E ( w t ) \nabla E(\mathbf{w}^{t}) ∇E(wt) 是目标函数在 w t \mathbf{w}^{t} wt 处的梯度向量, ∇ 2 E ( w t ) \nabla^{2}E(\mathbf{w}^{t}) ∇2E(wt) 是目标函数在 w t \mathbf{w}^{t} wt 处的 Hessian 矩阵。然而,计算 Hessian 矩阵及其逆矩阵在实际中计算量很大。

Levenberg - Marquardt 法使用一个近似的 Hessian 矩阵。它将目标函数 E ( w ) E(\mathbf{w}) E(w) 在当前点 w t \mathbf{w}^{t} wt 处进行二阶泰勒展开:

E ( w ) ≈ E ( w t ) + ∇ E ( w t ) T ( w − w t ) + 1 2 ( w − w t ) T H ( w − w t ) E(\mathbf{w})\approx E(\mathbf{w}^{t})+\nabla E(\mathbf{w}^{t})^{T}(\mathbf{w}-\mathbf{w}^{t})+\frac{1}{2}(\mathbf{w}-\mathbf{w}^{t})^{T}\mathbf{H}(\mathbf{w}-\mathbf{w}^{t}) E(w)≈E(wt)+∇E(wt)T(w−wt)+21​(w−wt)TH(w−wt)

其中, H \mathbf{H} H 是对 Hessian 矩阵的近似。在 LM 算法中,这个近似的 Hessian 矩阵为:

H = J T J + λ I \mathbf{H}=\mathbf{J}^{T}\mathbf{J}+\lambda\mathbf{I} H=JTJ+λI

其中, J \mathbf{J} J 是雅可比矩阵,它的元素是误差函数对权重的一阶偏导数, λ \lambda λ 是一个可调参数, I \mathbf{I} I 是单位矩阵。当 λ \lambda λ 很大时,算法接近梯度下降法;当 λ \lambda λ 很小时,算法接近牛顿法。

(二)参数更新公式

权重更新公式为:

w t + 1 = w t − ( J T J + λ I ) − 1 J T e \mathbf{w}^{t + 1}=\mathbf{w}^{t}-(\mathbf{J}^{T}\mathbf{J}+\lambda\mathbf{I})^{-1}\mathbf{J}^{T}\mathbf{e} wt+1=wt−(JTJ+λI)−1JTe

其中, e \mathbf{e} e 是误差向量。通过调整 λ \lambda λ 的值,可以控制算法的收敛速度和稳定性。在每次迭代中,如果误差减小,则减小 λ \lambda λ;如果误差增大,则增大 λ \lambda λ。

五、基于 Levenberg - Marquardt 法的 BP 网络学习改进算法步骤

(一)初始化

  1. 网络参数初始化
    初始化 BP 网络的权重和偏置,可将权重随机初始化为较小的值,例如在区间 [ − 0.5 , 0.5 ] [-0.5,0.5] [−0.5,0.5] 内。同时,初始化参数 λ \lambda λ(通常初始化为一个较小的值,如 0.01)、雅可比矩阵 J \mathbf{J} J(初始化为相应大小的零矩阵)和其他相关变量。
  2. 训练参数初始化
    设置训练的相关参数,如最大训练次数、误差阈值等,用于控制训练过程的终止条件。

(二)训练过程

  1. 前向传播
    对于每个训练样本,按照传统 BP 算法的前向传播方式计算网络的输出。
  2. 误差计算与雅可比矩阵计算
    计算当前样本的误差向量 e \mathbf{e} e,并通过反向传播计算雅可比矩阵 J \mathbf{J} J。雅可比矩阵的计算涉及到误差函数对每个权重的偏导数。
  3. 近似 Hessian 矩阵构建与权重更新
    根据当前的雅可比矩阵 J \mathbf{J} J 和参数 λ \lambda λ,构建近似 Hessian 矩阵 H = J T J + λ I \mathbf{H}=\mathbf{J}^{T}\mathbf{J}+\lambda\mathbf{I} H=JTJ+λI。然后,求解线性方程组 ( J T J + λ I ) Δ w = J T e (\mathbf{J}^{T}\mathbf{J}+\lambda\mathbf{I})\Delta\mathbf{w}=\mathbf{J}^{T}\mathbf{e} (JTJ+λI)Δw=JTe,得到权重更新量 Δ w \Delta\mathbf{w} Δw,并更新网络的权重和偏置: w t + 1 = w t − Δ w \mathbf{w}^{t + 1}=\mathbf{w}^{t}-\Delta\mathbf{w} wt+1=wt−Δw。
  4. 参数调整
    计算更新权重后的误差。如果误差减小,则减小 λ \lambda λ(例如, λ = λ / 10 \lambda=\lambda/10 λ=λ/10);如果误差增大,则增大 λ \lambda λ(例如, λ = 10 λ \lambda = 10\lambda λ=10λ)。
  5. 停止准则判断
    检查是否满足停止准则,如达到最大训练次数或者当前误差小于设定的误差阈值。如果满足,则停止训练;否则,返回步骤 1 继续下一次迭代。

六、代码示例

以下是使用 Python 实现的基于 Levenberg - Marquardt 法的 BP 网络学习改进算法的代码示例:

import numpy as np

# Sigmoid 激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# Sigmoid 函数的导数
def sigmoid_derivative(x):
    return x * (1 - x)

class NeuralNetwork:
    def __init__(self, input_size, hidden_size, output_size):
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
        # 随机初始化权重
        self.W1 = np.random.rand(self.input_size, self.hidden_size)
        self.b1 = np.zeros((1, self.hidden_size))
        self.W2 = np.random.rand(self.hidden_size, self.output_size)
        self.b2 = np.zeros((1, self.output_size))
        self.lambda_value = 0.01  # 初始lambda值

    def forward_propagation(self, X):
        self.z1 = np.dot(X, self.W1) + self.b1
        self.a1 = sigmoid(self.z1)
        self.z2 = np.dot(self.a1, self.W2) + self.b2
        self.a2 = sigmoid(self.z2)
        return self.a2

    def back_propagation(self, X, y):
        m = X.shape[0]
        dZ2 = (self.a2 - y) * sigmoid_derivative(self.z2)
        dW2 = np.dot(self.a1.T, dZ2)
        db2 = np.sum(dZ2, axis=0, keepdims=True)
        dZ1 = np.dot(dZ2, self.W2.T) * sigmoid_derivative(self.z1)
        dW1 = np.dot(X.T, dZ1)
        db1 = np.sum(dZ1, axis=0, keepdims=True)
        return dW1, db1, dW2, db2

    def jacobian_matrix(self, X, y):
        m = X.shape[0]
        J = np.zeros((m * self.output_size, (self.input_size * self.hidden_size) + self.hidden_size + (self.hidden_size * self.output_size) + self.output_size))
        for i in range(m):
            sample_X = X[i].reshape(1, -1)
            sample_y = y[i].reshape(1, -1)
            dW1, db1, dW2, db2 = self.back_propagation(sample_X, sample_y)
            start_idx_W1 = 0
            end_idx_W1 = self.input_size * self.hidden_size
            start_idx_b1 = end_idx_W1
            end_idx_b1 = end_idx_W1 + self.hidden_size
            start_idx_W2 = end_idx_b1
            end_idx_W2 = end_idx_b1 + self.hidden_size * self.output_size
            start_idx_b2 = end_idx_W2
            end_idx_b2 = end_idx_W2 + self.output_size
            J[i * self.output_size:(i + 1) * self.output_size, start_idx_W1:end_idx_W1] = dW1.flat
            J[i * self.output_size:(i + 1) * self.output_size, start_idx_b1:end_idx_b1] = db1.flat
            J[i * self.output_size:(i + 1) * self.output_size, start_idx_W2:end_idx_W2] = dW2.flat
            J[i * self.output_size:(i + 1) * self.output_size, start_idx_b2:end_idx_b2] = db2.flat
        return J

    def levenberg_marquardt_update(self, X, y):
        output = self.forward_propagation(X)
        error = output - y
        J = self.jacobian_matrix(X, y)
        H = np.dot(J.T, J) + self.lambda_value * np.eye(J.shape[1])
        gradient = np.dot(J.T, error.flat)
        update_vector = np.linalg.solve(H, gradient)
        self.W1 -= update_vector[:self.input_size * self.hidden_size].reshape(self.input_size, self.hidden_size)
        self.b1 -= update_vector[self.input_size * self.hidden_size:self.input_size * self.hidden_size + self.hidden_size].reshape(1, self.hidden_size)
        self.W2 -= update_vector[self.input_size * self.hidden_size + self.hidden_size:self.input_size * self.hidden_size + self.hidden_size + self.hidden_size * self.output_size].reshape(self.hidden_size, self.output_size)
        self.b2 -= update_vector[self.input_size * self.hidden_size + self.hidden_size + self.hidden_size * self.output_size:].reshape(1, self.output_size)
        new_error = np.mean((self.forward_propagation(X) - y) ** 2)
        old_error = np.mean((output - y) ** 2)
        if new_error < old_error:
            self.lambda_value = self.lambda_value / 10
        else:
            self.lambda_value = self.lambda_value * 10

    def train(self, X, y, epochs):
        for epoch in range(epochs):
            self.levenberg_marquardt_update(X, y)
            if epoch % 100 == 0:
                output = self.forward_propagation(X)
                error = np.mean((output - y) ** 2)
                print(f'Epoch {epoch}: Error = {error}, Lambda = {self.lambda_value}')

以下是一个简单的测试示例:

# 示例用法
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])
neural_network = NeuralNetwork(2, 3, 1)
neural_network.train(X, y, 1000)

七、总结

基于 Levenberg - Marquardt 法的 BP 网络学习改进算法通过巧妙地近似 Hessian 矩阵,结合了梯度下降法和牛顿法的优点。这种算法在 BP 网络训练中能够更快地收敛,并且在一定程度上减少了陷入局部最优解的可能性。代码示例详细展示了该算法在 Python 中的实现过程,在实际应用中,可以根据具体的问题和数据集进一步优化算法,如更精细地调整 λ \lambda λ 的调整策略、改进雅可比矩阵的计算方法等,以提高网络的训练效果和泛化能力。该算法在函数逼近、数据分类等需要高效训练神经网络的场景中具有重要的应用价值。

标签:mathbf,lambda,self,Marquardt,BP,output,hidden,Levenberg,size
From: https://blog.csdn.net/ashyyyy/article/details/143872839

相关文章

  • 基于共轭梯度法的 BP 网络学习改进算法详解
    基于共轭梯度法的BP网络学习改进算法详解一、引言BP(BackPropagation)神经网络是一种强大的机器学习工具,广泛应用于模式识别、函数逼近、数据分类等领域。然而,传统的BP算法在训练过程中存在一些问题,例如收敛速度慢、容易陷入局部最优解等。共轭梯度法作为一种高效的优......
  • Python用subprocess管理子进程在Windows平台实现平行效果
    在Python中,使用subprocess模块管理子进程时,如果你在Windows平台上尝试实现类似于Unix系统的“平行效果”(即父子进程可以同时运行),你可能会遇到一些问题。在Unix系统中,子进程是独立于父进程的,它们可以同时运行。但在Windows系统中,当你使用subprocess创建子进程时,默认情况下会存在父......
  • 【tokenization分词】WordPiece, Byte-Pair Encoding(BPE), Byte-level BPE(BBPE)的原
    目录前言1、word(词粒度)2、char(字符粒度)3、subword(子词粒度)WordPieceByte-PairEncoding(BPE)Byte-levelBPE(BBPE)总结前言Tokenization(分词)在自然语言处理(NLP)的任务中是最基本的一步,将文本处理成一串tokens用于后续的处理,把文本处理成token有一系列的......
  • KBPC3510-ASEMI整流桥KBPC3510参数、封装、尺寸
    编辑:llKBPC3510-ASEMI整流桥KBPC3510参数、封装、尺寸型号:KBPC3510品牌:ASEMI封装:KBPC-4正向电流:35A反向电压:1000V引脚数量:4芯片个数:4芯片尺寸:50MIL漏电流:>10ua恢复时间:>2000ns浪涌电流:400A芯片材质:GPP硅芯片正向电压:1.10V封装尺寸:如图特性:整流桥、插件桥堆工作结......
  • new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'], }),
    在Webpack配置中,ProvidePlugin是一个非常有用的插件,它可以自动向模块中注入特定的变量,而无需在每个模块中显式导入这些变量。你提到的配置片段使用了ProvidePlugin来注入Buffer和process对象。下面是对这段代码的详细解释:代码解析newwebpack.ProvidePlugin({Buffer......
  • chainWebpack: config => { // 移除 preload(预载) 插件 config.plugins.dele
    在VueCLI项目中,chainWebpack是一个用于自定义Webpack配置的钩子。通过chainWebpack,你可以对Webpack配置进行更细粒度的控制。你提到的代码片段的作用是移除preload和prefetch插件。下面是对这段代码的详细解释:代码解析chainWebpack:config=>{//移除preload......
  • PostgreSQL libpq的客户端故障转移
    什么是libpqlibpq是应用程序使用PostgreSQL的C接口。libpq是一个库函数的集合,它们允许客户端程序传递查询给PostgreSQL后端服务器并且接收这些查询的结果。libpq也是很多其他PostgreSQL应用接口的底层引擎,包括为C++、Perl、Python、Tcl和ECPG编写的接口。类似于Redis或者Mongo......
  • Antd 4.x Tabs组件 将末尾TabPane固定在右侧
    将最后一个TabPane固定在右侧先看效果代码样式设置注意先看效果代码 <TabPanetitle="Tab1"> </TabPane> <TabPanetitle="Tab2"> </TabPane> <TabPanetitle="Tab3"</......
  • BPMNJS设计器开发核心功能分析
    系统功能在开发一个前端工作流设计器,尤其是基于BPMN(业务流程建模与标注)或类似于钉钉的设计器时,主要需求可以总结为以下几个关键点:1.流程节点与边的设计节点类型多样化:支持基础节点(如开始、结束、任务节点、网关节点等)和自定义节点。节点可配置性:每个节点需要可以配置,例如设......
  • 预测模型-BP神经网络预测
     1,简介:BP网络(Back-PropagationNetwork)是1986年被提出的,是一种按误差逆向传播算法训练的多层前馈网络,是目前应用最广泛的神经网络模型之一,用于函数逼近、模型识别分类、数据压缩和时间序列预测等。2,预测网络常用模型结构: 前馈(Feed-Forward)网络前馈网络是感知器的集合,其中......