diff --git a/src/forward.jl b/src/forward.jl index 79bdc93..eedae6c 100644 --- a/src/forward.jl +++ b/src/forward.jl @@ -243,7 +243,7 @@ function lifForward( zit, linear_to_cartesian, ) i = (blockIdx().x - 1) * blockDim().x + threadIdx().x # gpu threads index - + if i <= length(wRec) # cartesian index i1, i2, i3, i4 = linear_to_cartesian(i, size(wRec)) @@ -416,7 +416,7 @@ function alifForward( zit, linear_to_cartesian, ) i = (blockIdx().x - 1) * blockDim().x + threadIdx().x # gpu threads index - + if i <= length(wRec) # cartesian index i1, i2, i3, i4 = linear_to_cartesian(i, size(wRec)) diff --git a/src/learn.jl b/src/learn.jl index b7a2cb3..b59bee9 100644 --- a/src/learn.jl +++ b/src/learn.jl @@ -266,25 +266,27 @@ end function learn!(kfn::kfn_1, device=cpu) # lif learn - lifLearn!(kfn.lif_wRec, - kfn.lif_wRecChange, - kfn.lif_arrayProjection4d, - kfn.lif_neuronInactivityCounter, - kfn.lif_synapticInactivityCounter, - kfn.lif_synapticConnectionNumber, - kfn.zitCumulative, - device) + kfn.lif_wRec, kfn.lif_neuronInactivityCounter, kfn.lif_synapticInactivityCounter = + lifLearn(kfn.lif_wRec, + kfn.lif_wRecChange, + kfn.lif_arrayProjection4d, + kfn.lif_neuronInactivityCounter, + kfn.lif_synapticInactivityCounter, + kfn.lif_synapticConnectionNumber, + kfn.zitCumulative, + device) # alif learn - alifLearn!(kfn.alif_wRec, - kfn.alif_wRecChange, - kfn.alif_arrayProjection4d, - kfn.alif_neuronInactivityCounter, - kfn.lif_synapticInactivityCounter, - kfn.alif_synapticConnectionNumber, - kfn.zitCumulative, - device) - + kfn.alif_wRec, kfn.alif_neuronInactivityCounter, kfn.alif_synapticInactivityCounter = + alifLearn(kfn.alif_wRec, + kfn.alif_wRecChange, + kfn.alif_arrayProjection4d, + kfn.alif_neuronInactivityCounter, + kfn.alif_synapticInactivityCounter, + kfn.alif_synapticConnectionNumber, + kfn.zitCumulative, + device) + error("DEBUG -> kfn learn! $(Dates.now())") # on learn onLearn!(kfn.on_wOut, kfn.on_wOutChange, @@ -297,7 +299,7 @@ function learn!(kfn::kfn_1, device=cpu) # error("DEBUG -> kfn learn! $(Dates.now())") end -function lifLearn!(wRec, +function lifLearn(wRec, wRecChange, arrayProjection4d, neuronInactivityCounter, @@ -305,9 +307,12 @@ function lifLearn!(wRec, synapticConnectionNumber, zitCumulative, device) + #WORKING - synapticInactivityCounter -10000 to 10000, weight change liquidity range from 1.0 to 0.1 respectively + # merge learning weight with average learning weight of all batch wRec .+= (sum(wRecChange, dims=4) ./ (size(wRec, 4))) .* arrayProjection4d + arrayProjection4d_cpu = arrayProjection4d |> cpu wRec_cpu = wRec |> cpu wRec_cpu = wRec_cpu[:,:,:,1] # since every batch has the same neuron wRec, (row, col, n) neuronInactivityCounter_cpu = neuronInactivityCounter |> cpu @@ -320,25 +325,33 @@ function lifLearn!(wRec, # weak / negative synaptic connection will get randomed in neuroplasticity() wRec_cpu = GeneralUtils.replaceBetween.(wRec_cpu, 0.0, 0.1, -1.0) # mark with -1.0 - # synaptic connection that has no inactivity will get randomed in neuroplasticity() - GeneralUtils.replace_elements!(neuronInactivityCounter_cpu, 0.0, wRec_cpu, -1.0) - # reset lif_inactivity elements to -9 - GeneralUtils.replace_elements!(neuronInactivityCounter_cpu, 0.0, -9.0) # -9.0 is base value + # synaptic connection that has no activity will get randomed in neuroplasticity() + mask = isless.(synapticInactivityCounter_cpu, -10_000) + GeneralUtils.replace_elements!(mask, 1, wRec_cpu, -1.0) + # reset lif_inactivity elements to base value + GeneralUtils.replace_elements!(mask, 1, synapticInactivityCounter_cpu, 0.0) - #WORKING neuroplasticity + # neuroplasticity, work on CPU side wRec_cpu = neuroplasticity(synapticConnectionNumber, zitCumulative_cpu, wRec_cpu, neuronInactivityCounter_cpu, synapticInactivityCounter_cpu) - error("DEBUG -> lifLearn! $(Dates.now())") - # #TODO send to device with correct dimension - # wRec = wRec |> device - # inactivityCounter = inactivityCounter_cpu |> device + wRec_cpu = wRec_cpu .* arrayProjection4d_cpu + wRec = wRec_cpu |> device + + neuronInactivityCounter_cpu = neuronInactivityCounter_cpu .* arrayProjection4d_cpu + neuronInactivityCounter = neuronInactivityCounter_cpu |> device + + synapticInactivityCounter_cpu = synapticInactivityCounter_cpu .* arrayProjection4d_cpu + synapticInactivityCounter = synapticInactivityCounter_cpu |> device + + # error("DEBUG -> lifLearn! $(Dates.now())") + return wRec, neuronInactivityCounter, synapticInactivityCounter end -function alifLearn!(wRec, +function alifLearn(wRec, wRecChange, arrayProjection4d, neuronInactivityCounter, @@ -346,16 +359,48 @@ function alifLearn!(wRec, synapticConnectionNumber, zitCumulative, device) - # merge learning weight with average learning weight + #WORKING - synapticInactivityCounter -10000 to 10000, weight change liquidity range from 1.0 to 0.1 respectively + + # merge learning weight with average learning weight of all batch wRec .+= (sum(wRecChange, dims=4) ./ (size(wRec, 4))) .* arrayProjection4d + arrayProjection4d_cpu = arrayProjection4d |> cpu + wRec_cpu = wRec |> cpu + wRec_cpu = wRec_cpu[:,:,:,1] # since every batch has the same neuron wRec, (row, col, n) + neuronInactivityCounter_cpu = neuronInactivityCounter |> cpu + neuronInactivityCounter_cpu = neuronInactivityCounter_cpu[:,:,:,1] # (row, col, n) + synapticInactivityCounter_cpu = synapticInactivityCounter |> cpu + synapticInactivityCounter_cpu = synapticInactivityCounter_cpu[:,:,:,1] + zitCumulative_cpu = zitCumulative |> cpu + zitCumulative_cpu = zitCumulative_cpu[:,:,1] # (row, col) + # weak / negative synaptic connection will get randomed in neuroplasticity() - wRec .= GeneralUtils.replaceLessThan.(wRec, 0.01, 0.0) + wRec_cpu = GeneralUtils.replaceBetween.(wRec_cpu, 0.0, 0.1, -1.0) # mark with -1.0 + + # synaptic connection that has no activity will get randomed in neuroplasticity() + mask = isless.(synapticInactivityCounter_cpu, -10_000) + GeneralUtils.replace_elements!(mask, 1, wRec_cpu, -1.0) + # reset alif_inactivity elements to base value + GeneralUtils.replace_elements!(mask, 1, synapticInactivityCounter_cpu, 0.0) - #TODO synaptic strength + # neuroplasticity, work on CPU side + wRec_cpu = neuroplasticity(synapticConnectionNumber, + zitCumulative_cpu, + wRec_cpu, + neuronInactivityCounter_cpu, + synapticInactivityCounter_cpu) + + wRec_cpu = wRec_cpu .* arrayProjection4d_cpu + wRec = wRec_cpu |> device + + neuronInactivityCounter_cpu = neuronInactivityCounter_cpu .* arrayProjection4d_cpu + neuronInactivityCounter = neuronInactivityCounter_cpu |> device - #TODO neuroplasticity + synapticInactivityCounter_cpu = synapticInactivityCounter_cpu .* arrayProjection4d_cpu + synapticInactivityCounter = synapticInactivityCounter_cpu |> device + # error("DEBUG -> alifLearn! $(Dates.now())") + return wRec, neuronInactivityCounter, synapticInactivityCounter end function onLearn!(wOut, @@ -378,9 +423,6 @@ function neuroplasticity(synapticConnectionNumber, wRec, # (row, col, n) neuronInactivityCounter, synapticInactivityCounter) # (row, col, n) - #WORKING - # - synapticInactivityCounter -10000 to 10000, weight liquidity range from 1.0 to 0.1 respectively - # - at synapticInactivityCounter -10000 mark -1.0 for new conn i1,i2,i3 = size(wRec) @@ -399,49 +441,43 @@ function neuroplasticity(synapticConnectionNumber, # clear -1.0 marker GeneralUtils.replace_elements!(wRec, -1.0, synapticInactivityCounter, -0.99) GeneralUtils.replace_elements!(wRec, -1.0, 0.0) # -1.0 marker is no longer required - - println("/////////") - println("zitCumulative ", zitCumulative) - println("neuronInactivityCounter ", size(neuronInactivityCounter)) - println("wRec 1 ", wRec[:,:,1]) - println("synapticInactivityCounter 1 ", neuronInactivityCounter[1,1,:], synapticInactivityCounter[:,:,1]) - println("wRec 2 ", wRec[:,:,2]) - println("synapticInactivityCounter 2 ", synapticInactivityCounter[:,:,2]) for i in 1:i3 - # if neuronInactivityCounter[1:1:i] <= -10000 - # w = wRec(i1,i2,1,) #WORKING neuron die i.e. reset all weight + if neuronInactivityCounter[1:1:i][1] < -10_000 # neuron die i.e. reset all weight + neuronInactivityCounter[:,:,i] .= 0 # reset + w = wRec(i1,i2,1,synapticConnectionNumber) + wRec[:,:,i] = w - - remaining = 0 - if subToFireNeuron_current[1,1,i] < subToFireNeuron_toBe - toAddConn = subToFireNeuron_toBe - subToFireNeuron_current[1,1,i] - totalNewConn[1,1,i] = totalNewConn[1,1,i] - toAddConn - # add new conn to firing neurons pool - remaining = addNewSynapticConn!(zitMask[:,:,i], 1, + a = similar(w) .= -0.99 # synapticConnectionNumber of this neuron + mask = (!iszero).(w) + GeneralUtils.replace_elements!(mask, 1, a, 0) + synapticInactivityCounter[:,:,i] = a + else + remaining = 0 + if subToFireNeuron_current[1,1,i] < subToFireNeuron_toBe + toAddConn = subToFireNeuron_toBe - subToFireNeuron_current[1,1,i] + totalNewConn[1,1,i] = totalNewConn[1,1,i] - toAddConn + # add new conn to firing neurons pool + remaining = addNewSynapticConn!(zitMask[:,:,i], 1, + @view(wRec[:,:,i]), + @view(synapticInactivityCounter[:,:,i]), + toAddConn) + totalNewConn[1,1,i] += remaining + end + + # add new conn to non-firing neurons pool + remaining = addNewSynapticConn!(zitMask[:,:,i], 0, @view(wRec[:,:,i]), @view(synapticInactivityCounter[:,:,i]), - toAddConn) - totalNewConn[1,1,i] += remaining - end - - # add new conn to non-firing neurons pool - remaining = addNewSynapticConn!(zitMask[:,:,i], 0, - @view(wRec[:,:,i]), - @view(synapticInactivityCounter[:,:,i]), - totalNewConn[1,1,i]) - if remaining > 0 # final get-all round if somehow non-firing pool has not enough slot - remaining = addNewSynapticConn!(zitMask[:,:,i], 1, - @view(wRec[:,:,i]), - @view(synapticInactivityCounter[:,:,i]), - remaining) + totalNewConn[1,1,i]) + if remaining > 0 # final get-all round if somehow non-firing pool has not enough slot + remaining = addNewSynapticConn!(zitMask[:,:,i], 1, + @view(wRec[:,:,i]), + @view(synapticInactivityCounter[:,:,i]), + remaining) + end end end - println("==========") - println("wRec 1 ", wRec[:,:,1]) - println("synapticInactivityCounter 1 ", synapticInactivityCounter[:,:,1]) - println("wRec 2 ", wRec[:,:,2]) - println("synapticInactivityCounter 2 ", synapticInactivityCounter[:,:,2]) # error("DEBUG -> neuroplasticity $(Dates.now())") return wRec @@ -449,77 +485,6 @@ end -# function neuroplasticity(synapticConnectionNumber, -# zitCumulative, # (row, col) -# wRec, # (row, col, n) -# neuronInactivityCounter, #WORKING neuron die i.e. reset all weight -# synapticInactivityCounter) # (row, col, n) - -# i1,i2,i3 = size(wRec) - -# # for each neuron, find total number of synaptic conn that should draw -# # new connection to firing and non-firing neurons pool -# subToFireNeuron_toBe = Int(floor(0.7 * synapticConnectionNumber)) -# subToNonFiringNeuron_toBe = synapticConnectionNumber - subToFireNeuron_toBe - -# # for each neuron, count how many synap already subscribed to firing-neurons -# zw = zitCumulative .* wRec -# subToFireNeuron_current = sum(GeneralUtils.isBetween.(zw, 0.0, 100.0), dims=(1,2)) # (1, 1, n) -# zitMask = (!iszero).(zitCumulative) # zitMask of firing neurons = 1, non-firing = 0 -# projection = ones(i1,i2,i3) -# zitMask = zitMask .* projection # (row, col, n) -# totalNewConn = sum(isequal.(wRec, -1.0), dims=(1,2)) # count new conn mark (-1.0), (1, 1, n) - -# # clear -1.0 marker -# GeneralUtils.replace_elements!(wRec, -1.0, synapticInactivityCounter, -0.99) -# GeneralUtils.replace_elements!(wRec, -1.0, 0.0) # -1.0 marker is no longer required - -# println("/////////") -# println("zitCumulative ", zitCumulative) -# println("wRec 1 ", wRec[:,:,1]) -# println("synapticInactivityCounter 1 ", synapticInactivityCounter[:,:,1]) -# println("wRec 2 ", wRec[:,:,2]) -# println("synapticInactivityCounter 2 ", synapticInactivityCounter[:,:,2]) - -# for i in 1:i3 -# remaining = 0 -# if subToFireNeuron_current[1,1,i] < subToFireNeuron_toBe -# toAddConn = subToFireNeuron_toBe - subToFireNeuron_current[1,1,i] -# totalNewConn[1,1,i] = totalNewConn[1,1,i] - toAddConn -# # add new conn to firing neurons pool -# remaining = addNewSynapticConn!(zitMask[:,:,i], 1, -# @view(wRec[:,:,i]), -# @view(synapticInactivityCounter[:,:,i]), -# toAddConn) -# totalNewConn[1,1,i] += remaining -# end - -# # add new conn to non-firing neurons pool -# remaining = addNewSynapticConn!(zitMask[:,:,i], 0, -# @view(wRec[:,:,i]), -# @view(synapticInactivityCounter[:,:,i]), -# totalNewConn[1,1,i]) -# if remaining > 0 # final get-all round if somehow non-firing pool has not enough slot -# remaining = addNewSynapticConn!(zitMask[:,:,i], 1, -# @view(wRec[:,:,i]), -# @view(synapticInactivityCounter[:,:,i]), -# remaining) -# end -# end -# println("==========") -# println("wRec 1 ", wRec[:,:,1]) -# println("synapticInactivityCounter 1 ", synapticInactivityCounter[:,:,1]) -# println("wRec 2 ", wRec[:,:,2]) -# println("synapticInactivityCounter 2 ", synapticInactivityCounter[:,:,2]) - -# # error("DEBUG -> neuroplasticity $(Dates.now())") -# return wRec -# end - - - - - diff --git a/src/type.jl b/src/type.jl index 0350828..84fb6ac 100644 --- a/src/type.jl +++ b/src/type.jl @@ -197,7 +197,8 @@ function kfn_1(params::Dict; device=cpu) # subscription synapticConnectionPercent = kfn.params[:computeNeuron][:lif][:params][:synapticConnectionPercent] - kfn.lif_synapticConnectionNumber, w = wRec(row, col, lif_n, synapticConnectionPercent) + kfn.lif_synapticConnectionNumber = Int(floor(row*col * synapticConnectionPercent/100)) + w = wRec(row, col, lif_n, kfn.lif_synapticConnectionNumber) # project 3D w into 4D kfn.lif_wRec (row, col, n, batch) kfn.lif_wRec = reshape(w, (row, col, lif_n, 1)) .* ones(row, col, lif_n, batch) |> device @@ -225,7 +226,8 @@ function kfn_1(params::Dict; device=cpu) kfn.lif_neuronInactivityCounter = (similar(kfn.lif_wRec) .= 0) kfn.lif_synapticInactivityCounter = Array(similar(kfn.lif_wRec) .= -0.99) # -9 for non-sub conn mask = Array((!iszero).(kfn.lif_wRec)) - GeneralUtils.replace_elements!(mask, 1, kfn.lif_synapticInactivityCounter, 0) # initial value subscribed conn + # initial value subscribed conn, synapticInactivityCounter range -10000 to +10000 + GeneralUtils.replace_elements!(mask, 1, kfn.lif_synapticInactivityCounter, 0) kfn.lif_synapticInactivityCounter = kfn.lif_synapticInactivityCounter |> device kfn.lif_arrayProjection4d = (similar(kfn.lif_wRec) .= 1) @@ -244,7 +246,8 @@ function kfn_1(params::Dict; device=cpu) # subscription synapticConnectionPercent = kfn.params[:computeNeuron][:alif][:params][:synapticConnectionPercent] - kfn.alif_synapticConnectionNumber, w = wRec(row, col, alif_n, synapticConnectionPercent) + kfn.alif_synapticConnectionNumber = Int(floor(row*col * synapticConnectionPercent/100)) + w = wRec(row, col, alif_n, kfn.alif_synapticConnectionNumber) # project 3D w into 4D kfn.alif_wRec kfn.alif_wRec = reshape(w, (row, col, alif_n, 1)) .* ones(row, col, alif_n, batch) |> device @@ -272,7 +275,8 @@ function kfn_1(params::Dict; device=cpu) kfn.alif_neuronInactivityCounter = (similar(kfn.alif_wRec) .= 0) kfn.alif_synapticInactivityCounter = Array(similar(kfn.alif_wRec) .= -0.99) # -9 for non-sub conn mask = Array((!iszero).(kfn.alif_wRec)) - GeneralUtils.replace_elements!(mask, 1, kfn.alif_synapticInactivityCounter, 0) # initial value subscribed conn + # initial value subscribed conn, synapticInactivityCounter range -10000 to +10000 + GeneralUtils.replace_elements!(mask, 1, kfn.alif_synapticInactivityCounter, 0) kfn.alif_synapticInactivityCounter = kfn.alif_synapticInactivityCounter |> device kfn.alif_arrayProjection4d = (similar(kfn.alif_wRec) .= 1) @@ -359,10 +363,10 @@ function kfn_1(params::Dict; device=cpu) return kfn end -function wRec(row, col, n, synapticConnectionPercent) +function wRec(row, col, n, synapticConnectionNumber) # subscription w = zeros(row, col, n) - synapticConnectionNumber = Int(floor(row*col * synapticConnectionPercent/100)) + for slice in eachslice(w, dims=3) pool = shuffle!([1:row*col...])[1:synapticConnectionNumber] for i in pool @@ -375,7 +379,7 @@ function wRec(row, col, n, synapticConnectionPercent) should_be_avg_weight = 1 / (0.1 * synapticConnectionNumber) w = w .* (should_be_avg_weight / maximum(w)) # adjust overall weight - return synapticConnectionNumber, w + return w #(row, col, n) end @@ -421,8 +425,6 @@ end - -