Fix dangling clusters
This commit is contained in:
parent
737cbfcfe5
commit
eb2adaeec3
@ -19,6 +19,8 @@ namespace NanoBrain.Unity {
|
|||||||
view.currentCluster ??= clusterPrefab.cluster;
|
view.currentCluster ??= clusterPrefab.cluster;
|
||||||
view.currentNucleus = clusterPrefab.cluster.defaultOutput;
|
view.currentNucleus = clusterPrefab.cluster.defaultOutput;
|
||||||
view.selectedOutput = view.currentNucleus;
|
view.selectedOutput = view.currentNucleus;
|
||||||
|
|
||||||
|
clusterPrefab.cluster.Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnInspectorGUI() {
|
public override void OnInspectorGUI() {
|
||||||
@ -395,24 +397,26 @@ namespace NanoBrain.Unity {
|
|||||||
.Where(synapse => synapse.neuron != null)
|
.Where(synapse => synapse.neuron != null)
|
||||||
.Select(synapse => synapse.neuron);
|
.Select(synapse => synapse.neuron);
|
||||||
|
|
||||||
IEnumerable<Nucleus> nuclei = cluster.cluster.nuclei
|
Nucleus[] nuclei = cluster.cluster.nuclei
|
||||||
.Except(synapseNuclei);
|
.Except(synapseNuclei).Distinct().ToArray();
|
||||||
IEnumerable<string> nucleiNames = nuclei
|
IEnumerable<string> nucleiNames = nuclei
|
||||||
.Select(n => {
|
.Select(n => {
|
||||||
int idx = n.name.IndexOf(':');
|
int idx = n.name.IndexOf(':');
|
||||||
return idx < 0 ? n.name : n.name[..idx];
|
return idx < 0 ? n.name : n.name[..idx];
|
||||||
})
|
});
|
||||||
.Distinct();
|
|
||||||
|
|
||||||
string[] names = nucleiNames.ToArray();
|
string[] names = nucleiNames.ToArray();
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
selectedConnectNucleus = EditorGUILayout.Popup(selectedConnectNucleus, names);
|
selectedConnectNucleus = EditorGUILayout.Popup(selectedConnectNucleus, names);
|
||||||
bool connecting = GUILayout.Button("Connect", GUILayout.Width(80));
|
bool connecting = GUILayout.Button("Connect", GUILayout.Width(80));
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
if (connecting) {
|
if (connecting && selectedConnectNucleus >= 0 && selectedConnectNucleus < nuclei.Length) {
|
||||||
Nucleus nucleus = nuclei.ElementAt(selectedConnectNucleus);
|
Nucleus nucleus = nuclei[selectedConnectNucleus];//nuclei.ElementAt(selectedConnectNucleus);
|
||||||
if (nucleus is Neuron neuron)
|
if (nucleus is Neuron neuron)
|
||||||
neuron.AddReceiver(this.view.currentNucleus);
|
neuron.AddReceiver(this.view.currentNucleus);
|
||||||
|
else if (nucleus is Cluster clusterToConnect) {
|
||||||
|
clusterToConnect.defaultOutput.AddReceiver(this.view.currentNucleus);
|
||||||
|
}
|
||||||
this.view.currentCluster.Refresh();
|
this.view.currentCluster.Refresh();
|
||||||
}
|
}
|
||||||
return connecting;
|
return connecting;
|
||||||
|
|||||||
@ -711,6 +711,7 @@ namespace NanoBrain {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// This can be used to recalculate derived properties after the set of nuclei has been changed
|
/// This can be used to recalculate derived properties after the set of nuclei has been changed
|
||||||
public void Refresh() {
|
public void Refresh() {
|
||||||
|
Cleanup();
|
||||||
// This should not be needed, but somehow somewhere the parent is changed...
|
// This should not be needed, but somehow somewhere the parent is changed...
|
||||||
foreach (Nucleus nucleus in this.nuclei) {
|
foreach (Nucleus nucleus in this.nuclei) {
|
||||||
nucleus.parent = this;
|
nucleus.parent = this;
|
||||||
@ -719,6 +720,16 @@ namespace NanoBrain {
|
|||||||
RefreshComputeOrders();
|
RefreshComputeOrders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Cleanup() {
|
||||||
|
foreach (Nucleus nucleus in this.nuclei.ToArray()) {
|
||||||
|
if (nucleus is not Cluster cluster)
|
||||||
|
continue;
|
||||||
|
List<Nucleus> receivers = cluster.CollectReceivers();
|
||||||
|
Debug.Log($"cluster receiver count = {receivers.Count}");
|
||||||
|
if (receivers.Count == 0)
|
||||||
|
this.nuclei.Remove(nucleus);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -363,6 +363,7 @@ namespace NanoBrain
|
|||||||
#region Combinator
|
#region Combinator
|
||||||
|
|
||||||
#if UNITY_MATHEMATICS
|
#if UNITY_MATHEMATICS
|
||||||
|
[NonSerialized]
|
||||||
public float3 combinationValue;
|
public float3 combinationValue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -742,6 +743,35 @@ namespace NanoBrain
|
|||||||
Debug.Log($"Updated weight: {error.magnitude} {error} {scaledOutput} {synapse.weight}");
|
Debug.Log($"Updated weight: {error.magnitude} {error} {scaledOutput} {synapse.weight}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BackPropagationWithLoss(Synapse synapse, Vector3 loss, float learningRate)
|
||||||
|
{
|
||||||
|
// loss is a derivative of error
|
||||||
|
// Backpropagation = loss * d(combinator)
|
||||||
|
|
||||||
|
Vector3 delta2;
|
||||||
|
switch (activator)
|
||||||
|
{
|
||||||
|
case ActivationType.Linear:
|
||||||
|
// Derivative of this (f'()) would be 1.
|
||||||
|
delta2 = loss * 1;
|
||||||
|
break;
|
||||||
|
case ActivationType.Power:
|
||||||
|
delta2 = loss * (2 * this.combinationValue);
|
||||||
|
break;
|
||||||
|
case ActivationType.Reciprocal:
|
||||||
|
delta2 = loss * (-1 / (this.combinationValue * this.combinationValue));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
delta2 = loss;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 scaledOutput = Vector3.Scale(delta2, synapse.neuron.outputValue);
|
||||||
|
float deltaWeight = Mathf.Abs(scaledOutput.x) + Mathf.Abs(scaledOutput.y) + Mathf.Abs(scaledOutput.z);
|
||||||
|
synapse.weight += learningRate * deltaWeight;
|
||||||
|
Debug.Log($"Updated weight: {loss.magnitude} {loss} {scaledOutput} {synapse.weight}");
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Back propagation
|
#endregion Back propagation
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user