-
compatibility_threshold:用于控制生物是属于同一物种(基因组距离小于该值)还是属于不同物种的阈值。较高的值表示进化过程的物种 形成能力较小。
-
compatibility_disjoint_coefficient:在基因组距离计算过程中用来计算不相交或多余基因对计算结果的贡献程度的系数。此参数较高会放大基因组距离计算中不相交或多余的基因存在的重要性。
-
compatibility_weight_coefficient:用于管理节点基因的偏置和响应属性之间的差异的基因组距离计算以及连接基因的权重属性对结果的贡献的系数。
-
conn_add_prob:在现有节点基因之间引入新连接基因的突变概率。
-
conn_delete_prob:从基因组中删除现有连接基因的突变概率。
-
enabled_default:新创建的连接基因的enabled属性的默认值。
-
enabled_mutate_rate:触发连接基因的启用属性的突变概率。
-
feed_forward:控制在生成过程中生成的表型网络的类型。如果设置为True,则不允许重复连接。
-
initial_connection:为新创建的基因组指定初始连接模式。允许的值包括unconnected,fs_neat_nohidden,fs_neat_hidden,full_direct,full_nodirect,partial_direct和partial_nodirect。
-
node_add_prob:添加新节点基因的突变概率。
node_delete_prob:从基因组及其所有连接中删除现有节点基因的突变概率。
-
num_hidden,num_inputs,num_outputs:初始种群基因组中隐藏,输入和输出节点的数量。
-
single_structural_mutation:如果设置为True,则在演化过程中仅允许结构突变,即,仅允许添加或移除节点或连接。
XOR实践采用超参数
[NEAT]
fitness_criterion = max
fitness_threshold = 15.5
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
initial_connection = full_direct
node add/remove rates
node_add_prob = 0.2
node_delete_prob = 0.2
The network parameters
num_hidden = 0
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.0
weight_min_value = -30.0
weight_mutate_power = 0.5
weight_mutate_rate = 0.8
weight_replace_rate = 0.1
[DefaultSpeciesSet]
compatibility_threshold = 3.0
[DefaultStagnation]
species_fitness_func = max
max_stagnation = 20
species_elitism = 2
[DefaultReproduction]
elitism = 2
survival_threshold = 0.2
min_species_size = 4
XOR实践运行
选择NEAT-Python库作为编写代码的框架。
环境配置
依赖库包括:
-
neat-python
-
matplotlib
-
graphviz
-
python-graphviz
用于可视化的源代码visualize.py
from future import print_function
import copy
import warnings
import graphviz
import matplotlib.pyplot as plt
import numpy as np
def plot_stats(statistics,ylog=False,view=False,filename=‘avg_fitness.svg’):
“”"
plots the population’s average and best fitness.
“”"
if plt is None:
warnings.warn(“This display is not available due to a missing optional dependency (matplotlib)”)
return
generation = range(len(statistics.most_fit_genomes))
best_fitness = [c.fitness for c in statistics.most_fit_genomes]
avg_fitness = np.array(statistics.get_fitness_mean())
stdev_fitness = np.array(statistics.get_fitness_stdev())
plt.plot(generation,avg_fitness,‘b-’,label=‘average’)
plt.plot(generation,avg_fitness-stdev_fitness,‘g-.’,label=‘-1 sd’)
plt.plot(generation,avg_fitness+stdev_fitness,‘g-’,label=‘+1 sd’)
plt.plot(generation,best_fitness,‘r-’,label=‘best’)
plt.title(“Population’s average and best fitness”)
plt.xlabel(“Generation”)
plt.ylabel(“Fitness”)
plt.grid()
plt.legend(loc=“best”)
if ylog:
plt.gca().set_yscale(‘symlog’)
plt.savefig(filename)
if view:
plt.show()
plt.close()
def plot_species(statistics,view=False,filename=‘speciation.svg’):
“”"
Visualizes speciation throughout evolution.
“”"
if plt is None:
warnings.warn(“This display is not available due to a missing optional dependency (matplotlib)”)
return
species_sizes = statistics.get_species_sizes()
num_generations = len(species_sizes)
curves = np.array(species_sizes).T
fig,ax = plt.subplots()
ax.stackplot(range(num_generations),*curves)
plt.title(“Speciation”)
plt.ylabel(“Size per Species”)
plt.xlabel(“Generations”)
plt.savefig(filename)
if view:
plt.show()
plt.close()
def draw_net(config,genome,view=False,filename=None,directory=None,
node_names=None,show_disabled=True,prune_unused=False,
node_colors=None,fmt=‘svg’):
“”"
Receives a genome and draws a neural network with arbitrary topology.
“”"
Attributes for network nodes.
if graphviz is None:
warnings.warn(“This display is not available due to a missing optional dependency (graphviz”)
return
if node_names is None:
node_names = {}
assert type(node_names) is dict
if node_colors is None:
node_colors = {}
assert type(node_colors) is dict
node_attrs = {
‘shape’: ‘circle’,
‘fontsize’: ‘9’,
‘height’: ‘0.2’,
‘width’: ‘0.2’
}
dot = graphviz.Digraph(format=fmt,node_attr=node_attrs)
inputs = set()
for k in config.genome_config.input_keys:
inputs.add(k)
name = node_names.get(k,str(k))
input_attrs = {‘style’:‘filled’,‘shape’:‘box’,‘fillcolor’:node_colors.get(k,‘lightgray’)}
dot.node(name,_attributes=input_attrs)
outputs = set()
for k in config.genome_config.output_keys:
outputs.add(k)
name = node_names.get(k,str(k))
node_attrs = {
‘style’:‘filled’,
‘fillcolor’:node_colors.get(k,‘lightgray’)
}
if prune_unused:
connections = set()
for cg in genome.connections.values():
if cg.enabled or show_disabled:
connections.add((cg.in_node_id,cg._out_node_id))
used_nodes = copy.copy(outputs)
pending = copy.copy(outputs)
while pending:
new_pending = set()
for a,b in connections:
for b in pending and a not in used_nodes:
new_pending.add(a)
used_nodes.add(a)
pending = new_pending
else:
used_nodes = set(genome.nodes.keys())
for n in used_nodes:
if n in inputs or n in outputs:
continue
attrs = {
‘style’:‘filled’,
‘fillecolor’:node_colors.get(n,‘while’)
}
dot.node(str(n),_attributes=attrs)
for cg in genome.connections.values():
if cg.enabled or show_disabled:
if cg.input not in used_nodes or cg.output not in used_nodes:
continue
input_node,output_node = cg.key
a = node_names.get(input_node,str(input_node))
b = node_names.get(output_node,str(output_node))
style = ’ solid’ if cg.enabled else ‘dotted’
color = ‘green’ if cg.weight > 0 else ‘red’
width = str(0.1 + abs(cg.weight / 5.0))
dot.edge(a,b,_attributes={‘style’:style,‘color’:color,‘penwidth’:width})
dot.render(filename,directory,view=view)
return dot
XOR实践源代码xor_experiment详解
- 首先,需要导入将在以后使用的库:
The Python standard library import
import os
The NEAT-Python library imports
import neat
The helper used to visualize experiment results
import visualize
- 接下来,需要编写适应度评估代码:
The XOR inputs and expected corresponding outputs for fitness evaluate
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_fitness(net):
“”"
Evaluates fitness of the genome that was used to generate provided net
Arguments:
net: The feed-forward neural network generated from genome
Returns:
The fitness score - the higher score the means the better fit organism.
Maximal score: 16.0
“”"
error_sum = 0.0
for xi,xo in zip(xor_inputs,xor_outputs):
output = net.activate(xi)
error_sum += abs(output[0] - xo[0])
calculate amplified fitness
fitness = (4 - error_sum) ** 2
return fitness
- 使用适应度评估函数,编写函数来评估当前一代中的所有生物,并相应地更新每个基因组的适应度:
def eval_genomes(genomes,config):
“”"
The fitness to evaluate the fitness of each genome in the genomes list.
The provided configuration is used to create feed-forward neural network from each
genome and after that created the neural neural network evaluated in its ability to
solve XOR problem.
As a result of that function execution, the fitness score of each genome updated to
the newly one.
“”"
for genome_id,genome in genomes:
genome.fitness = 4.0
net = neat.nn.FeedForwardNetwork.create(genome,config)
genome.fitness = eval_fitness(net)
- run_experiment函数从配置文件加载超参数配置,并创建初始基因组种群:
Load configuration
config = neat.Config(
neat.DefaultGenome,neat.DefaultReproduction,
neat.DefaultSpeciesSet,neat.DefaultStagnation,
config_file
)
Create the population, which is the top-level object for a NEAT run
p = neat.Population(config)
- 记录统计数据,以便评估实验并观察过程。保存检查点也是必不可少的,可以在出现故障的情况下从给定的检查点恢复执行。因此,可以按以下方式注册两种类型的报告器(标准输出和统计信息收集器)和检查点收集器:
Add a stdut reporter to show progress in the terminal
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
p.add_reporter(neat.Checkpointer(5,filename_prefix=‘out/neat-checkpoint-’))
- 之后,通过提供eval_genome函数,运行神经进化300代,该函数用于评估每个世代群体中每个基因组的适应度评分,直到找到解或该过程达到最大世代数为止:
Run for up to 300 generations
best_genome = p.run(eval_genomes,300)
- 当NEAT算法的执行由于成功或达到最大世代数而停止执行时,将返回最适合的基因组。可以检查该基因组是否是所求解:
Check if the best genome is an adequate XOR solor
best_genome_fitness = eval_fitness(net)
if best_genome_fitness > config.fitness_threshold:
print(“\n\nSUCCESS: The XOR problem solver found!!!”)
else:
print(“\n\nFAILURE: Failed to find XOR problem solver!!!”)
8.最后,可以将收集到的统计数据和最适合的基因组可视化,以探索神经进化过程的结果:
Visualize the experiment result
node_names = {-1:‘A’,-2:‘B’,0:‘A XOR B’}
visualize.draw_net(config,best_genome,True,node_names=node_names,directory=output_dir)
visualize.plot_stats(stats,ylog=False,view=True,filename=os.path.join(output_dir,‘avg_fitness.svg’))
visualize.plot_species(
stats,view=True,filename=os.path.join(output_dir,‘speciation.svg’)
)
xor_experiment.py完整代码
import os
import shutil
import neat
import visualize
The current working directory
local_dir = os.path.dirname(file)
The directory to store outputs
output_dir = os.path.join(local_dir,‘out’)
The XOR inputs and expected corresponding outputs for fitness evaluate
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_fitness(net):
“”"
Evaluates fitness of the genome that was used to generate provided net
Arguments:
net: The feed-forward neural network generated from genome
Returns:
The fitness score - the higher score the means the better fit organism.
Maximal score: 16.0
“”"
error_sum = 0.0
for xi,xo in zip(xor_inputs,xor_outputs):
output = net.activate(xi)
error_sum += abs(output[0] - xo[0])
calculate amplified fitness
fitness = (4 - error_sum) ** 2
return fitness
def eval_genomes(genomes,config):
“”"
The fitness to evaluate the fitness of each genome in the genomes list.
The provided configuration is used to create feed-forward neural network from each
genome and after that created the neural neural network evaluated in its ability to
solve XOR problem.
As a result of that function execution, the fitness score of each genome updated to
the newly one.
“”"
for genome_id,genome in genomes:
genome.fitness = 4.0
net = neat.nn.FeedForwardNetwork.create(genome,config)
genome.fitness = eval_fitness(net)
def run_experiment(config_file):
“”"
The function to run XOR experiment against hyper-parameters
defined in the provided configuration file.
The winner genome will be rendered as a graph as well as the
important statistics of neuroevolution process execution.
Arguments:
config_file: the path to the file with experiment configuration
“”"
Load configuration
config = neat.Config(
neat.DefaultGenome,neat.DefaultReproduction,
neat.DefaultSpeciesSet,neat.DefaultStagnation,
config_file
)
Create the population, which is the top-level object for a NEAT run
p = neat.Population(config)
Add a stdut reporter to show progress in the terminal
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
p.add_reporter(neat.Checkpointer(5,filename_prefix=‘out/neat-checkpoint-’))
Run for up to 300 generations
现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。
分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!