【數學建模學習筆記】啟發式算法:粒子群算法

零基礎小白看懂粒子群優化算法(PSO)

一、什么是粒子群優化算法?

簡單說,粒子群優化算法(PSO)是一種模擬鳥群 / 魚群覓食的智能算法。想象一群鳥在找食物:

  • 每只鳥(叫 “粒子”)不知道食物在哪,但能看到自己飛過的地方中 “最可能有食物” 的位置(個體經驗);
  • 也能看到整個群體中 “最可能有食物” 的位置(群體經驗);
  • 它們會根據這兩個經驗調整飛行方向和速度,慢慢靠近食物(最優解)。

PSO 就是用這種思路解決 “找最優解” 的問題,比如 “如何讓某個函數的結果最小(或最大)”。

二、核心概念拆解

  1. 粒子:算法中的 “搜索者”,每個粒子有兩個關鍵屬性:

    • 位置:當前在搜索空間中的坐標(比如在三維空間中,位置可以用 (x1, x2, x3) 表示);
    • 速度:下一步移動的方向和快慢。
  2. 適應度函數:判斷 “這個位置好不好” 的標準。比如我們想最小化函數f(x) = -10x1 - e^(-x2/10 - x3),那每個粒子的位置代入這個函數后,結果越小,說明位置越 “好”。

  3. 個體最優(p_best):每個粒子自己飛過的所有位置中,適應度最好的那個位置(“我之前飛過的地方里,這里最可能有食物”)。

  4. 全局最優(g_best):整個群體所有粒子飛過的位置中,適應度最好的那個位置(“大家飛過的地方里,這里最可能有食物”)。

  5. 位置和速度更新:粒子每次移動時,會根據以下規則調整速度和位置:

    • 速度 = 慣性(保持之前的速度) + 個體經驗(向自己的 p_best 靠近) + 群體經驗(向全局的 g_best 靠近);
    • 新位置 = 當前位置 + 新速度。

    就像鳥飛的時候,既不會完全忘記之前的方向(慣性),也會參考自己和同伴的最佳經驗調整方向。

三、算法怎么跑起來?(用例子和代碼說話)

假設我們要解決的問題是:最小化函數f(x) = -10x1 - e^(-x2/10 - x3),其中 x1 的范圍是 0-1,x2 是 1-80,x3 是 0-120。

1. 初始化

先創建 100 個粒子(N=100),每個粒子有 3 個維度(x1, x2, x3,即 D=3);隨機給每個粒子分配初始位置(在上述范圍內)和初始速度(比如 - 1 到 1 之間)。

在代碼中,初始化的實現如下:

# 導入必要的庫
import numpy as np  # 用于數值計算
import random       # 用于生成隨機數
import math         # 用于數學運算
import matplotlib.pyplot as plt  # 用于繪圖# 2. 初始化粒子的位置和速度
def initialize_particles(num_particles, num_dimensions, pos_low, pos_high, vel_low, vel_high):"""參數說明:- num_particles:粒子數量- num_dimensions:變量維度(這里是3,因為有x1、x2、x3)- pos_low/pos_high:每個變量的位置范圍(列表形式)- vel_low/vel_high:速度范圍"""# 初始化位置矩陣(行數=粒子數,列數=維度)positions = np.zeros((num_particles, num_dimensions))# 初始化速度矩陣velocities = np.zeros((num_particles, num_dimensions))for i in range(num_particles):  # 遍歷每個粒子for j in range(num_dimensions):  # 遍歷每個維度(變量)# 位置在[pos_low[j], pos_high[j]]范圍內隨機生成positions[i][j] = random.uniform(pos_low[j], pos_high[j])# 速度在[vel_low, vel_high]范圍內隨機生成velocities[i][j] = random.uniform(vel_low, vel_high)return positions, velocities

2. 定義適應度函數

適應度函數是判斷位置好壞的標準,對于我們要最小化的函數,代碼定義如下:

# 1. 定義適應度函數(目標函數)
# 這里要最小化的函數:f(x) = -10*x1 - e^(-x2/10 - x3)
def fitness(x):# x是一個列表,包含3個變量:x[0]是x1,x[1]是x2,x[2]是x3x1, x2, x3 = x[0], x[1], x[2]return -10 * x1 - math.exp(-x2/10 - x3)  # 計算函數值

3. 找初始最優

計算每個粒子的適應度(代入函數算結果);每個粒子的初始 “個體最優” 就是自己的初始位置;從所有粒子中挑出適應度最小的位置,作為 “全局最優”。

這部分在主函數中初始化個體最優和全局最優時實現:

# 初始化個體最優:一開始每個粒子的最優位置就是自己的初始位置
p_best_pos = positions.copy()  # 個體最優位置矩陣
# 計算每個粒子的初始適應度(目標函數值)
p_best_val = np.array([fitness(pos) for pos in positions])  # 個體最優值數組# 初始化全局最優:從個體最優中找最好的
g_best_idx = np.argmin(p_best_val)  # 找到適應度最小的索引(因為我們要最小化函數)
g_best_pos = p_best_pos[g_best_idx].copy()  # 全局最優位置
g_best_val = p_best_val[g_best_idx]  # 全局最優值

4. 迭代優化(重復 100 次,即 M=100)

每個粒子根據 “慣性、個體最優、全局最優” 更新速度和位置;每次移動后,重新計算適應度,如果比自己之前的 “個體最優” 更好,就更新個體最優;再從所有個體最優中挑出最好的,更新全局最優。

速度和位置更新的代碼實現:

# 3. 更新粒子的位置和速度
def update_particles(positions, velocities, p_best_pos, g_best_pos, w, c1, c2, pos_low, pos_high, vel_low, vel_high):"""參數說明:- p_best_pos:每個粒子的個體最優位置- g_best_pos:全局最優位置- w:慣性權重(控制對之前速度的保留程度)- c1、c2:學習因子(控制個體/群體經驗的影響程度)"""num_particles, num_dimensions = positions.shape  # 獲取粒子數和維度for i in range(num_particles):  # 遍歷每個粒子for j in range(num_dimensions):  # 遍歷每個維度# 生成0-1之間的隨機數(增加搜索隨機性)r1 = random.uniform(0, 1)r2 = random.uniform(0, 1)# 速度更新公式:慣性 + 個體經驗 + 群體經驗velocities[i][j] = (w * velocities[i][j]  # 慣性部分+ c1 * r1 * (p_best_pos[i][j] - positions[i][j])  # 向個體最優靠近+ c2 * r2 * (g_best_pos[j] - positions[i][j]))  # 向全局最優靠近# 限制速度在[vel_low, vel_high]范圍內(避免速度過大)velocities[i][j] = max(min(velocities[i][j], vel_high), vel_low)# 位置更新公式:當前位置 + 新速度positions[i][j] += velocities[i][j]# 限制位置在[pos_low[j], pos_high[j]]范圍內(避免超出變量定義域)positions[i][j] = max(min(positions[i][j], pos_high[j]), pos_low[j])return positions, velocities

5. 算法主函數

將上述步驟整合到主函數中,實現完整的 PSO 算法:

# 4. 粒子群優化算法主函數
def pso_algorithm(num_particles, num_dimensions, max_iter, pos_low, pos_high, vel_low, vel_high, w=0.9, c1=2, c2=2):"""參數說明:- max_iter:最大迭代次數(搜索多少次)- 其他參數同上"""# 初始化粒子位置和速度positions, velocities = initialize_particles(num_particles, num_dimensions, pos_low, pos_high, vel_low, vel_high)# 初始化個體最優:一開始每個粒子的最優位置就是自己的初始位置p_best_pos = positions.copy()  # 個體最優位置矩陣# 計算每個粒子的初始適應度(目標函數值)p_best_val = np.array([fitness(pos) for pos in positions])  # 個體最優值數組# 初始化全局最優:從個體最優中找最好的g_best_idx = np.argmin(p_best_val)  # 找到適應度最小的索引(因為我們要最小化函數)g_best_pos = p_best_pos[g_best_idx].copy()  # 全局最優位置g_best_val = p_best_val[g_best_idx]  # 全局最優值# 記錄每次迭代的最優值(用于畫圖)best_values = [g_best_val]# 開始迭代搜索for iter in range(max_iter):# 更新粒子位置和速度positions, velocities = update_particles(positions, velocities, p_best_pos, g_best_pos, w, c1, c2, pos_low, pos_high, vel_low, vel_high)# 更新個體最優和全局最優for i in range(num_particles):current_val = fitness(positions[i])  # 當前位置的適應度# 如果當前位置比個體最優好(值更小),就更新個體最優if current_val < p_best_val[i]:p_best_pos[i] = positions[i].copy()p_best_val[i] = current_val# 從個體最優中找新的全局最優current_g_best_idx = np.argmin(p_best_val)current_g_best_val = p_best_val[current_g_best_idx]# 如果新的全局最優更好,就更新全局最優if current_g_best_val < g_best_val:g_best_pos = p_best_pos[current_g_best_idx].copy()g_best_val = current_g_best_val# 記錄當前迭代的最優值best_values.append(g_best_val)# 打印迭代信息(每10次打印一次,避免輸出太多)if (iter + 1) % 10 == 0:print(f"迭代第{iter+1}次,當前最優值:{g_best_val:.6f}")# 畫收斂曲線(最優值隨迭代次數的變化)plt.figure(figsize=(8, 5))plt.plot(best_values)plt.xlabel("迭代次數")plt.ylabel("最優目標函數值")plt.title("PSO算法收斂曲線")plt.grid(True)plt.show()return g_best_pos, g_best_val  # 返回最終找到的最優位置和最優值

6. 運行程序并查看結果

通過主程序調用 PSO 算法,設置參數并運行:

# 5. 主程序:運行PSO算法
if __name__ == "__main__":# 問題設置num_particles = 100  # 粒子數量(100個粒子一起搜索)num_dimensions = 3   # 變量維度(x1, x2, x3三個變量)max_iter = 100       # 最大迭代次數(搜索100次)# 變量范圍:x1∈[0,1],x2∈[1,80],x3∈[0,120]pos_low = [0, 1, 0]pos_high = [1, 80, 120]# 速度范圍(一般設為位置范圍的10%-20%)vel_low = -1vel_high = 1# 運行PSO算法best_position, best_value = pso_algorithm(num_particles, num_dimensions, max_iter, pos_low, pos_high, vel_low, vel_high)# 輸出結果print("\n優化結束!")print(f"找到的最優位置:x1={best_position[0]:.4f}, x2={best_position[1]:.4f}, x3={best_position[2]:.4f}")print(f"對應的最優目標函數值:{best_value:.6f}")

迭代結束后,全局最優位置就是算法找到的 “最佳解”。比如例子中最后得到的最佳位置可能是 (1, 1, 0),對應的函數結果約為 - 10.9048。

四、為什么要用 PSO?

  • 簡單好懂:不需要復雜的數學推導,原理像 “群體找東西” 一樣直觀;
  • 靈活高效:能解決多變量、復雜函數的優化問題(比如最小化、最大化);
  • 容易實現:用 Python 等語言幾行代碼就能寫出基本版本,如上述示例代碼所示。

五、總結

粒子群優化算法(PSO)通過模擬群體中每個個體的 “學習”(參考自己和他人的經驗)來搜索最優解,步驟簡單、效果實用,是解決優化問題的常用工具。就像一群鳥通過互相 “借鑒” 飛行經驗,最終找到食物最多的地方一樣。

上述代碼實現了粒子群優化算法,用于尋找目標函數f(x) = -10x1 - e^(-x2/10 - x3)的最小值(其中 x1、x2、x3 有明確的范圍限制)。通過運行代碼,可以直觀看到粒子群算法如何通過群體協作逐步逼近最優解,適合零基礎小白理解 PSO 的核心邏輯。如果想解決其他優化問題,只需修改 fitness 函數(目標函數)和 pos_low/pos_high(變量范圍)即可。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98469.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98469.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98469.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Gitlab】Ubuntu 20.04服務器部署Gitlab

寫一個 適用于 Ubuntu 20.04/22.04 的 GitLab 一鍵部署腳本&#xff0c;包括&#xff1a;安裝依賴安裝 GitLab CE配置公網 IP 或域名自動開啟 HTTPS&#xff08;Let’s Encrypt&#xff09;配置防火墻下面是完整腳本&#xff1a;#!/bin/bash# # GitLab 一鍵安裝腳本 # # 1. 檢…

Android 15重磅升級:16KB內存頁機制詳解與適配指南

一、背景隨著Android硬件架構的持續演進&#xff0c;新一代設備開始采用16KB內存頁&#xff08;Page Size&#xff09;機制&#xff0c;逐步替代傳統的4KB內存頁設計。此項底層變更對應用兼容性產生直接影響&#xff0c;特別是對依賴Native層庫、JNI接口或自定義內存管理模塊的…

Mybatis-8 動態SQL

動態SQL-官方文檔 文檔地址 動態 SQL_MyBatis中文網 為什么需要動態SQL 1、動態SQL是MyBatis的強大特性之一 2、使用JDBC或其它類似的框架&#xff0c;根據不同條件拼接SQL語句非常麻煩&#xff0c;例如拼接時要確保不能忘記添加必要的空格&#xff0c;還要注意去掉列表最后一…

PySpark數據輸入

PySpark數據輸入 1.理解RDD對象 2.掌握PySpark數據輸入的2種方法 RDD對象 PySpark支持多種數據的輸入&#xff0c;在輸入完成后&#xff0c;都會得到一個&#xff1a;RDD類的對象 RDD全稱為&#xff1a;彈性分布式數據集&#xff08;Resilient Distributed Datasets&#xff09…

【系統架構設計(16)】軟件架構設計二:軟件架構風格:構建系統的設計模式與選擇指南

文章目錄一、核心思想二、數據流風格&#xff1a;以數據流動為核心的處理模式三、調用返回風格&#xff1a;基于程序調用的層次化組織四、獨立構件風格&#xff1a;基于事件驅動的松耦合架構五、虛擬機風格&#xff1a;提供抽象執行環境的架構模式六、倉庫風格&#xff1a;以數…

MySQL速記小冊(1)

1【Q】&#xff1a;Mysql中的數據排序是怎么實現的&#xff1f;【A】&#xff1a;排序過程中如果字段有索引&#xff0c;則利用索引排序。反之使用文件排序。在文件排序中&#xff0c;如果數據量少則在內存中排序&#xff0c;使用單路排序或雙路排序。如果數據量大則利于磁盤文…

20250904 10:45_排查10.1.3.35新QMS系統RMAN備份失敗問題(優化腳本里的環境配置,增加了check_oracle_env 函數)

一、RMAN備份失敗日志如下 [2025-09-04 04:00:01] 備份腳本啟動 [2025-09-04 04:00:01] 開始 RMAN 備份 CDB: ORCLCDB Message file RMAN<lang>.msb not found Verify that ORACLE_HOME is set properly [2025-09-04 04:00:01] RMAN 備份失敗! 二、原備份腳本存檔…

Vue3源碼reactivity響應式篇之EffectScope

概述 EffectScope是Vue3中一個響應式系統的輔助類&#xff0c;用于管理副作用&#xff08;effect&#xff09;的作用域。它可以幫助我們更好地組織和管理多個effect&#xff0c;便于一起停止或暫停以及恢復&#xff0c;避免了全局狀態的污染和管理的復雜性。 每一個vue組件的實…

MySQL 日志全解析:Binlog/Redo/Undo 等 5 類關鍵日志的配置、作用與最佳實踐

1 二進制日志&#xff08;Binlog&#xff09;&#xff1a;配置與核心作用 Binlog 是 MySQL 中跨存儲引擎的核心日志&#xff0c;記錄所有數據修改操作&#xff0c;主要用于主從復制、數據備份恢復與跨庫遷移。 1.1 Binlog 核心操作 開啟 Binlog 若需開啟 Binlog&#xff0c;需在…

springboot 之 HTML與圖片生成 (2)

前言 之前寫了一篇html轉圖片的 文章&#xff0c;使用中文時會出現亂碼情況&#xff0c;后來又從網上找了下信息&#xff0c;這篇主要介紹下另一個轉換庫。 依賴 <!-- 用于將html轉圖片--><dependency><groupId>gui.ava</groupId><artifactId>…

計算機組成原理:計算機的分類

&#x1f4cc;目錄&#x1f5a5;? 計算機組成原理&#xff1a;計算機的分類——從架構到應用的全景梳理一、按處理數據類型分類&#xff1a;從“數字”到“混合”的演進&#xff08;一&#xff09;數字計算機&#xff1a;離散數據的“精準管家”1. 核心原理2. 關鍵優勢3. 典型…

數據結構——單向循環鏈表代碼(補充)

在此前的文章中&#xff08;鏈接如下&#xff09;&#xff0c;只有單向鏈表的代碼&#xff0c;接下來我們來寫單向循環鏈表&#xff0c;并用其實現一個簡單的學生信息鏈表https://blog.csdn.net/2301_80406299/article/details/151157051?spm1011.2415.3001.10575&sharefr…

【Python自動化】 21.2 Pandas 讀取 Excel 時的 dtype 參數完全指南

一、dtype 參數概述 dtype 參數用于指定列的數據類型&#xff0c;在讀取 Excel 時非常重要&#xff0c;可以&#xff1a; 提高內存效率避免自動類型推斷錯誤確保數據一致性提升讀取性能 二、基本用法 1. 基礎語法 import pandas as pd# 指定列數據類型 df pd.read_excel(data.…

gtest全局套件的測試使用

gtest全局套件的測試使用 #include <iostream> #include "gtest/gtest.h" #include <unordered_map>class MyEnvironment: public testing::Environment {public:virtual void SetUp() override{std::cout<<"單元測試前的環境初始化&#xff…

【系統分析師】第7章-基礎知識:軟件工程(核心總結)

更多內容請見: 備考系統分析師-專欄介紹和目錄 文章目錄 一、軟件工程的基本概念 1.1 定義與意義 1.2 軟件工程的基本原則 1.3 核心定義與邊界 1.4 四大核心原則 1.5 三大核心目標 二、軟件生命周期 2.1 定義與階段劃分 2.2 軟件生命周期模型 三、軟件開發方法 3.1 結構化方法…

量化基金從小白到大師 - 金融數據獲取大全:從免費API到Tick級數據實戰指南

量化基金從小白到大師 - 金融數據獲取大全&#xff1a;從免費API到Tick級數據實戰指南 各位&#xff0c;今天咱們要啃一塊硬骨頭——金融數據獲取。別看這話題基礎&#xff0c;它可是整個量化大廈的地基&#xff0c;地基不穩&#xff0c;再牛的策略都得塌房。我見過太多人&…

構建一個“會思考”的房地產數據獲取腳本

—— 跨界思維&#xff1a;從認知自適應到房源信息監測 一、認知科學視角&#xff1a;什么是“會思考” 在心理學與認知科學中&#xff0c;所謂“會思考”&#xff0c;并不是指抽象的哲學推理&#xff0c;而是指個體能在復雜環境中不斷調整行動策略。 比如&#xff0c;出行時如…

JavaScript的庫簡介

JavaScript擁有豐富的庫生態系統,類似于Python的requests、numpy或C++的Boost。這些庫分為兩大類:前端庫(如React、Vue)和后端/工具庫(如Lodash、Axios)。以下是幾個核心庫的介紹與用法示例。 常用JavaScript庫分類 前端UI庫 React:Facebook開發的組件化庫,用于構建用…

【無GGuF版本】如何在Colab下T4運行gpt-oss 20B

OpenAI發布了gpt-oss 120B和20B版本。這兩個模型均采用Apache 2.0許可證。 特別說明的是&#xff0c;gpt-oss-20b專為低延遲及本地化/專業化場景設計&#xff08;210億總參數&#xff0c;36億活躍參數&#xff09;。 由于模型采用原生MXFP4量化訓練&#xff0c;使得20B版本即…

LeetCode - LCR 179. 查找總價格為目標值的兩個商品

題目 https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/submissions/660817798/ 思路 解法1是暴力解法&#xff0c;從第一個開始和后面的相加 暴力枚舉慢就慢在&#xff0c;這個遞增數組是排序好的數組&#xff0c;已經是有序的&#xff0c;暴力解法沒有利用這…