-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfsfffb.go
155 lines (120 loc) · 5.12 KB
/
fsfffb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright (c) 2019, The Emergent Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package fsfffb provides Fast and Slow
feedforward (FF) and feedback (FB) inhibition (FFFB)
based on incoming spikes (FF) and outgoing spikes (FB).
This produces a robust, graded k-Winners-Take-All dynamic of sparse
distributed representations having approximately k out of N neurons
active at any time, where k is typically 10-20 percent of N.
*/
package fsfffb
//go:generate core generate -add-types
import "cogentcore.org/core/vgpu/gosl/slbool"
//gosl:start fsfffb
// GiParams parameterizes feedforward (FF) and feedback (FB) inhibition (FFFB)
// based on incoming spikes (FF) and outgoing spikes (FB)
// across Fast (PV+) and Slow (SST+) timescales.
// FF -> PV -> FS fast spikes, FB -> SST -> SS slow spikes (slow to get going)
type GiParams struct {
// enable this level of inhibition
On slbool.Bool
// overall inhibition gain -- this is main parameter to adjust to change overall activation levels -- it scales both the the FS and SS factors uniformly
Gi float32 `min:"0" default:"1,1.1,0.75,0.9"`
// amount of FB spikes included in FF for driving FS -- for small networks, 0.5 or 1 works best; larger networks and more demanding inhibition requires higher levels.
FB float32 `min:"0" default:"0.5,1,4"`
// fast spiking (PV+) intgration time constant in cycles (msec) -- tau is roughly how long it takes for value to change significantly -- 1.4x the half-life.
FSTau float32 `min:"0" default:"6"`
// multiplier on SS slow-spiking (SST+) in contributing to the overall Gi inhibition -- FS contributes at a factor of 1
SS float32 `min:"0" default:"30"`
// slow-spiking (SST+) facilitation decay time constant in cycles (msec) -- facilication factor SSf determines impact of FB spikes as a function of spike input-- tau is roughly how long it takes for value to change significantly -- 1.4x the half-life.
SSfTau float32 `min:"0" default:"20"`
// slow-spiking (SST+) intgration time constant in cycles (msec) cascaded on top of FSTau -- tau is roughly how long it takes for value to change significantly -- 1.4x the half-life.
SSiTau float32 `min:"0" default:"50"`
// fast spiking zero point -- below this level, no FS inhibition is computed, and this value is subtracted from the FSi
FS0 float32 `default:"0.1"`
// time constant for updating a running average of the feedforward inhibition over a longer time scale, for computing FFPrv
FFAvgTau float32 `default:"50"`
// proportion of previous average feed-forward inhibition (FFAvgPrv) to add, resulting in an accentuated temporal-derivative dynamic where neurons respond most strongly to increases in excitation that exceeds inhibition from last time.
FFPrv float32 `default:"0"`
// minimum GeExt value required to drive external clamping dynamics (if clamp is set), where only GeExt drives inhibition. If GeExt is below this value, then the usual FS-FFFB drivers are used.
ClampExtMin float32 `default:"0.05"`
// rate = 1 / tau
FSDt float32 `edit:"-" display:"-" json:"-" xml:"-"`
// rate = 1 / tau
SSfDt float32 `edit:"-" display:"-" json:"-" xml:"-"`
// rate = 1 / tau
SSiDt float32 `edit:"-" display:"-" json:"-" xml:"-"`
// rate = 1 / tau
FFAvgDt float32 `edit:"-" display:"-" json:"-" xml:"-"`
pad float32
}
func (fb *GiParams) Update() {
fb.FSDt = 1 / fb.FSTau
fb.SSfDt = 1 / fb.SSfTau
fb.SSiDt = 1 / fb.SSiTau
fb.FFAvgDt = 1 / fb.FFAvgTau
}
func (fb *GiParams) Defaults() {
fb.Gi = 1.1
fb.FB = 1
fb.SS = 30
fb.FSTau = 6
fb.SSfTau = 20
fb.SSiTau = 50
fb.FS0 = 0.1
fb.FFAvgTau = 50
fb.FFPrv = 0
fb.ClampExtMin = 0.05
fb.Update()
}
func (fb *GiParams) ShouldShow(field string) bool {
switch field {
case "On":
return true
default:
return fb.On.IsTrue()
}
}
// FSiFromFFs updates fast-spiking inhibition from FFs spikes
func (fb *GiParams) FSiFromFFs(fsi *float32, ffs, fbs float32) {
*fsi += (ffs + fb.FB*fbs) - fb.FSDt**fsi // immediate up, slow down
}
// FS0Thr applies FS0 threshold to given value
func (fb *GiParams) FS0Thr(val float32) float32 {
val -= fb.FS0
if val < 0 {
val = 0
}
return val
}
// FS returns the current effective FS value based on fsi and fsd
// if clamped, then only use gext, without applying FS0
func (fb *GiParams) FS(fsi, gext float32, clamped bool) float32 {
if clamped && gext > fb.ClampExtMin {
return gext
}
return fb.FS0Thr(fsi) + gext
}
// SSFromFBs updates slow-spiking inhibition from FBs
func (fb *GiParams) SSFromFBs(ssf, ssi *float32, fbs float32) {
*ssi += fb.SSiDt * (*ssf*fbs - *ssi)
*ssf += fbs*(1-*ssf) - fb.SSfDt**ssf
}
// Inhib is full inhibition computation for given inhib state
// which has aggregated FFs and FBs spiking values
func (fb *GiParams) Inhib(inh *Inhib, gimult float32) {
if fb.On.IsFalse() {
inh.Zero()
return
}
inh.FFAvg += fb.FFAvgDt * (inh.FFs - inh.FFAvg)
fb.FSiFromFFs(&inh.FSi, inh.FFs, inh.FBs)
inh.FSGi = fb.Gi * fb.FS(inh.FSi, inh.GeExts, inh.Clamped.IsTrue())
fb.SSFromFBs(&inh.SSf, &inh.SSi, inh.FBs)
inh.SSGi = fb.Gi * fb.SS * inh.SSi
inh.Gi = inh.GiFromFSSS() + fb.FFPrv*inh.FFAvgPrv
inh.SaveOrig()
}
//gosl:end fsfffb