AI Flappy Bird 无法正确变异

AI Flappy Bird doesnt mutate corectly

我是编程新手,尤其擅长人工智能编程。如果问题很愚蠢或很容易解决,我很抱歉。 我用神经网络创建了一个原始的飞扬的小鸟游戏来控制它。一切顺利,直到所有的鸟都死了。在所有鸟死后,我选择最好的鸟,创建新种群数组,将新鸟 "brain" 设置为等于最好的鸟 "brain",最后我将所有新种群鸟的大脑变异为很小,所以它们不一样。我尝试使用概率进行变异,改变新鸟类大脑的所有权重,设置 if 语句,以便权重不会低于 1.0 或低于 -1.0。结果是一样的,所有下一代(第二代)的鸟都表现得像它们一样 "brain"。 这里有一些我认为值得检查的代码。我可以放置所有代码,但它很大。

再人口

        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 只鸟的大脑分配给 birds.get(i).brain=lastbird.brain 处所有新生代鸟中的 lastbird.brain 时,您正在设置所有新生鸟的所有大脑的参考到同一个大脑对象。 IE。任何 bird.brain 引用指向同一个大脑对象。所以当你改变(即变异)一只鸟的大脑时,它是在所有参考指向的共同对象上完成的,并且同时反映在所有鸟身上。

您需要复制大脑对象的内容,而不是指向同一个对象。您可以通过克隆或使用复制构造函数来做到这一点。复制构造函数优于克隆。您需要将 birds.get(i).brain=lastbird.brain 替换为

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

由于你没有给出Brain对象的代码,我无法给出拷贝构造函数的实现。您可以在构造函数中使用 = 符号分配原语(int、String 等)。但是对于所有自定义对象,您还需要为它们创建一个复制构造函数。

您可以在此处找到更多信息 How do I copy an object in Java?

编辑: 在提供网络 class 后添加实施。

 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;
    }