同一脚本的多个实例中的变量没有明显的原因就可以共享/覆盖

时间:2019-07-13 21:39:08

标签: c# unity3d

我正在研究一个小型神经网络进化学习项目。当我尝试随机改变我的NeuralNetwork脚本的多个实例上的权重和偏差时,这些脚本似乎相互之间没有明显的原因。

两个主要脚本是管理学习过程的GameManager脚本,还有许多NeuralNetwork脚本实例,每个实例都有各自的权重和偏见。

问题在于,当产生新一代时,每个NeuralNetwork脚本都具有相同的权重和偏差,它们随后使用NeuralNetwork脚本中的Mutate()函数对其进行随机且唯一地变异,它们最终都具有相同的权重和偏见。我已经检查过Mutate()函数是否正常工作,并分别为每个NeuralNetwork实例更改权重和偏差,但是它们都被“最后一个”脚本实例覆盖而发生突变。

我尝试在NeuralNetwork的每个实例中随机延迟Mutate()函数,尝试不通过预制实例化NeuralNetork脚本,尝试直接从GameManager和NeuralNetwork脚本中调用Mutate()函数一个“代理”布尔值。我还尝试将Mutate()函数移至GameManager。我什至尝试在突变发生之前就在运行时关闭GameManager。似乎没有任何帮助。

此功能用于在运行时开始时生成NeuralNetwork。

    void SpawnNeuralNetworks() {
    for (int i = 0; i < creaturesPerGeneration; i++) {
        neuralNetworkGameObjects[i] = Instantiate(new GameObject(), transform);
        neuralNetworkGameObjects[i].name = "NeuralNetwork" + i;
        neuralNetworkScripts[i] = neuralNetworkGameObjects[i].AddComponent<NeuralNetwork>() ;
        neuralNetworkScripts[i].layers = layers;
        neuralNetworkScripts[i].mutationChanceMultiplier = mutationChanceMultiplier;
        neuralNetworkScripts[i].mutationRateMultiplier = mutationRateMultiplier;
    }
}

此功能用于生成新一代生物(神经网络不会被破坏)。

void SpawnNextGeneration() {
    currentGeneration += 1;

    for (int i = 0; i < creaturesPerGeneration; i++) {
        Destroy(creatures[i]);
    }

    CalculateAverageWeightsandBiases();
    fitness = new float[creaturesPerGeneration];
    creatures = new GameObject[creaturesPerGeneration];

    for (int i = 0; i < creaturesPerGeneration; i++) {
        creatures[i] =  Instantiate(creaturePrefab);
        creatures[i].name = "Creature" + i;
        creatures[i].GetComponent<CreatureController>().neuralNetworkID = 
  i;

        neuralNetworkScripts[i].weights = bestWeights;
        neuralNetworkScripts[i].biases = bestBiases;
        neuralNetworkScripts[i].mutate = true;
    }
}

变异功能的例子。该功能在NeuralNetwork脚本中。

 private void Mutate() {
    for (int i = 0; i < weights.Length; i++) {
        for (int j = 0; j < weights[i].Length; j++) {
            for (int k = 0; k < weights[i][j].Length; k++) {
                if (Random.Range(0f, 100f) <= 100f * 
mutationChanceMultiplier) {
                    weights[i][j][k] *= (1 + Random.Range(-1 / 6f, 
0.2f)*mutationRateMultiplier);
                }
                }
            }
        }
    }
void FixedUpdate(){
testWeight = weights[1][1][1];
FeedForward();
}

我希望每个神经网络实例的testWeight值将与相应网络的print("HasMutated" + " " + weights[1][1][1])函数中Mutate()打印的值相对应。但是,每个实例的testWeight对应于打印到控制台的最后一个值(要更改的“最后一个”网络)。

1 个答案:

答案 0 :(得分:0)

我认为您应该在SpawnNextGeneration()方法中查看以下行: neuroNetworkScripts [i] .weights = bestWeights;

此行使NeuralNetwork的每个实例都引用GameManager.bestWeights 因此,每个实例将显示相同的结果。