BP仿真实验设计
为什么最终的误差和绝对误差值不一样?
误差计算方法的根本区别
训练过程中的误差(最终误差:0.0000000000)
计算方式:均方误差(MSE)
% 代码中的计算方式
E = E + 0.5 * sum(el.^2); % 累加每个样本的误差数学定义:
-
对每个样本:
0.5 * (期望输出 - 实际输出)² -
对所有样本求和
-
这是平方误差,放大了大误差的影响
特点:
-
训练时使用3个标准样本
-
样本简单,容易达到完美逼近
-
误差被平方,数值很小
函数逼近的绝对误差(平均绝对误差:0.648143)
计算方式:平均绝对误差(MAE)
% 代码中的计算方式
mean_error = mean(abs(Z_target(:) - Z_predicted(:)));数学定义:
-
对测试网格中每个点:|目标值 - 预测值|
-
对所有点求平均
-
这是绝对值误差,反映平均偏差
特点:
-
测试时使用400个网格点(20×20)
-
函数复杂:Z = sin(x)·sin(y)
-
反映真实逼近能力
具体数值差异的原因分析
原因1:测试对象不同
-
训练误差:针对3个简单标准样本
-
绝对误差:针对复杂函数Z = sin(x)·sin(y) 的400个测试点
原因2:误差度量标准不同
-
训练误差:平方误差 → 惩罚大误差更严厉
-
绝对误差:绝对值误差 → 线性反映偏差
原因3:样本复杂度差异
-
训练样本:线性映射关系,容易学习
-
测试函数:非线性振荡函数,逼近困难
数学公式对比
mean函数具体计算方法:MAE = (1/n) × ∑|y_i - ŷ_i|
实验结论
训练成功但泛化有限:
-
训练完美:对简单样本实现零误差映射
-
泛化一般:对复杂函数逼近存在平均0.648的偏差
-
误差度量差异:不同计算方法导致数值差异巨大
这体现了BP神经网络的一个典型特点:对训练样本可能达到很高精度,但对未见过复杂数据的泛化能力有限。误差值的差异正是这种训练-测试性能差异的量化体现。
BP算法理解
BP神经网络算法的工作逻辑
基本思想:"学习-纠错-改进"的循环过程
想象一下教一个小孩认字:
-
第一次:你给他看"猫"字,他说"狗" → 错了
-
你纠正:告诉他正确答案是"猫" → 计算误差
-
他记住:下次看到"猫"字,更可能说"猫" → 调整记忆
BP神经网络就是这样的学习过程,只不过是用数学公式来实现的。
网络结构:三层"大脑"
输入层 → 隐含层 → 输出层-
输入层:接收问题(比如看到"猫"字的笔画)
-
隐含层:思考过程(大脑分析笔画特征)
-
输出层:给出答案(说出"猫"字)
BP算法如何实现逼近
核心机制:误差反向传播
打个比方:你在射击训练
-
前向射击:瞄准目标开枪 → 子弹落在某个位置
-
观察误差:看子弹离靶心多远 → 计算偏差
-
反向调整:根据偏差调整瞄准角度 → 下次更准
具体实现步骤:
步骤1:前向传播(预测)
输入信号 → 加权求和 → 激活函数 → 输出结果-
加权求和:每个连接都有"重要性权重"
-
激活函数:决定神经元是否"兴奋"
-
输出结果:网络的预测值
步骤2:误差计算
误差 = 期望输出 - 实际输出-
计算预测值与真实值的差距
-
差距越大,说明网络越"笨"
步骤3:反向传播(学习)
从输出层 → 隐含层 → 输入层,逐层调整权重-
关键原理:链式法则(微积分)
-
调整规则:误差大的连接,权重调整幅度大
步骤4:权重更新
新权重 = 旧权重 + 学习率 × 误差梯度 + 动量项-
学习率:控制学习速度(太小学得慢,太大容易"学过头")
-
动量项:防止"震荡",让学习更平稳
具体工作流程(基于MATLAB代码)
阶段1:准备阶段
% 1. 初始化网络
w1 = rands(3, 6); % 输入层到隐含层权重(随机初始化)
w2 = rands(6, 2); % 隐含层到输出层权重
% 2. 设置学习参数
xite = 0.50; % 学习率 - 控制学习速度
alfa = 0.05; % 动量因子 - 防止震荡阶段2:训练循环(核心)
对每个样本执行:
前向传播:
% 隐含层计算
for j = 1:6
I(j) = x * w1(:, j); % 加权求和
Iout(j) = 1/(1 + exp(-I(j))); % Sigmoid激活函数
end
% 输出层计算
yl = w2' * Iout; % 得到预测输出误差计算:
el = y - yl; % 计算误差向量
E = E + 0.5 * sum(el.^2); % 累计均方误差反向传播:
% 输出层到隐含层权重调整
w2 = w2_1 + xite * Iout * el + alfa * (w2_1 - w2_2);
% 隐含层到输入层权重调整(链式法则)
for j = 1:6
S = 1/(1 + exp(-I(j)));
FI(j) = S * (1 - S); % 计算Sigmoid函数的导数
end
for i = 1:3
for j = 1:6
% 计算权重梯度
dw1(i,j) = xite * FI(j) * x(i) * (el(1)*w2(j,1) + el(2)*w2(j,2));
end
end
w1 = w1_1 + dw1 + alfa * (w1_1 - w1_2);阶段3:收敛判断
while E >= 1e-20 && k < 10000 % 直到误差足够小或达到最大迭代次数
k = k + 1; % 继续训练
end逼近机制的本质
万能逼近定理
理论上,只要有足够多的隐含层神经元,3层BP网络可以逼近任何连续函数。
权重调整的数学意义
-
每个权重调整都是在修正函数曲面的形状
-
通过大量微小调整,逐渐"雕刻"出目标函数的形状
学习过程可视化
-
开始:网络输出是随机曲面
-
训练中:曲面逐渐向目标函数靠拢
-
收敛后:网络输出与目标函数高度相似
通俗理解的关键点
-
"权重"就是"经验":权重越大,说明该连接越重要
-
"激活函数"就是"思考方式":决定如何响应输入信号
-
"反向传播"就是"反思改进":根据错误调整经验
-
"学习率"就是"学习速度":太快容易错过最优解,太慢学习效率低
-
"动量项"就是"惯性":让学习过程更平稳,避免来回震荡
这个算法之所以强大,是因为它通过大量简单的计算单元(神经元)和重复的调整过程,最终能够学习复杂的非线性关系,就像我们的大脑通过大量神经元的协同工作来学习复杂技能一样。
meshgrid函数介绍
meshgrid函数的作用
通俗理解:创建坐标网格
想象你要画一张地图:
-
x轴:经度(从西到东)
-
y轴:纬度(从南到北)
-
meshgrid就是帮你生成地图上所有经纬度交叉点的坐标
具体作用:
把两个一维数组(x坐标和y坐标)转换成两个二维矩阵,表示平面上所有点的坐标。
代码实现详解
原始数据:
x_test = linspace(-pi, pi, 20); % 生成20个x坐标:[-π, -2.8, -2.6, ..., π]
y_test = linspace(-pi, pi, 20); % 生成20个y坐标:[-π, -2.8, -2.6, ..., π]meshgrid转换后:
[X_test, Y_test] = meshgrid(x_test, y_test);转换结果:
-
X_test:20×20矩阵,每行都是相同的x_test -
Y_test:20×20矩阵,每列都是相同的y_test
实际生成的矩阵结构:
X_test =
[-π, -2.8, -2.6, ..., π] ← 第1行
[-π, -2.8, -2.6, ..., π] ← 第2行
...
[-π, -2.8, -2.6, ..., π] ← 第20行
Y_test =
[-π, -π, -π, ..., -π] ← 第1行
[-2.8, -2.8, -2.8, ..., -2.8] ← 第2行
...
[π, π, π, ..., π] ← 第20行可视化理解
生成的网格点:
( -π, -π) ( -2.8, -π) ( -2.6, -π) ... ( π, -π)
( -π, -2.8) ( -2.8, -2.8) ( -2.6, -2.8) ... ( π, -2.8)
( -π, -2.6) ( -2.8, -2.6) ( -2.6, -2.6) ... ( π, -2.6)
...
( -π, π) ( -2.8, π) ( -2.6, π) ... ( π, π)总共生成:20 × 20 = 400个测试点
手动实现meshgrid功能
如果你想自己实现meshgrid的功能,可以这样写:
% 手动实现meshgrid
X_test_manual = zeros(20, 20);
Y_test_manual = zeros(20, 20);
for i = 1:20 % 遍历y坐标
for j = 1:20 % 遍历x坐标
X_test_manual(i, j) = x_test(j); % 第i行第j列 = x_test的第j个值
Y_test_manual(i, j) = y_test(i); % 第i行第j列 = y_test的第i个值
end
end在BP神经网络中的应用
目的:评估网络泛化能力
Z_target = sin(X_test) .* sin(Y_test); % 计算目标函数在所有网格点的值作用:
-
创建测试集:400个均匀分布的测试点
-
计算真实值:得到目标函数Z = sin(x)·sin(y)的精确值
-
对比评估:与神经网络预测结果比较,评估逼近精度
具体应用场景:
% 假设已经训练好的神经网络
Z_predicted = zeros(20, 20); % 存储神经网络预测结果
% 对每个网格点进行预测
for i = 1:20
for j = 1:20
% 将网格点坐标输入神经网络
input_point = [X_test(i,j), Y_test(i,j), 1]'; % 添加偏置项
% 前向传播计算预测值
Z_predicted(i,j) = neural_network_predict(input_point, w1, w2);
end
end
% 计算逼近误差
error = abs(Z_target - Z_predicted);为什么需要meshgrid?
传统方法的问题:
% 如果不使用meshgrid,需要双重循环
Z_target_manual = zeros(20, 20);
for i = 1:20
for j = 1:20
Z_target_manual(i,j) = sin(x_test(j)) * sin(y_test(i));
end
endmeshgrid的优势:
-
代码简洁:一行代码替代双重循环
-
计算高效:MATLAB对矩阵运算优化更好
-
便于绘图:直接用于
surf,mesh等3D绘图函数
总结
meshgrid(x_test, y_test)的核心作用:
-
坐标转换:一维坐标 → 二维坐标网格
-
矩阵生成:创建等间距的测试点矩阵
-
函数评估:便于计算多元函数在所有网格点的值
-
可视化准备:为3D曲面图提供标准格式的坐标数据
在BP神经网络实验中,这个函数帮助我们系统性地评估网络在整个输入空间的表现,而不是仅仅在训练样本点上,从而更全面地分析网络的泛化能力和逼近精度。
归一化映射介绍
归一化映射的数学原理
线性变换公式
X_test_norm = (X_test + pi) / (2*pi);数学推导:
这是一个线性变换,将原始区间 [-π, π] 映射到目标区间 [0, 1]
变换步骤:
-
平移:
X_test + pi→ 将区间从[-π, π]平移到[0, 2π] -
缩放:
/ (2*pi)→ 将区间从[0, 2π]缩放到[0, 1]
具体数值示例
原始数据范围
x_test = linspace(-pi, pi, 20); % 生成:[-3.1416, ..., 3.1416]映射过程演示:
完整映射关系
原始区间 [-π, π] → 归一化区间 [0, 1]
边界点映射:
-π → (-π + π)/(2π) = 0/2π = 0
0 → (0 + π)/(2π) = π/2π = 0.5
+π → (π + π)/(2π) = 2π/2π = 1
中间点映射:
-π/2 ≈ -1.5708 → (-1.5708+3.1416)/6.2832 = 1.5708/6.2832 = 0.25
+π/2 ≈ +1.5708 → (1.5708+3.1416)/6.2832 = 4.7124/6.2832 = 0.75通用线性映射公式
这个映射遵循标准的线性变换公式:
% 通用线性映射公式
归一化值 = (原始值 - 原区间最小值) / (原区间最大值 - 原区间最小值)
% 应用到本例:
原区间最小值 = -π
原区间最大值 = +π
归一化值 = (X_test - (-π)) / (π - (-π))
= (X_test + π) / (2π) % 与代码完全一致在代码中的具体实现
原始数据:
X_test =
[-3.1416, -2.8109, -2.4802, ..., 3.1416] % 20×20网格
[-3.1416, -2.8109, -2.4802, ..., 3.1416]
...
[-3.1416, -2.8109, -2.4802, ..., 3.1416]归一化后:
X_test_norm =
[0.0000, 0.0526, 0.1053, ..., 1.0000] % 全部映射到[0,1]
[0.0000, 0.0526, 0.1053, ..., 1.0000]
...
[0.0000, 0.0526, 0.1053, ..., 1.0000]为什么需要归一化?
神经网络训练稳定性
-
Sigmoid激活函数在输入接近0时梯度最大
-
输入范围
[0,1]正好落在Sigmoid函数的敏感区域 -
避免梯度消失或爆炸问题
权重初始化友好
w1 = rands(3, 6); % 默认生成[-1,1]范围的随机权重归一化后的输入与权重范围匹配,训练更稳定
收敛速度提升
-
所有特征在相同尺度,梯度下降方向更准确
-
学习率选择更容易
数值计算稳定性
避免大数值计算带来的数值精度问题
反向映射(如果需要)
如果训练后需要将预测结果映射回原始范围:
% 反向映射公式
X_original = X_test_norm * (2*pi) - pi;
% 验证:0 → -π, 0.5 → 0, 1 → +π
X_original = X_test_norm * 6.2832 - 3.1416;映射的数学性质
线性保持性:
-
直线映射为直线
-
相对位置保持不变
-
比例关系保持不变
可逆性:
映射是一一对应的,可以完全还原
总结
这段归一化代码的核心是:
-
数学原理:线性变换
(x + π)/(2π) -
作用范围:将
[-π, π]完美映射到[0, 1] -
实现方式:简单的矩阵运算,MATLAB自动广播到所有元素
-
实际效果:所有测试点均匀分布在
[0,1]区间,便于神经网络处理
这种归一化是神经网络数据预处理的标准做法,能够显著提高训练效率和模型性能。
Sigmoid激活函数详解
数学定义
标准Sigmoid函数:
f(x) = 1 / (1 + e^(-x))函数特性:
-
定义域:(-∞, +∞)
-
值域:(0, 1)
-
中心对称点:(0, 0.5)
-
单调性:严格单调递增
在MATLAB中的实现
基本实现
% Sigmoid函数实现
function output = sigmoid(x)
output = 1 ./ (1 + exp(-x));
end在BP神经网络中的具体应用
从搜索结果中可以看到实际代码实现:
% 隐含层神经元输出计算
for j = 1:6
I(j) = x * w1(:, j); % 步骤1:加权求和
Iout(j) = 1/(1 + exp(-I(j))); % 步骤2:Sigmoid激活
end代码解析:
-
x * w1(:, j):计算第j个隐含层神经元的输入(加权和) -
1/(1 + exp(-I(j))):应用Sigmoid函数,将输入映射到(0,1)区间
导数计算(反向传播关键)
Sigmoid导数公式:
f'(x) = f(x) * (1 - f(x))MATLAB实现:
% 在反向传播中的导数计算
for j = 1:6
S = 1/(1 + exp(-I(j))); % Sigmoid输出
FI(j) = S * (1 - S); % 导数计算
end数学推导:
f(x) = 1/(1+e^(-x))
f'(x) = e^(-x)/(1+e^(-x))²
= [1/(1+e^(-x))] * [1 - 1/(1+e^(-x))]
= f(x) * (1 - f(x))主要作用
非线性变换
-
输入:任意实数 (-∞, +∞)
-
输出:压缩到 (0, 1) 区间
-
效果:引入非线性,使神经网络能够学习复杂模式
概率解释
-
输出值可以解释为概率或激活程度
-
接近0:神经元"不激活"
-
接近1:神经元"强烈激活"
-
0.5:决策边界
梯度平滑
-
导数处处连续且非零
-
便于梯度下降算法优化
在BP神经网络中的具体作用
前向传播
% 将线性组合转换为非线性激活
Iout(j) = 1/(1 + exp(-I(j))); % 线性→非线性反向传播误差计算
% 通过链式法则传播误差
for i = 1:3
for j = 1:6
dw1(i,j) = xite * FI(j) * x(i) * (el(1)*w2(j,1) + el(2)*w2(j,2));
% ↑学习率 ↑Sigmoid导数 ↑输入 ↑输出误差反向传播
end
end优缺点分析
优点
-
输出范围固定:(0,1)便于解释
-
函数平滑:处处可导,适合梯度下降
-
概率解释:输出可视为概率值
缺点
-
梯度消失:当|x|较大时,梯度接近0
-
输出非零中心:导致梯度下降效率较低
-
计算开销:涉及指数运算
与其他激活函数对比
实际应用建议
适用场景:
-
二分类问题的输出层
-
需要概率解释的场合
-
浅层神经网络的隐含层
不适用场景:
-
深层神经网络(梯度消失严重)
-
需要快速收敛的任务
-
大规模数据处理
总结
Sigmoid激活函数在BP神经网络中扮演着关键角色:
-
定义:
f(x) = 1/(1+e^(-x)),将输入压缩到(0,1) -
实现:MATLAB中直接使用
1/(1+exp(-x))公式 -
作用:引入非线性、提供概率解释、支持梯度反向传播
在您提供的BP神经网络代码中,Sigmoid函数是隐含层的核心激活机制,通过将线性加权和转换为非线性输出,使网络能够学习复杂的输入-输出映射关系。
基于搜索到的BP神经网络代码,我来详细分析偏置项1的作用:
偏置项1的介绍
在代码中定位偏置项1
从搜索结果中可以看到关键代码片段:
% 前向传播过程
for j = 1:6 % 遍历隐含层每个神经元
I(j) = x * w1(:, j); % 计算隐含层第j个神经元的输入(加权和)
Iout(j) = 1/(1 + exp(-I(j))); % 使用S型激活函数计算输出
end偏置项1的具体作用
数学表达
在BP神经网络中,偏置项通常作为额外的输入:
I(j) = w1(1,j)*x1 + w1(2,j)*x2 + w1(3,j)*1其中:
-
w1(1,j):输入x1到第j个隐含层神经元的权重 -
w1(2,j):输入x2到第j个隐含层神经元的权重 -
w1(3,j):偏置项1的权重(对应常数输入1)
作用机制
平移激活函数
I(j) = x * w1(:, j); % 包含偏置项的加权和
Iout(j) = 1/(1 + exp(-I(j))); % Sigmoid激活偏置项的效果:
-
当所有输入为0时:
I(j) = w1(3,j)(偏置权重) -
偏置项水平移动Sigmoid函数,改变激活阈值
具体功能
调整激活阈值
% 没有偏置项:激活阈值固定在0
I(j) = w1(1,j)*x1 + w1(2,j)*x2
Iout(j) = 1/(1 + exp(-I(j))) % 在I(j)=0时输出0.5
% 有偏置项:激活阈值可调节
I(j) = w1(1,j)*x1 + w1(2,j)*x2 + w1(3,j)*1
Iout(j) = 1/(1 + exp(-I(j))) % 在I(j)=-w1(3,j)时输出0.5增加模型灵活性
-
没有偏置项:决策边界必须通过原点
-
有偏置项:决策边界可以在任意位置
处理零输入情况
当所有输入特征为0时:
-
没有偏置项:神经元输出固定为0.5(Sigmoid中心)
-
有偏置项:神经元输出由偏置权重决定
在反向传播中的更新
从代码片段可以看到偏置项在权重更新中的作用:
for i = 1:3 % 遍历所有输入(包括偏置项)
for j = 1:6
dw1(i,j) = xite * FI(j) * x(i) * (el(1)*w2(j,1) + el(2)*w2(j,2));
end
end偏置项的特殊性:
-
当
i=3时,x(3) = 1(偏置项输入) -
偏置项的梯度:
dw1(3,j) = xite * FI(j) * 1 * error_term
实际应用示例
在正弦函数逼近任务中
% 输入向量构造
x = [X_norm, Y_norm, 1] % 前两个是坐标,第三个是偏置项1
% 隐含层计算
for j = 1:6
I(j) = x(1)*w1(1,j) + x(2)*w1(2,j) + 1*w1(3,j)
Iout(j) = sigmoid(I(j))
end偏置项对逼近效果的影响
-
调节激活区域:偏置权重决定神经元在输入空间的哪个区域激活
-
补偿非线性:帮助网络更好地逼近复杂的正弦函数曲面
-
提高拟合能力:增加了一个可学习的参数,提升模型表达能力
总结
偏置项1在BP神经网络中的作用:
-
数学功能:作为常数输入1,对应权重
w1(3,j),平移激活函数 -
网络效果:增加模型灵活性,允许决策边界不通过原点
-
训练作用:通过反向传播学习最优的激活阈值
-
实际意义:在函数逼近任务中,帮助网络更好地拟合复杂的非线性关系
偏置项1是网络能够成功逼近Z = sin(X)·sin(Y)函数的关键组件之一,它提供了必要的平移自由度,使网络能够更精确地匹配目标函数的形状和位置。
BP神经网络各步骤代码实现
BP神经网络各步骤代码实现详解
初始化阶段
% 网络权重初始化
w1 = rands(3, 6); % 输入层到隐含层权重矩阵 (3×6)
w2 = rands(6, 2); % 隐含层到输出层权重矩阵 (6×2)
% 学习参数设置
xite = 0.50; % 学习率 - 控制权重调整幅度
alfa = 0.05; % 动量因子 - 防止训练震荡代码解释:
-
rands(3,6):生成3行6列的随机矩阵,对应3个输入节点到6个隐含节点的连接权重 -
rands(6,2):生成6行2列的随机矩阵,对应6个隐含节点到2个输出节点的连接权重
训练循环控制
k = 0; % 迭代计数器
E = 1; % 初始误差(设为大于阈值)
while E >= 1e-20 && k < 10000 % 循环条件:误差>阈值且未超最大迭代
k = k + 1; % 迭代次数+1
E = 0; % 重置本轮误差
% ... 训练代码 ...
end前向传播实现
隐含层计算
for j = 1:6
I(j) = x * w1(:, j); % 步骤1:加权求和
Iout(j) = 1/(1 + exp(-I(j))); % 步骤2:Sigmoid激活函数
end代码详解:
-
x * w1(:, j):输入向量x与权重矩阵第j列的乘积 → 第j个隐含节点的输入 -
1/(1 + exp(-I(j))):Sigmoid函数,将输入映射到(0,1)区间
输出层计算
yl = w2' * Iout; % 输出层计算(线性输出)代码详解:
-
w2' * Iout:隐含层输出与输出层权重的乘积 → 最终预测输出
误差计算实现
el = y - yl; % 步骤1:计算输出误差向量
E = E + 0.5 * sum(el.^2); % 步骤2:累计均方误差代码详解:
-
y - yl:期望输出与实际输出的差值 -
0.5 * sum(el.^2):均方误差(乘以0.5是为了求导时消去系数)
反向传播实现
输出层权重调整
% 保存历史权重用于动量项
w2_2 = w2_1; w2_1 = w2;
% 权重更新公式
dw2 = xite * Iout * el + alfa * (w2_1 - w2_2);
w2 = w2_1 + dw2;代码详解:
-
xite * Iout * el:学习率 × 隐含层输出 × 输出误差 → 权重调整量 -
alfa * (w2_1 - w2_2):动量项,利用历史权重变化平滑训练过程
隐含层权重调整
% 保存历史权重
w1_2 = w1_1; w1_1 = w1;
% 计算Sigmoid函数的导数
for j = 1:6
S = 1/(1 + exp(-I(j)));
FI(j) = S * (1 - S); % f'(x) = f(x) * (1 - f(x))
end
% 计算隐含层权重梯度
for i = 1:3
for j = 1:6
dw1(i,j) = xite * FI(j) * x(i) * (el(1)*w2(j,1) + el(2)*w2(j,2));
end
end
% 更新隐含层权重
w1 = w1_1 + dw1 + alfa * (w1_1 - w1_2);代码详解:
-
FI(j) = S * (1 - S):Sigmoid函数导数,用于链式法则 -
el(1)*w2(j,1) + el(2)*w2(j,2):输出误差通过权重反向传播到隐含层 -
双重循环:遍历所有输入节点到隐含节点的连接
完整的训练流程代码
% 完整训练循环
for i = 1:1:3 % 遍历3个训练样本
% 选择训练样本
switch i
case 1, x = [0.970, 0.001, 0.001]'; y = [0.9862, 0.0094]';
case 2, x = [0.000, 0.980, 0.000]'; y = [0.0080, 0.4972]';
case 3, x = [0.002, 0.000, 1.040]'; y = [-0.0145, 1.0202]';
end
% 前向传播
for j = 1:6
I(j) = x * w1(:, j);
Iout(j) = 1/(1 + exp(-I(j)));
end
yl = w2' * Iout;
% 误差计算
el = y - yl;
E = E + 0.5 * sum(el.^2);
% 反向传播
w2_2 = w2_1; w2_1 = w2;
dw2 = xite * Iout * el + alfa * (w2_1 - w2_2);
w2 = w2_1 + dw2;
w1_2 = w1_1; w1_1 = w1;
for j = 1:6
S = 1/(1 + exp(-I(j)));
FI(j) = S * (1 - S);
end
for i = 1:3
for j = 1:6
dw1(i,j) = xite * FI(j) * x(i) * (el(1)*w2(j,1) + el(2)*w2(j,2));
end
end
w1 = w1_1 + dw1 + alfa * (w1_1 - w1_2);
end关键算法步骤总结
代码中的关键技巧
-
动量项:
alfa * (w_1 - w_2)防止训练震荡 -
链式法则:通过权重矩阵将输出误差反向传播到隐含层
-
激活函数导数:
S*(1-S)是Sigmoid函数的特殊性质 -
批量处理:对3个样本依次训练,累计误差
这个代码完整实现了BP算法的所有关键步骤,通过反复执行"预测-误差计算-权重调整"的循环,让网络逐渐学习到输入输出的映射关系。