本期课程到这里,博主就默认大家已经对BP、CNN、RNN等基本的神经网络属性以及训练过程都有相应的认知了,如果还未了解最基本的知识,可以翻看博主制作的深度学习的学习路线,按顺序阅读即可。
深度学习的学习路线:往期课程
Hello,又是一个分享的日子,之前博主给大家介绍了遗传演化神经网络,这期博主将在本期推文给大家介绍遗传拓扑神经网络。遗传拓扑神经网络同样是结合了神经网络和遗传算法与进化策略产生的一种全新模型。它通过模仿自然界“适者生存”的原则来赋予神经网络在代际循环中优化的力量,能有效克服传统神经网络在训练过程中的缺点。它与上期介绍的遗传演化神经网络不同的地方在于加入了交叉操作,且它的年代比较久远了,是2003年的一篇论文,因为近些年来算力的提升与强化学习的兴起,又走进了人们的视野。好了,闲言少叙,我们这就走进遗传与深度学习的世界。
Neat算法的论文
《Evolving Neural Networks through Augmenting Topologies 》
提取码:yxph https:// pan.baidu.com/s/1SmMEsg SMEdUwnhvsmwfnPg&shfl=sharepset
本文内容概要:
- 遗传拓扑神经网络(Neat算法)原理
- 遗传拓扑神经网络(Neat算法)实验
- 实验总结
- 新的征程---NLP修炼指北
1. 遗传拓扑神经网络的思想
1.1 原理
正如之前的遗传演化神经网络的推文所说,遗传算法是个通用框架,因此我们需要根据具体的问题来定义遗传算法。不过,既然它是框架,那它就会有通用的几部分供我们选择,因此博主在此给大家先讲下整体的流程。
整体框架可分为三部分:交叉、变异与适应度。不过虽然整体的流程是一致的,但是因为问题不同,我们定义的基因也有所不同,那交叉与变异也会随之变化。
这篇论文将神经元及其连接定义成基因组,而遗传演化神经网络论文是将网络层及其学习率定义成基因组,小伙伴们可以对比着学习两者的异同,这样也能更好地感受为什么说遗传算法是解决一般性问题的通用框架,就是因为我们可以根据问题去定义基因组。
1.2 算法核心
1.2.1 个体基因与种群规模
个体基因:(结点链接与结点类型)
种群规模:150
物种划分:基于权值相似度划分物种
由于该论文已经有人写好了框架,因此以上参数在配置文件中修改
即可,这将会在代码那里给大家演示。
while condition:
if random.random < 交叉率:
选择操作(适应度越高,越容易被选中)
物种内交叉
if random.random < 变异率:
变异操作
评估适应度
else: # 直接变异
if random.random < 变异率:
变异操作
评估适应度
# 淘汰操作
每个物种保留一定数量的个体
if random.random < 灭绝率:
灭绝最差的物种
种群间的物种交叉生成亚种, 弥补新的物种
conditon:迭代次数 or fittness达到设定的阈值
评估适应度:fitness = 1/(训练集的误差)^2
这里的适应度函数是自定义的,大家可以根据自己的想法去定义。
1.2.2 交叉操作:
论文通过一个链表定义基因的节点连接,选择两个个体进行交叉的时候,按照链表的顺序,逐一操作,最后生成新的子代。
1.2.3 变异操作:
同样地,变异操作也是在链表中进行,且会有两种变异:增加网络连接和增加网络节点。
2. 实验
2.1实验环境
- Anaconda Python 3.7
- Jupyter Notebook
- Keras
- 开发环境安装在之前的推文中已经介绍,还没安装的小伙伴可以翻一下。
- Python开发环境---Windows与服务器篇
- Python深度学习开发环境---Keras
- Neat-Python官网代码https://neat-python.readthedocs.io/en/latest/neat_overview.html
- 实现该篇论文的代码也加入了可视化操作
windows 用户:
cmd命令行输入以下命令
conda install -c conda-forge graphviz
conda install -c conda-forge python-graphviz
linux 用户:
命令行输入以下命令
sudo apt-get install graphviz
2.2 实验
2.1 数据与配置文件
这里实验使用官网的例子:实现一个能判断XOR异或操作的网络,让大家感受下具体如何操作。
xor_inputs = [(0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0)]
xor_outputs = [(0.0,), (1.0,), (1.0,), (0.0,)]
"""
异或:输入相异,输出1, 输入相同,输出0
"""
上文提到,有人已经实现了这篇论文的代码框架,我们只需要修改配置文件的相应参数,就可以运行Neat算法了,下面给大家介绍下Neat算法的配置文件,官网有对配置文件更详细的解释,这里博主只是标注一些自己用到的参数。
neat算法配置文件详细解释 https:// neat-python.readthedocs.io /en/latest/config_file.html
#--- parameters for the XOR-2 experiment ---#
[NEAT]
fitness_criterion = max
fitness_threshold = 3.9 # 适应度的阈值
pop_size = 150 # 种群规模
reset_on_extinction = False
[DefaultGenome]
# node activation options # 结点的激励函数
activation_default = sigmoid
activation_mutate_rate = 0.0
activation_options = sigmoid
# node aggregation options # 结点的聚合选择 (一般默认)
aggregation_default = sum
aggregation_mutate_rate = 0.0
aggregation_options = sum
# node bias options # 结点的偏置选择
bias_init_mean = 0.0
bias_init_stdev = 1.0
bias_max_value = 30.0
bias_min_value = -30.0
bias_mutate_power = 0.5
bias_mutate_rate = 0.7
bias_replace_rate = 0.1
# genome compatibility options
compatibility_disjoint_coefficient = 1.0
compatibility_weight_coefficient = 0.5
# connection add/remove rates
conn_add_prob = 0.5
conn_delete_prob = 0.5
# connection enable options
enabled_default = True
enabled_mutate_rate = 0.01
feed_forward = True # 是否加入RNN神经元
initial_connection = full
# node add/remove rates # 结点的添加和删除概率
node_add_prob = 0.2
node_delete_prob = 0.2
# network parameters # 输入层、输出层、隐藏层的神经元个数
num_hidden = 2
num_inputs = 2
num_outputs = 1
# node response options
response_init_mean = 1.0
response_init_stdev = 0.0
response_max_value = 30.0
response_min_value = -30.0
response_mutate_power = 0.0
response_mutate_rate = 0.0
response_replace_rate = 0.0
# connection weight options
weight_init_mean = 0.0
weight_init_stdev = 1.0
weight_max_value = 30
weight_min_value = -30
weight_mutate_power = 0.5
weight_mutate_rate = 0.8
weight_replace_rate = 0.1
[DefaultSpeciesSet]
# genomic distance小于此距离被认为是同一物种
compatibility_threshold = 3.0
[DefaultStagnation]
species_fitness_func = max
max_stagnation = 20
species_elitism = 2
[DefaultReproduction]
elitism = 2 # 保留最优的个体遗传到下一代的个数
survival_threshold = 0.2 # 每一代每个物种的存活率
2.2 核心代码
from __future__ import print_function
import os
import neat
import visualize
# XOR异或的输入输出数据
xor_inputs = [(0.0, 0.0), (0.0, 1.0), (1.0, 0.0), (1.0, 1.0)]
xor_outputs = [ (0.0,), (1.0,), (1.0,), (0.0,)]
def eval_genomes(genomes, config):
# 评估函数
for genome_id, genome in genomes:
genome.fitness = 4.0
net = neat.nn.FeedForwardNetwork.create(genome, config)
for xi, xo in zip(xor_inputs, xor_outputs):
output = net.activate(xi)
genome.fitness -= (output[0] - xo[0]) ** 2
def run(config_file):
# 读取配置配置文件
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
neat.DefaultSpeciesSet, neat.DefaultStagnation,
config_file)
# 创建种群
p = neat.Population(config)
# 打印训练过程
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
p.add_reporter(neat.Checkpointer(5))
# 迭代300次
winner = p.run(eval_genomes, 300)
# 显示最佳网络
print('nBest genome:n{!s}'.format(winner))
print('nOutput:')
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
for xi, xo in zip(xor_inputs, xor_outputs):
output = winner_net.activate(xi)
print("input {!r}, expected output {!r}, got {!r}".format(xi, xo, output))
node_names = {-1:'A', -2: 'B', 0:'A XOR B'}
visualize.draw_net(config, winner, True, node_names=node_names)
visualize.plot_stats(stats, ylog=False, view=True)
visualize.plot_species(stats, view=True)
p = neat.Checkpointer.restore_checkpoint('neat-checkpoint-4')
p.run(eval_genomes, 10)
if __name__ == '__main__':
config_path = os.path.join('config-feedforward')
run(config_path)
2.3 Git链接
代码ChileWang0228/DeepLearningTutorialgithub.com
2.4 训练结果
生成的.svg后缀文件用google浏览器打开即可,显示的就是下面两张图。
2.5 视频版
视频版包含了代码讲解部分,不过博主的代码都做了相应的注释,相信大家都能看懂,喜欢视频版的小伙伴可以去观看~~~
bilibili值得拥有~(っ•̀ω•́)っ✎⁾⁾ 我爱学习 https:// space.bilibili.com/2995 85150
3.总结
好了,到这里,我们就已经将遗传拓扑神经网络(Neat算法)的知识点讲完了。大家在掌握了整个流程之后,可以把官方代码下载下来,调一下配置文件,就可以运行了。当然,有些小伙伴可能会想着自己定义一个新的交叉或者变异操作,这就需要对着Neat算法的源码修改相应的代码了。
最后总结一下,因为算力的提升,遗传算法+深度学习近年来逐渐走入人们的视野,不过应用比较广泛的是在强化学习领域。究其原因还是因为强化学习的本质和遗传算法一致,都是适者生存,不适者淘汰。比如有人用Neat算法训练了个超级马里奥,其实就是训练一个机器人在游戏环境中生存,适应度函数可以定义为在游戏里的得分亦或者是在游戏中的存活时间,在不断迭代过程中,存活下来的机器人一定是对当前环境反馈最佳的。
当然了,这里提及Neat算法,主要是想让大家对比两期遗传算法的实验,掌握遗传算法的流程精髓,顺带了解一下强化学习是干嘛的。
最后还要说一下,到这里为止,深度学习的基础课程也就告一段落了。下一期开始,博主就开始更新NLP方面的内容了,这是博主研究生的主攻方向,希望能在接下来的分享中,大家共同进步。
~~~~~完结撒花~~~~~
如果本期推文有用,那就点个赞吧,你们的点赞是博主持续更新的动力,感谢每一位小伙伴的关注~