neat-python是對遺傳算法的拓展,結合了神經網絡和遺傳算法的模型,本文旨在使用不在講解。
本文利用neat計算x²來進行一個neat的初步使用,通過本文教程可以大致使用neat完成一些基礎任務。
pip install neat-python
neat利用config文件來進行參數配置,具體的配置文件模板可以在官方文檔中找到:配置文件模板地址。
[NEAT]
fitness_criterion = max
fitness_threshold = 3.9
pop_size = 50
reset_on_extinction = False
[DefaultGenome]
# node activation options
activation_default = square
activation_mutate_rate = 0.0
activation_options = square
# 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
# node add/remove rates
node_add_prob = 0.2
node_delete_prob = 0.2
# network parameters
num_hidden = 0
num_inputs = 1
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]
compatibility_threshold = 3.0
[DefaultStagnation]
species_fitness_func = max
max_stagnation = 20
species_elitism = 2
[DefaultReproduction]
elitism = 2
survival_threshold = 0.2
文件取名為config-feedforward.txt。
本文將不闡述每一個參數的內容,僅介紹將會使用的一些參數。
在本文中,我們需要計算x²,所以首先在腦海中需要明白我們的圖形產出是一個二次方程圖形:
所以我們選擇了:
activation_default = square
activation_mutate_rate = 0.0
activation_options = square
其他的激活函數可以查看官方文檔:激活函數列表。
在使用neat時,需要明白我們輸出的結果是什麼,比如本文,我們知道結果是平方,所以用square;如果需要輸出是或否,那可以選擇sigmoid。
在本文中,我們只有一個x,得到的結果只有一個y,例如2輸出4,3輸出9,所以在這部分我們設置為:
num_hidden = 0
num_inputs = 1
num_outputs = 1
我們沒有隱藏層,如果需要隱藏層,可以設置num_hidden。
本文中,將每一個族群設置為50個,阈值設為3.9,表示每一次計算會有50個子代,當適應值達到3.9,將停止迭代:
fitness_threshold = 3.9
pop_size = 50
我們需要設置的參數絕大部分都是上面的內容,其他參數特殊情況特殊配置,一般使用情況下可以直接使用默認參數值。
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, 'config-feedforward.txt') # 配置文件名稱
config = neat.config.Config(
neat.DefaultGenome,
neat.DefaultReproduction,
neat.DefaultSpeciesSet,
neat.DefaultStagnation,
config_path
)# 配置文件中每一組
p = neat.Population(config)
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
winner = p.run(eval_genomes, 1000) # 定義一個eval_genomes方法進行迭代,總共迭代100次
def eval_genomes(genomes, config):
# x ** 2
x_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 樣本
y_list = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] # 樣本結果
for genome_id, genome in genomes: # 循環50個子代
genome.fitness = 4.0 # 初始化適應度
net = neat.nn.FeedForwardNetwork.create(genome, config) # 創建前饋網絡
for i, x in enumerate(x_list):
output = net.activate((x, )) # 計算
genome.fitness -= (output[0] - y_list[i]) ** 2 # 使用誤差來進行適應值的降低
當進行p.run函數時,將進行eval_genomes函數的調用,在eval_genomes函數中,適當地給予每一個子代(基因)適應度的調整,來選擇合適的子代,當子代達到我們的適應值阈值時,將會停止迭代。
Population's average fitness: -42724756.48750 stdev: 220655177.29976
Best fitness: 3.98619 - size: (1, 1) - species 1 - id 3838
Best individual in generation 87 meets fitness threshold - complexity: (1, 1)
本次運行結果到第87代已經產生最佳適應度為3.98612的子代,我們可以通過保存計算結果來進行使用。
pickle.dump(winner, open("best.pickle", "wb"))
path = "xx/xx/xx/best.pickle"
with open(path, "rb") as f:
net = pickle.load(f)
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, 'config-feedforward.txt')
config = neat.config.Config(
neat.DefaultGenome,
neat.DefaultReproduction,
neat.DefaultSpeciesSet,
neat.DefaultStagnation,
config_path
)
net = neat.nn.FeedForwardNetwork.create(net, config)
output = net.activate((4,))
print(output[0])
輸出結果為:
15.842392247827298
可以看到,結果已經是我們想要的了。
# -*- coding: utf-8 -*-
import os
import neat
import pickle
def eval_genomes(genomes, config):
# x ** 2
x_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y_list = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
for genome_id, genome in genomes:
genome.fitness = 4.0
net = neat.nn.FeedForwardNetwork.create(genome, config)
for i, x in enumerate(x_list):
output = net.activate((x, ))
genome.fitness -= (output[0] - y_list[i]) ** 2
if __name__ == '__main__':
path = "xx/xx/xx/best.pickle"
with open(path, "rb") as f:
net = pickle.load(f)
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, 'config-feedforward.txt')
config = neat.config.Config(
neat.DefaultGenome,
neat.DefaultReproduction,
neat.DefaultSpeciesSet,
neat.DefaultStagnation,
config_path
)
net = neat.nn.FeedForwardNetwork.create(net, config)
output = net.activate((4,))
print(output[0])
# local_dir = os.path.dirname(__file__)
# config_path = os.path.join(local_dir, 'config-feedforward.txt')
#
# config = neat.config.Config(
# neat.DefaultGenome,
# neat.DefaultReproduction,
# neat.DefaultSpeciesSet,
# neat.DefaultStagnation,
# config_path
# )
#
# p = neat.Population(config)
#
# p.add_reporter(neat.StdOutReporter(True))
# stats = neat.StatisticsReporter()
# p.add_reporter(stats)
#
# winner = p.run(eval_genomes, 1000)
# pickle.dump(winner, open("best.pickle", "wb"))
More , Please visit mine Pers
1. rsaUtil.py #!/usr