AI Flappy Bird不会直接变异



我是编程新手,尤其是ai编程。如果问题很愚蠢或很容易解决,我很抱歉。我用神经网络控制了一个原始的拍打鸟游戏。一切都很顺利,直到所有的鸟都死了。在所有鸟类死亡后,我选择了最好的鸟类,创建了新种群的阵列,将新鸟类的"大脑"设置为等于最好的鸟类的"头脑",最后我将所有新种群的鸟类的大脑都变异一小部分,使它们不一样。我试着用概率进行变异,变异新鸟大脑的所有权重,设置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);
}
}
}

当您在birds.get(i).brain=lastbird.brain将第i只鸟的大脑分配给所有新一代鸟中的lastbird.brain时,您正在将所有新鸟的所有大脑的引用设置为同一个大脑对象。任何一只鸟的大脑参考都指向同一个大脑对象。因此,当你改变(即变异(一只鸟的大脑时,它是在所有参考所指向的共同对象上完成的,并且同时反映在所有鸟身上。

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

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

由于你还没有给出Brain对象的代码,我无法给出复制构造函数的实现。您可以在构造函数中使用=sign来分配基元(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;
}

最新更新