El concepto de algoritmo genético e implementación de python.

    El algoritmo genético es un algoritmo inteligente muy clásico, utilizado principalmente para resolver problemas de optimización. Este artículo presenta principalmente brevemente algunos principios y, al mismo tiempo, brinda una plantilla basada en Python para resolver problemas de optimización dentro de números reales.

Referencias en este artículo:

Principio: Introducción detallada a los algoritmos genéticos: se busca programador

una breve introducción

    El algoritmo genético se refiere a la genética en biología. Primero, se generan varias poblaciones y hay algunos individuos en ellas, es decir, soluciones. La aptitud se establece para diferentes soluciones, y los operadores se utilizan para generar nuevas soluciones. Los genes excelentes se encuentran continuamente heredado en la población, y finalmente se logra la optimización.

    Entonces, al final, debe haber varios grupos , y los individuos dentro son todos relativamente buenos, y los que no son buenos serán eliminados.

Conceptos relacionados

    Los siguientes son algunos conceptos básicos, me refiero al enlace mencionado anteriormente, pero solo extraje algunos y tomé algunas notas, puedes entender los detalles por ti mismo.

① Cromosoma: los cromosomas también se pueden llamar individuos de genotipo (individuos), un cierto número de individuos forman una población, y el número de individuos en la población se denomina tamaño de la población.

② Cadena de bits (Bit String): la representación de un individuo. Corresponde al cromosoma en genética.

③ Gen (Gen): Un gen es un elemento en un cromosoma, que se utiliza para representar las características de un individuo. Por ejemplo, si hay una cadena (es decir, un cromosoma) S=1011, los cuatro elementos 1, 0, 1 y 1 se denominan genes.

④ Valor de la característica (Característica): Cuando se usa una cadena para representar un número entero, el valor de la característica del gen es consistente con el peso del número binario; por ejemplo, en la cadena S=1011, el 1 en la posición del gen 3 tiene un valor de característica del gen de 2; la posición del gen 1 de 1, su valor propio del gen es 8.

⑤ Fitness (Fitness): La adaptabilidad de cada individuo al entorno se denomina fitness. Para reflejar la adaptabilidad de los cromosomas, se introduce una función que puede medir cada cromosoma en el problema, llamada función de aptitud. Esta función se suele utilizar para calcular la probabilidad de que un individuo sea utilizado en un grupo.

⑥ Genotipo (Genotype): o tipo genético, se refiere al genoma para definir las características genéticas y el rendimiento. Para cadenas de bits en GA.

⑦ Fenotipo: Las características de desempeño del genotipo de un organismo en un ambiente específico. Corresponde a los parámetros decodificados de la cadena de bits en GA.

El cromosoma es un individuo y, en un cálculo específico, es una solución en un espacio n-dimensional.

Una cadena de bits es una representación codificada de un individuo

Un gen es una característica contenida en un cromosoma, es decir, un bit codificado

El valor característico indica el significado de este bit bajo esta regla de codificación

La aptitud indica la probabilidad de ser utilizada en el proceso de cálculo, que generalmente es la situación de alta calidad de la solución.

cadena codificada de representación de genotipo

El fenotipo representa el parámetro decodificado.

pasos genéticos

  1. Reglas de codificación y decodificación

    Los dos procesos son procesos inversos. La codificación es decodificar una secuencia en una secuencia, generalmente usando codificación binaria , y la decodificación es a la inversa.

  2. generar valor inicial

    Este proceso es para generar las variables requeridas.

    Establezca el álgebra de evolución máxima T, el tamaño de la población M, la probabilidad de cruce Pc, la probabilidad de mutación Pm, genere aleatoriamente M individuos como la población inicial P0

  3. cambio de condición física

    Se utiliza principalmente para cambiar la aptitud de cada individuo para evitar que la aptitud sea igual, y entonces no habrá supervivencia del más apto.

    En términos generales, se refiere a las diferentes etapas de la iteración del algoritmo. Al cambiar adecuadamente la aptitud del individuo, puede evitar el debilitamiento de la competencia causado por la aptitud similar entre los grupos y hacer que la población converja a la solución óptima local. .

    Hay muchas formas, lineal no lineal...

  4. operador genético

    1. elegir

      La selección consiste en seleccionar una población excelente en una población antigua (que incluye múltiples individuos) y seleccionar individuos excelentes para reproducirse en ella, a fin de lograr una excelente natalidad y una excelente fertilidad.

      Comúnmente se usa la ruleta , es decir, la probabilidad de selección individual es el fitness del individuo dividido por el fitness total del grupo, si el fitness es alto, la probabilidad de ser seleccionado es alta y se puede obtener una descendencia excelente.

    2. cruz

      El cruce es generar algunos intercambios entre dos cromosomas, para completar la operación de generar nuevas soluciones, el cruce de un solo punto de uso común y otros ...

    3. Mutaciones

      La mutación significa que tiene cierta probabilidad de cambiarse a sí mismo, como cambiar un poco de binario, lo que también produce una nueva solución.

                Hay tres tipos de este proceso, que se utilizan principalmente para generar nuevas soluciones, liberar diferentes juntos o generar nuevas soluciones por sí mismo.A su vez, estos procesos también se pueden presentar de muchas maneras , no necesariamente limitadas a las mencionadas. , pero también para diferentes problemas Habrá diferentes soluciones.

punto importante

El algoritmo genético y generalmente tiene cuatro parámetros operativos que deben establecerse de antemano, a saber

M : tamaño de la población

T : Álgebra de evolución de terminación del algoritmo genético

Pc: Probabilidad de cruce, generalmente 0.4~0.99

Pm: probabilidad de mutación, generalmente 0.001~0.1

Código

     La siguiente es la implementación del código específico. El método de codificación que utilizo es generar directamente números de punto flotante . La operación de selección retiene una proporción establecida de individuos cada vez. La operación de cruce selecciona dos conjuntos de parámetros cada vez para intercambiar parámetros con un cierto probabilidad de generar nuevos individuos Operación de mutación Para cada valor, revaluar un parámetro con una cierta probabilidad para simular la operación de mutación.

        Hay tres grupos de parámetros registrados, que son la aptitud óptima de cada ronda, el resultado óptimo y los parámetros óptimos correspondientes, y el dibujo final.  

el código

import warnings
from math import log2
import matplotlib.pyplot as plt
import pandas as pd
warnings.filterwarnings('ignore')
import heapq
import itertools
from random import randint, random, uniform
import numpy as np

def select_op(fitness,op,select_rate,best_keep_rate):
    ans_list = []
    # 先选择保留部分
    keep_num = int(best_keep_rate * len(op)*select_rate)
    index_list = list(map(list(fitness).index, heapq.nlargest(keep_num, fitness)))
    for index in index_list:
        ans_list.append(op[index])
    # 保留的
    p =fitness/sum(fitness) # 计算每个个体占比
    p = np.array(list(itertools.accumulate(p))) # 计算累积密度函数
    # 采用轮盘赌方式选择
    for i in range(int(len(op)*select_rate)-keep_num): # 再产生这么多个
        r = random()
        index = np.argmax(p>r) # 找到第一个大于随机的值
        if index == 0 and p[0] < r: # 可能第一个并不大于这个数,可能是没找到,也是返回0
            continue
        ans_list.append(op[index])
    return ans_list

def cross_op(op,cross_rate,num):
    ans_list = []
    num_op = len(op) # 当前数量
    while num > 0:
        max_ = 5 # 最多找5次,如还是相同就用相同的,就说明这个基因很多
        while max_>0:
            n1 = randint(0,num_op-1)
            n2 = randint(0,num_op-1) # 不允许相同个体杂交
            max_ -= 1
            if op[n1] != op[n2]:
                break
        father = op[n1]
        mother = op[n2]
        if random() < cross_rate:
            location = randint(0,len(father)-1) # 随机产生交叉位置
            tmp = father[0:location+1] + mother[location+1:len(father)]
            ans_list.append(tmp)
            num -= 1
    return ans_list

def variation_op_10(new_op,variation_rate,low,high):
    for index,it in enumerate(new_op): # 一定概率变异
        if random() < variation_rate:
            location = randint(0, len(it) - 1)
            it = uniform(low[location],high[location])  # 随机产生数字
            new_op[index][location] = it
    return new_op


# 生成随机初始值
def ini_op(low_paras, high_paras, max_op_size):
    # 计算出每个参数应该占的位数
    st = 0
    ed = -1  # 为了保证st为-1
    para_range = []
    for i in range(len(low_paras)):
        low_it = low_paras[i]
        high_it = high_paras[i]
        num = int(log2(high_it - low_it + 1)) + 1  # 计算二进制位数
        st = ed + 1
        ed += num
        para_range.append((st, ed))  # 加入每个参数的范围,包括起始点和终点(在序列中的)
    op = []
    for i in range(max_op_size):
        tmp = [uniform(low_paras[k], high_paras[k]) for k in range(len(low_paras))]
        op.append(tmp)
    return op, para_range


def cal_fitness(op):
    ans_list = np.zeros((len(op), 1))
    for index, it in enumerate(op):  # 取出每个参数对应的数字
        if un_suit(it):  # 如果不满足约束条件
            ans_list[index] = 1000000000  # 给一个很大的值,最后要统一处理
            continue
        y = func(it)
        ans_list[index] = y
    ans_list = func_fitness(ans_list)
    return ans_list


# 自定义适应度函数计算
def func_fitness(ans_list):
    if model_dir == 'min':
        for index, it in enumerate(ans_list):
            ans_list[index] = 1 / it
    return ans_list


def un_suit(x):  # 定义参数不满足的约束条件
    # 参数范围约束
    for i in range(len(low_paras)):
        if x[i] < low_paras[i] or x[i] > high_paras[i]:
            return True
    # ...自行添加
    return False


# 定义计算函数
def func(x):
    return x[0] ** 2 + x[1] ** (3 / 2) + x[2] + x[3] ** (1 / 2)


# ---配置参数
paras_name = ['x1', 'x2', 'x3', 'x4']
high_paras = [60,60,40,30]  # 参数范围上限
low_paras = [10, 21,3,10]  # 参数范围下限
model_dir = 'min' # max表示越大越好,min表示越小越好
# ---配置遗传算法参数
max_op_size = 200  # 种群大小,这里也是考虑一个种群的优化问题
max_epochs = 200  # 迭代次数,也就是进化次数
cross_rate = 0.8  # 杂交率,选出两个个体之后以这个概率杂交(各取部分基因产生后代)
select_rate = 0.4  # 选择率,也就是选择保留占总的个数(这里实际是利用随机数抽取,而不是按照排序)
variation_rate = 0.1  # 变异率,产生新的个体以这个概率变异(一位重新赋值)
best_keep_rate = 0.1  # 每次选择必定保留的比例(排序靠前的部分)
# ---遗传算法求解
if __name__ == '__main__':
    data = np.array(pd.read_excel('../static/test.xlsx'))  # 读入数据
    op, para_range = ini_op(low_paras, high_paras, max_op_size)  # 初始化种群,返回种群和每个参数的位置范围[(l1,r1),(l2,r2)...]
    best_ans_history = []  # 记录最优答案历史
    best_para_history = []  # 记录最优对应参数
    best_fitness_history = []  # 记录最优适应度
    for i in range(1, max_epochs + 1):
        if i % 50 == 0:
            print('epoch:', i)
        # 计算适应度
        fitness = cal_fitness(op)  # 计算适应度
        index = np.argmax(np.array(fitness)) # 为什么已经保留了最佳适应度,最后的图还是会上下跳动
        best_fitness_history.append(fitness[index])
        best_para_history.append(op[index])
        best_ans_history.append(func(op[index]))
        op = select_op(fitness, op, select_rate, best_keep_rate)  # 选择个体,选择比例为
        # 交叉,产生后代
        new_op = cross_op(op, cross_rate, max_op_size - len(op))  # 后一个参数为需要产生的个数
        # 变异
        new_op = variation_op_10(new_op, variation_rate,low_paras,high_paras)  # 变异
        op.extend(new_op)  # 把新的个体加入群落

    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
    index = np.argmax(best_ans_history)
    print('最优结果为:', best_ans_history[index])
    print('最优参数如下')
    for name,index in zip(paras_name,best_para_history[index]):
        print('{}={}'.format(name,index))
    plt.plot(best_fitness_history, label='适应度曲线变化')
    plt.legend()
    plt.show()

ejemplo

Tomemos una función monótona como ejemplo:

x1 ** 2 + x2 ** (3/2) + x3 + x4 ** (1/2)

El rango de ajuste es el siguiente:

high_paras = [60,60,40,30]  # 参数范围上限
low_paras = [10, 21,3,10]  # 参数范围下限

Deténgase después de doscientas iteraciones y emita el resultado.

最优结果为: 262.08470155055244
最优参数如下
x1=10.92155546612619
x2=22.81339324058242
x3=30.588146368196167
x4=10.573758934746433

Salida de la curva de cambio de aptitud óptima:
 

Supongo que te gusta

Origin blog.csdn.net/weixin_60360239/article/details/130244042
Recomendado
Clasificación