遗传算法理论

遗传算法是模拟生物演化理论的最优求解算法。生物演化是一种群为基础的,组成种群的单个生物,生物都有过度繁殖的倾向,而种群的可利用的资源是有限的,因此对环境适应度高的、牛B的个体参与繁殖的机会比较多,后代就会越来越多。适应度低的个体参与繁殖的机会比较少,后代就会越来越少。,生物繁殖时会伴随着染色体的重新组合和基因变异,经过长时间的演化,才呈现出现在的生态系统。
简答来说,可分为以下几条:

  • 生物进化的基础是种群
  • 种群都有过度繁殖倾向
  • 繁殖过程中会有染色体交叉组合
  • 繁殖过程中会有基因变异
  • 只有适应环境的个体才具有较多的繁殖机会
    遗传算法也具备这几个特征:即繁殖、变异、重组、选择等,当然遗传算法还有编码和译码的过程。
    繁殖(Crossover):种群中个体复制,适应度高的个体繁殖机会大
    变异(Crossover):种群中某个体的某基因变异,即个体的某一位取反
    变异前:
    000001110000 0 00010000
    变异后:
    000001110000 1 00010000
    重组(Crossover):2条染色体交换部分基因,来构造下一代的2条新的染色体
    重组前:
    00000|011100000000|10000
    11100|000001111110|00101
    重组后:
    00000|000001111110|10000
    11100|011100000000|00101

遗传算法程序示例

关于遗传算法的机理以及相关参考资料很多,这里给出一个基本的程序参考脚本,可以在这个基础上改动使用。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import numpy as np
import random
class Population(object):
    """
    类名:population
    功能:遗传算法类
    参数:popsize 种群大小
        chromlength 字符串长度
        pc 交叉概率
        pm 变异概率
        pop 群体编码
    作者:犇丿灬犇
    """
    def __init__(self,popsize=20,chromlength=10,pc=0.6,pm=0.001):
        self._popsize=popsize
        self._chromlength=chromlength
        self._pc=pc
        self._pm=pm
        self._pop=self.__popinit()
        #np.around(np.random.random(size=(popsize,chromlength)))

    def __popinit(self):
        """
        函数名:__popinit 私有函数
        功能:种群编码
        返回值:行为种群数量,列为字符串长度的数列
        """
        pop=np.random.random(size=(self._popsize,self._chromlength))
        pop=np.around(pop)
        return pop
    def decodebinary(self,pop):
        """
        函数名:decodebinary 
        功能:将二进制数转化为十进制
        返回值:十进制数
        """
        px, py = pop.shape
        pop1 = []
        for i in range(py):
            mid_var=2**(py-i-1)*pop[:,i]
            pop1.append(mid_var)
        pop1= np.array(pop1)
        pop2=sum(pop1)
        return pop2
    def decodechrom(self,pop,spoint,length):
        """
        函数名:decodechrom
        功能:取字符串中几位转为十进制
        返回值:十进制数
        """
        py=self._chromlength
        try:
            pop1=pop[:,spoint:spoint+length]
            pop2 = self.decodebinary(pop1)
        except:
            pop1=pop[spoint:spoint+length]
            for i in range(py):
                pop1[i] = 2 ** (py - i - 1) * pop[i]
            pop2 = sum(pop1)



        return pop2
    def crossover(self,pop):
        """
        函数名:crossover
        功能:交叉
        返回值:交叉后种群
        """
        px, py = pop.shape
        newpop=np.ones(shape=(px,py))

        for i in range(px-1):
            if i%2:
                mid_var = random.random()
                if mid_var<self._pc:
                    cpoint=round(mid_var*py)
                    '''
                    col_var=np.array([pop[i,:cpoint],
                                          pop[i+1,cpoint:py]])
                    col_var.resize(py)
                    print(col_var)
                    '''
                    col_var=np.zeros(py)
                    col_var[:cpoint]=pop[i,:cpoint]
                    col_var[cpoint:py]=pop[i+1,cpoint:py]
                    newpop[i,:]=col_var
                    '''
                    col_var=np.array([pop[i+1,:cpoint],
                                          pop[i,cpoint:py]])
                    col_var.resize(py)
                    '''
                    col_var[:cpoint] = pop[i+1, :cpoint]
                    col_var[cpoint:py] = pop[i , cpoint:py]
                    newpop[i+1,:]=col_var
                else:
                    newpop[i,:]=pop[i,:]

                    newpop[i+1, :] = pop[i+1, :]
        return newpop
    def mutation(self,pop):
        """
        函数名: mutation
        功能:变异
        返回值:变异后种群
        """
        px, py = pop.shape
        newpop = np.ones(shape=(px, py))
        for i in range(px):
            mid_var = random.random()
            if mid_var<self._pm:
                mpoint=round(mid_var*py)
                if mpoint<=0:
                    mpoint=1
                newpop[i,:]=pop[i,:]
                if newpop[i,mpoint]==0:
                    newpop[i, mpoint]=1
                elif newpop[i,mpoint]==1:
                    newpop[i, mpoint]=0

            else:
                newpop[i, :] = pop[i, :]
        return newpop
    def selection(self,pop,fitvalue):
        """
        函数名: selection
        功能:   选择复制 
        返回值:  返回新种群
        """
        totalfit=sum(fitvalue)
        fitvalue=fitvalue/totalfit
        fitvalue=np.cumsum(fitvalue)
        px, py = pop.shape
        ms=np.random.random(px)
        ms=np.sort(ms)
        fitin=0
        newin=0
        newpop = np.ones(shape=(px, py))
        while newin<px:
            if ms[newin]<fitvalue[fitin]:
                newpop[newin]=pop[fitin]
                newin+=1
            else:
                fitin+=1
        return newpop

    def best(self, pop, fitvalue):
        """
        函数名: best
        功能:   求适应度最大的值
        返回值:  最大值适应值,最大个体
        """
        px, py = pop.shape
        bestindividual=pop[0,:]
        bestfit=fitvalue[0]
        for i in range(px):
            if fitvalue[i]>bestfit:
                bestfit=fitvalue[i]
                bestindividual=pop[i,:]
        return bestfit,bestindividual

应用实例

求函数


y=10×sin(5×x)+7×cos(4×x) y = 10 × sin ⁡ ( 5 × x ) + 7 × cos ⁡ ( 4 × x )

的最大值。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
from Genetic_algorithm import *
from math import *
import numpy as np
def calfitvalue(objvalue):
    Cmin=0
    x=objvalue.size
    fitvalue = np.zeros(x)
    for i in range(x):
        if objvalue[i]+Cmin>0:
            temp=objvalue[i]+Cmin
        else:
            temp=0
        fitvalue[i]=temp
    return fitvalue
def calobjvalue(c_pop):
    temp1=c_pop.decodechrom(c_pop._pop,0,c_pop._chromlength)
    x=temp1*10/1023

    obvalue=10*np.sin(5*x)+7*np.cos(4*x)
    #obvalue = -x**2+10*x+8
    return obvalue
if __name__ == '__main__':
    c_pop=Population(popsize=20,chromlength=10,pc=0.8,pm=0.001)
    iter_i=100
    x = np.zeros(iter_i)
    y=np.zeros(iter_i)
    for i in range(iter_i):
        objvalue=calobjvalue(c_pop)
        fitvalue =calfitvalue(objvalue)
        newpop=c_pop.selection(c_pop._pop,fitvalue)
        newpop=c_pop.crossover(newpop)
        newpop=c_pop.mutation(newpop)
        bestfit,bestindividual=c_pop.best(c_pop._pop,fitvalue)
        #print(bestindividual,bestfit)
        x[i]=c_pop.decodechrom(bestindividual,0,c_pop._chromlength)*10/1023
        y[i]=bestfit
        c_pop._pop=newpop
    print(x,y)
    print(max(y))

结果

遗传算法进行机器学习模型参数优化python_遗传算法

MATLAB工具包

matlab提供遗传算法工具包。曾经用它做过多智能体预测控制算法参数配置。要求矩阵


Ω=(AD+Bkyec+BakcCD−JN⊗C1BkzI)(1491) (1491) Ω = ( A D + B k y e c + B a k c B k z C D − J N ⊗ C 1 I )


的特征值在单位圆内。其中



AD=diag(A1,A2...AN)(1492) (1492) A D = d i a g ( A 1 , A 2 . . . A N )



Bkyec=diag(B1(Ky1+l11Ke1)C2,B2(Ky2+l22Ke2)C2,...,BN(KyN+lNNKeN)CN)(1493) (1493) B k y e c = d i a g ( B 1 ( K 1 y + l 11 K 1 e ) C 2 , B 2 ( K 2 y + l 22 K 2 e ) C 2 , . . . , B N ( K N y + l N N K N e ) C N )



Bakc=(B1(Ky1+l11Ke1)C2,B2(Ky2+l22Ke2)C2,...,BN(KyN+lNNKeN)CN)(1494) (1494) B a k c = ( B 1 ( K 1 y + l 11 K 1 e ) C 2 , B 2 ( K 2 y + l 22 K 2 e ) C 2 , . . . , B N ( K N y + l N N K N e ) C N )



Bakc=⎛⎝⎜⎜⎜⎜⎜a11B1Ke1C1a21B2Ke2C1⋮aN1BNKeNC1a12B1Ke1C2a22B2Ke2C2⋮aN2BNKeNC2⋯⋯⋱⋯a1NB1Ke1CNa2NB2Ke2CNaNNBNKeNCN⎞⎠⎟⎟⎟⎟⎟(1495) (1495) B a k c = ( a 11 B 1 K 1 e C 1 a 12 B 1 K 1 e C 2 ⋯ a 1 N B 1 K 1 e C N a 21 B 2 K 2 e C 1 a 22 B 2 K 2 e C 2 ⋯ a 2 N B 2 K 2 e C N ⋮ ⋮ ⋱ a N 1 B N K N e C 1 a N 2 B N K N e C 2 ⋯ a N N B N K N e C N )



Bkz=diag(B1Kz1,B2Kz2,...,BNKzN)(1496) (1496) B k z = d i a g ( B 1 K 1 z , B 2 K 2 z , . . . , B N K N z )



CD=diag(C1,C2...CN)(1497) (1497) C D = d i a g ( C 1 , C 2 . . . C N )



JN=[[0,1,...,1]T,0n×(n−1)](1498) (1498) J N = [ [ 0 , 1 , . . . , 1 ] T , 0 n × ( n − 1 ) ]

具体数值见参考文献[1],具体做法,如果矩阵Ω Ω 的特征值都在单位圆内,则绝对值最大的特征值应该也在单位圆内,只要不断优化其最大绝对值特征值即可,代码如下:

计算矩阵Ω Ω :

A_W=[0 1 1; 1 0 1; 1 1 0];
A1=[1.7 -1.3;1.6 -1.8];
B1=[1.0;2.0];
C1=[1.0 0.3];

A2=[1.8 -1.4;1.8 -1.9];
B2=[1.7 ;3.4];
C2=[0.7 0.2];

A3=[1.4 -1.1;1.3 -1.5];
B3=[0.8;1.6];
C3=[1.1 0.4];
T=0.1;
% [A1,B1]=c2d(A1,B1,T);
% [A2,B2]=c2d(A2,B2,T);
% [A3,B3]=c2d(A3,B3,T);
% z_root=[0.5-0.5i 0.5+0.5i 0.7+0.1i 0.7-0.1i 0.6+0.2i 0.6-0.2i -0.3+0.3i -0.3-0.3i];
% expand((z-z_root(1))*(z-z_root(2))*(z-z_root(3))*(z-z_root(4))*(z-z_root(5))*(z-z_root(6))*(z-z_root(7))*(z-z_root(8)))
AD=blkdiag(A1,A2,A3);
Bkyec=blkdiag(B1*(ky1+lii(A_W,1)*ke1)*C1,B2*(ky1+lii(A_W,2)*ke1)*C2,B3*(ky1+lii(A_W,3)*ke1)*C3);
Bakc=[A_W(1,1)*B1*ke1*C1 A_W(1,2)*B1*ke1*C2 A_W(1,3)*B1*ke1*C3;A_W(2,1)*B2*ke1*C1 A_W(2,2)*B2*ke1*C2 A_W(2,3)*B2*ke1*C3;A_W(3,1)*B3*ke1*C1 A_W(3,2)*B3*ke1*C2 A_W(3,3)*B3*ke1*C3];
Bkz=blkdiag(B1*kz1,B2*kz1,B3*kz1);
CD=blkdiag(C1,C2,C3);
JN=[[0;1;1],zeros(3,2)];
Omg=[AD+Bkyec+Bakc Bkz;CD-kron(JN,C1) eye(3)];

%  Root=eig(Omg)
function y=lii(A,i)
    S=sum(A,2);
    y=-S(i);
end

遗传算法

clc
clear
NIND=40;        %个体数目(Number of individuals)
MAXGEN=50;      %最大遗传代数(Maximum number of generations)
PRECI=20;       %变量的二进制位数(Precision of variables)
GGAP=0.9;       %代沟(Generation gap)
trace=zeros(4, MAXGEN);                        %寻优结果的初始值
FieldD=[PRECI PRECI PRECI;-1 -1 -1;1 1 1;1 1 1;0 0 0;1 1 1;1 1 1];                      %区域描述器(Build field descriptor)表示染色体个体到实际的数字的映射关系
Chrom=crtbp(NIND, PRECI*3);                      %初始种群
gen=0;                                         %代计数器
YZE=bs2rv(Chrom, FieldD);             %计算初始种群的十进制转换
Y=YZE(:,1);
Z=YZE(:,2);
E=YZE(:,3);
ObjV=zeros(40,1);
%%%%%%计算模最大的特征值%%%%%%%%%%%%%%%%%%%%
for i=1:40
    ky1=Y(i);
    kz1=Z(i);
    ke1=E(i);
    cal
    Root=eig(Omg);
    Mroot=abs(Root);
    ObjV(i)=max(Mroot);
end
%ObjV=-variable.*(variable - 4);        %计算目标函数值
while gen<MAXGEN
   FitnV=ranking(ObjV);     %分配适应度值(Assign fitness values)         
   SelCh=select('sus', Chrom, FitnV, GGAP);               %选择
   SelCh=recombin('xovsp', SelCh, 0.7);                   %重组
   SelCh=mut(SelCh);                                      %变异
   YZE=bs2rv(SelCh, FieldD); %子代个体的十进制转换
   Y=YZE(:,1);
   Z=YZE(:,2);
   E=YZE(:,3);
   ObjVSel=zeros(NIND*GGAP,1);
   for i=1:NIND*GGAP
        ky1=Y(i);
        kz1=Z(i);
        ke1=E(i);
        cal
        Root=eig(Omg);
        Mroot=abs(Root);
        ObjVSel(i)=max(Mroot);
    end
   %variable=bs2rv(SelCh, FieldD); %子代个体的十进制转换
   %ObjVSel=-variable.*(variable - 4);%计算子代的目标函数值
   [Chrom ObjV]=reins(Chrom, SelCh, 1, 1, ObjV, ObjVSel);
                                          %重插入子代的新种群
   variable=bs2rv(Chrom, FieldD);
   gen=gen+1;                            %代计数器增加
   %输出最优解及其序号,并在目标函数图像中标出,Y为最优解,I为种群的序号
   [Y, I]=min(ObjV);%hold on;
   %plot(variable(I), Y, 'bo');
   fprintf('%f,%f,%f   %f\n',variable(I,1),variable(I,2),variable(I,3),Y);
   trace(1, gen)=min(ObjV);             %遗传算法性能跟踪
   trace(2, gen)=sum(ObjV)/length(ObjV);
end
variable=bs2rv(Chrom, FieldD);            %最优个体的十进制转换
%hold on, grid;
%plot(variable,ObjV,'b*');
figure(1);
plot(trace(1,:));
hold on;
plot(trace(2,:),'-.');grid
legend('解的变化','种群均值的变化')

结果

遗传算法进行机器学习模型参数优化python_遗传算法_02