遗传算法简单实现

遗传算法:
一种求最大值/最小值近似解的办法。与“梯度下降”、“模拟退火”类似。计算过程如下:

1)选择种群
选择100个左右的x值(即参数值)并进行编码,作为个体, 构成集合C。

2)计算适应度,并淘汰一部分个体。
这里涉及到适应度函数,和选择函数,由自己定义。
适应度函数:a = F( x ), 输入一个个体x,计算其适应度a,计算过程与所求最值有关。
选择函数:C’ = S( C ), 输入原集合,根据适应度决定保留的个体,得到新集合C’。

3)交叉变异
即进行编码互换和编码随机变异两个过程。
编码互换:个体间相互交换部分编码
编码随机变异:个体的编码随机发生变异。
以上两个过程都将产生新的个体,从而得到新种群: C’’ = P( C‘ )。

循环2)3)步骤,直到接近最值。

参考:超详细的遗传算法(Genetic Algorithm)解析

下面以计算函数 y = (x-4)^2在 [-10, 10)范围的最小值为例:
在这里插入图片描述

代码如下:

import numpy as np
import matplotlib.pyplot as plt
import time

p1 = 0.8 #交叉概率
p2 = 0.1 #变异概率


#评价和选择
def choose(C):
    row, col = C.shape
    individuals = []
    for i in range(col):
        individuals.append([C[:, i], (np.sum(C[:, i]) - 4 ) ** 2])
    individuals.sort(key = lambda obj : obj[1])

	#只保留25个个体
    C = np.zeros((10, 25));
    for i in range(25):
        C[:, i] = individuals[i][0]
    
    return C;

#交叉和变异
def produce(C):
    row, col = C.shape
    gen = []
    for i in range(col):
        p = np.random.rand()
        if p <= p1: 
            index = int(np.random.rand() * 25)  """随机选择一个个体"""
            pos = int(np.random.rand() * 10)    """随机选择一个交叉位置"""
            new1 = C[:,i] + 0;
            new2 = C[:, index] + 0;
            temp = new1[pos]
            new1[pos] = new2[pos];
            new2[pos] = temp;
            gen.append(new1);
            gen.append(new2);

    for i in range(col):
        p = np.random.rand()
        if p <= p2:
            pos = int(np.random.rand() * 10); """随机选择一个变异位置"""
            new1 = C[:, i] + 0;
            new1[pos] = - new1[pos] + np.random.rand();
            gen.append(new1)
    #产生新种群
    newC = np.zeros((10, col + len(gen)))
    newC[:, 0:col] = C;
    for i in range(len(gen)):
        newC[:, i + col] = gen[i]

    return newC;


#(1)产生并编码
# 这里产生100个x,每个x范围为[-10, 10)
# 将每个x编码成10个数, 即x = [x1, x2, ... , x10], 因此这里产生1000个随机数
X = (np.random.rand(1000) * 2 - 1).reshape(10, 100);


"""迭代30次"""
for i in range(30):
    X = choose(X)
    X = produce(X)
    
    """画图"""
    sm = np.sum(X, axis = 0);
    np.sort(sm)
    plt.clf()
    plt.xlim(0, 10)
    plt.ylim(-1, 10)
    plt.title("iter=" + str(i + 1) + ", avg = " + str(np.mean(sm)))
    x = np.linspace(-10, 10, 100);
    plt.plot(x, (x - 4)**2)
    plt.scatter(sm, np.zeros((len(sm),)))
    plt.pause(0.03)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值