进化算法——遗传算法 使用Geatpy库实现

进化算法——遗传算法 使用Geatpy库实现

  • Geatpy
    • 种群初始化
      • Example
    • 进化迭代相关的函数
    • 选择 ea.selecting()
      • Example
    • 重组 recombin()
    • 突变 ea.mutate()
    • 数据可视化
  • 实验实例
    • 新建种群
    • 选择
    • 交叉
    • 变异
    • 整合数据
    • 重新计算适应度值
    • 绘图,保存
    • 写成了一个class
  • 参考文章及Blog

Geatpy

import geatpy as ea
import numpy as np

种群初始化

  • crtfld (生成译码矩阵,俗称“区域描述器”)
  • crtbp (创建二进制种群染色体矩阵)
  • crtip (创建元素是整数的种群染色体矩阵)
  • crtpp (创建排列编码种群染色体矩阵)
  • crtrp (创建元素是实数的种群染色体矩阵)
  • meshrng (网格化决策变量范围)
help(ea.crtfld)
Help on cython_function_or_method in module crtfld:crtfld(Encoding, varTypes, ranges, borders=None, precisions=None, codes=None, scales=None)crtfld : function - 译码矩阵生成函数描述:该函数根据输入的参数生成译码矩阵FieldD或FieldDR。语法:当Encoding为'RI'或'P'时:FieldDR = crtfld(Encoding, varTypes, ranges, borders)FieldDR = crtfld(Encoding, varTypes, ranges, borders, contraction)当Encoding为'BG'时:FieldD = crtfld(Encoding, varTypes, ranges, borders, precisions)FieldD = crtfld(Encoding, varTypes, ranges, borders, precisions, codes)FieldD = crtfld(Encoding, varTypes, ranges, borders, precisions, codes, scales)输入参数:Encoding : str   - 染色体编码方式,'BG':二进制/格雷编码;'RI':实整数编码,即实数和整数的混合编码;'P':排列编码。相关概念:“实值编码”包含实整数编码和排列编码,它们共同的特点是染色体不需要解码即可直接表示对应的决策变量。"实整数"指的是种群染色体既包含实数的小数,也包含实数的整数。varTypes : array - 连续或离散标记,0表示该种群染色体解码后的对应的决策变量是连续的;1表示该种群染色体解码后的变量是离散的。当变量是离散时,该函数会对borders标记为0的变量的范围往里收缩并取整,同时对其他非整数范围进行向里取整,最后把borders元素全设为1。例如:若varTypes=[0, 1, 1],表示有3个变量,第1个变量是实数,第2、3个变量是整数。此时若有:ranges=[[1.1, 2, 3.1],[3,   4, 5]]borders = [[1, 0, 1],[1, 1, 1]]则ranges会被修正为[[1.1, 3, 4],[3, 4, 5]]borders会被修正为:[[1, 1, 1],[1, 1, 1]]注意:'P'(排列编码)时,会无条件地会把varTypes的元素设置成全为1。ranges  : array  - 代表自变量的范围矩阵,要求上界必须大于下界。例如:[[1, 2, 3],[3, 4, 5]]表示有3个决策变量,其范围分别是1-3, 2-4, 3-5。borders : list - (可选参数)代表是否包含变量范围的边界,为1代表决策变量的范围包含该边界,当为None时,默认设置为全是1的矩阵。例如:[[1, 0, 1],[0, 1, 1]]表示上面的三个决策变量的范围分别是:[1, 3)、(2, 4]、[3, 5]。contraction : list - (可选参数)代表决策变量的“边界收缩率”,其元素必须不小于1。当不含边界时,变量范围会往里收缩0.1^contraction,最后把borders元素全设为1,例如:ranges=[[1, 2, 3],[3, 4, 5]]borders = [[1, 0, 1],[0, 1, 1]]此时若contraction为[1, 1, 1],则ranges会被修正为[[1, 2.1, 3],[2.9, 4, 5]]borders会被修正为:[[1, 1, 1],[1, 1, 1]]注:contraction仅在Encoding为'RI'时有效,当contraction缺省或为None时,默认它为元素全为4的列表。当Encoding为'BG'时,本函数的第四个参数的含义将不再是contraction而是precisions。precisions : list - (可选参数)代表决策变量的二进制/格雷编码精度(仅在Encoding为'BG'时有效),precision的元素必须不小于0。如等于4,表示对应的决策变量的编码可以精确到小数点后4位。当precisions参数缺省或为None时,默认precision为元素全为4的列表。但当对应的决策变量为整数时,即便传入precisions,但不会产生作用,这是因为整数的二进制/格雷码编码不需要用到精度。例如varTypes=[0, 1, 1],表示有3个变量,第1个变量是实数,第2、3个变量是整数,此时若precisions=[4,5,5],则只有第1位是起作用的。codes  : list  -(可选参数)代表变量的编码方式,(0:binary | 1:gray),默认采用二进制编码。该参数在Encoding为'BG'时使用。scales : list  - (可选参数)指明每个变量在解码时使用对数还是算术刻度(仅在Encoding为'BG'时有效),0为使用算术刻度,1为使用对数刻度,默认采用算术刻度,当采用对数刻度时,决策变量的范围不能包含0。类似于precisions,scales仅对于varTypes中元素为0对应的变量起作用,这同样是因为整数的二进制/格雷码编码不需要采用对数刻度进行变换。输出参数:FieldD : array  - 二进制/格雷码种群译码矩阵,Encoding为'BG'时返回的是这种结构的译码矩阵。它是描述种群每个个体的染色体长度和如何解码的矩阵,它有以下结构:[lens;           每个决策变量编码后在染色体中所占的长度。lb;             指明每个变量使用的下界。ub;             指明每个变量使用的上界。codes;  (0:binary     | 1:gray) 指明子串是怎么编码的,0为标准二进制编码,1为格雷编码。scales;   (0: rithmetic | 1:logarithmic) 指明每个子串是否使用对数或算术刻度,1为使用对数刻度,0为使用算术刻度。lbin;           (0:excluded   | 1:included)。ubin;           (0:excluded   | 1:included)。varTypes] (0:continued  | 1:discrete)。lbin和ubin指明范围中是否包含每个边界。lbin=0或ubin=0,表示范围中不包含相应边界。lbin=1或ubin=1,表示范围中包含相应边界。或FieldDR : array - 实值编码种群的译码矩阵,Encoding为'RI'或'P'时返回的是这种结构的译码矩阵。[lb;             指明每个变量使用的下界。ub;             指明每个变量使用的上界。varTypes] (0:continued | 1:discrete)。注意:1.参数codes和scales是在当Encoding为'BG'时才起作用的,因此当Encoding为'RI'或'P'时,codes和scales就算赋值也不会起作用。2.本函数会根据borders及边界收缩率对范围进行相应的调整,因此得到的范围可能会跟原来的ranges不一致,可使用print函数输出译码矩阵查看。Created on Sat Jun 30 10:18:01 2018@author: jazzbinChanged on Sat Jul 13 20:15:01 2019@author: jazzbin
help(ea.crtip)
Help on built-in function crtip in module crtip:crtip(...)crtip : function - (Create Integer Points)创建一个整数值种群染色体矩阵描述:该函数随机生成一个给定了大小和结构的整数型种群染色体矩阵。语法:Chrom = crtip(Nind, FieldDR)Chrom = crtip(Nind, FieldDR, Parallel)输入参数:Nind    : int   - 表示种群的个体数FieldDR : array - 实值种群译码矩阵,Encoding为'RI'或'P'时使用的是这种结构的译码矩阵。[lb;               指明每个变量使用的下界。ub;               指明每个变量使用的上界。varTypes] (0:continued | 1:discrete)。注意:传入该函数的FieldDR中的varTypes是无用参数,因为该函数只生成元素是整数的染色体矩阵。Parallel : bool  - (可选参数)表示是否采用并行计算,缺省或为None时默认为False。输出参数:Chrom    : array - 一个以种群个体数为行数、以染色体长度为列数的元素为随机整数值的矩阵。Created on Sun July 1 13:01:23 2018@author: jazzbin

Example

'''定义参数'''
MAXGEN = 50
maxormins = -1 #表示目标函数最小最大化标记,1表示最小化,-1表示最大化
recombine_rate = 0.7
mut_rate = 0.05
Nind = 10
num_hidden_neurons = 6
Encoding = "RI"
'''边界定义'''
ub_hidden_n = [1024] * num_hidden_neurons
lb_hidden_n = [32] * num_hidden_neuronsub_lr = [1000]
lb_lr = [1]ub_batch_size = [2]
lb_batch_size = [1]
'''生成需要的ranges, varTypes, borders等'''
ub = np.hstack((ub_hidden_n, ub_lr, ub_batch_size))
lb = np.hstack((lb_hidden_n, lb_lr, lb_batch_size))
ranges = np.vstack((lb, ub))
varTypes = np.ones(num_hidden_neurons + 2)
borders = np.ones((2, num_hidden_neurons + 2))
'''生成译码矩阵FieldDR'''
FieldDR = ea.crtfld(Encoding, varTypes, ranges, borders)
FieldDR
array([[3.200e+01, 3.200e+01, 3.200e+01, 3.200e+01, 3.200e+01, 3.200e+01,1.000e+00, 1.000e+00],[1.024e+03, 1.024e+03, 1.024e+03, 1.024e+03, 1.024e+03, 1.024e+03,1.000e+03, 2.000e+00],[1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 1.000e+00,1.000e+00, 1.000e+00]])
'''生成种群Chrom'''
Chrom = ea.crtip(Nind, FieldDR) #crtip (创建元素是整数的种群染色体矩阵)
Chrom
array([[ 554,  437,  100,  401,  908,  653,  866,    1],[ 746,  410,  992,   55,  101,  456,  626,    1],[ 391,  409,  388,  975,  899,  897,  660,    1],[ 469,  771,  993,  760, 1002,  624,  972,    2],[  36,   72,  900,  912,  694,  767,  960,    1],[ 153,  951,  439,  222,  383,   67,  226,    2],[ 444,  612,  692,  319,  484,  354,  482,    2],[ 101,  478,  657,   79,   77,  629,  551,    1],[ 670,  454,  962,  339,  196,  922,  697,    1],[ 849,  137,  507,  207,  172,  731,  893,    2]], dtype=int32)

进化迭代相关的函数

当完成了种群染色体的初始化后,就可以进行进化迭代了。这部分是在进化算法模板里调用。

迭代过程中包括:

  • 调用ranking 或scaling 等计算种群适应度。
  • 调用selecting 进行选择操作(也可以直接调用低级选择函数)。
  • 调用recombin 进行重组操作(也可以直接调用低级重组函数)。
  • 调用mutate 进行变异操作(也可以直接调用低级变异函数)。

选择 ea.selecting()

  • dup (Duplication,基于适应度排序的直接复制选择)
  • ecs (Elite Copy Selection,精英复制选择)
  • etour (精英保留锦标赛选择)
  • otos (One-to-One Survivor Selection,一对一生存者选择)
  • rcs (Random Compensation Selection,随机补偿选择)
  • rps (Random Permutation Selection,随机排列选择)
  • rws (Roulette Wheel Selection,轮盘赌选择)
  • sus (Stochastic Universal Sampling,随机抽样选择)
  • tour (Tournament,锦标赛选择)
  • urs (Uncommitted Random Selection,无约束随机选择)

Example

FitnV = np.random.rand(Nind)
FitnV = FitnV.reshape(-1,1)
FitnV
array([[0.47246408],[0.6966635 ],[0.8280383 ],[0.35520503],[0.60798975],[0.91590692],[0.69238913],[0.58686945],[0.45008303],[0.82214108]])
SelCh_sel = Chrom[ea.selecting('rws', FitnV, Nind-1), :] #选择,采用‘rws’轮盘赌选择
SelCh_sel
array([[391, 409, 388, 975, 899, 897, 660,   1],[101, 478, 657,  79,  77, 629, 551,   1],[444, 612, 692, 319, 484, 354, 482,   2],[ 36,  72, 900, 912, 694, 767, 960,   1],[746, 410, 992,  55, 101, 456, 626,   1],[153, 951, 439, 222, 383,  67, 226,   2],[849, 137, 507, 207, 172, 731, 893,   2],[153, 951, 439, 222, 383,  67, 226,   2],[153, 951, 439, 222, 383,  67, 226,   2]], dtype=int32)
SelCh_sel2 = Chrom[ea.selecting('tour', FitnV, Nind-1), :] #选择,采用‘rws’轮盘赌选择
SelCh_sel2
array([[101, 478, 657,  79,  77, 629, 551,   1],[444, 612, 692, 319, 484, 354, 482,   2],[849, 137, 507, 207, 172, 731, 893,   2],[153, 951, 439, 222, 383,  67, 226,   2],[849, 137, 507, 207, 172, 731, 893,   2],[153, 951, 439, 222, 383,  67, 226,   2],[746, 410, 992,  55, 101, 456, 626,   1],[391, 409, 388, 975, 899, 897, 660,   1],[391, 409, 388, 975, 899, 897, 660,   1]], dtype=int32)

重组 recombin()

交叉是重组的一部分

  • recdis (离散重组)
  • recint (中间重组)
  • reclin (线性重组)
  • recndx (正态分布交叉)
  • recsbx (模拟二进制交叉)
  • xovbd (二项式分布交叉)
  • xovdp (两点交叉)
  • xovexp (指数交叉)
  • xovmp (多点交叉)
  • xovox (顺序交叉)
  • xovpmx (部分匹配交叉)
  • xovsec (洗牌指数交叉)
  • xovsh (洗牌交叉)
  • xovsp (单点交叉)
  • xovud (均匀分布交叉)
help(ea.recombin)
Help on cython_function_or_method in module recombin:recombin(REC_F, Chrom, RecOpt=0.7, params2=None, params3=None, params4=None)recombin : function - 实现个体染色体的重组(高级重组函数)描述:该函数调用低级的重组函数对种群染色体进行重组并返回重组后的种群染色体矩阵。语法:NewChrom = recombin(REC_F, Chrom)NewChrom = recombin(REC_F, Chrom, RecOpt)NewChrom = recombin(REC_F, Chrom, RecOpt, params2)NewChrom = recombin(REC_F, Chrom, RecOpt, params2, params3)NewChrom = recombin(REC_F, Chrom, RecOpt, params2, params3, params4)输入参数:REC_F  : string  - 低级重组函数名,比如'xovdp'。Chrom  : array   - 用于重组的种群染色体矩阵,每一行对应着一个个体的染色体。RecOpt : float   - (可选参数) 指明了两个个体的染色体之间发生重组的概率,若为缺省值或None,则默认概率为0.7。params2, params3, params4均是需要传入低级变异函数的一些参数,其编号及具体含义与MUT_F指定的低级变异函数所需参数含义一致。输出参数:NewChrom : array - 重组后的种群染色体矩阵。Created on Fri Mar 30 13:56:07 2018@author: jazzbin
Selch_xov = ea.recombin('xovsp', SelCh_sel, 0.7)
Selch_xov
array([[391, 409, 388,  55, 101, 456, 626,   1],[101, 478, 657,  79, 383,  67, 226,   2],[444, 612, 692, 319, 484, 354, 482,   2],[ 36,  72, 900, 912, 694,  67, 226,   2],[746, 410, 992, 975, 899, 897, 660,   1],[153, 951, 439, 222,  77, 629, 551,   1],[849, 137, 507, 207, 172, 731, 893,   2],[153, 951, 439, 222, 383, 767, 960,   1],[153, 951, 439, 222, 383,  67, 226,   2]], dtype=int32)
Selch_xov == SelCh_sel
array([[ True,  True,  True, False, False, False, False,  True],[ True,  True,  True,  True, False, False, False, False],[ True,  True,  True,  True,  True,  True,  True,  True],[ True,  True,  True,  True,  True, False, False, False],[ True,  True,  True, False, False, False, False,  True],[ True,  True,  True,  True, False, False, False, False],[ True,  True,  True,  True,  True,  True,  True,  True],[ True,  True,  True,  True,  True, False, False, False],[ True,  True,  True,  True,  True,  True,  True,  True]])

突变 ea.mutate()

ea.mutate() 是高级的突变函数,它调用下面的低级突变函数:

  • mutbga (Mutation for Breeder Genetic Algorithm,Breeder GA 算法突变算子)
  • mutbin (Mutation for Binary Chromosomes,二进制变异算子)
  • mutde (Mutation for Differential Evolution,差分变异算子)
  • mutgau (Gaussian Mutation,高斯突变算子)
  • mutinv (Invertion Mutation,染色体片段逆转变异算子)
  • mutmove (Mutation by Moving,染色体片段移位变异算子)
  • mutpolyn (Polynomial Mutation,多项式变异)
  • mutpp (Mutation of Permutation Chromosomes,排列编码变异算子)
  • mutswap (Two Point Swapping Mutation,染色体两点互换变异算子)
  • mutuni (Uniform Mutation,均匀变异算子)
help(ea.mutate)
Help on cython_function_or_method in module mutate:mutate(MUT_F, Encoding, OldChrom, params2=None, params3=None, params4=None, params5=None, params6=None, params7=None)mutate : function - 高级变异函数描述:该函数接收一个种群染色体矩阵,对个体进行变异并返回新的种群矩阵,该函数调用低级突变函数来进行突变。语法:NewChrom = mutate(MUT_F, Encoding, OldChrom)NewChrom = mutate(MUT_F, Encoding, OldChrom, params2)NewChrom = mutate(MUT_F, Encoding, OldChrom, params2, params3)NewChrom = mutate(MUT_F, Encoding, OldChrom, params2, params3, params4)NewChrom = mutate(MUT_F, Encoding, OldChrom, params2, params3, params4, params5)NewChrom = mutate(MUT_F, Encoding, OldChrom, params2, params3, params4, params5, params6)NewChrom = mutate(MUT_F, Encoding, OldChrom, params2, params3, params4, params5, params6, params7)输入参数:MUT_F     : string- 低级变异函数的字符串,比如'mutbga'等。Encoding : str   - 染色体编码方式,'BG':二进制/格雷编码;'RI':实整数编码,即实数和整数的混合编码;'P':排列编码。相关概念:术语“实值编码”包含实整数编码和排列编码,它们共同的特点是染色体不需要解码即可直接表示对应的决策变量。OldChrom  : array - 待变异的旧种群,每一行对应着一个个体。params2, params3, params4, params5, params6, params7均是需要传入低级变异函数的一些参数,其编号及具体含义与MUT_F指定的低级变异函数所需参数含义一致。输出参数:NewChrom  : array - 变异后的种群染色体矩阵,其size跟OldChrom相同。Created on Mon Jun 17 11:23:16 2019@author: jazzbin
help(ea.mutde)
Help on built-in function mutde in module mutde:mutde(...)mutde : function - 差分变异(Mutation for Differential Evolution)描述:该函数对一个实整数编码的种群染色体矩阵(Encoding为'RI')进行差分变异,返回一个新的种群染色体矩阵。当无指定基向量Xr0或基向量索引r0时,r0按照随机的方式确定,并且保证每个元素都不等于i,其中i为个体索引(当种群个体数过小时无法保证);输入参数XrList存储了差分向量或差分向量的索引。如果无指定差分向量Xr1、Xr2(乃至Xr3、Xr4)或者差分向量索引r1、r2(乃至r3、r4)时,差分向量索引r1、r2(乃至r3、r4)按照随机的方式确定,并保证连同i和r0在内互不相等(当种群个体数过小时无法保证)。染色体的变异结果 = Xr0 + F*(Xr1 - Xr2)或者 = Xr0 + F*(Xr1 - Xr2 + Xr3 - Xr4)或者 = Xr0 + F1*(Xr1 - Xr2) + F2*(Xr3 - Xr4)。该函数先是采用实数值来进行变异,当结果超出译码矩阵FieldDR所设定的范围时,该函数会对其进行修复,支持截断、循环、往复、随机4种修复方式:截断修复:对超出边界范围的元素取与其最近的边界值。循环修复:例如变量范围是[0, 2],那么2.1、3.1将会被修复变成0.1;-2.1、-3.1将会被修复变成1.9。往复修复:例如变量范围是[0, 2],那么2.1、3.1将会被修复变成1.9;-2.1、-3.1将会被修复变成0.1。随机修复:对超出边界的元素修复为一个服从在变量范围内均匀分布的随机数。最后根据译码矩阵FieldDR用四舍五入法把变异结果中需要转换的部分转换为整数。注意:该函数不会检查边界范围的设置是否有误,因此建议采用crtfld函数对边界进行预处理。语法:NewChrom = mutde(Encoding, OldChrom, FieldDR)NewChrom = mutde(Encoding, OldChrom, FieldDR, XrList)NewChrom = mutde(Encoding, OldChrom, FieldDR, XrList, F)NewChrom = mutde(Encoding, OldChrom, FieldDR, XrList, F, FixType)NewChrom = mutde(Encoding, OldChrom, FieldDR, XrList, F, FixType, Parallel)NewChrom = mutde(Encoding, OldChrom, FieldDR, XrList, F, FixType, Parallel, params7)输入参数:Encoding : str   - 染色体编码方式,'BG':二进制/格雷编码;'RI':实整数编码,即实数和整数的混合编码;'P':排列编码。该函数只针对实整数值编码的种群进行变异,因此只允许Encoding为'RI'。OldChrom : array - 种群染色体矩阵,每一行对应一个个体的一条染色体。FieldDR  : array - 实值种群译码矩阵,Encoding为'RI'或'P'时使用的是这种结构的译码矩阵。[lb;              指明每个变量使用的下界。ub;              指明每个变量使用的上界。varTypes] (0:continued | 1:discrete)。注:不需要考虑是否包含变量的边界值。在crtfld中已经将是否包含边界值进行了处理,本函数规定包含当前FieldDR的边界。XrList   : list  - 存储基向量或基向量索引的列表。XrList = []或       [Xr0(r0)]或       [Xr0(r0), Xr1(r1)]或       [Xr0(r0), Xr1(r1), Xr2(r2)]或       [Xr0(r0), Xr1(r1), Xr2(r2), Xr3(r3)]或       [Xr0(r0), Xr1(r1), Xr2(r2), Xr3(r3), Xr4(r4)]上面的Xr0(r0)表示XrList的第一个元素可以是Xr0(基向量)或者是r0(基向量索引);当XrList的某个元素是个Numpy array类型“矩阵”(2维)时,意味着它表示的是DE中的“向量”(Xri),比如基向量Xr0、差分向量Xr1、Xr2等等;(注:这里采用带有矛盾的表述是为了方便描述,实质上这个“向量”Xr是所有“向量”组成的矩阵);当XrList的某个元素是个向量(1维Numpy array类型数组)时,意味着它表示的是DE中的“向量索引”(ri),比如基向量r0、差分向量r1、r2等等。当len(XrList)为0时,默认差分向量只有2个:Xr1以及Xr2;只有当len(XrList)大于3时,差分向量有4个:Xr1、Xr2、Xr3、Xr4。(注:如果不想指定中间的某个“向量”,需要把它设为None,例如:XrList = [r0, None, r2])当XrList缺省或为None时,默认XrList = [],此时r0、r1、r2按照随机的方式确定,并尽可能保证互不相等(当种群个体数过小时无法保证)。F        : float/list - (可选参数)差分变异缩放因子,可以是float和list两种类型:当输入的F为标量时,表示只有一个变异缩放因子,且不能小于0。当输入的F为list类型时,该list必须只包含2个标量,表示有2个变异缩放因子,即F1 = F[0], F2 = F[1],此时F1和F2不能小于0。当F缺省或为None时,或者F1、F2是None时,默认每个个体作差分变异时的对应差分变异缩放因子均为(0, 1)之间的随机数。例如:F = [0.5, None],表示F1=0.5,而F2在变异过程中随机生成。注:当输入两个变异缩放因子,而差分向量只有1对时,F2不会起作用;而当输入一个变异缩放因子,而差分向量有2对时,缺失的变异缩放因子会被设置为等于另一个变异缩放因子。FixType  : int   - (可选参数)表示采用哪种方式来修复染色体上超出指定范围的元素。1:截断修复;2:循环修复;3:往复修复;4:随机修复。缺省或为None时默认为1。Parallel : bool  - (可选参数)表示是否采用并行计算,缺省或为None时默认为False。params7 - 无用参数(为了兼容同类的其他函数)。输出参数:NewChrom  : array - 变异后的种群染色体矩阵。参考文献:[1] Price, K.V., Storn, R.N. and Lampinen, J.A.. Differential Evolution: A Practical Approach to Global Optimization. : Springer, 2005.Created on Sun Jun  9 23:49:35 2019@author: jazzbin

NewChrom = ea.mutate('mutswap', 'RI', Selch_xov, FieldDR)
NewChrom
array([[626, 409, 388,  55, 101, 456, 391,   1],[101, 478, 657, 226, 383,  67,  79,   2],[354, 612, 692, 319, 484, 444, 482,   2],[ 72,  36, 900, 912, 694,  67, 226,   2],[746, 410, 992, 975, 899, 660, 897,   1],[153, 951, 629, 222,  77, 439, 551,   1],[849, 172, 507, 207, 137, 731, 893,   2],[960, 951, 439, 222, 383, 767, 153,   1],[153, 951, 439, 222, 383, 286, 226,   2]], dtype=int32)
NewChrom == Selch_xov
array([[False,  True,  True,  True,  True,  True, False,  True],[ True,  True,  True, False,  True,  True, False,  True],[False,  True,  True,  True,  True, False,  True,  True],[False, False,  True,  True,  True,  True,  True,  True],[ True,  True,  True,  True,  True, False, False,  True],[ True,  True, False,  True,  True, False,  True,  True],[ True, False,  True,  True, False,  True,  True,  True],[False,  True,  True,  True,  True,  True, False,  True],[ True,  True,  True,  True,  True, False,  True,  True]])

数据可视化

  • moeaplot (多目标优化目标空间绘图函数)
  • soeaplot (单目标优化绘图函数)
  • trcplot (进化记录器绘图函数)
  • varplot (决策变量绘图函数)


实验实例

import geatpy as ea
import numpy as np

新建种群

MAXGEN = 50
maxormins = -1 #表示目标函数最小最大化标记,1表示最小化,-1表示最大化
recombine_rate = 0.7
mut_rate = 0.05
Nind = 10
num_hidden_neurons = 6
ub_hidden_n = [1024] * num_hidden_neurons
lb_hidden_n = [32] * num_hidden_neuronsub_lr = [1000]
lb_lr = [1]ub_batch_size = [2]
lb_batch_size = [1]
ub = np.hstack((ub_hidden_n, ub_lr, ub_batch_size))
lb = np.hstack((lb_hidden_n, lb_lr, lb_batch_size))
varTypes = [1] * (num_hidden_neurons + 2)
FieldDR = np.vstack((lb, ub, varTypes))
FieldDR
array([[  32,   32,   32,   32,   32,   32,    1,    1],[1024, 1024, 1024, 1024, 1024, 1024, 1000,    2],[   1,    1,    1,    1,    1,    1,    1,    1]])
hidden_neurons = np.random.randint(low=32, high=1024+1, size=[Nind, num_hidden_neurons], dtype=int)
lr = np.random.randint(low=1, high=1000+1, size=[Nind, 1], dtype=int)
batch_size = np.random.randint(low=1, high=2, size=[Nind, 1], dtype=int)
chrom = np.hstack((hidden_neurons, lr/10000, batch_size*100))
chrom
array([[4.70e+01, 1.83e+02, 4.31e+02, 5.48e+02, 7.33e+02, 6.35e+02,1.68e-02, 1.00e+02],[2.79e+02, 6.16e+02, 8.92e+02, 4.92e+02, 4.96e+02, 1.80e+02,9.03e-02, 1.00e+02],[2.98e+02, 7.89e+02, 9.17e+02, 2.02e+02, 8.33e+02, 3.95e+02,2.31e-02, 1.00e+02],[2.33e+02, 6.00e+01, 2.35e+02, 9.92e+02, 4.90e+01, 8.62e+02,1.70e-03, 1.00e+02],[1.62e+02, 6.85e+02, 8.32e+02, 8.99e+02, 7.21e+02, 9.90e+02,1.10e-03, 1.00e+02],[1.35e+02, 6.73e+02, 9.77e+02, 7.63e+02, 9.27e+02, 8.03e+02,3.18e-02, 1.00e+02],[1.19e+02, 9.54e+02, 1.05e+02, 4.43e+02, 3.76e+02, 4.85e+02,5.44e-02, 1.00e+02],[4.95e+02, 3.91e+02, 3.36e+02, 4.91e+02, 5.83e+02, 8.71e+02,1.66e-02, 1.00e+02],[5.10e+02, 5.22e+02, 1.58e+02, 8.53e+02, 1.12e+02, 5.06e+02,6.52e-02, 1.00e+02],[1.47e+02, 5.73e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,2.49e-02, 1.00e+02]])
Objv = np.random.rand(10,1)
Objv
array([[0.81776808],[0.168222  ],[0.9827996 ],[0.60088042],[0.31274793],[0.06498612],[0.34034563],[0.04131547],[0.82911323],[0.82916407]])
best_ind = np.argmax(Objv * maxormins)
best_ind
7
Fitnv = ea.ranking(Objv * maxormins)
Fitnv
array([[1.33333333],[0.44444444],[2.        ],[1.11111111],[0.66666667],[0.22222222],[0.88888889],[0.        ],[1.55555556],[1.77777778]])

选择

Selch = chrom[ea.selecting('rws', Fitnv, Nind-1), :]
Selch
array([[2.98e+02, 7.89e+02, 9.17e+02, 2.02e+02, 8.33e+02, 3.95e+02,2.31e-02, 1.00e+02],[5.10e+02, 5.22e+02, 1.58e+02, 8.53e+02, 1.12e+02, 5.06e+02,6.52e-02, 1.00e+02],[1.19e+02, 9.54e+02, 1.05e+02, 4.43e+02, 3.76e+02, 4.85e+02,5.44e-02, 1.00e+02],[1.47e+02, 5.73e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,2.49e-02, 1.00e+02],[2.98e+02, 7.89e+02, 9.17e+02, 2.02e+02, 8.33e+02, 3.95e+02,2.31e-02, 1.00e+02],[1.62e+02, 6.85e+02, 8.32e+02, 8.99e+02, 7.21e+02, 9.90e+02,1.10e-03, 1.00e+02],[1.47e+02, 5.73e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,2.49e-02, 1.00e+02],[4.70e+01, 1.83e+02, 4.31e+02, 5.48e+02, 7.33e+02, 6.35e+02,1.68e-02, 1.00e+02],[1.47e+02, 5.73e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,2.49e-02, 1.00e+02]])

交叉

Selch = ea.recombin('xovsp', Selch, 0.7)
Selch
array([[2.98e+02, 7.89e+02, 9.17e+02, 2.02e+02, 8.33e+02, 3.95e+02,2.31e-02, 1.00e+02],[5.10e+02, 5.22e+02, 1.58e+02, 8.53e+02, 1.12e+02, 5.06e+02,6.52e-02, 1.00e+02],[1.19e+02, 9.54e+02, 1.05e+02, 4.43e+02, 3.76e+02, 4.85e+02,5.44e-02, 1.00e+02],[1.47e+02, 5.73e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,2.49e-02, 1.00e+02],[2.98e+02, 7.89e+02, 9.17e+02, 2.02e+02, 8.33e+02, 3.95e+02,2.31e-02, 1.00e+02],[1.62e+02, 6.85e+02, 8.32e+02, 8.99e+02, 7.21e+02, 9.90e+02,1.10e-03, 1.00e+02],[1.47e+02, 5.73e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,2.49e-02, 1.00e+02],[4.70e+01, 1.83e+02, 4.31e+02, 5.48e+02, 7.33e+02, 6.35e+02,1.68e-02, 1.00e+02],[1.47e+02, 5.73e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,2.49e-02, 1.00e+02]])

变异

Selch = ea.mutate('mutswap', 'RI', Selch, FieldDR)
Selch
array([[298, 789, 917, 202, 395, 833, 665,   2],[510, 522, 158, 853, 112, 506, 100,   1],[119, 954, 105, 443, 485, 376, 279,   1],[147, 573, 731, 989, 289, 586, 681,   1],[298, 789, 917, 100, 833, 395, 178,   2],[162, 685, 899, 832, 721, 990, 391,   2],[573, 147, 681, 989, 289, 586, 568,   1],[ 47, 183, 431, 548, 635, 733, 508,   2],[147, 586, 681, 989, 289, 573, 414,   2]], dtype=int32)

整合数据

newchrom = np.vstack([chrom[best_ind, :], Selch])
newchrom
array([[4.95e+02, 3.91e+02, 3.36e+02, 4.91e+02, 5.83e+02, 8.71e+02,1.66e-02, 1.00e+02],[2.98e+02, 7.89e+02, 9.17e+02, 2.02e+02, 3.95e+02, 8.33e+02,6.65e+02, 2.00e+00],[5.10e+02, 5.22e+02, 1.58e+02, 8.53e+02, 1.12e+02, 5.06e+02,1.00e+02, 1.00e+00],[1.19e+02, 9.54e+02, 1.05e+02, 4.43e+02, 4.85e+02, 3.76e+02,2.79e+02, 1.00e+00],[1.47e+02, 5.73e+02, 7.31e+02, 9.89e+02, 2.89e+02, 5.86e+02,6.81e+02, 1.00e+00],[2.98e+02, 7.89e+02, 9.17e+02, 1.00e+02, 8.33e+02, 3.95e+02,1.78e+02, 2.00e+00],[1.62e+02, 6.85e+02, 8.99e+02, 8.32e+02, 7.21e+02, 9.90e+02,3.91e+02, 2.00e+00],[5.73e+02, 1.47e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.86e+02,5.68e+02, 1.00e+00],[4.70e+01, 1.83e+02, 4.31e+02, 5.48e+02, 6.35e+02, 7.33e+02,5.08e+02, 2.00e+00],[1.47e+02, 5.86e+02, 6.81e+02, 9.89e+02, 2.89e+02, 5.73e+02,4.14e+02, 2.00e+00]])
newchrom.shape
(10, 8)

重新计算适应度值

绘图,保存

help(ea.trcplot)
Help on cython_function_or_method in module trcplot:trcplot(trace, labels, titles=None, save_path='', xlabels=None, ylabels=None, gridFlags=None)trcplot : function - Trace Plot,进化记录器绘图函数语法:trcplot(trace, labels)trcplot(trace, labels, titles)trcplot(trace, labels, titles, save_path)trcplot(trace, labels, titles, save_path, xlabels)trcplot(trace, labels, titles, save_path, xlabels, ylabels)trcplot(trace, labels, titles, save_path, xlabels, ylabels, gridFlags)输入参数:trace     : array  - 进化记录器。每一列代表一个参数,如第一列代表个体最优目标函数值等,每一行对应一"代",比如第一行对应的是第一代种群的最优个体。labels    : list   - 二维列表,表示各图片中的图例。其每一列的含义与trace是对应的。例:1.假设trace有2列,含义分别是'a'和'b',则labels = [['a'],['b']],表示要画2张图,每张图画2个变量,图例分别是'a'和'b'2.假设trace有2列,含义分别是'a'和'b',则labels = [['a','b']],表示要画1张图,图中有2个变量,图例分别是'a'和'b'。3.假设trace有3列,含义分别是'a','b'和'c',则labels = [['a'],['b','c']],表示要画2张图,第一张图有1个变量,图例是'a',第二张图有2个变量,图例是'b'和'c'。注:labels的元素总数必须等于trace的列数。titles    : list   - (可选参数)二维列表,表示各图片的标题,元素设为空字符串则表示不显示图片标题,如titles = [['a'],['']],表示有2张图片,标题分别是a和不设标题,注:len(titles)必须等于len(labels)。缺省或为None时,该函数将不进行图片的保存。save_path : string - (可选参数)图片保存的路径。xlabels   : list   - (可选参数)二维列表,表示各图片的x轴标签,当缺省或为None时,默认所有的图片的x轴标签均为“Number of Generation”。格式与titles参数类似,xlabels的元素设为空字符串则表示不显示x轴标签,例如xlabels = [['time'],['']],表示有2张图片,标签分别是“time”和不设x轴标签,注:len(xlabels)必须等于len(labels)。ylabels   : list   - (可选参数)二维列表,表示各图片的y轴标签,当缺省或为None时,默认所有的图片的y轴标签均为“Value”。格式与titles参数类似,ylabels的元素设为空字符串则表示不显示y轴标签,例如ylabels = [['time'],['']],表示有2张图片,标签分别是“time”和不设y轴标签,注:len(ylabels)必须等于len(labels)。gridFlags : list   - (可选参数)二维列表,表示各图片是否绘制网格,当缺省或为None时,默认所有的图片均不绘制网格格式与titles参数类似,例如gridFlags = [[True],[False]],表示有2张图片,分别绘制网格和不绘制网格。注:len(gridFlags)必须等于len(labels)。Created on Sun Jul 29 17:09:11 2018@author: jazzbin

写成了一个class

class GA_CNN:def __init__(self, args, cfg, log):self.args = argsself.log = logself.cfg = cfg'''GA_params'''self.MAXGEN = self.cfg.PARA.GA_params.MAXGENself.Nind = self.cfg.PARA.GA_params.Nindself.maxormins = self.cfg.PARA.GA_params.maxormins  # -1:最大化 1:最小化self.xov_rate = self.cfg.PARA.GA_params.xov_rate  # 交叉概率'''chrom'''self.params_dict = {}self.FieldDR = Noneself.chrom_all = Noneself.Objv_all = None'''记录每一代的数据'''self.obj_trace = np.zeros((self.MAXGEN, 2))  # [MAXGEN, 2] 其中[0]记录当代种群的目标函数均值,[1]记录当代种群最优个体的目标函数值self.var_trace = np.zeros((self.MAXGEN, self.cfg.PARA.CNN_params.CNN_total_params))  # 记录当代种群最优个体的变量值self.time = None'''记录所有种群中的最优值'''self.best_gen = Noneself.best_Objv = Noneself.best_chrom_i = None# self.X = None # 把X和Y用chrom_all和Objv_all代替# self.Y = Nonedef Init_chrom(self):lb = np.hstack((self.cfg.PARA.CNN_params.conv_channels_1[0],self.cfg.PARA.CNN_params.conv_channels_2[0],self.cfg.PARA.CNN_params.conv_kernel_size[0],self.cfg.PARA.CNN_params.conv_kernel_size[0],self.cfg.PARA.CNN_params.pool_kernel_size[0],self.cfg.PARA.CNN_params.pool_stride[0],self.cfg.PARA.CNN_params.fc_features_1[0],self.cfg.PARA.CNN_params.fc_features_2[0],))ub = np.hstack((self.cfg.PARA.CNN_params.conv_channels_1[1],self.cfg.PARA.CNN_params.conv_channels_2[1],self.cfg.PARA.CNN_params.conv_kernel_size[1],self.cfg.PARA.CNN_params.conv_kernel_size[1],self.cfg.PARA.CNN_params.pool_kernel_size[1],self.cfg.PARA.CNN_params.pool_stride[1],self.cfg.PARA.CNN_params.fc_features_1[1],self.cfg.PARA.CNN_params.fc_features_2[1],))varTypes = [1] * (self.cfg.PARA.CNN_params.CNN_total_params)FieldDR = np.vstack((lb, ub, varTypes))chrom = ea.crtip(self.Nind, FieldDR)self.FieldDR = FieldDR  # 这个是固定不变的return chromdef get_Objv_i(self, chrom): #输入的chrom个体数 = 每一代种群的个数Nindchrom = np.int32(chrom)num = chrom.shape[0]Objv = np.zeros(shape=(num, 1))for i in range(num):self.params_dict['conv_channels'] = chrom[i, 0:2] #前两个,每次都会更新,重新赋值self.params_dict['conv_kernel_size'] = chrom[i, 2:4]self.params_dict['pool_kernel_size'] = chrom[i, 4]self.params_dict['pool_stride'] = chrom[i, 5]self.params_dict['fc_features'] = chrom[i, 6:8]Objv[i] = Train_GACNN(self.params_dict, self.args, self.cfg, self.log)# Objv = np.random.rand(num, 1)return Objvdef Evolution(self): #start_time = time.time()# 初始化种群Init_chrom = self.Init_chrom()# 开始进化self.log.logger.info('==> This is Init GEN <==' )Init_Objv = self.get_Objv_i(Init_chrom)best_ind = np.argmax(Init_Objv * self.maxormins) #记录最优个体的索引值self.chrom_all = Init_chromself.Objv_all = Init_Objvfor gen in range(self.MAXGEN):self.log.logger.info('==> This is No.%d GEN <==' % (gen))if gen==0: #第一代和后面有所不同chrom = Init_chromObjv = Init_Objvelse:chrom = NewChromObjv = NewObjvFitnV = ea.ranking(Objv * self.maxormins)Selch = chrom[ea.selecting('rws', FitnV, self.Nind-1), :] #轮盘赌选择 Nind-1 代,与上一代的最优个体再进行拼接Selch = ea.recombin('xovsp', Selch, self.xov_rate) #重组,即交叉Selch = ea.mutate('mutswap', 'RI', Selch, self.FieldDR) #变异Objv_Selch = self.get_Objv_i(Selch)NewChrom = np.vstack((chrom[best_ind, :], Selch)) #将上一代的最优个体与现在的种群拼接NewObjv =np.vstack((Objv[best_ind, :], Objv_Selch))best_ind = np.argmax(NewObjv * self.maxormins)self.chrom_all = np.vstack((self.chrom_all, NewChrom))self.Objv_all = np.vstack((self.Objv_all, NewObjv))self.obj_trace[gen, 0] = np.sum(NewObjv) / self.Nind  # 记录当代种群的目标函数均值self.obj_trace[gen, 1] = NewObjv[best_ind]  # 记录当代种群最有给他目标函数值self.var_trace[gen, :] = NewChrom[best_ind, :]  # 记录当代种群最优个体的变量值self.log.logger.info('GEN=%d,best_Objv=%.5f,best_chrom_i=%s\n'% (gen, NewObjv[best_ind], str(NewChrom[best_ind, :])))  # 记录每一代的最大适应度值和个体self.Save_chroms(self.chrom_all)self.Save_objvs(self.Objv_all)end_time = time.time()self.time = end_time - start_timeself.log.logger.info('The time of Evoluation is %.5f s. ' % self.time)def Plot_Save(self):self.best_gen = np.argmax(self.obj_trace[:, [1]])self.best_Objv = self.obj_trace[self.best_gen, 1]self.best_chrom_i = self.var_trace[self.best_gen]# pdb.set_trace()ea.trcplot(trace=self.obj_trace,labels=[['POP Mean Objv', 'Best Chrom i Objv']],titles=[['Mean_Best_Chromi_Objv']],save_path=self.cfg.PARA.CNN_params.save_data_path,xlabels=[['GEN']],ylabels=[['ACC']])with open(self.cfg.PARA.CNN_params.save_bestdata_txt, 'a') as f:f.write('best_Objv=%.5f,best_chrom_i=%s,total_time=%.5f\n' % (self.best_Objv, str(self.best_chrom_i), self.time))np.savetxt(self.cfg.PARA.CNN_params.save_data_path + 'MeanChromi_Objv.txt', self.obj_trace[:, 0])np.savetxt(self.cfg.PARA.CNN_params.save_data_path + 'BestChromi_Objv.txt', self.obj_trace[:, 1])np.savetxt(self.cfg.PARA.CNN_params.save_data_path + 'BestChromi.txt', self.var_trace)def Save_chroms(self, chrom):self.log.logger.info('==> Save Chroms to file <==')scio.savemat(self.cfg.PARA.CNN_params.save_x_mat, {"chrom": chrom})def Save_objvs(self, Objv):self.log.logger.info('==> Save Objvs to file <==')scio.savemat(self.cfg.PARA.CNN_params.save_y_mat, {"objv": Objv})

参考文章及Blog

1. Geatpy数据结构
2. Python遗传和进化算法框架(一)Geatpy快速入门
3. Python遗传和进化算法框架(二)Geatpy库函数和数据结构
4. Geatpy官网及相关教程


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部