AI Flappy Bird 变异不正确

我是一个编程新手,尤其是在编写AI程序方面。如果我的问题显得愚蠢或者容易解决,请原谅我。我创建了一个原始的Flappy Bird游戏,并使用神经网络来控制它。一切进展顺利,直到所有的鸟都死掉。所有的鸟死掉后,我会选择最佳的鸟,创建一个新种群的数组,将新鸟的“大脑”设置为与最佳鸟的“大脑”相同,最后我会对所有新种群鸟的大脑进行微小的变异以确保它们不完全相同。我尝试使用概率进行变异,对所有新鸟的大脑权重进行变异,并设置if语句以确保权重不会低于1.0或高于-1.0。然而,结果是一样的,所有下一代(第二代)的鸟行为表现得像是拥有相同的大脑。以下是我认为值得检查的一些代码。我可以提供所有代码,但代码量很大。

重新填充种群

        for (int i = 0; i < population; i++) {            birds.add(new Bird());            birds.get(i).brain=lastbird.brain;            birds.get(i).brain.mutate(0.1);        }

变异函数

        public void mutate(double eta) {        Random dice = new Random();        for (int layer = 1; layer < NETWORK_SIZE; layer++) {            for (int neuron = 0; neuron < NETWORK_LAYER_SIZES[layer]; neuron++) {                if (dice.nextDouble() < eta) {                    bias[layer][neuron] += dice.nextGaussian()/2;                }                for (int prevNeuron = 0; prevNeuron < NETWORK_LAYER_SIZES[layer - 1]; prevNeuron++) {                    if (dice.nextDouble() < eta) {                        weights[layer][neuron][prevNeuron] += dice.nextGaussian()/2;                    }                }        }        }        }

网络(脑)变量和构造函数

public class Network  {private double[][] output;private double[][][] weights;private double[][] bias;private double[][] error_signal;private double[][] output_derivative;public final int[] NETWORK_LAYER_SIZES;public final int INPUT_SIZE;public final int OUTPUT_SIZE;public final int NETWORK_SIZE;public Network(int... NETWORK_LAYER_SIZES) {    this.NETWORK_LAYER_SIZES = NETWORK_LAYER_SIZES;    this.INPUT_SIZE = NETWORK_LAYER_SIZES[0];    this.NETWORK_SIZE = NETWORK_LAYER_SIZES.length;    this.OUTPUT_SIZE = NETWORK_LAYER_SIZES[NETWORK_SIZE - 1];    this.output = new double[NETWORK_SIZE][];    this.weights = new double[NETWORK_SIZE][][];    this.bias = new double[NETWORK_SIZE][];    this.error_signal = new double[NETWORK_SIZE][];    this.output_derivative = new double[NETWORK_SIZE][];    for (int i = 0; i < NETWORK_SIZE; i++) {        this.output[i] = new double[NETWORK_LAYER_SIZES[i]];        this.error_signal[i] = new double[NETWORK_LAYER_SIZES[i]];        this.output_derivative[i] = new double[NETWORK_LAYER_SIZES[i]];        this.bias[i] = NetworkTools.createRandomArray(NETWORK_LAYER_SIZES[i], -0.5, 0.7);        if (i > 0) {            weights[i] = NetworkTools.createRandomArray(NETWORK_LAYER_SIZES[i], NETWORK_LAYER_SIZES[i - 1], -1, 1);        }    }}

回答:

当你将第i只鸟的大脑分配给lastbird.brain,即在birds.get(i).brain=lastbird.brain中对所有新一代的鸟进行设置时,你实际上是将所有新鸟的大脑引用设置为指向同一个大脑对象。也就是说,任何鸟的大脑引用都指向同一个大脑对象。因此,当你改变(即变异)一只鸟的大脑时,变异是在所有引用指向的共同对象上进行的,同时也会反映到所有鸟身上。

你需要复制大脑对象的内容,而不是指向同一个对象。你可以通过克隆或使用复制构造函数来实现这一点。复制构造函数比克隆更受欢迎。你需要将birds.get(i).brain=lastbird.brain替换为

birds.get(i).brain = new Brain(lastbird.brain);

由于你没有提供Brain对象的代码,我无法提供复制构造函数的实现。你可以在构造函数中使用=号来分配基本类型(如int、String等)。但对于所有自定义对象,你也需要为这些对象创建复制构造函数。

你可以在这里找到更多信息 如何在Java中复制对象?

编辑: 在提供了Network类之后,添加了实现。

 public Network( Network other )    {        this.output = copy2d( other.output );        this.weights = copy3d( other.weights );        this.bias = copy2d( other.bias );        this.error_signal = copy2d( other.error_signal );        this.output_derivative = copy2d( other.output_derivative );        this.NETWORK_LAYER_SIZES = copy1dInt(other.NETWORK_LAYER_SIZES);        this.INPUT_SIZE = other.INPUT_SIZE;        this.OUTPUT_SIZE = other.OUTPUT_SIZE;        this.NETWORK_SIZE = other.NETWORK_SIZE;    }    private static double[][][] copy3d( double[][][] original )    {        double[][][] copy = new double[original.length][][];        for( int i = 0; i < original.length; i++ )        {            copy[i] = copy2d( original[i] );        }        return copy;    }    private  static double[][] copy2d( double[][] original )    {        double[][] copy = new double[original.length][];        for( int i = 0; i < original.length; i++ )        {            copy[i] = copy1d( original[i] );        }        return copy;    }    private static double[] copy1d( double[] original )    {        int length = original.length;        double[] copy = new double[length];        System.arraycopy( original, 0, copy, 0, length );        return copy;    }    private static int[] copy1dInt( int[] original )    {        int length = original.length;        int[] copy = new int[length];        System.arraycopy( original, 0, copy, 0, length );        return copy;    }

Related Posts

Keras Dense层输入未被展平

这是我的测试代码: from keras import…

无法将分类变量输入随机森林

我有10个分类变量和3个数值变量。我在分割后直接将它们…

如何在Keras中对每个输出应用Sigmoid函数?

这是我代码的一部分。 model = Sequenti…

如何选择类概率的最佳阈值?

我的神经网络输出是一个用于多标签分类的预测类概率表: …

在Keras中使用深度学习得到不同的结果

我按照一个教程使用Keras中的深度神经网络进行文本分…

‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

我写了一个简单的TensorFlow代码,但不断遇到T…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注