差分进化算法原理与复现

目录

  • 摘要
  • 1、算法原理
    • 1.1、种群初始化
    • 1.2、变异
    • 1.3、交叉
    • 1.4、选择
  • 2、算法实现
    • 2.1、种群初始化
    • 2.2、变异
    • 2.3、交叉
    • 2.4、选择
    • 2.5、选取终代种群中最优秀个体

摘要

如何选取一组最佳的参数,使得代价函数值最优?这是优化算法做的事,一个直觉的方法是使用网格搜索,遍历参数值在值域上的所有组合,选取代价函数值最优的一组参数值,该方法搜索时无方向驱使,需遍历整个参数空间,复杂度太高。梯度下降算法通过代价函数对参数的导数有方向的更新参数值,无需搜索整个向量空间,速度很快,但无法解决不可导问题。而差分进化算法是一种基于“适者生存”思想的最优参数搜索算法。通过变异、交叉、选择循环维护 N P NP NP个最优秀个体的种群实现“适者生存”,达到最优参数搜索的目的,无需代价函数对参数可导。注意种群中的每个个体表示参数空间的一组向量值,个体的一个基因表示一个参数。本文参考97年原始论文,根据差分进化算法原理复现代码。

1、算法原理

差分进化算法核心是种群的演化,第 G G G代种群中的第 i i i个个体可用数学符号表示为 x i , G , i = 1 , 2 , … , N P x_{i, G},i=1,2, \ldots, NP xi,Gi=1,2,,NP。流程如下图,初始化时在值域空间随机选取 N P 个个体 NP个个体 NP个个体作为初始种群,通过变异交叉得到种群中每个个体对应的实验个体, 比较种群的现有个体与实验个体的代价值,选择更优的作为下一代种群中的个体,循环往复,直至满足结束条件。
在这里插入图片描述

1.1、种群初始化

根据参数的取值范围,随机生成 N P NP NP个个体,作为初始种群。

1.2、变异

对于种群中的每一个个体,随机抽取的2个个体加权差与之加和,得到变异个体 v i , G + 1 v_{i, G+1} vi,G+1,数学表示为:
v i , G + 1 = x r 1 , G + F ⋅ ( x r 2 , G − x r 3 , G ) (1) v_{i, G+1}=x_{r_{1}, G}+F \cdot\left(x_{r_{2}, G}-x_{r_{3}, G}\right)\tag1 vi,G+1=xr1,G+F(xr2,Gxr3,G)(1)
r 1 , r 2 , r 3 ∈ [ 1 , N P ] r_1,r_2,r_3\in[1,NP] r1,r2,r3[1,NP],是种群中的个体索引, F ∈ [ 0 , 2 ] F\in[0,2] F[0,2],是常数因子,用与控制差分的缩放。

1.3、交叉

变异个体与目标个体随机交换基因,得到下一代的实验个体。数学表示为:
u j i , G + 1 = { v j i , G + 1 if  ( randb ⁡ ( j ) ≤ C R ) or  j = rnbr ⁡ ( i ) x j i , G if  ( randb ⁡ ( j ) > C R ) and  j ≠ rnbr ⁡ ( i ) j = 1 , 2 , … , D . (2) \begin{aligned} u_{j i, G+1} & =\left\{\begin{array}{ll} v_{j i, G+1} & \text { if }(\operatorname{randb}(j) \leq C R) \text { or } j=\operatorname{rnbr}(i) \\ x_{j i, G} & \text { if }(\operatorname{randb}(j)>C R) \text { and } j \neq \operatorname{rnbr}(i) \end{array}\right. \\ j & =1,2, \ldots, D . \end{aligned}\tag2 uji,G+1j={vji,G+1xji,G if (randb(j)CR) or j=rnbr(i) if (randb(j)>CR) and j=rnbr(i)=1,2,,D.(2)
其中 j j j是个体基因的索引, u j i , G + 1 u_{j i, G+1} uji,G+1表示第 G + 1 G+1 G+1代种群第 i i i个个体的第 j j j个基因, r a n d b ( j ) randb(j) randb(j)是一个随机数生成器,生成值范围为 [ 0 , 1 ] [0,1] [0,1],CR是 [ 0 , 1 ] [0,1] [0,1]的交叉常数,当 r a n d b ( j ) > C R randb(j)>CR randb(j)>CR时交换目标个体和变异个体第 j j j个位置的基因,从而得到实验个体, r n b r ( i ) {rnbr}(i) rnbr(i)用于确保个体中至少一个基因发生交叉。

1.4、选择

通过比较种群中的个体与对应实验个体的代价函数,选择更优的作为下一轮种群中的个体,并判断是否达到搜索的终止条件,达到终止条件则从当前种群中选取代价函数值最优的个体作为结果。

2、算法实现

以搜索让代价函数 y = x 1 2 + ∣ x 2 ∣ + x 3 3 y=x_1^2+|x_2|+x_3^3 y=x12+x2+x33值最小的一组参数为例,其中 x 1 , x 2 , x 3 ∈ [ − 30 , 30 ] x_1,x_2,x_3\in[-30, 30] x1,x2,x3[30,30]。全部如下代码:

import math
import numpy as npdef cost_func(x:np.array)->float:"""代价函数:param x: 参数列表:return: 参数值对应的代价值"""return math.pow(x[0], 2) + np.abs(x[1]) + math.pow(x[2], 3)def population_init(x_bounds:list, n=50)->np.array:"""种群初始化:param x_bounds: 各参数上下边界:param n: 初始种群大小:return: 初始种群"""population = []for _ in range(n):vector = []for low, high in x_bounds:vector.append(np.random.uniform(low, high))population.append(vector)return np.array(population)def mutation(population:np.array, x_bounds:list, F=1.0):"""变异操作:param population: 种群:param x_bounds: 参数边界范围:param F: 变异的常数因子:return: 变异种群"""n = len(population)mutation_vectors = []for r1 in range(n):r2 = np.random.randint(1, n)r3 = np.random.randint(1, n)v = population[r1] + F*(population[r2]-population[r3])v = edge_deal(v, x_bounds)mutation_vectors.append(v)return np.array(mutation_vectors)def edge_deal(x:np.array, x_bounds:list)->np.array:"""边界处理:param x: 种群中的一个个体:param x_bounds: 参数边界范围:return: 满足边界条件的个体"""D = len(x)for j in range(D):low, high = x_bounds[j][0], x_bounds[j][1]if x[j] < low:x[j] = lowif x[j] > high:x[j] = highreturn xdef crossover(population:np.array, mutation_vectors:np.array, CR=0.5):"""交叉操作:param population: 种群:param mutation_vectors: 变异种群:param CR: 交叉的常数因子:return: 实验种群(种群和变异种群基因交叉后得到的)"""D = len(population[0])for i in range(len(population)):rnbr = np.random.randint(1, D)for j in range(D):if np.random.rand() > CR or j == rnbr:mutation_vectors[i][j] = population[i][j]return mutation_vectorsdef selector(population:np.array, trial_population:np.array, cost_func):"""选择操作:param population: 种群:param trial_population: 实验种群:param cost_func: 代价函数:return: 更优秀的下一代种群"""next_population = []for i in range(len(population)):if cost_func(population[i]) < cost_func(trial_population[i]):next_population.append(population[i])else:next_population.append(trial_population[i])return next_populationdef min_cost_get(population:np.array):"""获取种群中代价最小的个体:param population: 种群:return: 最优秀的个体和其对应的代价值"""min_cost = cost_func(population[0])min_cost_index = 0for i in range(1, len(population)):if cost_func(population[i]) < min_cost:min_cost = cost_func(population[i])min_cost_index = ireturn population[min_cost_index], min_costif __name__ == '__main__':max_items = 200x_bounds = [(-30, 30)] * 3population = population_init(x_bounds, 50)for i in range(max_items):mutation_vectors = mutation(population, x_bounds)trial_population = crossover(population, mutation_vectors)population = selector(population, trial_population, cost_func)print(min_cost_get(population))

2.1、种群初始化

def population_init(x_bounds:list, n=50)->np.array:"""种群初始化:param x_bounds: 各参数上下边界:param n: 初始种群大小:return: 初始种群"""population = []for _ in range(n):vector = []for low, high in x_bounds:vector.append(np.random.uniform(low, high))population.append(vector)return np.array(population)if __name__ == '__main__':max_items = 200x_bounds = [(-30, 30)] * 3population = population_init(x_bounds, 50)

2.2、变异

def mutation(population:np.array, x_bounds:list, F=1.0):"""变异操作:param population: 种群:param x_bounds: 参数边界范围:param F: 变异的常数因子:return: 变异种群"""n = len(population)mutation_vectors = []for r1 in range(n):r2 = np.random.randint(1, n)r3 = np.random.randint(1, n)v = population[r1] + F*(population[r2]-population[r3])v = edge_deal(v, x_bounds)mutation_vectors.append(v)return np.array(mutation_vectors)def edge_deal(x:np.array, x_bounds:list)->np.array:"""边界处理:param x: 种群中的一个个体:param x_bounds: 参数边界范围:return: 满足边界条件的个体"""D = len(x)for j in range(D):low, high = x_bounds[j][0], x_bounds[j][1]if x[j] < low:x[j] = lowif x[j] > high:x[j] = highreturn x

2.3、交叉

def crossover(population:np.array, mutation_vectors:np.array, CR=0.5):"""交叉操作:param population: 种群:param mutation_vectors: 变异种群:param CR: 交叉的常数因子:return: 实验种群(种群和变异种群基因交叉后得到的)"""D = len(population[0])for i in range(len(population)):rnbr = np.random.randint(1, D)for j in range(D):if np.random.rand() > CR or j == rnbr:mutation_vectors[i][j] = population[i][j]return mutation_vectors

2.4、选择

def selector(population:np.array, trial_population:np.array, cost_func):"""选择操作:param population: 种群:param trial_population: 实验种群:param cost_func: 代价函数:return: 更优秀的下一代种群"""next_population = []for i in range(len(population)):if cost_func(population[i]) < cost_func(trial_population[i]):next_population.append(population[i])else:next_population.append(trial_population[i])return next_population

2.5、选取终代种群中最优秀个体

def min_cost_get(population:np.array):"""获取种群中代价最小的个体:param population: 种群:return: 代价最小的个体和其对应的代价值"""min_cost = cost_func(population[0])min_cost_index = 0for i in range(1, len(population)):if cost_func(population[i]) < min_cost:min_cost = cost_func(population[i])min_cost_index = ireturn population[min_cost_index], min_cost

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/477797.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搜索引擎中广泛使用的文档排序算法——BM25(Best Matching 25)

在搜索场景中&#xff0c;BM25能计算每个文档与查询的匹配度&#xff0c;从中找出最相关的文档&#xff0c;并按相关性高低排序展示。 要理解BM25&#xff0c;需要掌握以下几个关键概念&#xff1a; 1. 词频&#xff08;Term Frequency, TF&#xff09;&#xff1a;某关键词在文…

C语言笔记(自定义类型:结构体、枚举、联合体 )

前言 本文对自定义类型的结构体创建、使用、结构体的存储方式和对齐方式&#xff0c;枚举的定义、使用方式以及联合体的定义、使用和存储方式展开叙述&#xff0c;如有错误&#xff0c;请各位指正。 目录 前言 1 结构体 1.1 结构体的声明 1.2 结构体的自引用 1.3 结构体变…

【C++】list模拟实现(详解)

本篇来详细说一下list的模拟实现&#xff0c;list的大体框架实现会比较简单&#xff0c;难的是list的iterator的实现。我们模拟实现的是带哨兵位头结点的list。 1.准备工作 为了不和C库里面的list冲突&#xff0c;我们在实现的时候用命名空间隔开。 //list.h #pragma once #…

数字化工厂 MES试点方案全解析(三)

目 录 三、试点实施步骤 需求分析与方案设计阶段 系统开发与测试阶段 系统部署与培训阶段 试点运行与优化阶段 总结与评估阶段 三、试点实施步骤 需求分析与方案设计阶段 1、成立由企业生产、工艺、质量、设备、IT 等多部门人员组成的项目团队&#xff0c;与 MES 供应商共…

ShuffleNet V2:高效卷积神经网络架构设计的实用指南

摘要 https://arxiv.org/pdf/1807.11164 当前&#xff0c;神经网络架构设计大多以计算复杂度的间接指标&#xff0c;即浮点运算数&#xff08;FLOPs&#xff09;为指导。然而&#xff0c;直接指标&#xff08;例如速度&#xff09;还取决于其他因素&#xff0c;如内存访问成本…

【Opencv学习】PART1-图像基础处理

目录 一、图像的读入、显示和保存 1、读入图像 imread函数 范例 显示控制参数 2、显示图像 imshow函数 范例 tips waitkey函数 含义 delay参数: tips destoryAllWindows函数 3、保存图像 imwrite函数 范例 实操 01-读入显示保存 代码 结果 二、图像处理入…

硬中断关闭后的堆栈抓取方法

一、背景 性能和稳定性是一个计算机工程里的一个永恒的主题。其中尤其稳定性这块的问题发现和问题分析及问题解决就依赖合适的对系统的观测的手段&#xff0c;帮助我们发现问题&#xff0c;识别问题原因最后才能解决问题。稳定性问题里尤其底层问题里&#xff0c;除了panic问题…

MT8768/MTK8768安卓核心板性能参数_联发科安卓智能模块开发方案

MT8768安卓核心板 是一款采用台积电12nm FinFET制程工艺的智能手机芯片。MT8768核心板不仅提供所有高级功能和出色体验&#xff0c;同时确保智能终端具备长电池寿命。该芯片提供了一个1600x720高清(20:9比例)分辨率显示屏&#xff0c;排除了清晰度和功耗之间的平衡问题。该芯片…

NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案

EasyNVR是基于端-边-云一体化架构的安防监控视频融合云平台&#xff0c;具有简单轻量的部署方式与多样的功能&#xff0c;支持多种协议&#xff08;如GB28181、RTSP、Onvif、RTMP&#xff09;和设备类型&#xff08;IPC、NVR等&#xff09;&#xff0c;提供视频直播、录像、回放…

ETAS工具导入DBC生成Com协议栈

文章目录 前言DBC配置关键属性Cobra参数配置Cobra使用isolar工程配置总结前言 ETAS工具导入DBC主要也是生成arxml用的,ETAS推荐使用Cobra导入,本文介绍导入过程及注意事项 DBC配置关键属性 对于普通Com报文,配置为周期发送,及其周期,NmMessage配置为No,示例如下: 对…

图形化界面MySQL(MySQL)(超级详细)

1.官网地址 MySQL :: Download MySQL Workbench 1.1在Linux直接点击NO thanks..... 下载完后是这个页面 1.2任何远端登录&#xff0c;再把jj数据库给授权 1.3建立新用户 进行连接 点击这个就运行了 只执行show tables&#xff1b;要先选中 圆圈处支持自己输入 点击这个就执…

vulhub靶场与pikachu靶场

一、搭建vulhub 环境&#xff1a;kaildocker 1.1 提权&#xff1a; :::color4 sudo su #权限升级为root ::: 1.2更新软件&#xff1a; :::color4 apt-get update ::: (此处我已更新过) 1.3安装HTTPS协议和CA证书&#xff1a; :::color4 apt-get install -y apt-transpo…

计算机网络socket编程(6)_TCP实网络编程现 Command_server

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络socket编程(6)_TCP实网络编程现 Command_server 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论…

D78【 python 接口自动化学习】- python基础之HTTP

day78 pycharm创建项目并进行接口请求 学习日期&#xff1a;20241124 学习目标&#xff1a;http定义及实战 -- pycharm创建项目并进行接口请求 学习笔记&#xff1a; 安装requests 安装方式&#xff1a;pip/pip3 install requests 官网教程&#xff1a;Requests: HTTP fo…

Android 设备使用 Wireshark 工具进行网络抓包

背景 电脑和手机连接同一网络&#xff0c;想使用wireshark抓包工具抓取Android手机网络日志&#xff0c;有以下两种连接方法&#xff1a; Wi-Fi 网络抓包。USB 网络共享抓包。需要USB 数据线将手机连接到电脑&#xff0c;并在开发者模式中启用 USB 网络共享。 查看设备连接信…

Docker安装ubuntu1604

首先pull镜像 sudo docker run -d -P m.daocloud.io/docker.io/library/ubuntu:16.04国内使用小技巧&#xff1a; https://github.com/DaoCloud/public-image-mirror pull完成之后查看 sudo docker images 运行docker sudo docker run -d -v /mnt/e:/mnt/e m.daocloud.io/…

【数据结构与算法】树和二叉树

【数据结构与算法】树和二叉树 文章目录 【数据结构与算法】树和二叉树前言一、树的基本概念二、二叉树的基本概念三、二叉树的递归遍历四、二叉树的编程五、二叉树的非递归遍历总结 前言 本篇文章将讲到树的基本概念&#xff0c;二叉树的基本概念&#xff0c;二叉树的递归遍历…

大语言模型---Llama7B和Llama8B的区别;模型参数量;权重文件的不同;嵌入层权重的不同;输入序列长度的不同;应用场景

文章目录 1.概要2. 模型参数量3. 权重文件的不同4. 嵌入层权重的不同5. 输入序列长度的不同6. 应用场景 1.概要 LLaMA&#xff08;Large Language Model Meta AI&#xff09;是由Meta开发的一系列语言模型&#xff0c;其中不同版本的参数量&#xff08;如7B、8B等&#xff09;…

Android Binder技术概览

Android中的Binder是一种基于远程过程调用&#xff08;Remote Procedure Call, RPC&#xff09;的轻量级通信机制&#xff0c;核心用于 Android 系统中的进程间通信&#xff08;Inter-Process Communication, IPC&#xff09;。Binder 是 Android 系统中不可或缺的一部分&#…

NoteExpress导入知网论文无法智能更新题录的处理方法

知网论文下载下来一般为“标题_作者.caj”&#xff0c;只要在导入文件时对字段默认值进行设置就行了。 其他地方下载的论文也是一样&#xff0c;根据文件名称设置字段默认值。