add neuroplasticity for output neuron
This commit is contained in:
@@ -36,8 +36,8 @@ using .interface
|
||||
Todo:
|
||||
[] using RL to control learning signal
|
||||
[] consider using Dates.now() instead of timestamp because time_stamp may overflow
|
||||
[] training should include adjusting α, neuron membrane potential decay factor
|
||||
which defined by neuron.tau_m formular in type.jl
|
||||
[1] training should include adjusting α, neuron membrane potential decay factor
|
||||
which defined by neuron.tau_m formula in type.jl
|
||||
|
||||
[DONE] each knowledgeFn should have its own noise generater
|
||||
[DONE] where to put pseudo derivative (n.phi)
|
||||
|
||||
@@ -60,7 +60,7 @@ function (kfn::kfn_1)(m::model, input_data::AbstractVector)
|
||||
for i in 1:length(input_data)]
|
||||
# noise = [rand(rng, Distributions.Binomial(1, 0.5)) for i in 1:10] # another option
|
||||
|
||||
input_data = [noise; input_data] # noise start from neuron id 1
|
||||
input_data = [noise; input_data] # noise must start from neuron id 1
|
||||
|
||||
for n in kfn.neuronsArray
|
||||
timestep_forward!(n)
|
||||
@@ -218,13 +218,13 @@ function (n::linearNeuron)(kfn::T) where T<:knowledgeFn
|
||||
|
||||
# decay of v_t1
|
||||
n.v_t1 = n.alpha * n.v_t
|
||||
n.vError = n.v_t1
|
||||
n.vError = n.v_t1 # store voltage that will be used to calculate error later
|
||||
else
|
||||
n.recSignal = sum(n.wRec .* n.z_i_t) # signal from other neuron that this neuron subscribed
|
||||
n.alpha_v_t = n.alpha * n.v_t
|
||||
n.v_t1 = n.alpha_v_t + n.recSignal
|
||||
n.v_t1 = no_negative!(n.v_t1)
|
||||
n.vError = n.v_t1
|
||||
n.vError = n.v_t1 # store voltage that will be used to calculate error later
|
||||
if n.v_t1 > n.v_th
|
||||
n.z_t1 = true
|
||||
n.refractoryCounter = n.refractoryDuration
|
||||
|
||||
@@ -27,8 +27,8 @@ function learn!(kfn::kfn_1, correctAnswer::AbstractVector)
|
||||
outs = [n.z_t1 for n in kfn.outputNeuronsArray]
|
||||
for (i, out) in enumerate(outs)
|
||||
if out != correctAnswer[i] # need to adjust weight
|
||||
kfnError = (kfn.outputNeuronsArray[i].v_th - kfn.outputNeuronsArray[i].vError) *
|
||||
100 / kfn.outputNeuronsArray[i].v_th
|
||||
kfnError = ( (kfn.outputNeuronsArray[i].v_th - kfn.outputNeuronsArray[i].vError) *
|
||||
100 / kfn.outputNeuronsArray[i].v_th ) * 0.1 # 0.1 for scaling down error
|
||||
|
||||
Threads.@threads for n in kfn.neuronsArray
|
||||
# for n in kfn.neuronsArray
|
||||
@@ -67,7 +67,7 @@ function learn!(kfn::kfn_1, correctAnswer::AbstractVector)
|
||||
n.wRec .*= nonFlipedSign # set weight that fliped sign to 0 for random new connection
|
||||
|
||||
synapticConnStrength!(n)
|
||||
neuroplasticity!(n, kfn.firedNeurons, kfn.nExInType)
|
||||
neuroplasticity!(n, kfn.firedNeurons, kfn.nExInType, kfn.kfnParams[:totalInputPort])
|
||||
end
|
||||
|
||||
kfn.learningStage = "inference"
|
||||
|
||||
@@ -362,7 +362,7 @@ end
|
||||
""" rewire of neuron synaptic connection that has 0 weight. Without connection's excitatory and
|
||||
inhabitory ratio constraint.
|
||||
"""
|
||||
function neuroplasticity!(n::Union{computeNeuron, outputNeuron}, firedNeurons::Vector,
|
||||
function neuroplasticity!(n::computeNeuron, firedNeurons::Vector,
|
||||
nExInTypeList::Vector)
|
||||
# if there is 0-weight then replace it with new connection
|
||||
zeroWeightConnIndex = findall(iszero.(n.wRec)) # connection that has 0 weight
|
||||
@@ -398,6 +398,44 @@ function neuroplasticity!(n::Union{computeNeuron, outputNeuron}, firedNeurons::V
|
||||
end
|
||||
end
|
||||
|
||||
function neuroplasticity!(n::outputNeuron, firedNeurons::Vector,
|
||||
nExInTypeList::Vector, totalInputNeuron::Integer)
|
||||
# if there is 0-weight then replace it with new connection
|
||||
zeroWeightConnIndex = findall(iszero.(n.wRec)) # connection that has 0 weight
|
||||
|
||||
# new synaptic connection must sample fron neuron that fires
|
||||
nFiredPool = filter(x -> x ∉ [n.id], firedNeurons) # exclude this neuron id from the id list
|
||||
filter!(x -> x ∉ n.subscriptionList, nFiredPool) # exclude this neuron's subscriptionList from the list
|
||||
filter!(x -> x ∉ [1:totalInputNeuron...], nFiredPool) # exclude input neuron
|
||||
|
||||
nNonFiredPool = setdiff!([1:length(nExInTypeList)...], nFiredPool)
|
||||
filter!(x -> x ∉ [n.id], nNonFiredPool) # exclude this neuron id from the id list
|
||||
filter!(x -> x ∉ n.subscriptionList, nNonFiredPool) # exclude this neuron's subscriptionList from the list
|
||||
filter!(x -> x ∉ [1:totalInputNeuron...], nNonFiredPool) # exclude input neuron
|
||||
|
||||
w = rand(0.01:0.01:0.2, length(zeroWeightConnIndex))
|
||||
synapticStrength = rand(-5:0.01:-4, length(zeroWeightConnIndex))
|
||||
|
||||
shuffle!(nFiredPool)
|
||||
shuffle!(nNonFiredPool)
|
||||
|
||||
# add new synaptic connection to neuron
|
||||
for (i, connIndex) in enumerate(zeroWeightConnIndex)
|
||||
if length(nFiredPool) != 0
|
||||
newConn = popfirst!(nFiredPool)
|
||||
else
|
||||
newConn = popfirst!(nNonFiredPool)
|
||||
end
|
||||
|
||||
""" conn that is being replaced has to go into nNonFiredPool so nNonFiredPool isn't empty
|
||||
"""
|
||||
push!(nNonFiredPool, n.subscriptionList[connIndex])
|
||||
n.subscriptionList[connIndex] = newConn
|
||||
n.wRec[connIndex] = w[i] * nExInTypeList[newConn]
|
||||
n.synapticStrength[connIndex] = synapticStrength[i]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -425,7 +463,6 @@ end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end # end module
|
||||
14
src/types.jl
14
src/types.jl
@@ -190,17 +190,17 @@ function kfn_1(kfnParams::Dict)
|
||||
throw(error("number of compute neuron must be greater than input neuron"))
|
||||
end
|
||||
|
||||
# Bn
|
||||
if kfn.kfnParams[:Bn] == "random"
|
||||
kfn.Bn = [Random.rand(0:0.001:1) for i in 1:kfn.kfnParams[:computeNeuronNumber]]
|
||||
else # in case I want to specify manually
|
||||
kfn.Bn = [kfn.kfnParams[:Bn] for i in 1:kfn.kfnParams[:computeNeuronNumber]]
|
||||
end
|
||||
# # Bn
|
||||
# if kfn.kfnParams[:Bn] == "random"
|
||||
# kfn.Bn = [Random.rand(0:0.001:1) for i in 1:kfn.kfnParams[:computeNeuronNumber]]
|
||||
# else # in case I want to specify manually
|
||||
# kfn.Bn = [kfn.kfnParams[:Bn] for i in 1:kfn.kfnParams[:computeNeuronNumber]]
|
||||
# end
|
||||
|
||||
# assign neurons ID by their position in kfn.neurons array because I think it is
|
||||
# straight forward way
|
||||
|
||||
# add input port
|
||||
# add input port, it must be added before any other neuron types
|
||||
for (k, v) in kfn.kfnParams[:inputPort]
|
||||
current_type = kfn.kfnParams[:inputPort][k]
|
||||
for i = 1:current_type[:numbers]
|
||||
|
||||
Reference in New Issue
Block a user