一种通用的蟒蛇遗传算法

naturalselection的Python项目详细描述


自然选择绿花标志

一种通用的蟒蛇遗传算法,它还内置了对神经网络的超参数调整支持。

安装

$ pip install naturalselection

用法

下面是一个玩具示例,它针对除法优化了一对数字。

>>>importnaturalselectionasns>>>>>>Pair=ns.Genus(x=range(1,10000),y=range(1,10000))>>>defdivision(number):...returnnumber.x/number.y...>>>pairs=ns.Population(genus=Pair,size=100,fitness_fn=division)>>>history=pairs.evolve(generations=50,progress_bars=1)Evolvingpopulation:100%|█████████████████████|50/50[00:09<00:00,5.28it/s]>>>>>>history.fittest{'genome':{'x':9974,'y':4},'fitness':2493.5}>>>>>>history.plot()

显示50代以上适应值的曲线图。在前五代中,平均值从0上升到1500,之后缓慢上升到大约2200。七代后,最大值收敛到25000左右,标准差始终保持在700左右。

我们还可以很容易地解决经典的onemax问题,即找到所有1的给定长度的位字符串。这里我们在evolve函数中设置goal=100如果我们在我们设定的最大世代数10000之前达到目标,就停止。请注意,这只需要一分钟,尽管完成进化所需的世代要少得多,但较大的种群似乎需要更长的时间。

>>>importnaturalselectionasns>>>>>># Length of the bit strings>>>N=100>>>BitString=ns.Genus(**{f'x{n}':(0,1)forninrange(N)})>>>>>>defsum_bits(bitstring):...returnsum(bitstring.get_genome().values())>>>>>>bitstrings=ns.Population(...genus=BitString,...size=2,...fitness_fn=sum_bits...)>>>>>>history=bitstrings.evolve(...generations=10000,...goal=100,...progress_bars=1...)Evolvingpopulation:45%|████████|4480/10000[01:00<01:58,46.43it/s]>>>>>>history.plot()

显示4500代以上适应度值的图,稳定地收敛到最佳填写顺序。

最后,这里是一个寻找一个完全连接的前馈神经网络来建模mnist的例子。请注意,这需要每个CPU核心大约1GB的可用内存(通常是4)。如果没有此功能,请将evolve调用中的workers参数设置为2或3左右,或将多处理设置为false以完全关闭并行性。

如果你是gpu的幸运拥有者,那么你也需要设置多处理=false(并将max廑u training廑time设置为较小的值,和/或将max廑pochs设置为较小的值)。

>>>importnaturalselectionasns>>>>>># MNIST packages>>>fromtensorflow.keras.utilsimportto_categorical>>>importmnist>>>>>># Standard train and test sets for MNIST>>>X_train=((mnist.train_images()/255)-0.5).reshape((-1,784))>>>Y_train=to_categorical(mnist.train_labels())>>>X_val=((mnist.test_images()/255)-0.5).reshape((-1,784))>>>Y_val=to_categorical(mnist.test_labels())>>>>>>fnns=ns.FNNs(>>>size=50,>>>train_val_sets=(X_train,Y_train,X_val,Y_val),>>>loss_fn='binary_crossentropy',>>>score='accuracy',>>>output_activation='softmax',>>>max_training_time=60>>>)>>>>>>history=fnns.evolve(generations=20)Evolvingpopulation:100%|██████████████████|20/20[4:28:35<00:00,776.70s/it]Computingfitnessforgen19:100%|████████████|46/46[13:22<00:00,17.44s/it]>>>>>>history.fittest{'genome':{'optimizer':'adam','hidden_activation':'elu','batch_size':128,'initializer':'glorot_uniform','input_dropout':0.1,'neurons0':128,'dropout0':0.0,'neurons1':64,'dropout1':0.0,'neurons2':1024,dropout2': 0.1, 'neurons3': 32, 'dropout3': 0.4,'neurons4':256,'dropout4':0.1},'fitness':0.973}>>>>>>history.plot(...title="Validation accuracy by generation",...ylabel="Validation accuracy"...)

显示20代的适应度值(在本例中是准确的)的曲线图,大约收敛到97%。

>>># Training the best model and saving it to mnist_model.h5>>>best_score=fnns.train_best(file_name='mnist_model')Epoch:0-loss:0.277,val_loss:0.179:100%|██████████|60000/60000[00:31<00:00,244.79it/s](...)>>>best_score0.9793

算法细节

该算法遵循遗传算法的标准蓝图,如在维基百科页面上所述,大致如下:

  1. 构造初始总体
  2. 计算种群中所有生物体的适应度值
  3. 选择一部分人群(精英人才库)。
  4. 选择一个种群子集(繁殖池)。
  5. 从繁殖池中选出一对,它们将繁殖出一种新的"子"有机体,其基因组由"父"有机体组合而成。继续繁殖,直到孩子和精英组成与原始种群大小相同的种群
  6. 选择子代的子集(突变池)。
  7. 突变库中的每个孩子都发生了突变,这意味着他们的基因组将以某种方式发生改变
  8. 返回步骤2

现在,我们将更详细地描述这个特定实现中的各个步骤。请注意,第3步有时会被完全忽略,但由于这只是对应于一个空的精英人才库,所以我决定保留它,以供一般使用。

第一步:构建初始种群

种群是由属决定的可能基因组值的均匀随机样本,当创建新的种群对象时运行。或者,您可以将初始的基因组设置为您想要的任何基因组,这将使一个完全同质的群体仅由该基因组的有机体组成(突变将在每一代中产生一些多样性)。

>>>pairs=ns.Population(...genus=Pair,...size=100,...fitness_fn=division,...initial_genome={'x':9750,'y':15}...)Evolvingpopulation:100%|███████████████████|100/100[00:09<00:00,5.28it/s]>>>>>>self.fittest{'genome':{'x':9846,'y':1},'fitness':9846.0}

步骤2:计算适应值

这发生在evolve函数调用的get_fitness函数中。默认情况下,这些计算将为每个CPU核心并行计算,因此在上面的mnist示例中,这将需要4-5GB RAM。或者,可以通过将workers设置为一个小值来显式设置并行计算的数量,或者通过将multiprocessing=false设置为完全禁用并行计算。

步骤3&4:选择精英池和繁殖池

这两个池的选择方式完全相同,只是每个池中的生物体数量不同,默认的精英化率为5%,繁殖率为80%。在池的选择中,它根据密度函数的分布来选择种群,即适应值除以种群的所有适应值之和。这意味着一个有机体的适应度得分越高,就越有可能被选为游泳池的一部分。该算法的精确实现遵循在wikipedia页面上指定的算法。

第5步:繁殖

在这个实现中,父母的有机体是随机选择的,当确定孩子的基因组的值时,每个基因都是父母对该特定基因的值之间的随机选择。

步骤6:选择突变池

与其他两个基因库相比,突变库是随机选择的,否则,我们可能会突然"变异"掉许多适者有机体的好基因。默认的变异率为20%。

步骤7:突变

这种实现方式大致是位串变异,即生物的每一个基因都有1/n机会被另一个基因均匀随机替换,其中n是生物中的基因数。的基因组。这意味着,平均来说,突变会导致一个基因发生改变。

未来可能的扩展

这些是我想在未来实施的想法。检查dev分支上正在进行的过程。

  • 启用对CNN的支持
  • 支持RNN,特别是LSTM
  • 包括在基因之间建立依赖关系的选项。在神经网络的设置中,这可能包括作为所有层特异性基因依赖的基因的拓扑结构,这与本文中采用的方法类似。

许可证

该项目是在麻省理工学院许可证下获得许可的

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何定制springdata存储库方法名称?   html有没有办法将java应用程序或JApplet嵌入到网站中?   Jackson ObjectMapper将java从字符串序列化为JSON作为namevalue   java刷新JTable?   用Java程序分发用JavaDB制作的数据库   java Android如何启动新活动   当集合大小超过500.000时,java的处理速度会显著降低   在java的分层目录中的多个目录中查找相同的文件   java如何将ArrayList数据插入数据库   java如何修改此代码,使其时间复杂度为o(logn)或o(n),而不是o(n^2)   java面板(SimplePanel)中仅显示图像的前1/3(大约),   jakarta ee Java Bean和企业Java Bean之间的区别?   创建AWS Cloudfront自签名URL(java sdk)时出现amazon web服务错误   基于Jersey和Jackson查询参数的java动态属性过滤