当前位置:首页 > 技术 > 正文内容

Python实战:淘金优化算法(GRO)的完整实现与性能评估

访客 技术 2026年9月29日 11

算法概述与环境配置

淘金优化算法(Gold Rush Optimizer, GRO)是一种于2023年提出的新型元启发式算法。该算法通过模拟淘金者的勘探行为,将搜索过程抽象为迁移、开采和协作三个核心阶段,在解决高维复杂优化问题时展现出优异的寻优能力。为了在Python中高效实现该算法,我们需要预先配置以下科学计算与可视化库:

pip install numpy matplotlib tqdm joblib
  • NumPy:提供高效的矩阵与向量运算支持,是实现群体智能算法向量化计算的核心。
  • Matplotlib:用于构建适应度收敛曲线及搜索空间的动态演化图。
  • tqdm:在终端输出迭代进度条,优化长时间运算的交互体验。
  • Joblib:用于后续进阶章节中的种群适应度并行评估。

GRO算法核心架构设计

我们首先定义算法的基础类结构。为了提升计算效率,代码设计中将尽量采用NumPy的广播机制和向量化操作,替代低效的Python原生for循环。

import numpy as np
from tqdm import trange

class GROAlgorithm:
    def __init__(self, objective_fn, dimensions=2, swarm_size=40, max_epochs=150, bounds=None):
        self.objective_fn = objective_fn
        self.dimensions = dimensions
        self.swarm_size = swarm_size
        self.max_epochs = max_epochs
        
        # 默认搜索边界设置
        if bounds is None:
            self.lower_bound = np.full(dimensions, -10.0)
            self.upper_bound = np.full(dimensions, 10.0)
        else:
            self.lower_bound = np.array(bounds[0])
            self.upper_bound = np.array(bounds[1])
            
        self.control_param = 1.0  # 核心控制参数 le
        
    def _init_swarm(self):
        """生成初始种群及其适应度"""
        self.positions = np.random.uniform(
            self.lower_bound, self.upper_bound, (self.swarm_size, self.dimensions)
        )
        self.fitness = np.apply_along_axis(self.objective_fn, 1, self.positions)
        self.best_global_idx = np.argmin(self.fitness)
        self.best_global_pos = self.positions[self.best_global_idx].copy()
        self.best_global_fit = self.fitness[self.best_global_idx]

    def _update_control_params(self, epoch):
        """动态调整非线性控制因子"""
        decay_ratio = (self.max_epochs - epoch) / (self.max_epochs - 1)
        self.control_param = (decay_ratio ** 2) * (2 - 1 / self.max_epochs) + (1 / self.max_epochs)
        
    def _enforce_boundaries(self, positions):
        """边界截断处理"""
        return np.clip(positions, self.lower_bound, self.upper_bound)

    def _migration_step(self):
        """阶段一:全局迁移(向最优区域靠拢)"""
        pass

    def _mining_step(self):
        """阶段二:局部开采(精细搜索)"""
        pass

    def _collaboration_step(self):
        """阶段三:信息协作(种群交互)"""
        pass

    def run(self):
        """执行主优化循环"""
        self._init_swarm()
        history = []
        
        for epoch in trange(self.max_epochs, desc="GRO Optimization"):
            self._update_control_params(epoch)
            
            self._migration_step()
            self._mining_step()
            self._collaboration_step()
            
            # 更新全局最优记录
            current_best_idx = np.argmin(self.fitness)
            if self.fitness[current_best_idx] < self.best_global_fit:
                self.best_global_fit = self.fitness[current_best_idx]
                self.best_global_pos = self.positions[current_best_idx].copy()
                
            history.append(self.best_global_fit)
            
        return history, self.best_global_pos

三大核心搜索机制实现

1. 迁移机制 (Migration)

迁移阶段旨在利用当前全局最优解引导种群向高潜力区域移动。通过引入随机扰动因子,平衡算法的探索与开发能力。

def _migration_step(self):
    # 生成随机系数矩阵
    rand_matrix_1 = np.random.rand(self.swarm_size, self.dimensions)
    rand_matrix_2 = np.random.rand(self.swarm_size, self.dimensions)
    
    # 计算移动步长与方向因子
    step_factor = 1.0 + self.control_param * (rand_matrix_1 - 0.5)
    direction_factor = 2.0 * rand_matrix_2
    
    # 计算指向全局最优的位移向量
    displacement = direction_factor * (self.best_global_pos - self.positions)
    new_positions = self.positions + step_factor * displacement
    
    new_positions = self._enforce_boundaries(new_positions)
    new_fitness = np.apply_along_axis(self.objective_fn, 1, new_positions)
    
    # 贪婪选择策略
    mask = new_fitness < self.fitness
    self.positions[mask] = new_positions[mask]
    self.fitness[mask] = new_fitness[mask]

2. 开采机制 (Gold Mining)

开采阶段模拟淘金者在特定矿脉附近的深度挖掘。此过程不依赖全局最优信息,而是通过个体间的随机配对来维持种群多样性,防止算法陷入局部极值。

def _mining_step(self):
    # 为每个个体随机分配一个交互伙伴(排除自身)
    partner_indices = np.random.randint(0, self.swarm_size, self.swarm_size)
    for i in range(self.swarm_size):
        while partner_indices[i] == i:
            partner_indices[i] = np.random.randint(0, self.swarm_size)
            
    partner_positions = self.positions[partner_indices]
    
    # 计算开采扰动
    rand_vec = np.random.rand(self.swarm_size, self.dimensions)
    mining_factor = 2.0 * self.control_param * rand_vec - self.control_param
    
    relative_dist = self.positions - partner_positions
    new_positions = partner_positions + mining_factor * relative_dist
    
    new_positions = self._enforce_boundaries(new_positions)
    new_fitness = np.apply_along_axis(self.objective_fn, 1, new_positions)
    
    mask = new_fitness < self.fitness
    self.positions[mask] = new_positions[mask]
    self.fitness[mask] = new_fitness[mask]

3. 协作机制 (Collaboration)

协作阶段通过随机抽取两个其他个体,利用它们之间的空间差异来更新当前个体的位置。这种无中心化的信息交换模式在处理多峰复杂地形时具有显著优势。

def _collaboration_step(self):
    # 随机抽取两个不同的邻居个体
    neighbor_1 = np.random.randint(0, self.swarm_size, self.swarm_size)
    neighbor_2 = np.random.randint(0, self.swarm_size, self.swarm_size)
    
    # 确保邻居不与当前个体重复,且互不相同
    for i in range(self.swarm_size):
        while neighbor_1[i] == i:
            neighbor_1[i] = np.random.randint(0, self.swarm_size)
        while neighbor_2[i] == i or neighbor_2[i] == neighbor_1[i]:
            neighbor_2[i] = np.random.randint(0, self.swarm_size)
            
    pos_1 = self.positions[neighbor_1]
    pos_2 = self.positions[neighbor_2]
    
    # 基于邻居差异进行位置更新
    random_scale = np.random.rand(self.swarm_size, self.dimensions)
    new_positions = self.positions + random_scale * (pos_2 - pos_1)
    
    new_positions = self._enforce_boundaries(new_positions)
    new_fitness = np.apply_along_axis(self.objective_fn, 1, new_positions)
    
    mask = new_fitness < self.fitness
    self.positions[mask] = new_positions[mask]
    self.fitness[mask] = new_fitness[mask]

算法性能评估与可视化

基准测试函数定义

为了验证算法的鲁棒性,我们选取三种具有不同地形特征的基准函数进行测试:

函数名称 数学表达式 地形特征
Sphere f(x) = Σx² 单峰、连续凸函数,测试基础收敛速度
Rastrigin f(x) = 10d + Σ[x² - 10cos(2πx)] 多峰、存在大量局部极小值,测试逃逸能力
Ackley 包含指数与余弦项的复杂组合 全局平坦且中心存在极小值,测试局部开发精度
def sphere_func(x):
    return np.sum(np.square(x))

def rastrigin_func(x):
    return 10 * len(x) + np.sum(np.square(x) - 10 * np.cos(2 * np.pi * x))

def ackley_func(x):
    part1 = -0.2 * np.sqrt(np.mean(np.square(x)))
    part2 = np.mean(np.cos(2 * np.pi * x))
    return -20 * np.exp(part1) - np.exp(part2) + 20 + np.e

# 执行批量测试
test_suite = {
    'Sphere': sphere_func,
    'Rastrigin': rastrigin_func,
    'Ackley': ackley_func
}

convergence_logs = {}
for name, func in test_suite.items():
    optimizer = GROAlgorithm(func, dimensions=2, swarm_size=50, max_epochs=100, bounds=[[-5, -5], [5, 5]])
    history, _ = optimizer.run()
    convergence_logs[name] = history

收敛曲线绘制

通过Matplotlib将各测试函数的适应度下降过程进行对数级可视化:

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
for name, log in convergence_logs.items():
    plt.plot(log, label=name, linewidth=2)

plt.xlabel('Epoch')
plt.ylabel('Log Fitness')
plt.title('GRO Convergence Analysis on Benchmark Functions')
plt.yscale('log')
plt.legend()
plt.grid(True, which="both", ls="--", alpha=0.5)
plt.tight_layout()
plt.show()

从输出图表中可以观察到:Sphere函数在初期呈现极快的下降斜率;Rastrigin函数由于地形崎岖,收敛曲线存在明显的阶梯状停滞,但最终仍能逼近全局最优;Ackley函数则展现了算法在平坦区域与陡峭极值区之间的良好过渡能力。

进阶优化策略

1. 控制参数非线性衰减

原始GRO的控制参数呈二次曲线衰减。为了在搜索后期提供更平滑的局部挖掘能力,可将其替换为余弦退火机制:

def _update_control_params(self, epoch):
    # 余弦退火策略
    progress = epoch / self.max_epochs
    self.control_param = 0.5 * (1 + np.cos(np.pi * progress))

2. 适应度并行评估

当目标函数计算成本较高(如有限元分析或深度学习模型推理)时,串行评估将成为性能瓶颈。利用joblib可实现种群级别的并行计算:

from joblib import Parallel, delayed

class ParallelGRO(GROAlgorithm):
    def __init__(self, *args, n_cores=-1, **kwargs):
        super().__init__(*args, **kwargs)
        self.n_cores = n_cores

    def _parallel_evaluate(self, positions):
        return np.array(Parallel(n_jobs=self.n_cores)(
            delayed(self.objective_fn)(ind) for ind in positions
        ))

    def _init_swarm(self):
        self.positions = np.random.uniform(
            self.lower_bound, self.upper_bound, (self.swarm_size, self.dimensions)
        )
        self.fitness = self._parallel_evaluate(self.positions)
        self.best_global_idx = np.argmin(self.fitness)
        self.best_global_pos = self.positions[self.best_global_idx].copy()
        self.best_global_fit = self.fitness[self.best_global_idx]

3. 约束条件处理

针对带有不等式或等式约束的实际工程问题,可通过外部罚函数法将约束优化转化为无约束优化:

def apply_penalty(original_fn, constraint_fns, penalty_weight=1e6):
    def penalized_fn(x):
        base_val = original_fn(x)
        penalty = 0.0
        for c_fn in constraint_fns:
            violation = c_fn(x)
            if violation > 0:
                penalty += penalty_weight * (violation ** 2)
        return base_val + penalty
    return penalized_fn

# 使用示例:
# constrained_fn = apply_penalty(my_objective, [constraint_1, constraint_2])
# optimizer = GROAlgorithm(constrained_fn, ...)
标签: GRO

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。