看起来我的程序在尝试学习到某个点之后就满足了,然后不再改进和变化。经过我的测试,它通常最多达到-5的值,然后无论我运行多久,它都保持在这个值上。结果集也没有变化。
为了跟踪这个情况,我自己做了一种日志记录方式,以便查看哪个表现最好。由一和零组成的数组指的是AI做出正确选择(1)的频率,以及AI做出错误选择(0)的频率。
我的目标是让AI重复一个模式,即超过0.5然后低于0.5,而不是特意找出奇数。这只是一个小测试,看看我能否让AI在一些基本数据上正常工作,然后再做一些更高级的尝试。
但遗憾的是,它没有工作,我不确定为什么。
代码如下:
import osimport neatdef main(genomes, config): networks = [] ge = [] choices = [] for _, genome in genomes: network = neat.nn.FeedForwardNetwork.create(genome, config) networks.append(network) genome.fitness = 0 ge.append(genome) choices.append([]) for x in range(25): for i, genome in enumerate(ge): output = networks[i].activate([x]) # print(str(x) + " - " + str(i) + " chose " + str(output[0])) if output[0] > 0.5: if x % 2 == 0: ge[i].fitness += 1 choices[i].append(1) else: ge[i].fitness -= 5 choices[i].append(0) else: if not x % 2 == 0: ge[i].fitness += 1 choices[i].append(1) else: ge[i].fitness -= 5 choices[i].append(0) pass # Optional death function, if I use this there are no winners at any point. # if ge[i].fitness <= 20: # ge[i].fitness -= 100 # ge.pop(i) # choices.pop(i) # networks.pop(i) if len(ge) > 0: fittest = -1 fitness = -999999 for i, genome in enumerate(ge): if ge[i].fitness > fitness: fittest = i fitness = ge[i].fitness print("Best: " + str(fittest) + " with fitness " + str(fitness)) print(str(choices[fittest])) else: print("Done with no best.")def run(config_path): config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path) pop = neat.Population(config) #pop.add_reporter(neat.StdOutReporter(True)) #stats = neat.StatisticsReporter() #pop.add_reporter(stats) winner = pop.run(main, 100)if __name__ == "__main__": local_dir = os.path.dirname(__file__) config_path = os.path.join(local_dir, "config-feedforward.txt") run(config_path)
NEAT配置如下:
[NEAT]fitness_criterion = maxfitness_threshold = 100000pop_size = 5000reset_on_extinction = False[DefaultGenome]# node activation optionsactivation_default = tanhactivation_mutate_rate = 0.0activation_options = tanh# node aggregation optionsaggregation_default = sumaggregation_mutate_rate = 0.0aggregation_options = sum# node bias optionsbias_init_mean = 0.0bias_init_stdev = 1.0bias_max_value = 30.0bias_min_value = -30.0bias_mutate_power = 0.5bias_mutate_rate = 0.7bias_replace_rate = 0.1# genome compatibility optionscompatibility_disjoint_coefficient = 1.0compatibility_weight_coefficient = 0.5# connection add/remove ratesconn_add_prob = 0.5conn_delete_prob = 0.5# connection enable optionsenabled_default = Trueenabled_mutate_rate = 0.1feed_forward = Trueinitial_connection = full# node add/remove ratesnode_add_prob = 0.2node_delete_prob = 0.2# network parametersnum_hidden = 0num_inputs = 1num_outputs = 1# node response optionsresponse_init_mean = 1.0response_init_stdev = 0.0response_max_value = 30.0response_min_value = -30.0response_mutate_power = 0.0response_mutate_rate = 0.0response_replace_rate = 0.0# connection weight optionsweight_init_mean = 0.0weight_init_stdev = 1.0weight_max_value = 30weight_min_value = -30weight_mutate_power = 0.5weight_mutate_rate = 0.8weight_replace_rate = 0.1[DefaultSpeciesSet]compatibility_threshold = 3.0[DefaultStagnation]species_fitness_func = maxmax_stagnation = 20species_elitism = 2[DefaultReproduction]elitism = 2survival_threshold = 0.2
回答:
很遗憾地告诉你,这种方法行不通。请记住,神经网络通常是由矩阵乘法然后与0取最大值(称为RELU)构建的,所以基本上每层都是线性的带有截止(不,选择不同的激活函数如sigmoid也帮不上忙)。你希望网络产生>.5, <.5, >.5, <.5, … 25次。想象一下用RELU块构建这个需要什么。你至少需要一个大约25层的深度网络,而NEAT在没有持续的进化增量进展的情况下,是不会产生这么大的网络的。不过你并不孤单,你所做的事情相当于学习模运算,这个问题已经研究了多年。这里有一个成功的帖子,尽管不是使用NEAT。 Keras: 制作一个神经网络来找出一个数的模数
你能在NEAT上取得的唯一真正的进展是给网络提供更多的输入特征,例如,提供x%2
作为输入,它会很快学会,尽管这显然是“作弊”。