有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

爪哇AI Flappy鸟不会正确变异

我是编程新手,尤其是人工智能编程。如果问题很愚蠢或很容易解决,我很抱歉。 我用神经网络创建了一个原始的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);
        }
    }
}

共 (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);
    

    既然你没有给出大脑对象的代码,我就不能给出复制构造函数的实现。可以在构造函数中使用=sign来分配原语(int、String等)。但对于所有自定义对象,也需要为它们创建一个副本构造函数

    你可以在这里找到更多信息

    编辑:在提供网络类后添加实现

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