Pulsar neuron and firing actions
This commit is contained in:
parent
fd7359acd0
commit
6f67def8e6
@ -678,24 +678,46 @@ public class ClusterInspector : Editor {
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void AddInput(Nucleus.Type selectedType, Nucleus nucleus) {
|
||||
switch (selectedType) {
|
||||
case Nucleus.Type.Neuron:
|
||||
AddNeuronInput(nucleus);
|
||||
break;
|
||||
case Nucleus.Type.MemoryCell:
|
||||
AddMemoryCellInput(nucleus);
|
||||
break;
|
||||
case Nucleus.Type.Selector:
|
||||
AddSelectorInput(nucleus);
|
||||
break;
|
||||
case Nucleus.Type.Cluster:
|
||||
AddClusterInput(nucleus);
|
||||
break;
|
||||
case Nucleus.Type.Pulsar:
|
||||
AddPulsarInput(nucleus);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void AddInput(int selectedInputType, Nucleus nucleus) {
|
||||
switch (selectedInputType) {
|
||||
case 0: // Neuron
|
||||
AddInputNeuron(nucleus);
|
||||
AddNeuronInput(nucleus);
|
||||
break;
|
||||
case 1: // MemoryCell
|
||||
AddInputMemoryCell(nucleus);
|
||||
AddMemoryCellInput(nucleus);
|
||||
break;
|
||||
case 2: // Selector
|
||||
AddSelectorInput(nucleus);
|
||||
break;
|
||||
case 3: // Cluster
|
||||
AddCluster(nucleus);
|
||||
AddClusterInput(nucleus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void AddInputNeuron(Nucleus nucleus) {
|
||||
protected virtual void AddNeuronInput(Nucleus nucleus) {
|
||||
//Neuron newNeuroid = new(this.cluster, "New neuron");
|
||||
Neuron newNeuroid = new(this.prefab, "New neuron");
|
||||
newNeuroid.AddReceiver(nucleus);
|
||||
@ -725,14 +747,21 @@ public class ClusterInspector : Editor {
|
||||
BuildLayers();
|
||||
}
|
||||
|
||||
protected virtual void AddInputMemoryCell(Nucleus nucleus) {
|
||||
protected void AddPulsarInput(Nucleus nucleus) {
|
||||
Pulsar newPulsar = new(this.prefab, "New Pulsar");
|
||||
newPulsar.AddReceiver(nucleus);
|
||||
this.currentNucleus = newPulsar;
|
||||
BuildLayers();
|
||||
}
|
||||
|
||||
protected virtual void AddMemoryCellInput(Nucleus nucleus) {
|
||||
MemoryCell newMemory = new(this.prefab, "New memory cell");
|
||||
newMemory.AddReceiver(nucleus);
|
||||
this.currentNucleus = newMemory;
|
||||
BuildLayers();
|
||||
}
|
||||
|
||||
protected virtual void AddCluster(Nucleus nucleus) {
|
||||
protected virtual void AddClusterInput(Nucleus nucleus) {
|
||||
ClusterPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
||||
}
|
||||
|
||||
@ -777,11 +806,13 @@ public class ClusterInspector : Editor {
|
||||
if (cluster == null)
|
||||
return;
|
||||
|
||||
string[] options = { "Neuron", "MemoryCell", "Selector", "Cluster" };
|
||||
int selectedInputType = -1;
|
||||
selectedInputType = EditorGUILayout.Popup("Add", selectedInputType, options);
|
||||
if (selectedInputType >= 0)
|
||||
AddInput(selectedInputType, this.currentNucleus);
|
||||
//string[] options = { "Neuron", "MemoryCell", "Selector", "Cluster" };
|
||||
//int selectedInputType = -1;
|
||||
//selectedInputType = EditorGUILayout.Popup("Add", selectedInputType, options);
|
||||
//if (selectedInputType >= 0)
|
||||
Nucleus.Type selectedType = (Nucleus.Type)EditorGUILayout.EnumPopup("Add", Nucleus.Type.None);
|
||||
if (selectedType != Nucleus.Type.None)
|
||||
AddInput(selectedType, this.currentNucleus);
|
||||
}
|
||||
|
||||
protected virtual void DisconnectNucleus(Neuron nucleus) {
|
||||
|
||||
72
Neuron.cs
72
Neuron.cs
@ -129,29 +129,33 @@ public class Neuron : Nucleus {
|
||||
|
||||
// this clone the nucleus without the synapses and receivers
|
||||
public override Nucleus ShallowCloneTo(Cluster newParent) {
|
||||
Neuron clone = new(newParent, this.name) {
|
||||
array = null,
|
||||
bias = this.bias,
|
||||
curve = this.curve,
|
||||
curvePreset = this.curvePreset,
|
||||
curveMax = this.curveMax,
|
||||
average = this.average
|
||||
};
|
||||
Neuron clone = new(newParent, this.name);
|
||||
// {
|
||||
// array = null,
|
||||
// bias = this.bias,
|
||||
// curve = this.curve,
|
||||
// curvePreset = this.curvePreset,
|
||||
// curveMax = this.curveMax,
|
||||
// average = this.average
|
||||
// };
|
||||
CloneFields(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public override Nucleus Clone(ClusterPrefab prefab) {
|
||||
Neuron clone = new(prefab, this.name) {
|
||||
//Neuron clone = new(this.parent, this.name) {
|
||||
array = this.array,
|
||||
curve = this.curve,
|
||||
curvePreset = this.curvePreset,
|
||||
curveMax = this.curveMax,
|
||||
average = this.average
|
||||
};
|
||||
Neuron clone = new(prefab, this.name);
|
||||
// {
|
||||
// //Neuron clone = new(this.parent, this.name) {
|
||||
// array = this.array,
|
||||
// curve = this.curve,
|
||||
// curvePreset = this.curvePreset,
|
||||
// curveMax = this.curveMax,
|
||||
// average = this.average
|
||||
// };
|
||||
// if (clone.cluster != null)
|
||||
// clone.cluster.nuclei.Add(clone);
|
||||
|
||||
CloneFields(clone);
|
||||
foreach (Synapse synapse in this.synapses) {
|
||||
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
|
||||
clonedSynapse.weight = synapse.weight;
|
||||
@ -162,6 +166,15 @@ public class Neuron : Nucleus {
|
||||
return clone;
|
||||
}
|
||||
|
||||
protected virtual void CloneFields(Neuron clone) {
|
||||
clone.array = null;
|
||||
clone.bias = this.bias;
|
||||
clone.curve = this.curve;
|
||||
clone.curvePreset = this.curvePreset;
|
||||
clone.curveMax = this.curveMax;
|
||||
clone.average = this.average;
|
||||
}
|
||||
|
||||
public static void Delete(Nucleus nucleus) {
|
||||
foreach (Synapse synapse in nucleus.synapses) {
|
||||
if (synapse.nucleus is Neuron synapse_nucleus) {
|
||||
@ -205,32 +218,37 @@ public class Neuron : Nucleus {
|
||||
sum /= n;
|
||||
|
||||
// Activation function
|
||||
float3 result = Activation(sum);
|
||||
if (this.stale > staleValueForSleep)
|
||||
this.outputValue = new float3(0, 0, 0);
|
||||
else
|
||||
this.outputValue = result;
|
||||
}
|
||||
|
||||
protected float3 Activation(float3 input) {
|
||||
float3 result = Vector3.zero;
|
||||
switch (this.curvePreset) {
|
||||
case CurvePresets.Linear:
|
||||
result = sum;
|
||||
result = input;
|
||||
break;
|
||||
case CurvePresets.Sqrt:
|
||||
result = normalize(sum) * System.MathF.Sqrt(length(sum));
|
||||
result = normalize(input) * System.MathF.Sqrt(length(input));
|
||||
break;
|
||||
case CurvePresets.Power:
|
||||
result = normalize(sum) * System.MathF.Pow(length(sum), 2);
|
||||
result = normalize(input) * System.MathF.Pow(length(input), 2);
|
||||
break;
|
||||
case CurvePresets.Reciprocal: {
|
||||
float magnitude = length(sum);
|
||||
float magnitude = length(input);
|
||||
if (magnitude > 0)
|
||||
result = normalize(sum) * (1 / magnitude);
|
||||
result = normalize(input) * (1 / magnitude);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
float activatedValue = this.curve.Evaluate(length(sum));
|
||||
result = normalize(sum) * activatedValue;
|
||||
float activatedValue = this.curve.Evaluate(length(input));
|
||||
result = normalize(input) * activatedValue;
|
||||
break;
|
||||
}
|
||||
if (this.stale > staleValueForSleep)
|
||||
this.outputValue = new float3(0,0,0);
|
||||
else
|
||||
this.outputValue = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual void ProcessStimulus(Vector3 inputValue, string thingName = null) {
|
||||
|
||||
18
Nucleus.cs
18
Nucleus.cs
@ -6,12 +6,6 @@ using static Unity.Mathematics.math;
|
||||
|
||||
[Serializable]
|
||||
public abstract class Nucleus {
|
||||
// [SerializeField]
|
||||
// protected string _name;
|
||||
// public virtual string name {
|
||||
// get => _name;
|
||||
// set => _name = value;
|
||||
// }
|
||||
public string name;
|
||||
|
||||
//[Obsolete]
|
||||
@ -26,9 +20,12 @@ public abstract class Nucleus {
|
||||
//this.stale = 0;
|
||||
// this._isSleeping = false;
|
||||
_outputValue = value;
|
||||
if (this.isFiring)
|
||||
WhenFiring?.Invoke();
|
||||
}
|
||||
}
|
||||
public bool isFiring => length(_outputValue) > 0.5f;
|
||||
public Action WhenFiring;
|
||||
|
||||
public bool isSleeping => lengthsq(this.outputValue) == 0;
|
||||
[NonSerialized]
|
||||
@ -38,6 +35,15 @@ public abstract class Nucleus {
|
||||
public abstract Nucleus ShallowCloneTo(Cluster parent);
|
||||
public abstract Nucleus Clone(ClusterPrefab prefab);
|
||||
|
||||
public enum Type {
|
||||
None,
|
||||
Neuron,
|
||||
MemoryCell,
|
||||
Selector,
|
||||
Cluster,
|
||||
Pulsar
|
||||
}
|
||||
|
||||
#region Synapses
|
||||
|
||||
public Vector3 bias = Vector3.zero;
|
||||
|
||||
54
Pulsar.cs
Normal file
54
Pulsar.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using Unity.Mathematics;
|
||||
|
||||
/// <summary>
|
||||
/// The Pulsar represents a type of neuron that operates based on
|
||||
/// the product of its weighted inputs rather than the traditional summation.
|
||||
/// Drawing inspiration from the concept of pulsars in astrophysics
|
||||
/// —highly magnetized rotating neutron stars that emit beams of radiation—
|
||||
/// the Pulsar could symbolize dynamic, focused output based on the interaction of multiple factors.
|
||||
/// </summary>
|
||||
/// Multiplicative Functionality:
|
||||
/// Instead of summing inputs, the Pulsar takes the weighted product of its inputs.
|
||||
/// This means that all inputs must be active (non-zero) for the neuron to "pulse" or activate.
|
||||
/// Output Behavior:
|
||||
/// The output could amplify or diminish depending on the magnitude of the inputs.
|
||||
/// The product would be sensitive to small values,
|
||||
/// which means that even a small input could significantly lower the overall output if multiplied.
|
||||
/// Activation Mechanism:
|
||||
/// The activation function can further refine the output from the product result.
|
||||
/// For instance, a certain threshold could be used to determine if a pulse occurs.
|
||||
/// Modeling Complex Interactions:
|
||||
/// The Pulsar could be particularly beneficial for modeling situations where interactions multiply rather than add.
|
||||
/// This is useful in fields such as economics (e.g., compound growth models),
|
||||
/// biology (e.g., interaction of hormones), and machine learning where multiplicative relationships exist.
|
||||
[Serializable]
|
||||
public class Pulsar : Neuron {
|
||||
public Pulsar(Cluster parent, string name) : base(parent, name) {
|
||||
// To prevent mistakes, bias one (instead of zero for standard neurons)
|
||||
this.bias = new float3(1, 1, 1);
|
||||
}
|
||||
public Pulsar(ClusterPrefab parent, string name) : base(parent, name) {
|
||||
// To prevent mistakes, bias one (instead of zero for standard neurons)
|
||||
this.bias = new float3(1, 1, 1);
|
||||
}
|
||||
|
||||
public override Nucleus ShallowCloneTo(Cluster newParent) {
|
||||
Pulsar clone = new(newParent, this.name);
|
||||
CloneFields(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public override void UpdateStateIsolated(float3 _bias) {
|
||||
float3 product = this.bias;
|
||||
|
||||
//Applying the weight factors
|
||||
foreach (Synapse synapse in this.synapses) {
|
||||
float3 input = synapse.weight * synapse.nucleus.outputValue;
|
||||
product *= input;
|
||||
}
|
||||
|
||||
// Activation function
|
||||
this.outputValue = Activation(product);
|
||||
}
|
||||
}
|
||||
2
Pulsar.cs.meta
Normal file
2
Pulsar.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46bd155173053a01585411c3e07f85d4
|
||||
Loading…
x
Reference in New Issue
Block a user