退火算法
物理現象:退火現象指物體逐漸降溫的物理現象,溫度愈低,物體的能量狀態會低;溫度足夠低后,液體開始冷凝與結晶,在結晶狀態時,系統的能量狀態最低。大自然在緩慢降溫(即退火)時,可找到最低能量狀態:結晶。但是,如果過程過急過快,快速降溫(亦稱淬煉)時,會導致不是最低能態的非晶形。
算法概述
- 目標函數 f 在第 i+1 步比第 i 步更優,即移動后比移動前更優,則總是向該方向移動
- 目標函數 f 移動后比移動前要差,則以一定概率接受該移動,這個概率隨著時間推移而降低(逐步降低則趨向穩定)
這個根據一定概率P是否選擇差解的方法,叫做Metropolis準則(這個準則來源于模擬退火,故整個方法成為模擬退火)
# --- 2. 模擬退火算法優化隨機森林 ---
print("\n--- 2. 模擬退火算法優化隨機森林 (訓練集 -> 測試集) ---")import random
import numpy as np
import time# 定義適應度函數
def fitness_function(params): n_estimators, max_depth, min_samples_split, min_samples_leaf = paramsmodel = RandomForestClassifier(n_estimators=int(n_estimators),max_depth=int(max_depth),min_samples_split=int(min_samples_split),min_samples_leaf=int(min_samples_leaf),random_state=42)model.fit(X_train, y_train)y_pred = model.predict(X_test)accuracy = accuracy_score(y_test, y_pred)return accuracy# 模擬退火算法實現(simulated_annealing函數的初始化階段)
def simulated_annealing(initial_solution, bounds, initial_temp, final_temp, alpha):current_solution = initial_solution # 把你的當前位置設為起始點current_fitness = fitness_function(current_solution) # 給當前位置評分best_solution = current_solutionbest_fitness = current_fitnesstemp = initial_temp # 探索熱情值,會隨時間遞減while temp > final_temp:# 只要溫度高于最終值,必定生成鄰域解neighbor_solution = []for i in range(len(current_solution)):new_val = current_solution[i] + random.uniform(-1, 1) * (bounds[i][1] - bounds[i][0]) * 0.1 # 隨機生成一組鄰域解/新參數new_val = max(bounds[i][0], min(bounds[i][1], new_val)) # 規范一組新參數,確保新值在邊界范圍內neighbor_solution.append(new_val)neighbor_fitness = fitness_function(neighbor_solution)delta_fitness = neighbor_fitness - current_fitness # 計算新解與當前解的適應度差,本質上就是在比較新舊參數(也就是新舊解)的好壞if delta_fitness > 0 or random.random() < np.exp(delta_fitness / temp):# 如果 delta_fitness > 0 ,意味著鄰域解的適應度值高于當前解,也就是鄰域解更優,此時會直接接受鄰域解# 如果 delta_fitness < 0 ,意味著鄰域解的適應度值低于當前解,也就是鄰域解更差,此時會以一定概率接受鄰域解,概率與 delta_fitness 的大小成正比,即 delta_fitness 越大,接受鄰域解的概率越大。current_solution = neighbor_solutioncurrent_fitness = neighbor_fitnessif current_fitness > best_fitness:best_solution = current_solutionbest_fitness = current_fitnesstemp *= alphareturn best_solution, best_fitness # 新函數simulated_annealing輸出最優解與最優解的適應度值# 超參數范圍
bounds = [(50, 200), (10, 30), (2, 10), (1, 4)] # n_estimators, max_depth, min_samples_split, min_samples_leaf# 模擬退火算法參數
initial_temp = 100 # 初始溫度
final_temp = 0.1 # 終止溫度
alpha = 0.95 # 溫度衰減系數# 初始化初始解
initial_solution = [random.uniform(bounds[i][0], bounds[i][1]) for i in range(len(bounds))]start_time = time.time()
best_params, best_fitness = simulated_annealing(initial_solution, bounds, initial_temp, final_temp, alpha)
end_time = time.time()print(f"模擬退火算法優化耗時: {end_time - start_time:.4f} 秒")
print("最佳參數: ", {'n_estimators': int(best_params[0]),'max_depth': int(best_params[1]),'min_samples_split': int(best_params[2]),'min_samples_leaf': int(best_params[3])
})# 使用最佳參數的模型進行預測
best_model = RandomForestClassifier(n_estimators=int(best_params[0]),max_depth=int(best_params[1]),min_samples_split=int(best_params[2]),min_samples_leaf=int(best_params[3]),random_state=42)
best_model.fit(X_train, y_train)
best_pred = best_model.predict(X_test)print("\n模擬退火算法優化后的隨機森林 在測試集上的分類報告:")
print(classification_report(y_test, best_pred))
print("模擬退火算法優化后的隨機森林 在測試集上的混淆矩陣:")
print(confusion_matrix(y_test, best_pred))
粒子群算法
想象你在公園里和一群小伙伴的目標是找到全公園最甜的那棵蘋果樹。
初始狀態:隨機撒網
- 1.你們所有人(粒子)一開始蒙著眼睛,被隨機扔到公園各個角落(隨機初始位置)
- 2.每個人手里有個小本子,用來記錄自己找到過的最甜蘋果的位置(個體最優解)。
- 3.公園廣播會實時播報當前所有人找到的最甜蘋果的位置(群體最優解)。
找蘋果的規則:邊跑邊交流,方向由三部分決定:
- 1.慣性: 你本來跑的方向(比如你本來往東跑,會保持一點慣性繼續往東)
- 2.個體經驗: 你記得自己之前找到過的好位置,會不自覺往那個方向偏。
- 3.群體經驗: 聽說某個區域有人找到超甜的蘋果,大家會一起往那個方向沖
調整速度: 每次移動時綜合這三個因素調整速度和方向(如60%慣性+20%自己經驗+20%群體經驗)
邊走邊更新:
- 1.如果你現在的位置蘋果比以前記錄的更甜,就更新自己小本子的位置。
- 2.如果某人的蘋果比廣播里說的還甜,公園廣播會立刻更新全群最優位置。
- 3.最終結果:群體智慧爆發
經過幾輪邊跑邊交流,所有人會逐漸聚集到公園里蘋果最甜的那棵樹附近。即使一開始有人走錯路,但通過不斷分享信息,最終大家都能找到最優解!
步驟類比
1.定義尋寶規則(初始化優化目標)
- 定義參數范圍:# 告訴小伙伴要找什么樣的蘋果樹
- 樹的數量范圍=(50,200)
- 最大深度范圍 =(5,30)
- 葉子樣本范圍 =(1,10)
定義甜度檢測函數(參數):驗貨員嘗蘋果流程
- 將參數轉換為整數 ->(樹的數量,深度,葉子樣本)
- 用這些參數種一片蘋果樹
- 摘取蘋果進行檢測,計算甜度分數(F1值)
- 返回甜度的負值(因為要找更甜的)
2.組織小伙伴開始尋寶(初始化粒子群)設置尋寶隊參數:
- 小伙伴數量=20
- 最大尋寶輪次=30
- 慣性權重=0.6 # 保持原方向跑的傾向
- 個體學習率=1.5 # 相信自己經驗的強度
- 集體學習率=1.5 # 相信廣播的強度
初始化所有小伙伴:
- 隨機分配到公園各地 -> 初始位置
- 每人發空白小本子 -> 記錄個人最佳
- 初始速度為0 -> 站在原地不動
- 收集所有初始位置甜度 -> 首次廣播最佳位置
3. 開始多輪尋寶(優化循環)
for 每輪尋寶 in 總輪次:
for 每個小伙伴 in 隊伍:
# 調整跑步方向(速度更新)
- 慣性方向 = 慣性權重 * 當前速度
- 個人傾向 = 個體學習率 * 隨機數 * (小本子位置 - 當前位置)
- 集體傾向 = 集體學習率 * 隨機數 * (廣播位置 - 當前位置)
- 新速度 = 慣性方向 + 個人傾向 + 集體傾向
移動腳步(位置更新),新位置 = 當前位置 + 新速度
確保不跑出公園邊界 -> 修正坐標
# 評估新位置蘋果
當前甜度 = 甜度檢測函數(新位置)
?# 更新記錄(最優解更新)
if 當前甜度 > 小本子記錄:更新小本子: 位置和甜度
if 當前甜度 > 廣播甜度:更新全公園廣播 -> 新最佳位置
4. 宣布最終發現(輸出結果)
原文鏈接:https://blog.csdn.net/2503_91003121/article/details/147647065
# --- 2. 粒子群優化算法優化隨機森林 ---
print("\n--- 2. 粒子群優化算法優化隨機森林 (訓練集 -> 測試集) ---")# 定義適應度函數,本質就是構建了一個函數實現 參數--> 評估指標的映射
def fitness_function(params): n_estimators, max_depth, min_samples_split, min_samples_leaf = params # 序列解包,允許你將一個可迭代對象(如列表、元組、字符串等)中的元素依次賦值給多個變量。model = RandomForestClassifier(n_estimators=int(n_estimators),max_depth=int(max_depth),min_samples_split=int(min_samples_split),min_samples_leaf=int(min_samples_leaf),random_state=42)model.fit(X_train, y_train)y_pred = model.predict(X_test)accuracy = accuracy_score(y_test, y_pred)return accuracy# 粒子群優化算法實現
def pso(num_particles, num_iterations, c1, c2, w, bounds): # 粒子群優化算法核心函數# num_particles:粒子的數量,每個粒子代表一組參數組合,即算法中用于搜索最優解的個體數量。# num_iterations:迭代次數,算法運行的最大循環次數。# c1:認知學習因子,用于控制粒子向自身歷史最佳位置移動的程度。# c2:社會學習因子,用于控制粒子向全局最佳位置移動的程度。# w:慣性權重,控制粒子的慣性,影響粒子在搜索空間中的移動速度和方向。# bounds:超參數的取值范圍,是一個包含多個元組的列表,每個元組表示一個超參數的最小值和最大值。num_params = len(bounds) particles = np.array([[random.uniform(bounds[i][0], bounds[i][1]) for i in range(num_params)] for _ inrange(num_particles)])velocities = np.array([[0] * num_params for _ in range(num_particles)])personal_best = particles.copy()personal_best_fitness = np.array([fitness_function(p) for p in particles]) # 可以理解為給每個粒子代表的超參數組合進行評分global_best_index = np.argmax(personal_best_fitness) # 找到評分最高的粒子的索引global_best = personal_best[global_best_index]global_best_fitness = personal_best_fitness[global_best_index]for _ in range(num_iterations):r1 = np.array([[random.random() for _ in range(num_params)] for _ in range(num_particles)]) # 生成一個與粒子數量和參數數量相同的隨機數矩陣r2 = np.array([[random.random() for _ in range(num_params)] for _ in range(num_particles)])velocities = w * velocities + c1 * r1 * (personal_best - particles) + c2 * r2 * (global_best - particles) # particles = particles + velocities # 新位置 = 當前位置 + 新速度for i in range(num_particles): # 確保粒子的位置在超參數的取值范圍內for j in range(num_params):if particles[i][j] < bounds[j][0]:particles[i][j] = bounds[j][0]elif particles[i][j] > bounds[j][1]:particles[i][j] = bounds[j][1]fitness_values = np.array([fitness_function(p) for p in particles]) # 對每個粒子代表的超參數組合進行評分improved_indices = fitness_values > personal_best_fitness # 只有當找到更好的解/參數組合時才會更新這個記錄personal_best[improved_indices] = particles[improved_indices] # 更新個體最佳位置personal_best_fitness[improved_indices] = fitness_values[improved_indices] # 更新個體的最佳參數組合評分current_best_index = np.argmax(personal_best_fitness)if personal_best_fitness[current_best_index] > global_best_fitness: # 更新全局最佳位置和適應度值global_best = personal_best[current_best_index] # 個體找到更高評分對應的參數組合后,才會更新到全局最優位置global_best_fitness = personal_best_fitness[current_best_index]return global_best, global_best_fitness# 超參數范圍
bounds = [(50, 200), (10, 30), (2, 10), (1, 4)] # n_estimators, max_depth, min_samples_split, min_samples_leaf# 粒子群優化算法參數
num_particles = 20 # num_particles:粒子的數量,每個粒子代表一組參數組合,即算法中用于搜索最優解的個體數量。
num_iterations = 10 # num_iterations:迭代次數,算法運行的最大循環次數。
c1 = 1.5 # c1:認知學習因子,用于控制粒子向自身歷史最佳位置移動的程度。
c2 = 1.5 # c2:社會學習因子,用于控制粒子向全局最佳位置移動的程度。
w = 0.5 # w:慣性權重,控制粒子的慣性,影響粒子在搜索空間中的移動速度和方向。start_time = time.time()
best_params, best_fitness = pso(num_particles, num_iterations, c1, c2, w, bounds)
end_time = time.time()print(f"粒子群優化算法優化耗時: {end_time - start_time:.4f} 秒")
print("最佳參數: ", {'n_estimators': int(best_params[0]),'max_depth': int(best_params[1]),'min_samples_split': int(best_params[2]),'min_samples_leaf': int(best_params[3])
})# 使用最佳參數的模型進行預測
best_model = RandomForestClassifier(n_estimators=int(best_params[0]),max_depth=int(best_params[1]),min_samples_split=int(best_params[2]),min_samples_leaf=int(best_params[3]),random_state=42)
best_model.fit(X_train, y_train)
best_pred = best_model.predict(X_test)print("\n粒子群優化算法優化后的隨機森林 在測試集上的分類報告:")
print(classification_report(y_test, best_pred))
print("粒子群優化算法優化后的隨機森林 在測試集上的混淆矩陣:")
print(confusion_matrix(y_test, best_pred))
?