diff --git a/Runtime/Scripts/Core/Neuron.cs b/Runtime/Scripts/Core/Neuron.cs index 1e99a80..3e876ec 100644 --- a/Runtime/Scripts/Core/Neuron.cs +++ b/Runtime/Scripts/Core/Neuron.cs @@ -755,7 +755,6 @@ namespace NanoBrain { } public void BackPropagation2(float derivative, float learningRate) { - // Bias if (this.trainable) { // This does not work well, because the derivative/error does not have a 3D direction @@ -797,6 +796,25 @@ namespace NanoBrain { } } + public void BackPropagation3D(Vector3 derivative, float learningRate) { + foreach (Synapse synapse in this.synapses) + synapse.BackPropagation(this, derivative, learningRate); + + // Bias + if (this.trainable) { + switch (this.activator) { // dActivator/dBias + case ActivationType.Linear: + derivative *= 1; + break; + default: + break; + } + + this.bias += derivative * learningRate; + Debug.Log($"bias {derivative} {this.bias}"); + } + } + #endregion Back propagation /// diff --git a/Runtime/Scripts/Core/Synapse.cs b/Runtime/Scripts/Core/Synapse.cs index cd7859e..072ef45 100644 --- a/Runtime/Scripts/Core/Synapse.cs +++ b/Runtime/Scripts/Core/Synapse.cs @@ -64,7 +64,39 @@ namespace NanoBrain { float deltaWeight = learningRate * derivative; this.weight += deltaWeight; } + } + public virtual void BackPropagation(Neuron receiver, Vector3 derivative, float learningRate) { + //Vector3 derivative = error; + + switch (receiver.activator) { + case Neuron.ActivationType.Linear: + derivative *= 1; + break; + case Neuron.ActivationType.Power: + // untested + derivative *= 2 * math.length(this.neuron.combination); + break; + case Neuron.ActivationType.Reciprocal: + // untested + derivative *= -1 / Mathf.Pow(math.length(this.neuron.combination), 2); + break; + default: + Debug.Log("other activator"); + break; + } + + this.neuron.BackPropagation3D(derivative * this.weight, learningRate); + + derivative = Vector3.Scale(derivative, this.neuron.activation); + + if (this.trainable) { + // Compared to the 1D solution, this does not decrease the weight. + // direction and sign are different.... + // Perhaps the sign is determine by the direction of the derivative and the neuron activation? + // When they are oppositie, the sign is negative? (or the other way round...) + this.weight += learningRate * derivative.magnitude; + } } }