/// <inheritdoc/> public void Recompute(bool collectStatistics) { //Spike leak handling if (OutputData._spikingSignal > 0) { //Spike during previous cycle, so reset the counter OutputData._afterFirstSpike = true; OutputData._spikeLeak = 0; } ++OutputData._spikeLeak; double normalizedActivation; if (_activationFn.TypeOfActivation == ActivationType.Spiking) { //Spiking activation AFSpikingBase af = (AFSpikingBase)_activationFn; OutputData._spikingSignal = af.Compute(_tStimuli); //OutputData._analogSignal = OutputData._spikingSignal; _activationState = af.InternalState; normalizedActivation = OutputRange.Rescale(af.InternalState, af.InternalStateRange).Bound(OutputRange.Min, OutputRange.Max); OutputData._analogSignal = normalizedActivation; } else { //Analog activation _activationState = (_analogRetainmentStrength * _activationState) + (1d - _analogRetainmentStrength) * _activationFn.Compute(_tStimuli); normalizedActivation = OutputRange.Rescale(_activationState, _activationFn.OutputRange).Bound(OutputRange.Min, OutputRange.Max); double activationDifference = _histActivationsQueue == null ? ((normalizedActivation - OutputData._analogSignal)) : (_histActivationsQueue.Full ? (normalizedActivation - _histActivationsQueue.Dequeue()) : (normalizedActivation - 0.5d)); //Firing event decision bool firingEvent = activationDifference > _analogFiringThreshold; //Enqueue last normalized activation _histActivationsQueue?.Enqueue(normalizedActivation); //New output data OutputData._analogSignal = normalizedActivation; OutputData._spikingSignal = firingEvent ? 1d : 0d; } //Update predictors _predictorsProvider?.Update(_activationState, normalizedActivation, (OutputData._spikingSignal > 0)); //Update statistics if (collectStatistics) { Statistics.Update(_iStimuli, _rStimuli, _tStimuli, _activationState, OutputData._analogSignal, OutputData._spikingSignal); } return; }
//Methods private void TestSpikingAF(AFSpikingBase af, int simLength, double constCurrent, int from, int count) { for (int i = 1; i <= simLength; i++) { double signal; double input; if (i >= from && i < from + count) { input = double.IsNaN(constCurrent) ? _rand.NextDouble() : constCurrent; } else { input = 0d; } signal = af.Compute(input); Console.WriteLine($"{af.GetType().Name} step {i}, State {(af.TypeOfActivation == ActivationType.Spiking ? af.InternalState : signal)} signal {signal}"); } Console.ReadLine(); return; }
//Constructor /// <summary> /// Creates an initialized instance. /// </summary> /// <param name="location">The neuron's location.</param> /// <param name="spikingActivation">The instance of a spiking activation function.</param> /// <param name="bias">The constant bias.</param> /// <param name="predictorsProviderCfg">The configuration of the predictors provider.</param> public HiddenNeuron(NeuronLocation location, AFSpikingBase spikingActivation, double bias, PredictorsProviderSettings predictorsProviderCfg ) { Location = location; Statistics = new NeuronStatistics(); Bias = bias; //Activation check if (spikingActivation.TypeOfActivation == ActivationType.Analog) { //Spiking throw new ArgumentException($"Wrong type of the activation function.", "spikingActivation"); } _activationFn = spikingActivation; _analogFiringThreshold = 0; _histActivationsQueue = null; _analogRetainmentStrength = 0; _predictorsProvider = predictorsProviderCfg != null ? new PredictorsProvider(predictorsProviderCfg) : null; OutputData = new NeuronOutputData(); Reset(false); return; }