符号回归工具之 geppy: Python中的基因表达编程框架

article/2025/8/24 13:25:13

符号回归工具之 geppy: Python中的基因表达编程框架

geppy是一个专门用于基因表达编程(GEP)的计算框架,由 C. Ferreira 在 2001 年提出 [1]。 geppy是在 Python 3 中开发的。这个框架个人认为稍微了解下遗传算法和遗传规划即可入门。

官网链接

什么是 GEP?

基因表达编程 (GEP) 是一种流行且成熟的进化算法,用于自动生成计算机程序和数学模型。它在符号回归、分类、自动模型设计、组合优化和实参数优化问题中得到了广泛的应用[2]。

基因表达式编程GEP(Gene Expression Programming)是一种基于生物基因结构和功能发明的一种新型自适应演化算法。

GEP可以看作是传统 遗传编程(GP)的变体,它使用固定长度的简单线性染色体来编码遗传信息。虽然染色体(基因)的长度是固定的,但由于其基因型-表型表达系统,它可以产生各种大小的表达树。许多实验表明,GEP 比 GP 更有效,并且由 GEP 进化的树的大小往往比 GP 的小。

geppy建立在优秀的进化计算框架DEAP之上,用于使用 GEP 进行快速原型设计和测试。DEAP 为 GP 提供基本支持,但缺乏对 GEP 的支持。geppy尽量遵循 DEAP 的风格,并试图保持与 DEAP 主要基础设施的兼容性。也就是说,geppy在某种程度上可以被认为是DEAP的一个插件,专门支持GEP。如果你熟悉 DEAP,那么很容易掌握geppy。此外,还提供全面的文档。

特征

  • GEP中的核心数据结构,包括基因、染色体、表达树和K-表达。
  • GEP中常见变异、转置、倒置和交叉算子的实现。
  • 样板算法,包括标准 GEP 算法和集成局部优化器以进行数值常数优化的高级算法。
  • 灵活的内置算法接口,可以支持任意数量的自定义变异和类交叉算子。
  • 表达式树的可视化。
  • 后处理中基因、染色体或 K 表达的符号简化。

框架运行流程

  • 数据集、观测数据的处理
  • 创建基元集即定义输入变量的内容以及算子
  • 注册基因、染色体和个体以及种群的基本参数
  • 定义适应度评价函数
  • 注册遗传算子
  • 迭代进化(预测)
  • 可视化

算法流程


在这里插入图片描述

在这里插入图片描述


  • 基因 - 基础公式算子

  • 个体(染色体) - 由多个基因组成即预测的公式

  • 种群 - 所有预测的公式合集

  • 变异 - 在交叉操作过后形成的新个体,有一定的概率会发生基因变异,与选择操作一样,这个操作是基于概率。

  • 交叉 - 选择两个进行相互交配,将他们的染色体按照某种方式相互交换部分基因,形成两个新的个体的过程。

三个例子

1.布尔函数的预测(与或非)

# 布尔值回归# 定义数据集Y标签生成函数
def f(a, b, c, d):""" The true model, which only involves three inputs on purpose."""return (a and d) or not c# 生成数据集[X,Y]
import itertools
X = []
Y = []
for a, b, c, d in itertools.product([True, False], repeat=4):X.append((a, b, c, d))Y.append(f(a, b, c, d))# 创建geppy初始数据集
import geppy as gep
import operator
pset = gep.PrimitiveSet('Main', input_names=['a', 'b', 'c', 'd'])# 加入算子
pset.add_function(operator.and_, 2)
pset.add_function(operator.or_, 2)
pset.add_function(operator.not_, 1)from deap import creator, base, tools
creator.create("FitnessMax", base.Fitness, weights=(1,))  # 最大化目标函数
creator.create("Individual", gep.Chromosome, fitness=creator.FitnessMax)h = 5   # 基因头长度
n_genes = 2  # 一条染色体中基因的长度
toolbox = gep.Toolbox()
toolbox.register('gene_gen', gep.Gene, pset=pset, head_length=h)
toolbox.register('individual', creator.Individual, gene_gen=toolbox.gene_gen, n_genes=n_genes, linker=operator.or_)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)# 将个人转化为可执行的lambda函数,即编译后可以得到预测值结果,再用于优化
toolbox.register('compile', gep.compile_, pset=pset)def evaluate(individual):"""Evalute the fitness of an individual"""func = toolbox.compile(individual) n_correct = 0for (a, b, c, d), y in zip(X, Y):prediction = func(a, b, c, d)if prediction == y:n_correct += 1return n_correct,toolbox.register('evaluate', evaluate)
toolbox.register('select', tools.selRoulette)# 定义变异概率
toolbox.register('mut_uniform', gep.mutate_uniform, pset=pset, ind_pb=2 / (2 * h + 1))
toolbox.pbs['mut_uniform'] = 0.1
toolbox.register('mut_invert', gep.invert, pb=0.1)
toolbox.register('mut_is_ts', gep.is_transpose, pb=0.1)
toolbox.register('mut_ris_ts', gep.ris_transpose, pb=0.1)
toolbox.register('mut_gene_ts', gep.gene_transpose, pb=0.1)# 定义交叉算子
toolbox.register('cx_1p', gep.crossover_one_point, pb=0.1)
toolbox.pbs['cx_1p'] = 0.4   # just show that the probability can be overwritten
toolbox.register('cx_2p', gep.crossover_two_point, pb=0.2)
toolbox.register('cx_gene', gep.crossover_gene, pb=0.1)# 用于进化过程中评估函数中间结果的显示 
import numpy 
stats = tools.Statistics(key=lambda ind: ind.fitness.values[0])
stats.register("avg", numpy.mean)
stats.register("std", numpy.std)
stats.register("min", numpy.min)
stats.register("max", numpy.max)import random
random.seed(123)# 种群基本参数
n_pop = 50
n_gen = 50pop = toolbox.population(n=n_pop)
hof = tools.HallOfFame(1)   # 记录最好的个体# 开始进化 - 预测
pop, log = gep.gep_simple(pop, toolbox,n_generations=n_gen, n_elites=2,stats=stats, hall_of_fame=hof, verbose=True)best = hof[0]
symplified_best = gep.simplify(best)
print('\n')
print("符号回归结果:",symplified_best)
print('\n')

结果

在这里插入图片描述
最好的个人预测结果,可以看到其基因组成,基因是由geppy框架中toolbox注册,即一个基因由多少个算子组成。

  • 个人认为最终的预测结果好坏可能需要去找到一些合适的算子和参数。

可视化

在这里插入图片描述


2.数值表达式的推理(只涉及整数常量,结果一般比较唯一)

基本流程与布尔函数预测一样,注册加减乘除算子,然后就是评估函数应该是最小化np.mean(np.abs(Y - Yp)) 与布尔函数不同。

import geppy as gep
from deap import creator, base, tools
import numpy as np
import randoms = 0
random.seed(s)
np.random.seed(s)def f(x):return -2 * x ** 2 + 11 * x + 1.8n_cases = 100
X = np.random.uniform(-10, 10, size=n_cases)  
Y = f(X) + np.random.normal(size=n_cases) 
print(Y)def protected_div(x1, x2):if abs(x2) < 1e-6:return 1return x1 / x2import operator pset = gep.PrimitiveSet('Main', input_names=['x'])
pset.add_function(operator.add, 2)
pset.add_function(operator.sub, 2)
pset.add_function(operator.mul, 2)
pset.add_function(protected_div, 2)
pset.add_ephemeral_terminal(name='enc', gen=lambda: random.randint(-10, 10)) # each ENC is a random integer within [-10, 10]from deap import creator, base, toolscreator.create("FitnessMin", base.Fitness, weights=(-1,))  # to minimize the objective (fitness)
creator.create("Individual", gep.Chromosome, fitness=creator.FitnessMin)h = 7 
n_genes = 2   toolbox = gep.Toolbox()
toolbox.register('gene_gen', gep.Gene, pset=pset, head_length=h)
toolbox.register('individual', creator.Individual, gene_gen=toolbox.gene_gen, n_genes=n_genes, linker=operator.add)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)toolbox.register('compile', gep.compile_, pset=pset)def evaluate(individual):func = toolbox.compile(individual)Yp = np.array(list(map(func, X)))return np.mean(np.abs(Y - Yp)),toolbox.register('evaluate', evaluate)toolbox.register('select', tools.selTournament, tournsize=3)toolbox.register('mut_uniform', gep.mutate_uniform, pset=pset, ind_pb=0.05, pb=1)
toolbox.register('mut_invert', gep.invert, pb=0.1)
toolbox.register('mut_is_transpose', gep.is_transpose, pb=0.1)
toolbox.register('mut_ris_transpose', gep.ris_transpose, pb=0.1)
toolbox.register('mut_gene_transpose', gep.gene_transpose, pb=0.1)
toolbox.register('cx_1p', gep.crossover_one_point, pb=0.4)
toolbox.register('cx_2p', gep.crossover_two_point, pb=0.2)
toolbox.register('cx_gene', gep.crossover_gene, pb=0.1)
toolbox.register('mut_ephemeral', gep.mutate_uniform_ephemeral, ind_pb='1p') 
toolbox.pbs['mut_ephemeral'] = 1  stats = tools.Statistics(key=lambda ind: ind.fitness.values[0])
stats.register("avg", np.mean)
stats.register("std", np.std)
stats.register("min", np.min)
stats.register("max", np.max)n_pop = 100
n_gen = 100pop = toolbox.population(n=n_pop)
hof = tools.HallOfFame(3)   # start evolution
pop, log = gep.gep_simple(pop, toolbox, n_generations=n_gen, n_elites=1,stats=stats, hall_of_fame=hof, verbose=True)best_ind = hof[0]
symplified_best = gep.simplify(best_ind)
print('Symplified best individual: ')
print(symplified_best)# 可视化
# import os
# os.environ["PATH"] += os.pathsep + 'D:/Program Files (x86)/Graphviz/bin/'# rename_labels = {'add': '+', 'sub': '-', 'mul': '*', 'protected_div': '/'}  
# gep.export_expression_tree(best_ind, rename_labels, 'data/numerical_expression_tree.png')# from IPython.display import Image
# Image(filename='data/numerical_expression_tree.png') 

结果

在这里插入图片描述

可视化

在这里插入图片描述


3.是用线性缩放的高阶符号回归(可以处理小数点型连续实数,结果可能不唯一)

import geppy as gep
from deap import creator, base, tools
import numpy as np
import randoms = 10
random.seed(s)
np.random.seed(s)# 定义是否使用线性缩放
LINEAR_SCALING = Truedef f(x):return -2.45 * x ** 2 + 9.87 * x  + 14.56n_cases = 100
X = np.random.uniform(-10, 10, size=n_cases)
Y = f(X) + np.random.normal(size=n_cases) 
Y = f(X)def protected_div(a, b):if np.isscalar(b):if abs(b) < 1e-6:b = 1else:b[abs(b) < 1e-6] = 1return a / bimport operator pset = gep.PrimitiveSet('Main', input_names=['x'])
pset.add_function(operator.add, 2)
pset.add_function(operator.sub, 2)
pset.add_function(operator.mul, 2)
pset.add_function(protected_div, 2)
pset.add_ephemeral_terminal(name='enc', gen=lambda: random.uniform(-5, 5)) from deap import creator, base, toolscreator.create("FitnessMin", base.Fitness, weights=(-1,))  # 最小化目标函数
creator.create("Individual", gep.Chromosome, fitness=creator.FitnessMin, a=float, b=float)h = 7
n_genes = 2   
toolbox = gep.Toolbox()
toolbox.register('gene_gen', gep.Gene, pset=pset, head_length=h)
toolbox.register('individual', creator.Individual, gene_gen=toolbox.gene_gen, n_genes=n_genes, linker=operator.add)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)toolbox.register('compile', gep.compile_, pset=pset)def evaluate(individual):func = toolbox.compile(individual)Yp = func(X)  return np.mean((Y - Yp) ** 2), # 均方差def evaluate_linear_scaling(individual):func = toolbox.compile(individual)Yp = func(X).if isinstance(Yp, np.ndarray):Q = np.hstack((np.reshape(Yp, (-1, 1)), np.ones((len(Yp), 1))))(individual.a, individual.b), residuals, _, _ = np.linalg.lstsq(Q, Y, rcond=None)   if residuals.size > 0:return residuals[0] / len(Y),  individual.a = 0individual.b = np.mean(Y)return np.mean((Y - individual.b) ** 2),if LINEAR_SCALING:toolbox.register('evaluate', evaluate_linear_scaling)
else:toolbox.register('evaluate', evaluate)toolbox.register('select', tools.selTournament, tournsize=3)
# 1. general operators
toolbox.register('mut_uniform', gep.mutate_uniform, pset=pset, ind_pb=0.05, pb=1)
toolbox.register('mut_invert', gep.invert, pb=0.1)
toolbox.register('mut_is_transpose', gep.is_transpose, pb=0.1)
toolbox.register('mut_ris_transpose', gep.ris_transpose, pb=0.1)
toolbox.register('mut_gene_transpose', gep.gene_transpose, pb=0.1)
toolbox.register('cx_1p', gep.crossover_one_point, pb=0.4)
toolbox.register('cx_2p', gep.crossover_two_point, pb=0.2)
toolbox.register('cx_gene', gep.crossover_gene, pb=0.1)
toolbox.register('mut_ephemeral', gep.mutate_uniform_ephemeral, ind_pb='1p')  
toolbox.pbs['mut_ephemeral'] = 1  stats = tools.Statistics(key=lambda ind: ind.fitness.values[0])
stats.register("avg", np.mean)
stats.register("std", np.std)
stats.register("min", np.min)
stats.register("max", np.max)n_pop = 100
n_gen = 200pop = toolbox.population(n=n_pop)
hof = tools.HallOfFame(3)   pop, log = gep.gep_simple(pop, toolbox, n_generations=n_gen, n_elites=1,stats=stats, hall_of_fame=hof, verbose=True)print(hof[0])for i in range(3):ind = hof[i]symplified_model = gep.simplify(ind)if LINEAR_SCALING:symplified_model = ind.a * symplified_model + ind.bprint('Symplified best individual {}: '.format(i))print(symplified_model)

结果

在这里插入图片描述

可视化

在这里插入图片描述


http://chatgpt.dhexx.cn/article/yJr2L4Yt.shtml

相关文章

如何在Geany中添加python的中文注释

在Geany中编译Python中直接添加中文注释会出现如下错误 只需要在程序的开始位置添加一句&#xff1a;# coding:utf-8

python中安装gensim包

安装gensim扩展包需要先安装numpy和scipy 先下载这三个文件的安装包。 注意安装包版本问题&#xff0c;可以进入python查看&#xff1a; 这里注意图中划线的两个地方即可&#xff0c;win代表的是是windows系统 WinR cmd 切换到安装包所在路径&#xff1a; pip install numpy…

搭建云端数据库【MongoDB】

MongoDB官方网站&#xff1a;http://www.cloud.mongodb.com 进入官网后首先点击TRY FREE 创建database 数据库创建完成 点击连接按钮 选择第二个选项 复制连接到项目中&#xff0c;输入密码和数据库名称 在服务端做一些相关配置 1、在根目录下新建d…

云端数据库的春天真来了

点 10月24日&#xff0c;阿里云推出了国内首个云端数据库跑分平台&#xff0c;在行业圈中引起了不少讨论。在阿明看来&#xff0c;这个平台推出的背后&#xff0c;实际上仍然潜藏着数据库领域&#xff0c;用云数据库替换传统数据库的大趋势&#xff0c;正如19世纪末汽车的出现…

【腾讯云技术沙龙预告】云端数据库的设计之美

数据科学俱乐部 中国数据科学家社区 以数据为中心的信息化社会&#xff0c;数据库可以看做是所有应用程序成功运行的核心。而结合云计算&#xff0c;数据库的高可用性能够被放大到极致&#xff0c;可以实现按需付费、按需扩展、高可用性以及存储整合等优势。 本期云社区技术沙龙…

ApiCloud链接云端数据库

apicloud的mcm模块其实就是应用云端数据库完成一系列操作&#xff0c;说到云端数据&#xff0c;当然要先创建数据库&#xff0c;按照如下方式创建&#xff0c;当然&#xff0c;双击就可添加数据 之后就简单了&#xff0c;在项目的页面里写上这样的查询就ok了&#xff0c;其中ap…

云端数据库审计,你不能不知道的秘密

云端数据安全,是云安全中核心的问题之一。要实现云数据安全,需要从多个角度去努力。对数据访问情况的跟踪记录审计,是云数据安全的基本要求。本文从数据源头——数据库的保护角度,以几个问题的问答方式,分析数据库的安全审计问题。 1.什么是云端数据库? 广义的说,云端数…

建立APICloud云端数据库

在我们平常做项目的过程总是会遇到一个较为苦逼的问题——就像假如你是移动端or网页前端的话&#xff0c;想开发一个可以联网的项目&#xff0c;仍然需要一个专门开发后台的人员来跟你一起合作开发项目&#xff0c;但是&#xff0c;假如你是使用APICloud的话&#xff0c;那你就…

一文看懂阿里云端数据库配置+Navicat premium安装

&#x1f388;写在前文 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是小王&#x1f64b;‍♂️&#x1f4dd; 个人主页&#xff1a;你隔壁的小王&#x1f525;&#x1f389; 欢迎点赞&#x1f44d;收藏⭐️留言&#x1f4dd;&#x1f4e3;专栏&#xff1a;SQL&…

阿里云创建云端数据库

阿里云创建云端数据库 从小白开始创建云端数据库。希望可以帮到大家&#xff08;白嫖一个月&#xff09; 1.浏览器中搜索阿里云&#xff08;https://cn.aliyun.com/&#xff09; 2.依次点击&#xff1a;产品—数据库----云数据库 PolarDB 3.进入云数据库 PolarDB后找到新用户…

微信小程序 - 无法获取云端数据库中的数据的问题(修改云端数据库权限)

小程序中从云端数据库获取不到数据 从云端数据库中取数据 // 使用云数据库 const db wx.cloud.database(); export default{data(){return {shopData:[]}},onLoad(){// 获取集合数据&#xff0c;或获取根据查询条件筛选后的集合数据。db.collection(mycloud).get().then(res…

Auto.js 如何通过云服务器,连接云端数据库读写数据。 可用来做脚本云端自动化等....

一、前情提要 Auto.js与按键精灵功能类似 但更加强大&#xff0c;比如控件操作 &#xff0c;以及调用java插件 扩展性强。 但它们有个共通的缺陷&#xff01;&#xff01; 无法从移动端直接链接数据库 读写数据&#xff0c; 所以需要做一个中转站来传递读写信息。 二、大概原…

JS访问云端数据库小问题之代码不会顺序执行

微信小程序云开发JS访问云端数据库小问题之代码不会顺序执行 用ES6写法的 .then .catch 徽派在后边执行&#xff1a; formSubmit(e) { // 表单提交items e.detail.valuewx.cloud.database().collection(Student)//单条数据查询.where({number: items.number}).get().then(res…

锋云数据服务器管理文件说明书,云端数据库使用说明

NoteExpress提供云端文献库功能了&#xff01;云端文献库会自动将题录、笔记及附件同步到云服务器&#xff0c;便于在不同电脑之间同步您的工作。 登录 使用云端文献库&#xff0c;需要在NoteExpress中登录&#xff0c;建议勾选自动登录。 使用 登录后&#xff0c;在NoteExpres…

(esp32+MQTT+云服务器+MySQL)实现物联网温湿度数据采集到云端数据库MySQL

前言 之前物联网硬件采集数据一直都是通过阿里云实现数据的可视化&#xff0c;没有将硬件采集到的数据存入云数据库&#xff0c;没有进一步利用数据进行操作。 本文一共有五个步骤&#xff1a; 1.esp32通过arduino平台和硬件DHT11温湿度模块采集数据 2.创建EMQ X Cloud MQTT云服…

mysql 数据库迁移到云数据库,从本地MySQL迁移到云数据库为什么是Amazon Aurora?mysql云端数据库...

近两年&#xff0c;随灭云情况的成熟&#xff0c;良多企业的营业都正在向云端迁徙。于是&#xff0c;“云数据库”成为最时髦词汇之一&#xff0c;被AWS、微软、阿里、华为等大厂推崇。那么&#xff0c;对于用户来说&#xff0c;他们若何对待云数据库的成长示状&#xff0c;到底…

使用EMQX搭建的MQTT服务器 如何转发数据并保存到云端数据库?

记录一下自己解决这个问题的方法! 一、技术原理 新建一个转发指定数据的资源接口,然后在规则引擎中设置过滤主题消息的规则,筛选出你所需要主题的消息,设置转发的http接口(URL),http请求选择POST或GET请求,要求是在编写servlet接口时与doPost()、doGet()方法对应。se…

从硬件采集到云端数据库全实现之物联网体温检测系统(ESP32+MQTT+云服务器+MySQL )

前言 学了这么久的物联网&#xff0c;一直停留在硬件层面的数据采集和显示&#xff0c;虽然也用过Ubuntu系统进行过项目开发&#xff08;年初的时候用树莓派完成了口罩识别的项目&#xff09;&#xff0c;也使用过云服务器与硬件简单的MQTT通讯&#xff0c;但是一直没有把两者…

微信小程序云开发:基本介绍及云端数据库的使用

基本介绍 开发者可以使用云开发快速开发小程序、小游戏、公众号网页等&#xff0c;并且原生打通微信开放能力。 发布小程序需要使用云开发。 开发者无需搭建服务器&#xff0c;可免鉴权直接使用平台提供的 API 进行业务开发。 配有云端数据库&#xff0c;与传统数据库相比操…

20210117noteexpress云端数据库经验分享

同步到云端数据库 蒙蔽了&#xff0c;居然要占老子C盘空间 这个 简直银魂不散吧&#xff0c;都删了又要来 貌似把这个附件文件夹从C盘改到其他盘就OK 了 C:\Users\16442\AppData\Roaming\NoteExpress\OnlineDBs 一占用就是几个G的文件夹&#xff0c;草 测试成功&#xff…