refractoring
This commit is contained in:
@@ -34,9 +34,11 @@ using .interface
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
Todo:
|
Todo:
|
||||||
[*3] no "start learning" use reset learning and "inference", "learning" mode instead
|
[*3] implement "start learning", reset learning and "during_learning", "end_learning and
|
||||||
[4] output neuron connect to multiple compute neuron
|
"inference"
|
||||||
[7] add time-based learning method. Also implement "thinking period"
|
[4] output neuron connect to random multiple compute neurons
|
||||||
|
[7] add time-based learning method.
|
||||||
|
[] implement "thinking period"
|
||||||
[8] verify that model can complete learning cycle with no error
|
[8] verify that model can complete learning cycle with no error
|
||||||
[5] synaptic connection strength concept
|
[5] synaptic connection strength concept
|
||||||
[6] neuroplasticity() i.e. change connection
|
[6] neuroplasticity() i.e. change connection
|
||||||
|
|||||||
105
src/forward.jl
105
src/forward.jl
@@ -12,7 +12,7 @@ using ..types, ..snn_utils
|
|||||||
"""
|
"""
|
||||||
function (m::model)(input_data::AbstractVector)
|
function (m::model)(input_data::AbstractVector)
|
||||||
# m.global_tick += 1
|
# m.global_tick += 1
|
||||||
m.time_stamp += 1
|
m.timeStep += 1
|
||||||
|
|
||||||
# process all corresponding KFN
|
# process all corresponding KFN
|
||||||
raw_model_respond = m.knowledgeFn[:I](m, input_data)
|
raw_model_respond = m.knowledgeFn[:I](m, input_data)
|
||||||
@@ -28,9 +28,9 @@ end
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
function (kfn::kfn_1)(m::model, input_data::AbstractVector)
|
function (kfn::kfn_1)(m::model, input_data::AbstractVector)
|
||||||
kfn.time_stamp = m.time_stamp
|
kfn.timeStep = m.timeStep
|
||||||
kfn.softreset = m.softreset
|
kfn.softreset = m.softreset
|
||||||
kfn.learning_stage = m.learning_stage
|
kfn.learningStage = m.learningStage
|
||||||
kfn.error = m.error
|
kfn.error = m.error
|
||||||
|
|
||||||
# generate noise
|
# generate noise
|
||||||
@@ -40,53 +40,38 @@ function (kfn::kfn_1)(m::model, input_data::AbstractVector)
|
|||||||
|
|
||||||
input_data = [noise; input_data] # noise start from neuron id 1
|
input_data = [noise; input_data] # noise start from neuron id 1
|
||||||
|
|
||||||
for n in kfn.neurons_array
|
for n in kfn.neuronsArray
|
||||||
timestep_forward!(n)
|
timestep_forward!(n)
|
||||||
end
|
end
|
||||||
for n in kfn.output_neurons_array
|
for n in kfn.outputNeuronsArray
|
||||||
timestep_forward!(n)
|
timestep_forward!(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
kfn.learning_stage = m.learning_stage
|
|
||||||
if kfn.learning_stage == "start_learning"
|
|
||||||
# reset params here instead of at the end_learning so that neuron's parameter data
|
|
||||||
# don't gets wiped and can be logged for visualization later
|
|
||||||
for n in kfn.neurons_array
|
|
||||||
# epsilon_rec need to be reset because it counting how many each synaptic fires and
|
|
||||||
# use this info to calculate how much synaptic weight should be adjust
|
|
||||||
reset_learning_params!(n)
|
|
||||||
end
|
|
||||||
|
|
||||||
# clear variables
|
|
||||||
kfn.firing_neurons_list = Vector{Int64}()
|
|
||||||
kfn.outputs = nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
# pass input_data into input neuron.
|
# pass input_data into input neuron.
|
||||||
# number of data point equals to number of input neuron starting from id 1
|
# number of data point equals to number of input neuron starting from id 1
|
||||||
for (i, data) in enumerate(input_data)
|
for (i, data) in enumerate(input_data)
|
||||||
kfn.neurons_array[i].z_t1 = data
|
kfn.neuronsArray[i].z_t1 = data
|
||||||
end
|
end
|
||||||
|
|
||||||
kfn.snn_firing_state_t0 = [n.z_t for n in kfn.neurons_array] #TODO check if it is used?
|
kfn.firedNeurons_t0 = [n.z_t for n in kfn.neuronsArray] #TODO check if it is used?
|
||||||
|
|
||||||
#CHANGE Threads.@threads for n in kfn.neurons_array
|
#CHANGE Threads.@threads for n in kfn.neuronsArray
|
||||||
for n in kfn.neurons_array
|
for n in kfn.neuronsArray
|
||||||
n(kfn)
|
n(kfn)
|
||||||
end
|
end
|
||||||
|
|
||||||
kfn.snn_firing_state_t1 = [n.z_t1 for n in kfn.neurons_array]
|
kfn.firedNeurons_t1 = [n.z_t1 for n in kfn.neuronsArray]
|
||||||
append!(kfn.firing_neurons_list, findall(kfn.snn_firing_state_t1)) # store id of neuron that fires
|
append!(kfn.firedNeurons, findall(kfn.firedNeurons_t1)) # store id of neuron that fires
|
||||||
if kfn.learning_stage == "end_learning" # use for random new neuron connection
|
if kfn.learningStage == "end_learning"
|
||||||
kfn.firing_neurons_list |> unique!
|
kfn.firedNeurons |> unique! # use for random new neuron connection
|
||||||
end
|
end
|
||||||
|
|
||||||
# Threads.@threads for n in kfn.output_neurons_array
|
# Threads.@threads for n in kfn.outputNeuronsArray
|
||||||
for n in kfn.output_neurons_array
|
for n in kfn.outputNeuronsArray
|
||||||
n(kfn)
|
n(kfn)
|
||||||
end
|
end
|
||||||
|
|
||||||
out = [n.out_t1 for n in kfn.output_neurons_array]
|
out = [n.out_t1 for n in kfn.outputNeuronsArray]
|
||||||
|
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
@@ -96,7 +81,7 @@ end
|
|||||||
""" passthrough_neuron forward()
|
""" passthrough_neuron forward()
|
||||||
"""
|
"""
|
||||||
function (n::passthrough_neuron)(kfn::knowledgeFn)
|
function (n::passthrough_neuron)(kfn::knowledgeFn)
|
||||||
n.time_stamp = kfn.time_stamp
|
n.timeStep = kfn.timeStep
|
||||||
# n.global_tick = kfn.global_tick
|
# n.global_tick = kfn.global_tick
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -105,40 +90,40 @@ end
|
|||||||
""" lif_neuron forward()
|
""" lif_neuron forward()
|
||||||
"""
|
"""
|
||||||
function (n::lif_neuron)(kfn::knowledgeFn)
|
function (n::lif_neuron)(kfn::knowledgeFn)
|
||||||
n.time_stamp = kfn.time_stamp
|
n.timeStep = kfn.timeStep
|
||||||
|
|
||||||
# pulling other neuron's firing status at time t
|
# pulling other neuron's firing status at time t
|
||||||
n.z_i_t = getindex(kfn.snn_firing_state_t0, n.subscription_list)
|
n.z_i_t = getindex(kfn.firedNeurons_t0, n.subscriptionList)
|
||||||
n.z_i_t .*= n.sub_ExIn_type
|
n.z_i_t .*= n.subExInType
|
||||||
|
|
||||||
if n.refractory_counter != 0
|
if n.refractoryCounter != 0
|
||||||
n.refractory_counter -= 1
|
n.refractoryCounter -= 1
|
||||||
|
|
||||||
# neuron is in refractory state, skip all calculation
|
# neuron is in refractory state, skip all calculation
|
||||||
n.z_t1 = false # used by timestep_forward() in kfn. Set to zero because neuron spike
|
n.z_t1 = false # used by timestep_forward() in kfn. Set to zero because neuron spike
|
||||||
# last only 1 timestep follow by a period of refractory.
|
# last only 1 timestep follow by a period of refractory.
|
||||||
n.recurrent_signal = n.recurrent_signal * 0.0
|
n.recSignal = n.recSignal * 0.0
|
||||||
|
|
||||||
# Exponantial decay of v_t1
|
# Exponantial decay of v_t1
|
||||||
n.v_t1 = n.v_t * n.alpha^(n.time_stamp - n.last_firing_time) # or n.v_t1 = n.alpha * n.v_t
|
n.v_t1 = n.v_t * n.alpha^(n.timeStep - n.lastFiringTime) # or n.v_t1 = n.alpha * n.v_t
|
||||||
else
|
else
|
||||||
n.recurrent_signal = sum(n.w_rec .* n.z_i_t) # signal from other neuron that this neuron subscribed
|
n.recSignal = sum(n.w_rec .* n.z_i_t) # signal from other neuron that this neuron subscribed
|
||||||
|
|
||||||
n.alpha_v_t = n.alpha * n.v_t
|
n.alpha_v_t = n.alpha * n.v_t
|
||||||
n.v_t1 = n.alpha_v_t + n.recurrent_signal
|
n.v_t1 = n.alpha_v_t + n.recSignal
|
||||||
n.v_t1 = no_negative!.(n.v_t1)
|
n.v_t1 = no_negative!.(n.v_t1)
|
||||||
|
|
||||||
if n.v_t1 > n.v_th
|
if n.v_t1 > n.v_th
|
||||||
n.z_t1 = true
|
n.z_t1 = true
|
||||||
n.refractory_counter = n.refractory_duration
|
n.refractoryCounter = n.refractoryDuration
|
||||||
n.firing_counter += 1
|
n.firingCounter += 1
|
||||||
n.v_t1 = n.v_t1 - n.v_th
|
n.v_t1 = n.vRest
|
||||||
else
|
else
|
||||||
n.z_t1 = false
|
n.z_t1 = false
|
||||||
end
|
end
|
||||||
|
|
||||||
# there is a difference from alif formula
|
# there is a difference from alif formula
|
||||||
n.phi = (n.gamma_pd / n.v_th) * max(0, 1 - (n.v_t1 - n.v_th) / n.v_th)
|
n.phi = (n.gammaPd / n.v_th) * max(0, 1 - (n.v_t1 - n.v_th) / n.v_th)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -147,41 +132,41 @@ end
|
|||||||
""" alif_neuron forward()
|
""" alif_neuron forward()
|
||||||
"""
|
"""
|
||||||
function (n::alif_neuron)(kfn::knowledgeFn)
|
function (n::alif_neuron)(kfn::knowledgeFn)
|
||||||
n.time_stamp = kfn.time_stamp
|
n.timeStep = kfn.timeStep
|
||||||
|
|
||||||
n.z_i_t = getindex(kfn.snn_firing_state_t0, n.subscription_list)
|
n.z_i_t = getindex(kfn.firedNeurons_t0, n.subscriptionList)
|
||||||
n.z_i_t .*= n.sub_ExIn_type
|
n.z_i_t .*= n.subExInType
|
||||||
|
|
||||||
if n.refractory_counter != 0
|
if n.refractoryCounter != 0
|
||||||
n.refractory_counter -= 1
|
n.refractoryCounter -= 1
|
||||||
|
|
||||||
# neuron is in refractory state, skip all calculation
|
# neuron is in refractory state, skip all calculation
|
||||||
n.z_t1 = false # used by timestep_forward() in kfn. Set to zero because neuron spike last only 1 timestep follow by a period of refractory.
|
n.z_t1 = false # used by timestep_forward() in kfn. Set to zero because neuron spike last only 1 timestep follow by a period of refractory.
|
||||||
n.a = (n.rho * n.a) + ((1 - n.rho) * n.z_t)
|
n.a = (n.rho * n.a) + ((1 - n.rho) * n.z_t)
|
||||||
n.recurrent_signal = n.recurrent_signal * 0.0
|
n.recSignal = n.recSignal * 0.0
|
||||||
|
|
||||||
# Exponantial decay of v_t1
|
# Exponantial decay of v_t1
|
||||||
n.v_t1 = n.v_t * n.alpha^(n.time_stamp - n.last_firing_time) # or n.v_t1 = n.alpha * n.v_t
|
n.v_t1 = n.v_t * n.alpha^(n.timeStep - n.lastFiringTime) # or n.v_t1 = n.alpha * n.v_t
|
||||||
n.phi = 0
|
n.phi = 0
|
||||||
else
|
else
|
||||||
n.z_t = isnothing(n.z_t) ? false : n.z_t
|
n.z_t = isnothing(n.z_t) ? false : n.z_t
|
||||||
n.a = (n.rho * n.a) + ((1 - n.rho) * n.z_t)
|
n.a = (n.rho * n.a) + ((1 - n.rho) * n.z_t)
|
||||||
n.av_th = n.v_th + (n.beta * n.a)
|
n.av_th = n.v_th + (n.beta * n.a)
|
||||||
n.recurrent_signal = sum(n.w_rec .* n.z_i_t) # signal from other neuron that this neuron subscribed
|
n.recSignal = sum(n.w_rec .* n.z_i_t) # signal from other neuron that this neuron subscribed
|
||||||
n.alpha_v_t = n.alpha * n.v_t
|
n.alpha_v_t = n.alpha * n.v_t
|
||||||
n.v_t1 = n.alpha_v_t + n.recurrent_signal
|
n.v_t1 = n.alpha_v_t + n.recSignal
|
||||||
n.v_t1 = no_negative!.(n.v_t1)
|
n.v_t1 = no_negative!.(n.v_t1)
|
||||||
if n.v_t1 > n.av_th
|
if n.v_t1 > n.av_th
|
||||||
n.z_t1 = true
|
n.z_t1 = true
|
||||||
n.refractory_counter = n.refractory_duration
|
n.refractoryCounter = n.refractoryDuration
|
||||||
n.firing_counter += 1
|
n.firingCounter += 1
|
||||||
n.v_t1 = n.v_t1 - n.v_th
|
n.v_t1 = n.vRest
|
||||||
else
|
else
|
||||||
n.z_t1 = false
|
n.z_t1 = false
|
||||||
end
|
end
|
||||||
|
|
||||||
# there is a difference from lif formula
|
# there is a difference from lif formula
|
||||||
n.phi = (n.gamma_pd / n.v_th) * max(0, 1 - (n.v_t1 - n.av_th) / n.v_th)
|
n.phi = (n.gammaPd / n.v_th) * max(0, 1 - (n.v_t1 - n.av_th) / n.v_th)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -191,8 +176,8 @@ end
|
|||||||
In this implementation, each output neuron is fully connected to every lif and alif neuron.
|
In this implementation, each output neuron is fully connected to every lif and alif neuron.
|
||||||
"""
|
"""
|
||||||
function (n::linear_neuron)(kfn::T) where T<:knowledgeFn
|
function (n::linear_neuron)(kfn::T) where T<:knowledgeFn
|
||||||
n.time_stamp = kfn.time_stamp
|
n.timeStep = kfn.timeStep
|
||||||
n.out_t1 = getindex(kfn.snn_firing_state_t1, n.subscription_list)[1]
|
n.out_t1 = getindex(kfn.firedNeurons_t1, n.subscriptionList)[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
184
src/learn.jl
184
src/learn.jl
@@ -10,11 +10,21 @@ export learn!
|
|||||||
|
|
||||||
#------------------------------------------------------------------------------------------------100
|
#------------------------------------------------------------------------------------------------100
|
||||||
|
|
||||||
function learn!(m::model, model_respond, correct_answer)
|
function learn!(m::model, modelRespond, correctAnswer=nothing, correctTiming=nothing)
|
||||||
if m.learning_stage == "learning"
|
|
||||||
|
# set all KFN
|
||||||
|
if m.learningStage == "start_learning"
|
||||||
|
m.knowledgeFn[:I].learningStage = "start_learning"
|
||||||
|
elseif m.learningStage == "end_learning"
|
||||||
|
m.knowledgeFn[:I].learningStage = "end_learning"
|
||||||
|
else
|
||||||
|
end
|
||||||
|
|
||||||
#WORKING compute error
|
#WORKING compute error
|
||||||
if m.time_stamp < m.model_params[:perfect_timing]
|
# timingError =
|
||||||
too_early = m.model_params[:perfect_timing] - m.time_stamp
|
|
||||||
|
|
||||||
|
too_early = m.modelParams[:perfect_timing] - m.timeStep
|
||||||
model_error = (model_respond .- correct_answer) * too_early
|
model_error = (model_respond .- correct_answer) * too_early
|
||||||
|
|
||||||
|
|
||||||
@@ -25,9 +35,6 @@ function learn!(m::model, model_respond, correct_answer)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
model_error = Flux.logitcrossentropy(model_respond, correct_answer)
|
model_error = Flux.logitcrossentropy(model_respond, correct_answer)
|
||||||
output_elements_error = model_respond - correct_answer
|
output_elements_error = model_respond - correct_answer
|
||||||
|
|
||||||
@@ -38,28 +45,12 @@ function learn!(m::model, model_respond, correct_answer)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else
|
|
||||||
model_error = nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
return model_error
|
return model_error
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# function learn!(m::model, raw_model_respond, correct_answer=nothing)
|
# function learn!(m::model, raw_model_respond, correct_answer=nothing)
|
||||||
# if m.learning_stage != "doing_inference"
|
# if m.learningStage != "doing_inference"
|
||||||
# model_error = Flux.logitcrossentropy(raw_model_respond, correct_answer)
|
# model_error = Flux.logitcrossentropy(raw_model_respond, correct_answer)
|
||||||
# output_elements_error = raw_model_respond - correct_answer
|
# output_elements_error = raw_model_respond - correct_answer
|
||||||
|
|
||||||
@@ -77,18 +68,33 @@ end
|
|||||||
""" knowledgeFn learn()
|
""" knowledgeFn learn()
|
||||||
"""
|
"""
|
||||||
function learn!(kfn::knowledgeFn, error::Union{Float64,Nothing}=nothing,
|
function learn!(kfn::knowledgeFn, error::Union{Float64,Nothing}=nothing,
|
||||||
output_error::Union{Vector,Nothing}=nothing)
|
outputError::Union{Vector,Nothing}=nothing)
|
||||||
kfn.error = error
|
kfn.error = error
|
||||||
kfn.output_error = output_error
|
kfn.outputError = outputError
|
||||||
|
|
||||||
# Threads.@threads for n in kfn.neurons_array
|
kfn.learningStage = m.learningStage
|
||||||
for n in kfn.neurons_array
|
if m.learningStage == "start_learning"
|
||||||
|
# reset params here instead of at the end_learning so that neuron's parameter data
|
||||||
|
# don't gets wiped and can be logged for visualization later
|
||||||
|
for n in kfn.neuronsArray
|
||||||
|
# epsilonRec need to be reset because it counting how many each synaptic fires and
|
||||||
|
# use this info to calculate how much synaptic weight should be adjust
|
||||||
|
reset_learning_params!(n)
|
||||||
|
end
|
||||||
|
|
||||||
|
# clear variables
|
||||||
|
kfn.firedNeurons = Vector{Int64}()
|
||||||
|
kfn.outputs = nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
# Threads.@threads for n in kfn.neuronsArray
|
||||||
|
for n in kfn.neuronsArray
|
||||||
learn!(n, kfn) # Neurons are always learning, besides error from model output
|
learn!(n, kfn) # Neurons are always learning, besides error from model output
|
||||||
end
|
end
|
||||||
|
|
||||||
if kfn.output_error !== nothing
|
if kfn.outputError !== nothing
|
||||||
# Threads.@threads for n in kfn.output_neurons_array
|
# Threads.@threads for n in kfn.outputNeuronsArray
|
||||||
for n in kfn.output_neurons_array # not use multithreading because 1st output neuron
|
for n in kfn.outputNeuronsArray # not use multithreading because 1st output neuron
|
||||||
# will set learning rate that will be used by
|
# will set learning rate that will be used by
|
||||||
# other output neurons
|
# other output neurons
|
||||||
learn!(n, kfn)
|
learn!(n, kfn)
|
||||||
@@ -96,21 +102,21 @@ function learn!(kfn::knowledgeFn, error::Union{Float64,Nothing}=nothing,
|
|||||||
#TODO: put other KFN to learn here
|
#TODO: put other KFN to learn here
|
||||||
|
|
||||||
# for main loop user's display and training's exit condition
|
# for main loop user's display and training's exit condition
|
||||||
avg_neurons_firing_rate = 0.0
|
avgNeuronsFiringRate = 0.0
|
||||||
for n in kfn.neurons_array
|
for n in kfn.neuronsArray
|
||||||
if typeof(n) <: compute_neuron
|
if typeof(n) <: compute_neuron
|
||||||
avg_neurons_firing_rate += n.firing_rate
|
avgNeuronsFiringRate += n.firingRate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
kfn.avg_neurons_firing_rate = avg_neurons_firing_rate /
|
kfn.avgNeuronsFiringRate = avgNeuronsFiringRate /
|
||||||
kfn.kfn_params[:compute_neuron_number]
|
kfn.kfnParams[:compute_neuron_number]
|
||||||
avg_neurons_v_t1 = 0.0
|
avgNeurons_v_t1 = 0.0
|
||||||
for n in kfn.neurons_array
|
for n in kfn.neuronsArray
|
||||||
if typeof(n) <: compute_neuron
|
if typeof(n) <: compute_neuron
|
||||||
avg_neurons_v_t1 += n.v_t1
|
avgNeurons_v_t1 += n.v_t1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
kfn.avg_neurons_v_t1 = avg_neurons_v_t1 / kfn.kfn_params[:compute_neuron_number]
|
kfn.avgNeurons_v_t1 = avgNeurons_v_t1 / kfn.kfnParams[:compute_neuron_number]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -125,139 +131,139 @@ end
|
|||||||
function learn!(n::lif_neuron, kfn::knowledgeFn)
|
function learn!(n::lif_neuron, kfn::knowledgeFn)
|
||||||
if n.learnable_flag == true
|
if n.learnable_flag == true
|
||||||
|
|
||||||
n.decayed_epsilon_rec = n.alpha * n.epsilon_rec
|
n.decayedEpsilonRec = n.alpha * n.epsilonRec
|
||||||
n.epsilon_rec = n.decayed_epsilon_rec + n.z_i_t
|
n.epsilonRec = n.decayedEpsilonRec + n.z_i_t
|
||||||
n.e_rec = n.phi * n.epsilon_rec
|
n.eRec = n.phi * n.epsilonRec
|
||||||
end
|
end
|
||||||
|
|
||||||
# a piece of knowledgeFn error that belongs to this neuron
|
# a piece of knowledgeFn error that belongs to this neuron
|
||||||
n.error = isnothing(kfn.error) ? nothing : kfn.error * n.Bn
|
n.error = isnothing(kfn.error) ? nothing : kfn.error * n.Bn
|
||||||
n.learning_stage = kfn.learning_stage
|
n.learningStage = kfn.learningStage
|
||||||
|
|
||||||
# accumulate voltage regularization terms
|
# accumulate voltage regularization terms
|
||||||
Snn_utils.cal_v_reg!(n)
|
Snn_utils.cal_v_reg!(n)
|
||||||
|
|
||||||
if n.learning_stage == "doing_inference"
|
if n.learningStage == "doing_inference"
|
||||||
# no learning
|
# no learning
|
||||||
elseif n.learning_stage == "start_learning" ||
|
elseif n.learningStage == "start_learning" ||
|
||||||
n.learning_stage == "start_learning_no_wchange_reset"
|
n.learningStage == "start_learning_no_wchange_reset"
|
||||||
|
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing
|
if n.error !== nothing
|
||||||
Snn_utils.firing_rate!(n)
|
Snn_utils.firing_rate!(n)
|
||||||
Snn_utils.firing_diff!(n)
|
Snn_utils.firing_diff!(n)
|
||||||
n.w_rec_change = n.w_rec_change +
|
n.wRecChange = n.wRecChange +
|
||||||
-apply!(n.optimiser, n.w_rec,
|
-apply!(n.optimiser, n.w_rec,
|
||||||
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
|
(n.error + Snn_utils.voltage_error!(n) + n.firingRateError) * n.eRec) +
|
||||||
-Snn_utils.firing_rate_regulator!(n) +
|
-Snn_utils.firing_rate_regulator!(n) +
|
||||||
-Snn_utils.voltage_regulator!(n)
|
-Snn_utils.voltage_regulator!(n)
|
||||||
end
|
end
|
||||||
elseif n.learning_stage == "during_learning"
|
elseif n.learningStage == "during_learning"
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing
|
if n.error !== nothing
|
||||||
Snn_utils.firing_rate!(n)
|
Snn_utils.firing_rate!(n)
|
||||||
Snn_utils.firing_diff!(n)
|
Snn_utils.firing_diff!(n)
|
||||||
n.w_rec_change = n.w_rec_change +
|
n.wRecChange = n.wRecChange +
|
||||||
-apply!(n.optimiser, n.w_rec,
|
-apply!(n.optimiser, n.w_rec,
|
||||||
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
|
(n.error + Snn_utils.voltage_error!(n) + n.firingRateError) * n.eRec) +
|
||||||
-Snn_utils.firing_rate_regulator!(n) +
|
-Snn_utils.firing_rate_regulator!(n) +
|
||||||
-Snn_utils.voltage_regulator!(n)
|
-Snn_utils.voltage_regulator!(n)
|
||||||
end
|
end
|
||||||
elseif n.learning_stage == "end_learning"
|
elseif n.learningStage == "end_learning"
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing
|
if n.error !== nothing
|
||||||
Snn_utils.firing_rate!(n)
|
Snn_utils.firing_rate!(n)
|
||||||
Snn_utils.firing_diff!(n)
|
Snn_utils.firing_diff!(n)
|
||||||
n.w_rec_change = n.w_rec_change +
|
n.wRecChange = n.wRecChange +
|
||||||
-apply!(n.optimiser, n.w_rec,
|
-apply!(n.optimiser, n.w_rec,
|
||||||
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
|
(n.error + Snn_utils.voltage_error!(n) + n.firingRateError) * n.eRec) +
|
||||||
-Snn_utils.firing_rate_regulator!(n) +
|
-Snn_utils.firing_rate_regulator!(n) +
|
||||||
-Snn_utils.voltage_regulator!(n)
|
-Snn_utils.voltage_regulator!(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
not_zero = (!iszero).(n.w_rec)
|
not_zero = (!iszero).(n.w_rec)
|
||||||
# set 0 in w_rec_change update according to 0 in w_rec for hard constrain connection
|
# set 0 in wRecChange update according to 0 in w_rec for hard constrain connection
|
||||||
n.w_rec = n.w_rec + (not_zero .* n.w_rec_change)
|
n.w_rec = n.w_rec + (not_zero .* n.wRecChange)
|
||||||
replace!(x -> x < 0 ? 0 : x, n.w_rec) # no negative weight
|
replace!(x -> x < 0 ? 0 : x, n.w_rec) # no negative weight
|
||||||
|
|
||||||
Snn_utils.neuroplasticity!(n, kfn.firing_neurons_list)
|
Snn_utils.neuroplasticity!(n, kfn.firedNeurons)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
""" alif_neuron learn()
|
""" alif_neuron learn()
|
||||||
"""
|
"""
|
||||||
function learn!(n::alif_neuron, kfn::knowledgeFn)
|
function learn!(n::alif_neuron, kfn::knowledgeFn)
|
||||||
n.decayed_epsilon_rec = n.alpha * n.epsilon_rec
|
n.decayedEpsilonRec = n.alpha * n.epsilonRec
|
||||||
n.epsilon_rec = n.decayed_epsilon_rec + n.z_i_t
|
n.epsilonRec = n.decayedEpsilonRec + n.z_i_t
|
||||||
n.epsilon_rec_a = (n.phi * n.epsilon_rec) +
|
n.epsilonRecA = (n.phi * n.epsilonRec) +
|
||||||
((n.rho - (n.phi * n.beta)) * n.epsilon_rec_a)
|
((n.rho - (n.phi * n.beta)) * n.epsilonRecA)
|
||||||
n.e_rec_v = n.phi * n.epsilon_rec
|
n.eRec_v = n.phi * n.epsilonRec
|
||||||
n.e_rec_a = -n.phi * n.beta * n.epsilon_rec_a
|
n.eRec_a = -n.phi * n.beta * n.epsilonRecA
|
||||||
n.e_rec = n.e_rec_v + n.e_rec_a
|
n.eRec = n.eRec_v + n.eRec_a
|
||||||
|
|
||||||
# a piece of knowledgeFn error that belongs to this neuron
|
# a piece of knowledgeFn error that belongs to this neuron
|
||||||
n.error = isnothing(kfn.error) ? nothing : kfn.error * n.Bn
|
n.error = isnothing(kfn.error) ? nothing : kfn.error * n.Bn
|
||||||
n.learning_stage = kfn.learning_stage
|
n.learningStage = kfn.learningStage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if n.learning_stage == "doing_inference"
|
if n.learningStage == "doing_inference"
|
||||||
# no learning
|
# no learning
|
||||||
elseif n.learning_stage == "start_learning" ||
|
elseif n.learningStage == "start_learning" ||
|
||||||
n.learning_stage == "start_learning_no_wchange_reset"
|
n.learningStage == "start_learning_no_wchange_reset"
|
||||||
|
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing
|
if n.error !== nothing
|
||||||
Snn_utils.firing_rate!(n)
|
Snn_utils.firing_rate!(n)
|
||||||
Snn_utils.firing_diff!(n)
|
Snn_utils.firing_diff!(n)
|
||||||
n.w_rec_change = n.w_rec_change +
|
n.wRecChange = n.wRecChange +
|
||||||
-apply!(n.optimiser, n.w_rec,
|
-apply!(n.optimiser, n.w_rec,
|
||||||
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
|
(n.error + Snn_utils.voltage_error!(n) + n.firingRateError) * n.eRec) +
|
||||||
-Snn_utils.firing_rate_regulator!(n) +
|
-Snn_utils.firing_rate_regulator!(n) +
|
||||||
-Snn_utils.voltage_regulator!(n)
|
-Snn_utils.voltage_regulator!(n)
|
||||||
end
|
end
|
||||||
elseif n.learning_stage == "during_learning"
|
elseif n.learningStage == "during_learning"
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing
|
if n.error !== nothing
|
||||||
Snn_utils.firing_rate!(n)
|
Snn_utils.firing_rate!(n)
|
||||||
Snn_utils.firing_diff!(n)
|
Snn_utils.firing_diff!(n)
|
||||||
n.w_rec_change = n.w_rec_change +
|
n.wRecChange = n.wRecChange +
|
||||||
-apply!(n.optimiser, n.w_rec,
|
-apply!(n.optimiser, n.w_rec,
|
||||||
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
|
(n.error + Snn_utils.voltage_error!(n) + n.firingRateError) * n.eRec) +
|
||||||
-Snn_utils.firing_rate_regulator!(n) +
|
-Snn_utils.firing_rate_regulator!(n) +
|
||||||
-Snn_utils.voltage_regulator!(n)
|
-Snn_utils.voltage_regulator!(n)
|
||||||
end
|
end
|
||||||
elseif n.learning_stage == "end_learning"
|
elseif n.learningStage == "end_learning"
|
||||||
|
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing
|
if n.error !== nothing
|
||||||
Snn_utils.firing_rate!(n)
|
Snn_utils.firing_rate!(n)
|
||||||
Snn_utils.firing_diff!(n)
|
Snn_utils.firing_diff!(n)
|
||||||
n.w_rec_change = n.w_rec_change +
|
n.wRecChange = n.wRecChange +
|
||||||
-apply!(n.optimiser, n.w_rec,
|
-apply!(n.optimiser, n.w_rec,
|
||||||
(n.error + Snn_utils.voltage_error!(n) + n.firing_rate_error) * n.e_rec) +
|
(n.error + Snn_utils.voltage_error!(n) + n.firingRateError) * n.eRec) +
|
||||||
-Snn_utils.firing_rate_regulator!(n) +
|
-Snn_utils.firing_rate_regulator!(n) +
|
||||||
-Snn_utils.voltage_regulator!(n)
|
-Snn_utils.voltage_regulator!(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
not_zero = (!iszero).(n.w_rec)
|
not_zero = (!iszero).(n.w_rec)
|
||||||
# set 0 in w_rec_change update according to 0 in w_rec for hard constrain connection
|
# set 0 in wRecChange update according to 0 in w_rec for hard constrain connection
|
||||||
n.w_rec = n.w_rec + (not_zero .* n.w_rec_change)
|
n.w_rec = n.w_rec + (not_zero .* n.wRecChange)
|
||||||
replace!(x -> x < 0 ? 0 : x, n.w_rec) # no negative weight
|
replace!(x -> x < 0 ? 0 : x, n.w_rec) # no negative weight
|
||||||
|
|
||||||
Snn_utils.neuroplasticity!(n, kfn.firing_neurons_list)
|
Snn_utils.neuroplasticity!(n, kfn.firedNeurons)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
""" linear_neuron learn()
|
""" linear_neuron learn()
|
||||||
"""
|
"""
|
||||||
function learn!(n::linear_neuron, kfn::knowledgeFn)
|
function learn!(n::linear_neuron, kfn::knowledgeFn)
|
||||||
n.error = kfn.output_error[n.id]
|
n.error = kfn.outputError[n.id]
|
||||||
n.learning_stage = kfn.learning_stage
|
n.learningStage = kfn.learningStage
|
||||||
|
|
||||||
if n.learning_stage == "doing_inference"
|
if n.learningStage == "doing_inference"
|
||||||
# no learning
|
# no learning
|
||||||
elseif n.learning_stage == "start_learning"
|
elseif n.learningStage == "start_learning"
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
|
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
|
||||||
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
|
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
|
||||||
@@ -266,13 +272,13 @@ function learn!(n::linear_neuron, kfn::knowledgeFn)
|
|||||||
Δb = -n.eta * n.error
|
Δb = -n.eta * n.error
|
||||||
n.b_change = n.b_change + Δb
|
n.b_change = n.b_change + Δb
|
||||||
elseif n.error !== nothing && n.id !== 1
|
elseif n.error !== nothing && n.id !== 1
|
||||||
n.eta = kfn.output_neurons_array[1].eta
|
n.eta = kfn.outputNeuronsArray[1].eta
|
||||||
Δw = -n.eta * n.error * n.epsilon_j
|
Δw = -n.eta * n.error * n.epsilon_j
|
||||||
n.w_out_change = n.w_out_change + Δw
|
n.w_out_change = n.w_out_change + Δw
|
||||||
Δb = -n.eta * n.error
|
Δb = -n.eta * n.error
|
||||||
n.b_change = n.b_change + Δb
|
n.b_change = n.b_change + Δb
|
||||||
end
|
end
|
||||||
elseif n.learning_stage == "during_learning"
|
elseif n.learningStage == "during_learning"
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
|
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
|
||||||
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
|
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
|
||||||
@@ -281,13 +287,13 @@ function learn!(n::linear_neuron, kfn::knowledgeFn)
|
|||||||
Δb = -n.eta * n.error
|
Δb = -n.eta * n.error
|
||||||
n.b_change = n.b_change + Δb
|
n.b_change = n.b_change + Δb
|
||||||
elseif n.error !== nothing && n.id !== 1
|
elseif n.error !== nothing && n.id !== 1
|
||||||
n.eta = kfn.output_neurons_array[1].eta
|
n.eta = kfn.outputNeuronsArray[1].eta
|
||||||
Δw = -n.eta * n.error * n.epsilon_j
|
Δw = -n.eta * n.error * n.epsilon_j
|
||||||
n.w_out_change = n.w_out_change + Δw
|
n.w_out_change = n.w_out_change + Δw
|
||||||
Δb = -n.eta * n.error
|
Δb = -n.eta * n.error
|
||||||
n.b_change = n.b_change + Δb
|
n.b_change = n.b_change + Δb
|
||||||
end
|
end
|
||||||
elseif n.learning_stage == "end_learning"
|
elseif n.learningStage == "end_learning"
|
||||||
# if error signal available then accumulates Δw
|
# if error signal available then accumulates Δw
|
||||||
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
|
if n.error !== nothing && n.id == 1 # NOT working w/ multithreading training
|
||||||
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
|
Δw = -apply!(n.optimiser, n.w_out, (n.error * n.epsilon_j))
|
||||||
@@ -296,7 +302,7 @@ function learn!(n::linear_neuron, kfn::knowledgeFn)
|
|||||||
Δb = -n.eta * n.error
|
Δb = -n.eta * n.error
|
||||||
n.b_change = n.b_change + Δb
|
n.b_change = n.b_change + Δb
|
||||||
elseif n.error !== nothing && n.id !== 1
|
elseif n.error !== nothing && n.id !== 1
|
||||||
n.eta = kfn.output_neurons_array[1].eta
|
n.eta = kfn.outputNeuronsArray[1].eta
|
||||||
Δw = -n.eta * n.error * n.epsilon_j
|
Δw = -n.eta * n.error * n.epsilon_j
|
||||||
n.w_out_change = n.w_out_change + Δw
|
n.w_out_change = n.w_out_change + Δw
|
||||||
Δb = -n.eta * n.error
|
Δb = -n.eta * n.error
|
||||||
|
|||||||
@@ -32,24 +32,22 @@ no_negative!(x) = x < 0.0 ? 0.0 : x
|
|||||||
precision(x::Array{<:Array}) = ( std(mean.(x)) / mean(mean.(x)) ) * 100
|
precision(x::Array{<:Array}) = ( std(mean.(x)) / mean(mean.(x)) ) * 100
|
||||||
|
|
||||||
# reset functions for LIF/ALIF neuron
|
# reset functions for LIF/ALIF neuron
|
||||||
reset_last_firing_time!(n::compute_neuron) = n.last_firing_time = 0.0
|
reset_last_firing_time!(n::compute_neuron) = n.lastFiringTime = 0.0
|
||||||
reset_refractory_state_active!(n::compute_neuron) = n.refractory_state_active = false
|
reset_refractory_state_active!(n::compute_neuron) = n.refractory_state_active = false
|
||||||
reset_v_t!(n::compute_neuron) = n.v_t = n.v_t_default
|
reset_v_t!(n::compute_neuron) = n.v_t = n.v_t_default
|
||||||
reset_z_t!(n::compute_neuron) = n.z_t = false
|
reset_z_t!(n::compute_neuron) = n.z_t = false
|
||||||
reset_epsilon_rec!(n::compute_neuron) = n.epsilon_rec = n.epsilon_rec * 0.0
|
reset_epsilon_rec!(n::compute_neuron) = n.epsilonRec = n.epsilonRec * 0.0
|
||||||
reset_epsilon_rec_a!(n::alif_neuron) = n.epsilon_rec_a = n.epsilon_rec_a * 0.0
|
reset_epsilon_rec_a!(n::alif_neuron) = n.epsilonRecA = n.epsilonRecA * 0.0
|
||||||
reset_epsilon_in!(n::compute_neuron) = n.epsilon_in = isnothing(n.epsilon_in) ? nothing : n.epsilon_in * 0.0
|
reset_epsilon_in!(n::compute_neuron) = n.epsilon_in = isnothing(n.epsilon_in) ? nothing : n.epsilon_in * 0.0
|
||||||
reset_error!(n::Union{compute_neuron, linear_neuron}) = n.error = nothing
|
reset_error!(n::Union{compute_neuron, linear_neuron}) = n.error = nothing
|
||||||
reset_w_in_change!(n::compute_neuron) = n.w_in_change = isnothing(n.w_in_change) ? nothing : n.w_in_change * 0.0
|
reset_w_in_change!(n::compute_neuron) = n.w_in_change = isnothing(n.w_in_change) ? nothing : n.w_in_change * 0.0
|
||||||
reset_w_rec_change!(n::compute_neuron) = n.w_rec_change = n.w_rec_change * 0.0
|
reset_w_rec_change!(n::compute_neuron) = n.wRecChange = n.wRecChange * 0.0
|
||||||
reset_a!(n::alif_neuron) = n.a = n.a * 0.0
|
reset_a!(n::alif_neuron) = n.a = n.a * 0.0
|
||||||
reset_reg_voltage_a!(n::compute_neuron) = n.reg_voltage_a = n.reg_voltage_a * 0.0
|
reset_reg_voltage_a!(n::compute_neuron) = n.reg_voltage_a = n.reg_voltage_a * 0.0
|
||||||
reset_reg_voltage_b!(n::compute_neuron) = n.reg_voltage_b = n.reg_voltage_b * 0.0
|
reset_reg_voltage_b!(n::compute_neuron) = n.reg_voltage_b = n.reg_voltage_b * 0.0
|
||||||
reset_reg_voltage_error!(n::compute_neuron) = n.reg_voltage_error = n.reg_voltage_error * 0.0
|
reset_reg_voltage_error!(n::compute_neuron) = n.reg_voltage_error = n.reg_voltage_error * 0.0
|
||||||
reset_firing_counter!(n::compute_neuron) = n.firing_counter = n.firing_counter * 0.0
|
reset_firing_counter!(n::compute_neuron) = n.firingCounter = n.firingCounter * 0.0
|
||||||
reset_firing_diff!(n::Union{compute_neuron, linear_neuron}) = n.firing_diff = n.firing_diff * 0.0
|
reset_firing_diff!(n::Union{compute_neuron, linear_neuron}) = n.firingDiff = n.firingDiff * 0.0
|
||||||
reset_previous_error!(n::Union{compute_neuron}) =
|
|
||||||
n.previous_error = n.previous_error * 0.0
|
|
||||||
|
|
||||||
# reset function for output neuron
|
# reset function for output neuron
|
||||||
reset_epsilon_j!(n::linear_neuron) = n.epsilon_j = n.epsilon_j * 0.0
|
reset_epsilon_j!(n::linear_neuron) = n.epsilon_j = n.epsilon_j * 0.0
|
||||||
@@ -151,7 +149,7 @@ end
|
|||||||
|
|
||||||
function store_knowledgefn_error!(kfn::knowledgeFn)
|
function store_knowledgefn_error!(kfn::knowledgeFn)
|
||||||
# condition to adjust nueron in KFN plane in addition to weight adjustment inside each neuron
|
# condition to adjust nueron in KFN plane in addition to weight adjustment inside each neuron
|
||||||
if kfn.learning_stage == "start_learning"
|
if kfn.learningStage == "start_learning"
|
||||||
if kfn.recent_knowledgeFn_error === nothing && kfn.knowledgeFn_error === nothing
|
if kfn.recent_knowledgeFn_error === nothing && kfn.knowledgeFn_error === nothing
|
||||||
kfn.recent_knowledgeFn_error = [[]]
|
kfn.recent_knowledgeFn_error = [[]]
|
||||||
elseif kfn.recent_knowledgeFn_error === nothing
|
elseif kfn.recent_knowledgeFn_error === nothing
|
||||||
@@ -161,13 +159,13 @@ function store_knowledgefn_error!(kfn::knowledgeFn)
|
|||||||
else
|
else
|
||||||
push!(kfn.recent_knowledgeFn_error, [kfn.knowledgeFn_error])
|
push!(kfn.recent_knowledgeFn_error, [kfn.knowledgeFn_error])
|
||||||
end
|
end
|
||||||
elseif kfn.learning_stage == "during_learning"
|
elseif kfn.learningStage == "during_learning"
|
||||||
if kfn.knowledgeFn_error === nothing
|
if kfn.knowledgeFn_error === nothing
|
||||||
#skip
|
#skip
|
||||||
else
|
else
|
||||||
push!(kfn.recent_knowledgeFn_error[end], kfn.knowledgeFn_error)
|
push!(kfn.recent_knowledgeFn_error[end], kfn.knowledgeFn_error)
|
||||||
end
|
end
|
||||||
elseif kfn.learning_stage == "end_learning"
|
elseif kfn.learningStage == "end_learning"
|
||||||
if kfn.recent_knowledgeFn_error === nothing
|
if kfn.recent_knowledgeFn_error === nothing
|
||||||
#skip
|
#skip
|
||||||
else
|
else
|
||||||
@@ -184,15 +182,15 @@ end
|
|||||||
|
|
||||||
function update_Bn!(kfn::knowledgeFn)
|
function update_Bn!(kfn::knowledgeFn)
|
||||||
Δw = nothing
|
Δw = nothing
|
||||||
for n in kfn.output_neurons_array
|
for n in kfn.outputNeuronsArray
|
||||||
Δw = Δw === nothing ? n.w_out_change : Δw + n.w_out_change
|
Δw = Δw === nothing ? n.w_out_change : Δw + n.w_out_change
|
||||||
n.w_out = n.w_out - (n.Bn_wout_decay * n.w_out) # w_out decay
|
n.w_out = n.w_out - (n.Bn_wout_decay * n.w_out) # w_out decay
|
||||||
end
|
end
|
||||||
# Δw = Δw / kfn.kfn_params[:linear_neuron_number] # average
|
# Δw = Δw / kfn.kfnParams[:linear_neuron_number] # average
|
||||||
|
|
||||||
input_neuron_number = kfn.kfn_params[:input_neuron_number] # skip input neuron
|
input_neuron_number = kfn.kfnParams[:input_neuron_number] # skip input neuron
|
||||||
for i = 1:kfn.kfn_params[:compute_neuron_number]
|
for i = 1:kfn.kfnParams[:compute_neuron_number]
|
||||||
n = kfn.neurons_array[input_neuron_number+i]
|
n = kfn.neuronsArray[input_neuron_number+i]
|
||||||
n.Bn = n.Bn + Δw[i]
|
n.Bn = n.Bn + Δw[i]
|
||||||
n.Bn = n.Bn - (n.Bn_wout_decay * n.Bn) # w_out decay
|
n.Bn = n.Bn - (n.Bn_wout_decay * n.Bn) # w_out decay
|
||||||
end
|
end
|
||||||
@@ -208,7 +206,7 @@ function cal_v_reg!(n::lif_neuron)
|
|||||||
|
|
||||||
component_b = n.v_t1 - n.v_th < 0 ? 0 : n.v_t1 - n.v_th
|
component_b = n.v_t1 - n.v_th < 0 ? 0 : n.v_t1 - n.v_th
|
||||||
#FIXME: not sure the following line is correct
|
#FIXME: not sure the following line is correct
|
||||||
n.reg_voltage_b = n.reg_voltage_b + (component_b * n.epsilon_rec)
|
n.reg_voltage_b = n.reg_voltage_b + (component_b * n.epsilonRec)
|
||||||
end
|
end
|
||||||
|
|
||||||
function cal_v_reg!(n::alif_neuron)
|
function cal_v_reg!(n::alif_neuron)
|
||||||
@@ -219,7 +217,7 @@ function cal_v_reg!(n::alif_neuron)
|
|||||||
|
|
||||||
component_b = n.v_t1 - n.av_th < 0 ? 0 : n.v_t1 - n.av_th
|
component_b = n.v_t1 - n.av_th < 0 ? 0 : n.v_t1 - n.av_th
|
||||||
#FIXME: not sure the following line is correct
|
#FIXME: not sure the following line is correct
|
||||||
n.reg_voltage_b = n.reg_voltage_b + (component_b * (n.epsilon_rec - n.epsilon_rec_a))
|
n.reg_voltage_b = n.reg_voltage_b + (component_b * (n.epsilonRec - n.epsilonRecA))
|
||||||
end
|
end
|
||||||
|
|
||||||
function voltage_error!(n::compute_neuron)
|
function voltage_error!(n::compute_neuron)
|
||||||
@@ -232,23 +230,23 @@ function voltage_regulator!(n::compute_neuron) # running average
|
|||||||
return Δw
|
return Δw
|
||||||
end
|
end
|
||||||
|
|
||||||
function firing_rate_error(kfn::knowledgeFn)
|
function firingRateError(kfn::knowledgeFn)
|
||||||
start_id = kfn.kfn_params[:input_neuron_number] + 1
|
start_id = kfn.kfnParams[:input_neuron_number] + 1
|
||||||
return 0.5 * sum([(n.firing_diff)^2 for n in kfn.neurons_array[start_id:end]])
|
return 0.5 * sum([(n.firingDiff)^2 for n in kfn.neuronsArray[start_id:end]])
|
||||||
end
|
end
|
||||||
|
|
||||||
function firing_rate_regulator!(n::compute_neuron)
|
function firing_rate_regulator!(n::compute_neuron)
|
||||||
# n.firing_rate NOT running average (average over learning batch)
|
# n.firingRate NOT running average (average over learning batch)
|
||||||
Δw = n.optimiser.eta * n.c_reg *
|
Δw = n.optimiser.eta * n.c_reg *
|
||||||
(n.firing_rate - n.firing_rate_target) * n.e_rec
|
(n.firingRate - n.firingRateTarget) * n.eRec
|
||||||
Δw = n.firing_rate > n.firing_rate_target ? Δw : Δw * 0.0
|
Δw = n.firingRate > n.firingRateTarget ? Δw : Δw * 0.0
|
||||||
return Δw
|
return Δw
|
||||||
end
|
end
|
||||||
|
|
||||||
firing_rate!(n::compute_neuron) = n.firing_rate = (n.firing_counter / n.time_stamp) * 1000
|
firing_rate!(n::compute_neuron) = n.firingRate = (n.firingCounter / n.timeStep) * 1000
|
||||||
firing_diff!(n::compute_neuron) = n.firing_diff = n.firing_rate - n.firing_rate_target
|
firing_diff!(n::compute_neuron) = n.firingDiff = n.firingRate - n.firingRateTarget
|
||||||
|
|
||||||
function neuroplasticity!(n::compute_neuron, firing_neurons_list::Vector)
|
function neuroplasticity!(n::compute_neuron, firedNeurons::Vector)
|
||||||
# if there is 0-weight then replace it with new connection
|
# if there is 0-weight then replace it with new connection
|
||||||
zero_weight_index = findall(iszero.(n.w_rec))
|
zero_weight_index = findall(iszero.(n.w_rec))
|
||||||
if length(zero_weight_index) != 0
|
if length(zero_weight_index) != 0
|
||||||
@@ -257,8 +255,8 @@ function neuroplasticity!(n::compute_neuron, firing_neurons_list::Vector)
|
|||||||
not fire = no information
|
not fire = no information
|
||||||
"""
|
"""
|
||||||
|
|
||||||
subscribe_options = filter(x -> x ∉ [n.id], firing_neurons_list) # exclude this neuron id from the list
|
subscribe_options = filter(x -> x ∉ [n.id], firedNeurons) # exclude this neuron id from the list
|
||||||
filter!(x -> x ∉ n.subscription_list, subscribe_options) # exclude this neuron's subscription_list from the list
|
filter!(x -> x ∉ n.subscriptionList, subscribe_options) # exclude this neuron's subscriptionList from the list
|
||||||
shuffle!(subscribe_options)
|
shuffle!(subscribe_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -266,7 +264,7 @@ function neuroplasticity!(n::compute_neuron, firing_neurons_list::Vector)
|
|||||||
percentage = [new_connection_percent, 100.0 - new_connection_percent] / 100.0
|
percentage = [new_connection_percent, 100.0 - new_connection_percent] / 100.0
|
||||||
for i in zero_weight_index
|
for i in zero_weight_index
|
||||||
if Utils.random_choices([true, false], percentage)
|
if Utils.random_choices([true, false], percentage)
|
||||||
n.subscription_list[i] = pop!(subscribe_options)
|
n.subscriptionList[i] = pop!(subscribe_options)
|
||||||
n.w_rec[i] = 0.01 # new connection should not send large signal otherwise it would throw
|
n.w_rec[i] = 0.01 # new connection should not send large signal otherwise it would throw
|
||||||
# RSNN off path. Let weight grow by an optimiser
|
# RSNN off path. Let weight grow by an optimiser
|
||||||
end
|
end
|
||||||
@@ -283,7 +281,7 @@ function push_epsilon_rec_a!(n::lif_neuron)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function push_epsilon_rec_a!(n::alif_neuron)
|
function push_epsilon_rec_a!(n::alif_neuron)
|
||||||
push!(n.epsilon_rec_a, 0)
|
push!(n.epsilonRecA, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
391
src/types.jl
391
src/types.jl
@@ -26,19 +26,19 @@ abstract type compute_neuron <: neuron end
|
|||||||
"""
|
"""
|
||||||
Base.@kwdef mutable struct model <: Ironpen
|
Base.@kwdef mutable struct model <: Ironpen
|
||||||
knowledgeFn::Union{Dict,Nothing} = nothing
|
knowledgeFn::Union{Dict,Nothing} = nothing
|
||||||
model_params::Union{Dict,Nothing} = nothing
|
modelParams::Union{Dict,Nothing} = nothing
|
||||||
error::Union{Float64,Nothing} = 0.0
|
error::Union{Float64,Nothing} = 0.0
|
||||||
output_error::Union{Array,Nothing} = Vector{AbstractFloat}()
|
outputError::Union{Array,Nothing} = Vector{AbstractFloat}()
|
||||||
|
|
||||||
""" "inference" = no learning params will be collected.
|
""" "inference" = no learning params will be collected.
|
||||||
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
||||||
correct answer is available then merge Δw_rec_change into w_rec_change then
|
correct answer is available then merge Δw_rec_change into wRecChange then
|
||||||
reset epsilon_j.
|
reset epsilon_j.
|
||||||
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
|
"reflect" = neuron will merge wRecChange into w_rec then reset wRecChange. """
|
||||||
learning_stage::String = "inference"
|
learningStage::String = "inference"
|
||||||
|
|
||||||
softreset::Bool = false
|
softreset::Bool = false
|
||||||
time_stamp::Number = 0.0
|
timeStep::Number = 0.0
|
||||||
end
|
end
|
||||||
""" Model outer constructor
|
""" Model outer constructor
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ end
|
|||||||
:v_th => 2.0, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
:v_th => 2.0, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
||||||
:z_t => false, # neuron firing status at time = t
|
:z_t => false, # neuron firing status at time = t
|
||||||
:z_t1 => false, # neuron firing status at time = t+1
|
:z_t1 => false, # neuron firing status at time = t+1
|
||||||
:gamma_pd => 0.3, # discount factor. The value is from the paper
|
:gammaPd => 0.3, # discount factor. The value is from the paper
|
||||||
:phi => 0.0, # psuedo derivative
|
:phi => 0.0, # psuedo derivative
|
||||||
:refractory_duration => 2.0, # neuron refractory period in tick
|
:refractoryDuration => 2.0, # neuron refractory period in tick
|
||||||
:delta => 1.0,
|
:delta => 1.0,
|
||||||
:tau_m => 20.0, # membrane time constant in millisecond. The value is from the paper
|
:tau_m => 20.0, # membrane time constant in millisecond. The value is from the paper
|
||||||
:eta => 0.01, # learning rate
|
:eta => 0.01, # learning rate
|
||||||
@@ -59,15 +59,15 @@ end
|
|||||||
I_kfn = Ironpen_ai_gpu.knowledgeFn(I_kfnparams, lif_neuron_params, alif_neuron_params,
|
I_kfn = Ironpen_ai_gpu.knowledgeFn(I_kfnparams, lif_neuron_params, alif_neuron_params,
|
||||||
linear_neuron_params)
|
linear_neuron_params)
|
||||||
|
|
||||||
model_params_1 = Dict(:knowledgeFn => Dict(:I => I_kfn,
|
modelParams_1 = Dict(:knowledgeFn => Dict(:I => I_kfn,
|
||||||
:run => run_kfn),
|
:run => run_kfn),
|
||||||
:learning_stage => "doing_inference",)
|
:learningStage => "doing_inference",)
|
||||||
|
|
||||||
model_1 = Ironpen_ai_gpu.model(model_params_1)
|
model_1 = Ironpen_ai_gpu.model(modelParams_1)
|
||||||
"""
|
"""
|
||||||
function model(params::Dict)
|
function model(params::Dict)
|
||||||
m = model()
|
m = model()
|
||||||
m.model_params = params
|
m.modelParams = params
|
||||||
|
|
||||||
fields = fieldnames(typeof(m))
|
fields = fieldnames(typeof(m))
|
||||||
for i in fields
|
for i in fields
|
||||||
@@ -84,39 +84,37 @@ end
|
|||||||
""" knowledgeFn struct
|
""" knowledgeFn struct
|
||||||
"""
|
"""
|
||||||
Base.@kwdef mutable struct kfn_1 <: knowledgeFn
|
Base.@kwdef mutable struct kfn_1 <: knowledgeFn
|
||||||
knowledgefn_name::Union{String,Nothing} = nothing
|
knowledgeFnName::Union{String,Nothing} = nothing
|
||||||
kfn_params::Union{Dict,Nothing} = nothing # store params of knowledgeFn itself for later use
|
kfnParams::Union{Dict,Nothing} = nothing # store params of knowledgeFn itself for later use
|
||||||
time_stamp::Number = 0.0
|
timeStep::Number = 0.0
|
||||||
|
|
||||||
# Bn contain error coefficient for both neurons and output neurons in one place
|
# Bn contain error coefficient for both neurons and output neurons in one place
|
||||||
Bn::Vector{Float64} = Vector{Float64}() # error projection coefficient from kfn output's error to each neurons's error
|
Bn::Vector{Float64} = Vector{Float64}() # error projection coefficient from kfn output's error to each neurons's error
|
||||||
neurons_array::Union{Array,Nothing} = [] # put neurons here
|
neuronsArray::Union{Array,Nothing} = [] # put neurons here
|
||||||
|
|
||||||
""" put output neuron here. I seperate output neuron because
|
""" put output neuron here. I seperate output neuron because
|
||||||
1. its calculation is difference than other neuron types
|
1. its calculation is difference than other neuron types
|
||||||
2. other neuron type will not induced to connnect to output neuron
|
2. other neuron type will not induced to connnect to output neuron
|
||||||
3. output neuron does not induced to connect to its own type """
|
3. output neuron does not induced to connect to its own type """
|
||||||
output_neurons_array::Union{Array,Nothing} = []
|
outputNeuronsArray::Union{Array,Nothing} = []
|
||||||
|
|
||||||
""" "inference" = no learning params will be collected.
|
""" "inference" = no learning params will be collected.
|
||||||
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
||||||
correct answer is available then merge Δw_rec_change into w_rec_change then
|
correct answer is available then merge Δw_rec_change into wRecChange then
|
||||||
reset epsilon_j.
|
reset epsilon_j.
|
||||||
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
|
"reflect" = neuron will merge wRecChange into w_rec then reset wRecChange. """
|
||||||
learning_stage::String = "inference"
|
learningStage::String = "inference"
|
||||||
|
|
||||||
error::Union{Float64,Nothing} = nothing
|
error::Union{Float64,Nothing} = nothing
|
||||||
output_error::Union{Array,Nothing} = Vector{AbstractFloat}()
|
outputError::Union{Array,Nothing} = Vector{AbstractFloat}()
|
||||||
recent_knowledgeFn_error::Union{Any,Nothing} = nothing
|
|
||||||
softreset::Bool = false
|
softreset::Bool = false
|
||||||
meta_params::Union{Dict{Any,Any},Nothing} = Dict()
|
|
||||||
|
|
||||||
firing_neurons_list::Array{Int64} = Vector{Int64}() # store id of firing neurons
|
firedNeurons::Array{Int64} = Vector{Int64}() # store unique id of firing neurons to be used when random neuron connection
|
||||||
snn_firing_state_t0::Union{Vector{Bool},Nothing} = nothing # store firing state of all neurons at t0
|
firedNeurons_t0::Union{Vector{Bool},Nothing} = nothing # store firing state of all neurons at t0
|
||||||
snn_firing_state_t1::Union{Vector{Bool},Nothing} = nothing # store firing state of all neurons at t1
|
firedNeurons_t1::Union{Vector{Bool},Nothing} = nothing # store firing state of all neurons at t1
|
||||||
|
|
||||||
avg_neurons_firing_rate::Union{Float64,Nothing} = 0.0 # for displaying average firing rate over all neurons
|
avgNeuronsFiringRate::Union{Float64,Nothing} = 0.0 # for displaying average firing rate over all neurons
|
||||||
avg_neurons_v_t1::Union{Float64,Nothing} = 0.0 # for displaying average v_t1 over all neurons
|
avgNeurons_v_t1::Union{Float64,Nothing} = 0.0 # for displaying average v_t1 over all neurons
|
||||||
end
|
end
|
||||||
|
|
||||||
#------------------------------------------------------------------------------------------------100
|
#------------------------------------------------------------------------------------------------100
|
||||||
@@ -129,8 +127,8 @@ end
|
|||||||
:type => "lif_neuron",
|
:type => "lif_neuron",
|
||||||
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
||||||
:z_t => false, # neuron firing status at time = t
|
:z_t => false, # neuron firing status at time = t
|
||||||
:gamma_pd => 0.3, # discount factor. The value is from the paper
|
:gammaPd => 0.3, # discount factor. The value is from the paper
|
||||||
:refractory_duration => 2.0, # neuron refractory period in tick
|
:refractoryDuration => 2.0, # neuron refractory period in tick
|
||||||
:delta => 1.0,
|
:delta => 1.0,
|
||||||
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
|
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
|
||||||
)
|
)
|
||||||
@@ -139,8 +137,8 @@ end
|
|||||||
:type => "alif_neuron",
|
:type => "alif_neuron",
|
||||||
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
||||||
:z_t => false, # neuron firing status at time = t
|
:z_t => false, # neuron firing status at time = t
|
||||||
:gamma_pd => 0.3, # discount factor. The value is from the paper
|
:gammaPd => 0.3, # discount factor. The value is from the paper
|
||||||
:refractory_duration => 2.0, # neuron refractory period in millisecond
|
:refractoryDuration => 2.0, # neuron refractory period in millisecond
|
||||||
:delta => 1.0,
|
:delta => 1.0,
|
||||||
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
|
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
|
||||||
|
|
||||||
@@ -159,14 +157,14 @@ end
|
|||||||
)
|
)
|
||||||
|
|
||||||
I_kfnparams = Dict(
|
I_kfnparams = Dict(
|
||||||
:knowledgefn_name => "I",
|
:knowledgeFnName => "I",
|
||||||
:lif_neuron_number => 200,
|
:lif_neuron_number => 200,
|
||||||
:alif_neuron_number => 100, # from Allen Institute, ALIF is 40% of LIF
|
:alif_neuron_number => 100, # from Allen Institute, ALIF is 40% of LIF
|
||||||
:linear_neuron_number => 5, # output neuron, this is also the output length
|
:linear_neuron_number => 5, # output neuron, this is also the output length
|
||||||
:Bn => "random", # error projection coefficient from kfn output's error to each neurons's error
|
:Bn => "random", # error projection coefficient from kfn output's error to each neurons's error
|
||||||
:learning_rate => 0.01,
|
:learning_rate => 0.01,
|
||||||
:neuron_connection_pattern => "100%", # number of each neuron subscribe to other neuron in knowledgeFn.neurons_array
|
:neuron_connection_pattern => "100%", # number of each neuron subscribe to other neuron in knowledgeFn.neuronsArray
|
||||||
:output_neuron_connection_pattern => "100%", # "60%" of kfn.neurons_array or number
|
:output_neuron_connection_pattern => "100%", # "60%" of kfn.neuronsArray or number
|
||||||
:maximum_input_data_length => 5, # in case of GloVe word encoding, it is 300
|
:maximum_input_data_length => 5, # in case of GloVe word encoding, it is 300
|
||||||
:neuron_w_in_generation_pattern => "random", # number or "random"
|
:neuron_w_in_generation_pattern => "random", # number or "random"
|
||||||
:neuron_w_rec_generation_pattern => "random",
|
:neuron_w_rec_generation_pattern => "random",
|
||||||
@@ -180,86 +178,86 @@ end
|
|||||||
:meta_params => Dict(:is_first_cycle => true,
|
:meta_params => Dict(:is_first_cycle => true,
|
||||||
:launch_time => 0.0,))
|
:launch_time => 0.0,))
|
||||||
|
|
||||||
kfn1 = knowledgeFn(kfn_params, lif_neuron_params, alif_neuron_params, linear_neuron_params)
|
kfn1 = knowledgeFn(kfnParams, lif_neuron_params, alif_neuron_params, linear_neuron_params)
|
||||||
"""
|
"""
|
||||||
function kfn_1(kfn_params::Dict)
|
function kfn_1(kfnParams::Dict)
|
||||||
|
|
||||||
kfn = kfn_1()
|
kfn = kfn_1()
|
||||||
kfn.kfn_params = kfn_params
|
kfn.kfnParams = kfnParams
|
||||||
kfn.knowledgefn_name = kfn.kfn_params[:knowledgefn_name]
|
kfn.knowledgeFnName = kfn.kfnParams[:knowledgeFnName]
|
||||||
|
|
||||||
if kfn.kfn_params[:compute_neuron_number] < kfn.kfn_params[:total_input_port]
|
if kfn.kfnParams[:compute_neuron_number] < kfn.kfnParams[:total_input_port]
|
||||||
throw(error("number of compute neuron must be greater than input neuron"))
|
throw(error("number of compute neuron must be greater than input neuron"))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Bn
|
# Bn
|
||||||
if kfn.kfn_params[:Bn] == "random"
|
if kfn.kfnParams[:Bn] == "random"
|
||||||
kfn.Bn = [Random.rand(0:0.001:1) for i in 1:kfn.kfn_params[:compute_neuron_number]]
|
kfn.Bn = [Random.rand(0:0.001:1) for i in 1:kfn.kfnParams[:compute_neuron_number]]
|
||||||
else # in case I want to specify manually
|
else # in case I want to specify manually
|
||||||
kfn.Bn = [kfn.kfn_params[:Bn] for i in 1:kfn.kfn_params[:compute_neuron_number]]
|
kfn.Bn = [kfn.kfnParams[:Bn] for i in 1:kfn.kfnParams[:compute_neuron_number]]
|
||||||
end
|
end
|
||||||
|
|
||||||
# assign neurons ID by their position in kfn.neurons array because I think it is
|
# assign neurons ID by their position in kfn.neurons array because I think it is
|
||||||
# straight forward way
|
# straight forward way
|
||||||
|
|
||||||
# add input port
|
# add input port
|
||||||
for (k, v) in kfn.kfn_params[:input_port]
|
for (k, v) in kfn.kfnParams[:input_port]
|
||||||
current_type = kfn.kfn_params[:input_port][k]
|
current_type = kfn.kfnParams[:input_port][k]
|
||||||
for i = 1:current_type[:numbers]
|
for i = 1:current_type[:numbers]
|
||||||
n_id = length(kfn.neurons_array) + 1
|
n_id = length(kfn.neuronsArray) + 1
|
||||||
neuron = init_neuron(n_id, current_type[:params], kfn.kfn_params)
|
neuron = init_neuron(n_id, current_type[:params], kfn.kfnParams)
|
||||||
push!(kfn.neurons_array, neuron)
|
push!(kfn.neuronsArray, neuron)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# add compute neurons
|
# add compute neurons
|
||||||
for (k, v) in kfn.kfn_params[:compute_neuron]
|
for (k, v) in kfn.kfnParams[:compute_neuron]
|
||||||
current_type = kfn.kfn_params[:compute_neuron][k]
|
current_type = kfn.kfnParams[:compute_neuron][k]
|
||||||
for i = 1:current_type[:numbers]
|
for i = 1:current_type[:numbers]
|
||||||
n_id = length(kfn.neurons_array) + 1
|
n_id = length(kfn.neuronsArray) + 1
|
||||||
neuron = init_neuron(n_id, current_type[:params], kfn.kfn_params)
|
neuron = init_neuron(n_id, current_type[:params], kfn.kfnParams)
|
||||||
push!(kfn.neurons_array, neuron)
|
push!(kfn.neuronsArray, neuron)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1:kfn.kfn_params[:output_port][:numbers]
|
for i = 1:kfn.kfnParams[:output_port][:numbers]
|
||||||
neuron = init_neuron(i, kfn.kfn_params[:output_port][:params],
|
neuron = init_neuron(i, kfn.kfnParams[:output_port][:params],
|
||||||
kfn.kfn_params)
|
kfn.kfnParams)
|
||||||
push!(kfn.output_neurons_array, neuron)
|
push!(kfn.outputNeuronsArray, neuron)
|
||||||
end
|
end
|
||||||
|
|
||||||
# random which neuron output port subscribed to, 1-compute_neuron for each output port
|
# random which neuron output port subscribed to, 1-compute_neuron for each output port
|
||||||
sub_list = shuffle!([kfn.kfn_params[:total_input_port]+1:length(kfn.neurons_array)...])
|
sub_list = shuffle!([kfn.kfnParams[:total_input_port]+1:length(kfn.neuronsArray)...])
|
||||||
sub_output_neuron = [pop!(sub_list) for i in 1:kfn.kfn_params[:output_port][:numbers]]
|
sub_output_neuron = [pop!(sub_list) for i in 1:kfn.kfnParams[:output_port][:numbers]]
|
||||||
for i in kfn.output_neurons_array
|
for i in kfn.outputNeuronsArray
|
||||||
i.subscription_list = [pop!(sub_output_neuron)]
|
i.subscriptionList = [pop!(sub_output_neuron)]
|
||||||
end
|
end
|
||||||
|
|
||||||
for n in kfn.neurons_array
|
for n in kfn.neuronsArray
|
||||||
if typeof(n) <: compute_neuron
|
if typeof(n) <: compute_neuron
|
||||||
n.firing_rate_target = kfn.kfn_params[:neuron_firing_rate_target]
|
n.firingRateTarget = kfn.kfnParams[:neuron_firing_rate_target]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# excitatory neuron to inhabitory neuron = 60:40 % of compute_neuron
|
# excitatory neuron to inhabitory neuron = 60:40 % of compute_neuron
|
||||||
ex_number = Int(floor(0.6 * kfn.kfn_params[:compute_neuron_number]))
|
ex_number = Int(floor(0.6 * kfn.kfnParams[:compute_neuron_number]))
|
||||||
ex_n = [1 for i in 1:ex_number]
|
ex_n = [1 for i in 1:ex_number]
|
||||||
in_number = kfn.kfn_params[:compute_neuron_number] - ex_number
|
in_number = kfn.kfnParams[:compute_neuron_number] - ex_number
|
||||||
in_n = [-1 for i in 1:in_number]
|
in_n = [-1 for i in 1:in_number]
|
||||||
ex_in = shuffle!([ex_n; in_n])
|
ex_in = shuffle!([ex_n; in_n])
|
||||||
|
|
||||||
# input neurons are always excitatory, compute_neurons are random between excitatory
|
# input neurons are always excitatory, compute_neurons are random between excitatory
|
||||||
# and inhabitory
|
# and inhabitory
|
||||||
for n in reverse(kfn.neurons_array)
|
for n in reverse(kfn.neuronsArray)
|
||||||
try n.ExIn_type = pop!(ex_in) catch end
|
try n.ExInType = pop!(ex_in) catch end
|
||||||
end
|
end
|
||||||
|
|
||||||
# add ExIn_type into each compute_neuron sub_ExIn_type
|
# add ExInType into each compute_neuron subExInType
|
||||||
for n in reverse(kfn.neurons_array)
|
for n in reverse(kfn.neuronsArray)
|
||||||
try # input neuron doest have n.subscription_list
|
try # input neuron doest have n.subscriptionList
|
||||||
for sub_id in n.subscription_list
|
for sub_id in n.subscriptionList
|
||||||
n_ExIn_type = kfn.neurons_array[sub_id].ExIn_type
|
n_ExInType = kfn.neuronsArray[sub_id].ExInType
|
||||||
push!(n.sub_ExIn_type, n_ExIn_type)
|
push!(n.subExInType, n_ExInType)
|
||||||
end
|
end
|
||||||
catch
|
catch
|
||||||
end
|
end
|
||||||
@@ -275,11 +273,11 @@ end
|
|||||||
Base.@kwdef mutable struct passthrough_neuron <: input_neuron
|
Base.@kwdef mutable struct passthrough_neuron <: input_neuron
|
||||||
id::Union{Int64,Nothing} = nothing # ID of this neuron which is it position in knowledgeFn array
|
id::Union{Int64,Nothing} = nothing # ID of this neuron which is it position in knowledgeFn array
|
||||||
type::String = "passthrough_neuron"
|
type::String = "passthrough_neuron"
|
||||||
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
knowledgeFnName::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
||||||
z_t::Bool = false
|
z_t::Bool = false
|
||||||
z_t1::Bool = false
|
z_t1::Bool = false
|
||||||
time_stamp::Number = 0.0 # current time
|
timeStep::Number = 0.0 # current time
|
||||||
ExIn_type::Integer = 1 # 1 excitatory, -1 inhabitory. input neuron is always excitatory
|
ExInType::Integer = 1 # 1 excitatory, -1 inhabitory. input neuron is always excitatory
|
||||||
end
|
end
|
||||||
|
|
||||||
function passthrough_neuron(params::Dict)
|
function passthrough_neuron(params::Dict)
|
||||||
@@ -305,17 +303,18 @@ end
|
|||||||
Base.@kwdef mutable struct lif_neuron <: compute_neuron
|
Base.@kwdef mutable struct lif_neuron <: compute_neuron
|
||||||
id::Union{Int64,Nothing} = nothing # this neuron ID i.e. position of this neuron in knowledgeFn
|
id::Union{Int64,Nothing} = nothing # this neuron ID i.e. position of this neuron in knowledgeFn
|
||||||
type::String = "lif_neuron"
|
type::String = "lif_neuron"
|
||||||
ExIn_type::Integer = 1 # 1 excitatory, -1 inhabitory
|
ExInType::Integer = 1 # 1 excitatory, -1 inhabitory
|
||||||
# Bn::Union{Float64,Nothing} = Random.rand() # Bias for neuron error
|
# Bn::Union{Float64,Nothing} = Random.rand() # Bias for neuron error
|
||||||
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
knowledgeFnName::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
||||||
subscription_list::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
|
subscriptionList::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
|
||||||
sub_ExIn_type::Array{Int64} = Vector{Int64}() # store ExIn type of subscribed neurons
|
subExInType::Array{Int64} = Vector{Int64}() # store ExIn type of subscribed neurons
|
||||||
time_stamp::Number = 0.0 # current time
|
timeStep::Number = 0.0 # current time
|
||||||
w_rec::Union{Array{Float64},Nothing} = nothing # synaptic weight (for receiving signal from other neuron)
|
w_rec::Union{Array{Float64},Nothing} = nothing # synaptic weight (for receiving signal from other neuron)
|
||||||
v_t::Float64 = 0.0 # vᵗ, postsynaptic neuron membrane potential of previous timestep
|
v_t::Float64 = 0.0 # vᵗ, postsynaptic neuron membrane potential of previous timestep
|
||||||
v_t1::Float64 = 0.0 # vᵗ⁺¹, postsynaptic neuron membrane potential at current timestep
|
v_t1::Float64 = 0.0 # vᵗ⁺¹, postsynaptic neuron membrane potential at current timestep
|
||||||
v_t_default::Union{Float64,Nothing} = 0.0 # default membrane potential voltage
|
v_t_default::Union{Float64,Nothing} = 0.0 # default membrane potential voltage
|
||||||
v_th::Float64 = 1.0 # vᵗʰ, neuron firing threshold
|
v_th::Float64 = 1.0 # vᵗʰ, neuron firing threshold
|
||||||
|
vRest::Float64 = 0.0 # resting potential after neuron fired
|
||||||
z_t::Bool = false # zᵗ, neuron postsynaptic firing of previous timestep
|
z_t::Bool = false # zᵗ, neuron postsynaptic firing of previous timestep
|
||||||
# zᵗ⁺¹, neuron firing status at time = t+1. I need this because the way I calculate all
|
# zᵗ⁺¹, neuron firing status at time = t+1. I need this because the way I calculate all
|
||||||
# neurons forward function at each timestep-by-timestep is to do every neuron
|
# neurons forward function at each timestep-by-timestep is to do every neuron
|
||||||
@@ -325,42 +324,38 @@ Base.@kwdef mutable struct lif_neuron <: compute_neuron
|
|||||||
z_i_t::Union{Array{Bool},Nothing} = nothing # neuron presynaptic firing at current timestep (which is other neuron postsynaptic firing of previous timestep)
|
z_i_t::Union{Array{Bool},Nothing} = nothing # neuron presynaptic firing at current timestep (which is other neuron postsynaptic firing of previous timestep)
|
||||||
# Bn_wout_decay::Union{Float64,Nothing} = 0.01 # use to balance Bn and w_out
|
# Bn_wout_decay::Union{Float64,Nothing} = 0.01 # use to balance Bn and w_out
|
||||||
|
|
||||||
gamma_pd::Union{Float64,Nothing} = 0.3 # γ_pd, discount factor, value from paper
|
gammaPd::Union{Float64,Nothing} = 0.3 # γ_pd, discount factor, value from paper
|
||||||
alpha::Union{Float64,Nothing} = nothing # α, neuron membrane potential decay factor
|
alpha::Union{Float64,Nothing} = nothing # α, neuron membrane potential decay factor
|
||||||
phi::Union{Float64,Nothing} = nothing # ϕ, psuedo derivative
|
phi::Union{Float64,Nothing} = nothing # ϕ, psuedo derivative
|
||||||
epsilon_rec::Union{Array{Float64},Nothing} = nothing # ϵ_rec, eligibility vector for neuron spike
|
epsilonRec::Union{Array{Float64},Nothing} = nothing # ϵ_rec, eligibility vector for neuron spike
|
||||||
decayed_epsilon_rec::Union{Array{Float64},Nothing} = nothing # α * epsilon_rec
|
decayedEpsilonRec::Union{Array{Float64},Nothing} = nothing # α * epsilonRec
|
||||||
e_rec::Union{Array{Float64},Nothing} = nothing # eligibility trace for neuron spike
|
eRec::Union{Array{Float64},Nothing} = nothing # eligibility trace for neuron spike
|
||||||
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
|
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
|
||||||
last_firing_time::Union{Float64,Nothing} = 0.0 # the last time neuron fires
|
lastFiringTime::Union{Float64,Nothing} = 0.0 # the last time neuron fires
|
||||||
refractory_duration::Union{Float64,Nothing} = 3 # neuron's refratory period in millisecond
|
refractoryDuration::Union{Float64,Nothing} = 3 # neuron's refratory period in millisecond
|
||||||
# refractory_state_active::Union{Bool,Nothing} = false # if true, neuron is in refractory state and cannot process new information
|
# refractory_state_active::Union{Bool,Nothing} = false # if true, neuron is in refractory state and cannot process new information
|
||||||
refractory_counter::Integer = 0
|
refractoryCounter::Integer = 0
|
||||||
tau_m::Union{Float64,Nothing} = nothing # τ_m, membrane time constant in millisecond
|
tau_m::Union{Float64,Nothing} = nothing # τ_m, membrane time constant in millisecond
|
||||||
eta::Union{Float64,Nothing} = 0.01 # η, learning rate
|
eta::Union{Float64,Nothing} = 0.01 # η, learning rate
|
||||||
w_rec_change::Union{Array{Float64},Nothing} = nothing # Δw_rec, cumulated w_rec change
|
wRecChange::Union{Array{Float64},Nothing} = nothing # Δw_rec, cumulated w_rec change
|
||||||
recurrent_signal::Union{Float64,Nothing} = nothing # incoming recurrent signal
|
recSignal::Union{Float64,Nothing} = nothing # incoming recurrent signal
|
||||||
alpha_v_t::Union{Float64,Nothing} = nothing # alpha * v_t
|
alpha_v_t::Union{Float64,Nothing} = nothing # alpha * v_t
|
||||||
voltage_drop_percentage::Union{Float64,Nothing} = 1.0 # voltage drop as a percentage of v_th
|
voltageDropPercentage::Union{Float64,Nothing} = 1.0 # voltage drop as a percentage of v_th
|
||||||
error::Union{Float64,Nothing} = nothing # local neuron error
|
error::Union{Float64,Nothing} = nothing # local neuron error
|
||||||
optimiser::Union{Any,Nothing} = load_optimiser("AdaBelief") # Flux optimizer
|
optimiser::Union{Any,Nothing} = load_optimiser("AdaBelief") # Flux optimizer
|
||||||
|
|
||||||
firing_counter::Float64 = 0.0 # store how many times neuron fires
|
firingCounter::Float64 = 0.0 # store how many times neuron fires
|
||||||
firing_rate_target::Float64 = 20.0 # neuron's target firing rate in Hz
|
firingRateTarget::Float64 = 20.0 # neuron's target firing rate in Hz
|
||||||
firing_diff::Float64 = 0.0 # e-prop supplement paper equation 5
|
firingDiff::Float64 = 0.0 # e-prop supplement paper equation 5
|
||||||
firing_rate_error::Float64 = 0.0 # local neuron error w.r.t. firing regularization
|
firingRateError::Float64 = 0.0 # local neuron error w.r.t. firing regularization
|
||||||
firing_rate::Float64 = 0.0 # running average of firing rate in Hz
|
firingRate::Float64 = 0.0 # running average of firing rate in Hz
|
||||||
|
|
||||||
current_error::Union{Float64,Nothing} = 0.0
|
|
||||||
previous_error::Union{Float64,Nothing} = 0.0
|
|
||||||
error_diff::Union{Array{Float64},Nothing} = Vector{Float64}()
|
|
||||||
|
|
||||||
""" "inference" = no learning params will be collected.
|
""" "inference" = no learning params will be collected.
|
||||||
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
||||||
correct answer is available then merge Δw_rec_change into w_rec_change then
|
correct answer is available then merge Δw_rec_change into wRecChange then
|
||||||
reset epsilon_j.
|
reset epsilon_j.
|
||||||
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
|
"reflect" = neuron will merge wRecChange into w_rec then reset wRecChange. """
|
||||||
learning_stage::String = "inference"
|
learningStage::String = "inference"
|
||||||
end
|
end
|
||||||
|
|
||||||
""" lif neuron outer constructor
|
""" lif neuron outer constructor
|
||||||
@@ -371,8 +366,8 @@ end
|
|||||||
:type => "lif_neuron",
|
:type => "lif_neuron",
|
||||||
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I use auto generate)
|
||||||
:z_t => false, # neuron firing status at time = t
|
:z_t => false, # neuron firing status at time = t
|
||||||
:gamma_pd => 0.3, # discount factor. The value is from the paper
|
:gammaPd => 0.3, # discount factor. The value is from the paper
|
||||||
:refractory_duration => 2.0, # neuron refractory period in tick
|
:refractoryDuration => 2.0, # neuron refractory period in tick
|
||||||
:delta => 1.0,
|
:delta => 1.0,
|
||||||
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
|
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use for 1 sequence
|
||||||
)
|
)
|
||||||
@@ -402,17 +397,18 @@ end
|
|||||||
Base.@kwdef mutable struct alif_neuron <: compute_neuron
|
Base.@kwdef mutable struct alif_neuron <: compute_neuron
|
||||||
id::Union{Int64,Nothing} = nothing # this neuron ID i.e. position of this neuron in knowledgeFn
|
id::Union{Int64,Nothing} = nothing # this neuron ID i.e. position of this neuron in knowledgeFn
|
||||||
type::String = "alif_neuron"
|
type::String = "alif_neuron"
|
||||||
ExIn_type::Integer = -1 # 1 excitatory, -1 inhabitory
|
ExInType::Integer = -1 # 1 excitatory, -1 inhabitory
|
||||||
# Bn::Union{Float64,Nothing} = Random.rand() # Bias for neuron error
|
# Bn::Union{Float64,Nothing} = Random.rand() # Bias for neuron error
|
||||||
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
knowledgeFnName::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
||||||
subscription_list::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
|
subscriptionList::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
|
||||||
sub_ExIn_type::Array{Int64} = Vector{Int64}() # store ExIn type of subscribed neurons
|
subExInType::Array{Int64} = Vector{Int64}() # store ExIn type of subscribed neurons
|
||||||
time_stamp::Union{Number,Nothing} = nothing # current time
|
timeStep::Union{Number,Nothing} = nothing # current time
|
||||||
w_rec::Union{Array{Float64},Nothing} = nothing # synaptic weight (for receiving signal from other neuron)
|
w_rec::Union{Array{Float64},Nothing} = nothing # synaptic weight (for receiving signal from other neuron)
|
||||||
v_t::Float64 = 0.0 # vᵗ, postsynaptic neuron membrane potential of previous timestep
|
v_t::Float64 = 0.0 # vᵗ, postsynaptic neuron membrane potential of previous timestep
|
||||||
v_t1::Float64 = 0.0 # vᵗ⁺¹, postsynaptic neuron membrane potential at current timestep
|
v_t1::Float64 = 0.0 # vᵗ⁺¹, postsynaptic neuron membrane potential at current timestep
|
||||||
v_t_default::Union{Float64,Nothing} = 0.0
|
v_t_default::Union{Float64,Nothing} = 0.0
|
||||||
v_th::Float64 = 1.0 # vᵗʰ, neuron firing threshold
|
v_th::Float64 = 1.0 # vᵗʰ, neuron firing threshold
|
||||||
|
vRest::Float64 = 0.0 # resting potential after neuron fired
|
||||||
z_t::Bool = false # zᵗ, neuron postsynaptic firing of previous timestep
|
z_t::Bool = false # zᵗ, neuron postsynaptic firing of previous timestep
|
||||||
# zᵗ⁺¹, neuron firing status at time = t+1. I need this because the way I calculate all
|
# zᵗ⁺¹, neuron firing status at time = t+1. I need this because the way I calculate all
|
||||||
# neurons forward function at each timestep-by-timestep is to do every neuron
|
# neurons forward function at each timestep-by-timestep is to do every neuron
|
||||||
@@ -424,37 +420,32 @@ Base.@kwdef mutable struct alif_neuron <: compute_neuron
|
|||||||
|
|
||||||
alpha::Union{Float64,Nothing} = nothing # α, neuron membrane potential decay factor
|
alpha::Union{Float64,Nothing} = nothing # α, neuron membrane potential decay factor
|
||||||
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
|
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
|
||||||
epsilon_rec::Union{Array{Float64},Nothing} = nothing # ϵ_rec(v), eligibility vector for neuron i spike
|
epsilonRec::Union{Array{Float64},Nothing} = nothing # ϵ_rec(v), eligibility vector for neuron i spike
|
||||||
epsilon_rec_a::Union{Array{Float64},Nothing} = nothing # ϵ_rec(a)
|
epsilonRecA::Union{Array{Float64},Nothing} = nothing # ϵ_rec(a)
|
||||||
decayed_epsilon_rec::Union{Array{Float64},Nothing} = nothing # α * epsilon_rec
|
decayedEpsilonRec::Union{Array{Float64},Nothing} = nothing # α * epsilonRec
|
||||||
e_rec_v::Union{Array{Float64},Nothing} = nothing # a component of neuron's eligibility trace resulted from v_t
|
eRec_v::Union{Array{Float64},Nothing} = nothing # a component of neuron's eligibility trace resulted from v_t
|
||||||
e_rec_a::Union{Array{Float64},Nothing} = nothing # a component of neuron's eligibility trace resulted from av_th
|
eRec_a::Union{Array{Float64},Nothing} = nothing # a component of neuron's eligibility trace resulted from av_th
|
||||||
e_rec::Union{Array{Float64},Nothing} = nothing # neuron's eligibility trace
|
eRec::Union{Array{Float64},Nothing} = nothing # neuron's eligibility trace
|
||||||
eta::Union{Float64,Nothing} = 0.01 # eta, learning rate
|
eta::Union{Float64,Nothing} = 0.01 # eta, learning rate
|
||||||
gamma_pd::Union{Float64,Nothing} = 0.3 # γ_pd, discount factor, value from paper
|
gammaPd::Union{Float64,Nothing} = 0.3 # γ_pd, discount factor, value from paper
|
||||||
last_firing_time::Union{Float64,Nothing} = 0.0 # the last time neuron fires
|
lastFiringTime::Union{Float64,Nothing} = 0.0 # the last time neuron fires
|
||||||
phi::Union{Float64,Nothing} = nothing # ϕ, psuedo derivative
|
phi::Union{Float64,Nothing} = nothing # ϕ, psuedo derivative
|
||||||
refractory_duration::Union{Float64,Nothing} = 3 # neuron's refractory period in millisecond
|
refractoryDuration::Union{Float64,Nothing} = 3 # neuron's refractory period in millisecond
|
||||||
# refractory_state_active::Union{Bool,Nothing} = false # if true, neuron is in refractory state and cannot process new information
|
# refractory_state_active::Union{Bool,Nothing} = false # if true, neuron is in refractory state and cannot process new information
|
||||||
refractory_counter::Integer = 0
|
refractoryCounter::Integer = 0
|
||||||
tau_m::Union{Float64,Nothing} = nothing # τ_m, membrane time constant in millisecond
|
tau_m::Union{Float64,Nothing} = nothing # τ_m, membrane time constant in millisecond
|
||||||
w_rec_change::Union{Array{Float64},Nothing} = nothing # Δw_rec, cumulated w_rec change
|
wRecChange::Union{Array{Float64},Nothing} = nothing # Δw_rec, cumulated w_rec change
|
||||||
recurrent_signal::Union{Float64,Nothing} = nothing # incoming recurrent signal
|
recSignal::Union{Float64,Nothing} = nothing # incoming recurrent signal
|
||||||
alpha_v_t::Union{Float64,Nothing} = nothing # alpha * v_t
|
alpha_v_t::Union{Float64,Nothing} = nothing # alpha * v_t
|
||||||
voltage_drop_percentage::Union{Float64,Nothing} = 1.0 # voltage drop as a percentage of v_th
|
voltageDropPercentage::Union{Float64,Nothing} = 1.0 # voltage drop as a percentage of v_th
|
||||||
error::Union{Float64,Nothing} = nothing # local neuron error
|
error::Union{Float64,Nothing} = nothing # local neuron error
|
||||||
optimiser::Union{Any,Nothing} = load_optimiser("AdaBelief") # Flux optimizer
|
optimiser::Union{Any,Nothing} = load_optimiser("AdaBelief") # Flux optimizer
|
||||||
|
|
||||||
firing_counter::Float64 = 0.0 # store how many times neuron fires
|
firingCounter::Float64 = 0.0 # store how many times neuron fires
|
||||||
firing_rate_target::Float64 = 20.0 # neuron's target firing rate in Hz
|
firingRateTarget::Float64 = 20.0 # neuron's target firing rate in Hz
|
||||||
firing_diff::Float64 = 0.0 # e-prop supplement paper equation 5
|
firingDiff::Float64 = 0.0 # e-prop supplement paper equation 5
|
||||||
firing_rate_error::Float64 = 0.0 # local neuron error w.r.t. firing regularization
|
firingRateError::Float64 = 0.0 # local neuron error w.r.t. firing regularization
|
||||||
firing_rate::Float64 = 0.0 # running average of firing rate, Hz
|
firingRate::Float64 = 0.0 # running average of firing rate, Hz
|
||||||
|
|
||||||
|
|
||||||
current_error::Union{Float64,Nothing} = 0.0
|
|
||||||
previous_error::Union{Float64,Nothing} = 0.0
|
|
||||||
error_diff::Union{Array{Float64},Nothing} = Vector{Float64}()
|
|
||||||
|
|
||||||
tau_a::Union{Float64,Nothing} = nothing # τ_a, adaption time constant in millisecond
|
tau_a::Union{Float64,Nothing} = nothing # τ_a, adaption time constant in millisecond
|
||||||
beta::Union{Float64,Nothing} = 0.15 # β, constant, value from paper
|
beta::Union{Float64,Nothing} = 0.15 # β, constant, value from paper
|
||||||
@@ -464,10 +455,10 @@ Base.@kwdef mutable struct alif_neuron <: compute_neuron
|
|||||||
|
|
||||||
""" "inference" = no learning params will be collected.
|
""" "inference" = no learning params will be collected.
|
||||||
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
"learning" = neuron will accumulate epsilon_j, compute Δw_rec_change each time
|
||||||
correct answer is available then merge Δw_rec_change into w_rec_change then
|
correct answer is available then merge Δw_rec_change into wRecChange then
|
||||||
reset epsilon_j.
|
reset epsilon_j.
|
||||||
"reflect" = neuron will merge w_rec_change into w_rec then reset w_rec_change. """
|
"reflect" = neuron will merge wRecChange into w_rec then reset wRecChange. """
|
||||||
learning_stage::String = "inference"
|
learningStage::String = "inference"
|
||||||
|
|
||||||
end
|
end
|
||||||
""" alif neuron outer constructor
|
""" alif neuron outer constructor
|
||||||
@@ -479,8 +470,8 @@ end
|
|||||||
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I
|
:v_th => 1.2, # neuron firing threshold (this value is treated as maximum bound if I
|
||||||
use auto generate)
|
use auto generate)
|
||||||
:z_t => false, # neuron firing status at time = t
|
:z_t => false, # neuron firing status at time = t
|
||||||
:gamma_pd => 0.3, # discount factor. The value is from the paper
|
:gammaPd => 0.3, # discount factor. The value is from the paper
|
||||||
:refractory_duration => 2.0, # neuron refractory period in millisecond
|
:refractoryDuration => 2.0, # neuron refractory period in millisecond
|
||||||
:delta => 1.0,
|
:delta => 1.0,
|
||||||
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use
|
:tau_m => 5.0, # membrane time constant in millisecond. It should equals to time use
|
||||||
for 1 sequence
|
for 1 sequence
|
||||||
@@ -516,9 +507,9 @@ end
|
|||||||
Base.@kwdef mutable struct linear_neuron <: output_neuron
|
Base.@kwdef mutable struct linear_neuron <: output_neuron
|
||||||
id::Union{Int64,Nothing} = nothing # ID of this neuron which is it position in knowledgeFn array
|
id::Union{Int64,Nothing} = nothing # ID of this neuron which is it position in knowledgeFn array
|
||||||
type::String = "linear_neuron"
|
type::String = "linear_neuron"
|
||||||
knowledgefn_name::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
knowledgeFnName::Union{String,Nothing} = nothing # knowledgeFn that this neuron belongs to
|
||||||
subscription_list::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
|
subscriptionList::Union{Array{Int64},Nothing} = nothing # list of other neuron that this neuron synapse subscribed to
|
||||||
time_stamp::Union{Number,Nothing} = nothing # current time
|
timeStep::Union{Number,Nothing} = nothing # current time
|
||||||
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
|
delta::Union{Float64,Nothing} = 1.0 # δ, discreate timestep size in millisecond
|
||||||
out_t::Bool = false # output of linear neuron BEFORE forward()
|
out_t::Bool = false # output of linear neuron BEFORE forward()
|
||||||
out_t1::Bool = false # output of linear neuron AFTER forward()
|
out_t1::Bool = false # output of linear neuron AFTER forward()
|
||||||
@@ -572,91 +563,91 @@ function load_optimiser(optimiser_name::String; params::Union{Dict,Nothing} = no
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function init_neuron!(id::Int64, n::passthrough_neuron, n_params::Dict, kfn_params::Dict)
|
function init_neuron!(id::Int64, n::passthrough_neuron, n_params::Dict, kfnParams::Dict)
|
||||||
n.id = id
|
n.id = id
|
||||||
n.knowledgefn_name = kfn_params[:knowledgefn_name]
|
n.knowledgeFnName = kfnParams[:knowledgeFnName]
|
||||||
end
|
end
|
||||||
|
|
||||||
# function init_neuron!(id::Int64, n::lif_neuron, kfn_params::Dict)
|
# function init_neuron!(id::Int64, n::lif_neuron, kfnParams::Dict)
|
||||||
# n.id = id
|
# n.id = id
|
||||||
# n.knowledgefn_name = kfn_params[:knowledgefn_name]
|
# n.knowledgeFnName = kfnParams[:knowledgeFnName]
|
||||||
# subscription_options = shuffle!([1:(kfn_params[:input_neuron_number]+kfn_params[:compute_neuron_number])...])
|
# subscription_options = shuffle!([1:(kfnParams[:input_neuron_number]+kfnParams[:compute_neuron_number])...])
|
||||||
# if typeof(kfn_params[:synaptic_connection_number]) == String
|
# if typeof(kfnParams[:synaptic_connection_number]) == String
|
||||||
# percent = parse(Int, kfn_params[:synaptic_connection_number][1:end-1]) / 100
|
# percent = parse(Int, kfnParams[:synaptic_connection_number][1:end-1]) / 100
|
||||||
# synaptic_connection_number = floor(length(subscription_options) * percent)
|
# synaptic_connection_number = floor(length(subscription_options) * percent)
|
||||||
# n.subscription_list = [pop!(subscription_options) for i = 1:synaptic_connection_number]
|
# n.subscriptionList = [pop!(subscription_options) for i = 1:synaptic_connection_number]
|
||||||
# end
|
# end
|
||||||
# filter!(x -> x != n.id, n.subscription_list)
|
# filter!(x -> x != n.id, n.subscriptionList)
|
||||||
# n.epsilon_rec = zeros(length(n.subscription_list))
|
# n.epsilonRec = zeros(length(n.subscriptionList))
|
||||||
# n.w_rec = Random.rand(length(n.subscription_list))
|
# n.w_rec = Random.rand(length(n.subscriptionList))
|
||||||
# n.w_rec_change = zeros(length(n.subscription_list))
|
# n.wRecChange = zeros(length(n.subscriptionList))
|
||||||
# n.reg_voltage_b = zeros(length(n.subscription_list))
|
# n.reg_voltage_b = zeros(length(n.subscriptionList))
|
||||||
# n.alpha = calculate_α(n)
|
# n.alpha = calculate_α(n)
|
||||||
# end
|
# end
|
||||||
|
|
||||||
function init_neuron!(id::Int64, n::lif_neuron, n_params::Dict, kfn_params::Dict)
|
function init_neuron!(id::Int64, n::lif_neuron, n_params::Dict, kfnParams::Dict)
|
||||||
n.id = id
|
n.id = id
|
||||||
n.knowledgefn_name = kfn_params[:knowledgefn_name]
|
n.knowledgeFnName = kfnParams[:knowledgeFnName]
|
||||||
subscription_options = shuffle!([1:kfn_params[:total_neurons]...])
|
subscription_options = shuffle!([1:kfnParams[:total_neurons]...])
|
||||||
subscription_numbers = Int(floor(n_params[:synaptic_connection_number] *
|
subscription_numbers = Int(floor(n_params[:synaptic_connection_number] *
|
||||||
kfn_params[:total_neurons] / 100.0))
|
kfnParams[:total_neurons] / 100.0))
|
||||||
n.subscription_list = [pop!(subscription_options) for i = 1:subscription_numbers]
|
n.subscriptionList = [pop!(subscription_options) for i = 1:subscription_numbers]
|
||||||
|
|
||||||
# prevent subscription to itself by removing this neuron id
|
# prevent subscription to itself by removing this neuron id
|
||||||
filter!(x -> x != n.id, n.subscription_list)
|
filter!(x -> x != n.id, n.subscriptionList)
|
||||||
|
|
||||||
n.epsilon_rec = zeros(length(n.subscription_list))
|
n.epsilonRec = zeros(length(n.subscriptionList))
|
||||||
n.w_rec = Random.rand(length(n.subscription_list))
|
n.w_rec = Random.rand(length(n.subscriptionList))
|
||||||
n.w_rec_change = zeros(length(n.subscription_list))
|
n.wRecChange = zeros(length(n.subscriptionList))
|
||||||
# n.reg_voltage_b = zeros(length(n.subscription_list))
|
# n.reg_voltage_b = zeros(length(n.subscriptionList))
|
||||||
n.alpha = calculate_α(n)
|
n.alpha = calculate_α(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
function init_neuron!(id::Int64, n::alif_neuron, n_params::Dict,
|
function init_neuron!(id::Int64, n::alif_neuron, n_params::Dict,
|
||||||
kfn_params::Dict)
|
kfnParams::Dict)
|
||||||
n.id = id
|
n.id = id
|
||||||
n.knowledgefn_name = kfn_params[:knowledgefn_name]
|
n.knowledgeFnName = kfnParams[:knowledgeFnName]
|
||||||
subscription_options = shuffle!([1:kfn_params[:total_neurons]...])
|
subscription_options = shuffle!([1:kfnParams[:total_neurons]...])
|
||||||
subscription_numbers = Int(floor(n_params[:synaptic_connection_number] *
|
subscription_numbers = Int(floor(n_params[:synaptic_connection_number] *
|
||||||
kfn_params[:total_neurons] / 100.0))
|
kfnParams[:total_neurons] / 100.0))
|
||||||
n.subscription_list = [pop!(subscription_options) for i = 1:subscription_numbers]
|
n.subscriptionList = [pop!(subscription_options) for i = 1:subscription_numbers]
|
||||||
|
|
||||||
# prevent subscription to itself by removing this neuron id
|
# prevent subscription to itself by removing this neuron id
|
||||||
filter!(x -> x != n.id, n.subscription_list)
|
filter!(x -> x != n.id, n.subscriptionList)
|
||||||
|
|
||||||
n.epsilon_rec = zeros(length(n.subscription_list))
|
n.epsilonRec = zeros(length(n.subscriptionList))
|
||||||
n.w_rec = Random.rand(length(n.subscription_list))
|
n.w_rec = Random.rand(length(n.subscriptionList))
|
||||||
n.w_rec_change = zeros(length(n.subscription_list))
|
n.wRecChange = zeros(length(n.subscriptionList))
|
||||||
# n.reg_voltage_b = zeros(length(n.subscription_list))
|
# n.reg_voltage_b = zeros(length(n.subscriptionList))
|
||||||
n.alpha = calculate_α(n) # the more time has passed from the last time neuron was
|
n.alpha = calculate_α(n) # the more time has passed from the last time neuron was
|
||||||
# activated, the more neuron membrane potential is reduced
|
# activated, the more neuron membrane potential is reduced
|
||||||
n.rho = calculate_ρ(n)
|
n.rho = calculate_ρ(n)
|
||||||
n.epsilon_rec_a = zeros(length(n.subscription_list))
|
n.epsilonRecA = zeros(length(n.subscriptionList))
|
||||||
end
|
end
|
||||||
|
|
||||||
# function init_neuron!(id::Int64, n::linear_neuron, kfn_params::Dict)
|
# function init_neuron!(id::Int64, n::linear_neuron, kfnParams::Dict)
|
||||||
# n.id = id
|
# n.id = id
|
||||||
# n.knowledgefn_name = kfn_params[:knowledgefn_name]
|
# n.knowledgeFnName = kfnParams[:knowledgeFnName]
|
||||||
# start_id = kfn_params[:input_neuron_number] + 1 # don't readout from input neurons
|
# start_id = kfnParams[:input_neuron_number] + 1 # don't readout from input neurons
|
||||||
# n.subscription_list = [start_id:(start_id+kfn_params[:compute_neuron_number]-1)...]
|
# n.subscriptionList = [start_id:(start_id+kfnParams[:compute_neuron_number]-1)...]
|
||||||
# n.epsilon_j = zeros(length(n.subscription_list))
|
# n.epsilon_j = zeros(length(n.subscriptionList))
|
||||||
# n.w_out = Random.randn(length(n.subscription_list))
|
# n.w_out = Random.randn(length(n.subscriptionList))
|
||||||
# n.w_out_change = zeros(length(n.subscription_list))
|
# n.w_out_change = zeros(length(n.subscriptionList))
|
||||||
# n.b = Random.randn()
|
# n.b = Random.randn()
|
||||||
# n.b_change = 0.0
|
# n.b_change = 0.0
|
||||||
# n.k = calculate_k(n)
|
# n.k = calculate_k(n)
|
||||||
# end
|
# end
|
||||||
#WORKING
|
#WORKING
|
||||||
function init_neuron!(id::Int64, n::linear_neuron, n_params::Dict, kfn_params::Dict)
|
function init_neuron!(id::Int64, n::linear_neuron, n_params::Dict, kfnParams::Dict)
|
||||||
n.id = id
|
n.id = id
|
||||||
n.knowledgefn_name = kfn_params[:knowledgefn_name]
|
n.knowledgeFnName = kfnParams[:knowledgeFnName]
|
||||||
# start_id = kfn_params[:total_input_port] + 1 # don't readout from input neurons
|
# start_id = kfnParams[:total_input_port] + 1 # don't readout from input neurons
|
||||||
# subscription_options = [start_id:(start_id+kfn_params[:total_compute_neuron]-1)...]
|
# subscription_options = [start_id:(start_id+kfnParams[:total_compute_neuron]-1)...]
|
||||||
# n.subscription_list = [rand(subscription_options)]
|
# n.subscriptionList = [rand(subscription_options)]
|
||||||
|
|
||||||
# n.epsilon_j = zeros(length(n.subscription_list))
|
# n.epsilon_j = zeros(length(n.subscriptionList))
|
||||||
# n.w_out = Random.randn(length(n.subscription_list))
|
# n.w_out = Random.randn(length(n.subscriptionList))
|
||||||
# n.w_out_change = zeros(length(n.subscription_list))
|
# n.w_out_change = zeros(length(n.subscriptionList))
|
||||||
# n.b = Random.randn()
|
# n.b = Random.randn()
|
||||||
# n.b_change = 0.0
|
# n.b_change = 0.0
|
||||||
# n.k = calculate_k(n)
|
# n.k = calculate_k(n)
|
||||||
@@ -664,9 +655,9 @@ end
|
|||||||
|
|
||||||
""" Make a neuron intended for use with knowledgeFn
|
""" Make a neuron intended for use with knowledgeFn
|
||||||
"""
|
"""
|
||||||
function init_neuron(id::Int64, n_params::Dict, kfn_params::Dict)
|
function init_neuron(id::Int64, n_params::Dict, kfnParams::Dict)
|
||||||
n = instantiate_custom_types(n_params)
|
n = instantiate_custom_types(n_params)
|
||||||
init_neuron!(id, n, n_params, kfn_params)
|
init_neuron!(id, n, n_params, kfnParams)
|
||||||
|
|
||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
@@ -700,22 +691,22 @@ end
|
|||||||
""" Add a new neuron into a knowledgeFn
|
""" Add a new neuron into a knowledgeFn
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
add_neuron!(kfn.kfn_params[:lif_neuron_params], kfn)
|
add_neuron!(kfn.kfnParams[:lif_neuron_params], kfn)
|
||||||
"""
|
"""
|
||||||
# function add_neuron!(neuron_Dict::Dict, kfn::knowledgeFn)
|
# function add_neuron!(neuron_Dict::Dict, kfn::knowledgeFn)
|
||||||
# id = length(kfn.neurons_array) + 1
|
# id = length(kfn.neuronsArray) + 1
|
||||||
# neuron = init_neuron(id, neuron_Dict, kfn.kfn_params,
|
# neuron = init_neuron(id, neuron_Dict, kfn.kfnParams,
|
||||||
# total_neurons = (length(kfn.neurons_array) + 1))
|
# total_neurons = (length(kfn.neuronsArray) + 1))
|
||||||
# push!(kfn.neurons_array, neuron)
|
# push!(kfn.neuronsArray, neuron)
|
||||||
|
|
||||||
# # Randomly select an output neuron to add a new neuron to
|
# # Randomly select an output neuron to add a new neuron to
|
||||||
# add_n_output_n!(Random.rand(kfn.output_neurons_array), id)
|
# add_n_output_n!(Random.rand(kfn.outputNeuronsArray), id)
|
||||||
# end
|
# end
|
||||||
|
|
||||||
""" Add a new neuron to output neuron's subscription_list
|
""" Add a new neuron to output neuron's subscriptionList
|
||||||
"""
|
"""
|
||||||
function add_n_output_n!(o_n::linear_neuron, id::Int64)
|
function add_n_output_n!(o_n::linear_neuron, id::Int64)
|
||||||
push!(o_n.subscription_list, id)
|
push!(o_n.subscriptionList, id)
|
||||||
push!(o_n.epsilon_j, 0.0)
|
push!(o_n.epsilon_j, 0.0)
|
||||||
push!(o_n.w_out, Random.randn(1)[1])
|
push!(o_n.w_out, Random.randn(1)[1])
|
||||||
push!(o_n.w_out_change, 0.0)
|
push!(o_n.w_out_change, 0.0)
|
||||||
|
|||||||
Reference in New Issue
Block a user