当前位置: 首页 > news >正文

30天打牢数模基础-粒子群算法讲解

 

import random
import numpy as np
import matplotlib.pyplot as plt# ------------------------------
# 1. 模拟训练数据(带噪声的线性数据)
# ------------------------------
# 真实模型:y = 2x + 1(w=2,b=1)
x_data = np.array([1, 2, 3, 4, 5])  # 输入x
y_true = 2 * x_data + 1 + np.random.uniform(-0.1, 0.1, size=x_data.shape)  # 带噪声的实际值
print("模拟训练数据:")
print(f"输入x: {x_data}")
print(f"实际值y_true: {y_true.round(2)}")# ------------------------------
# 2. 定义适应度函数(均方误差MSE,越小越好)
# ------------------------------
def calculate_mse(w, b, x, y):"""计算线性模型y=w*x + b的均方误差(MSE)参数:w: 权重(float)b: 偏置(float)x: 输入数据(numpy数组)y: 实际值(numpy数组)返回:mse: 均方误差(float)"""y_pred = w * x + b  # 模型预测值mse = np.mean((y - y_pred) ** 2)  # 均方误差计算公式return mse# ------------------------------
# 3. 初始化PSO参数(小白经典值)
# ------------------------------
n_particles = 30  # 粒子数量(平衡多样性与计算量)
w_inertia = 0.8  # 惯性权重(控制探索与细化的平衡)
c1 = 2  # 认知学习因子(重视自己的经验)
c2 = 2  # 社会学习因子(重视群体的经验)
max_iter = 100  # 最大迭代次数(足够收敛)# 位置范围(w和b的可行域)
w_min, w_max = 0, 4  # 权重w的范围(真实值为2)
b_min, b_max = 0, 2  # 偏置b的范围(真实值为1)# 速度范围(限制粒子移动速度,避免飞过头)
v_w_min, v_w_max = -1, 1  # w的速度范围
v_b_min, v_b_max = -0.5, 0.5  # b的速度范围# ------------------------------
# 4. 初始化粒子群(每个粒子代表一组(w,b)候选解)
# ------------------------------
particles = []
for _ in range(n_particles):# 随机初始化位置(w, b):在可行域内随机取值w = random.uniform(w_min, w_max)b = random.uniform(b_min, b_max)# 随机初始化速度(v_w, v_b):在速度范围内随机取值v_w = random.uniform(v_w_min, v_w_max)v_b = random.uniform(v_b_min, v_b_max)# 初始个体最优(pbest):当前位置(因为还没有历史数据)pbest_w = wpbest_b = b# 计算初始pbest的适应度(MSE)pbest_fitness = calculate_mse(pbest_w, pbest_b, x_data, y_true)# 将粒子信息存入字典(方便管理)particles.append({'w': w,           # 当前w值'b': b,           # 当前b值'v_w': v_w,       # 当前w的速度'v_b': v_b,       # 当前b的速度'pbest_w': pbest_w,  # 个体最优w'pbest_b': pbest_b,  # 个体最优b'pbest_fitness': pbest_fitness  # 个体最优适应度(MSE)})# ------------------------------
# 5. 初始化全局最优(gbest:所有粒子pbest中的最优解)
# ------------------------------
gbest_w = particles[0]['pbest_w']  # 初始gbest的w(取第一个粒子的pbest)
gbest_b = particles[0]['pbest_b']  # 初始gbest的b(取第一个粒子的pbest)
gbest_fitness = particles[0]['pbest_fitness']  # 初始gbest的MSE
# 遍历所有粒子,找到真正的gbest(MSE最小)
for p in particles:if p['pbest_fitness'] < gbest_fitness:gbest_fitness = p['pbest_fitness']gbest_w = p['pbest_w']gbest_b = p['pbest_b']# ------------------------------
# 6. 迭代优化(核心过程)
# ------------------------------
fitness_history = []  # 记录每一代的gbest MSE(用于可视化)
for iter in range(max_iter):# 遍历每个粒子,更新速度、位置、pbestfor p in particles:# 生成随机数r1、r2(0到1之间,增加随机性)r1 = random.random()r2 = random.random()# ------------------------------# 更新速度(核心公式:惯性+认知+社会)# ------------------------------# w的速度更新:v_w = 惯性项 + 认知项(自己的经验) + 社会项(群体的经验)p['v_w'] = (w_inertia * p['v_w'] +c1 * r1 * (p['pbest_w'] - p['w']) +  # 认知项:向自己的pbest靠近c2 * r2 * (gbest_w - p['w']))         # 社会项:向群体的gbest靠近# b的速度更新(同理)p['v_b'] = (w_inertia * p['v_b'] +c1 * r1 * (p['pbest_b'] - p['b']) +c2 * r2 * (gbest_b - p['b']))# 限制速度在设定范围内(避免飞太快)p['v_w'] = max(min(p['v_w'], v_w_max), v_w_min)p['v_b'] = max(min(p['v_b'], v_b_max), v_b_min)# ------------------------------# 更新位置(位置 = 当前位置 + 速度)# ------------------------------p['w'] += p['v_w']  # 更新w的值p['b'] += p['v_b']  # 更新b的值# 限制位置在可行域内(避免飞出边界)p['w'] = max(min(p['w'], w_max), w_min)p['b'] = max(min(p['b'], b_max), b_min)# ------------------------------# 更新个体最优(pbest:保留自己的最佳经验)# ------------------------------current_fitness = calculate_mse(p['w'], p['b'], x_data, y_true)  # 当前位置的MSEif current_fitness < p['pbest_fitness']:  # 如果当前MSE更小,更新pbestp['pbest_w'] = p['w']p['pbest_b'] = p['b']p['pbest_fitness'] = current_fitness# ------------------------------# 更新全局最优(gbest:保留群体的最佳经验)# ------------------------------for p in particles:if p['pbest_fitness'] < gbest_fitness:  # 如果某个粒子的pbest更优,更新gbestgbest_fitness = p['pbest_fitness']gbest_w = p['pbest_w']gbest_b = p['pbest_b']# 记录当前代的gbest MSE(用于可视化)fitness_history.append(gbest_fitness)# 每10代打印一次进度(方便观察)if (iter + 1) % 10 == 0:print(f"迭代次数:{iter+1:2d},当前gbest MSE:{gbest_fitness:.4f}")# ------------------------------
# 7. 输出优化结果
# ------------------------------
print("\n" + "-"*50)
print("PSO优化完成!")
print(f"最优权重w: {gbest_w:.4f}(真实值:2)")
print(f"最优偏置b: {gbest_b:.4f}(真实值:1)")
print(f"最小均方误差(MSE): {gbest_fitness:.4f}")
print("-"*50 + "\n")# ------------------------------
# 8. 可视化结果(小白必看,直观理解优化过程)
# ------------------------------
# 图1:迭代次数与MSE变化(看是否收敛)
plt.figure(figsize=(10, 6))
plt.plot(range(max_iter), fitness_history, color='blue', linewidth=2, label='gbest MSE')
plt.xlabel('迭代次数', fontsize=12)
plt.ylabel('均方误差(MSE)', fontsize=12)
plt.title('PSO优化线性模型:迭代次数与MSE关系', fontsize=14)
plt.legend(fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()# 图2:模型拟合效果(看是否接近真实数据)
plt.figure(figsize=(10, 6))
plt.scatter(x_data, y_true, color='red', s=100, label='实际数据(带噪声)')  # 实际数据点
x_plot = np.linspace(min(x_data)-1, max(x_data)+1, 100)  # 生成平滑的x轴数据
y_plot = gbest_w * x_plot + gbest_b  # 用最优参数计算预测值
plt.plot(x_plot, y_plot, color='blue', linewidth=2, label=f'拟合模型:y={gbest_w:.2f}x + {gbest_b:.2f}')
plt.xlabel('输入x', fontsize=12)
plt.ylabel('输出y', fontsize=12)
plt.title('PSO优化线性模型:拟合效果', fontsize=14)
plt.legend(fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

三、代码使用说明

http://www.dtcms.com/a/289124.html

相关文章:

  • 详解Mysql索引合并
  • Jetpack - ViewModel、LiveData、DataBinding(数据绑定、双向数据绑定)
  • langchain调用本地ollama语言模型和嵌入模型
  • 梯度提升之原理
  • COGNEX康耐视IS5403-01智能相机加Navitar 18R00 LR1010WM52镜头
  • React 英语打地鼠游戏——一个寓教于乐的英语学习游戏
  • [Windows] Bili视频转图文笔记 v1.7.5
  • 网鼎杯2020青龙组notes复现
  • 7. 命令模式
  • Modbus Slave 使用教程:快速搭建模拟从站进行测试与开发
  • Ribbon轮询实现原理
  • Unity笔记——Unity 封装方法指南
  • day24——Java高级技术深度解析:单元测试、反射、注解与动态代理
  • [Python] -项目实战类3- 用Python制作一个记事本应用
  • CVE-2022-41128
  • Python数据处理库与语法总结
  • API获取及调用(以豆包为例实现图像分析)
  • FreeRTOS任务创建与删除
  • 掌握配置文件(三):运用Profile实现多环境配置隔离
  • 三级知识点汇总(详解)【c++】——3
  • 让不符合要求的任何电脑升级Windows11
  • 《通信原理》学习笔记——第五章
  • 开源安全大模型Foundation-Sec 8B的安全实践
  • 分享如何在保证画质的前提下缩小视频体积实用方案
  • 【记某次线上消息积压问题排查及解决方案】
  • 基于Pytorch的人脸识别程序
  • 基于FPGA实现ARINC818
  • Milvus Dify 学习笔记
  • Unity学习笔记(五)——3DRPG游戏(2)
  • DFS 迷宫问题 难度:★★★★☆