From ba7330c31dda6481a4b607b42bf5ca8ce6461337 Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Wed, 21 Aug 2024 11:19:22 -0700 Subject: [PATCH] simplify control panel elements for neuron and detector -- we can introduce those more in later models -- and use new new-window tag so digits come up automatically. ViewUpdate is add-fields so it doesn't drive scrolling. fix detector readme accordingly. --- ch2/detector/README.md | 6 +++--- ch2/detector/detector.go | 34 +++++++++++++++++----------------- ch2/neuron/neuron.go | 30 ++++++++++++++++++------------ go.mod | 4 ++-- go.sum | 8 ++++---- 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/ch2/detector/README.md b/ch2/detector/README.md index 96cea7cc..e987f05e 100644 --- a/ch2/detector/README.md +++ b/ch2/detector/README.md @@ -15,7 +15,7 @@ We begin by examining the `Network` tab, showing the Detector network. The netwo You should now see the `Input` grid lit up in the pattern of an `8`. This is the weight pattern for the receiving unit for connections from the input units, with the weight value displayed in the corresponding sending (input) unit. Thus, when the input units have an activation pattern that matches this weight pattern, the receiving unit will be maximally activated. Input patterns that are close to the target `8` input will produce graded activations as a function of how close they are. Thus, this pattern of weights determines what the unit detects, as we will see. First, we will examine the patterns of inputs that will be presented to the network. -* Click on the `DigitPats` button (next to the `Pats` label) on the left side of the window -- this *control panel* contains all the main ingredients for this model. +* Click on the `Digits` button (next to the `Patterns` label) on the left side of the window -- this *control panel* contains the main settings for this model. The display that comes up shows all of the different *input patterns* that will be presented ("clamped") onto the `Input` layer, so we can see how the receiving unit responds. Each row of the display represents a single *trial* that will be presented to the network. As you can see, the input data this case contains the digits from 0 to 9, represented in a simple font on a 5x7 grid of pixels (picture elements). Each pixel in a given event (digit) will drive the corresponding input unit in the network. @@ -47,9 +47,9 @@ The graph shows the activation (`Act`) for the unit as a function of trial (and Now, let's try to understand exactly why the unit responds as it does. The key to doing so is to understand the relationship between the pattern of weights and the input pattern. -* Click the `DigitPats` button again, holding down the `Shift` key while clicking (on desktop platforms) and scroll inside so that the `8` digit is visible. Now resize the whole window so it is roughly big enough to only show the `8` and position the window so it is next to the main window that includes the `Netview` display. The idea is that you can see both side-by-side, so you may want/need to shrink the main window to prevent occlusion of the `DigitPats` window. Then do `Init` in the toolbar and `Step` for each input digit in turn. +* Click the `Digits` button again (it the window was closed) and scroll inside so that the `8` digit is visible. Now resize the whole window so it is roughly big enough to only show the `8` and position the window so it is next to the main window that includes the `Network` display. The idea is that you can see both side-by-side, so you may want/need to shrink the main window to prevent occlusion of the `Digits` window. Then do `Init` in the toolbar and `Step` for each input digit in turn. -> **Question 2.8:** For each digit, report the number of active `Input` units where there is also a weight of 1 according to the `8` digit pattern. In other words, report the *overlap* between the input activity and the weight pattern. *HINT: Strictly speaking, the `8` display in the `DigitPats` window is NOT representing the weights per se, but as we saw earlier using the `r.Wt` functionality in `Network,` they are the same pattern -- and displaying the windows side-by-side just makes the counting easier.* +> **Question 2.8:** For each digit, report the number of active `Input` units where there is also a weight of 1 according to the `8` digit pattern. In other words, report the *overlap* between the input activity and the weight pattern. *HINT: Strictly speaking, the `8` display in the `Digits` window is NOT representing the weights per se, but as we saw earlier using the `r.Wt` functionality in `Network,` they are the same pattern -- and displaying the windows side-by-side just makes the counting easier.* The number of inputs having a weight of 1 that you just calculated should correspond to the total excitatory input `Ge`, also called the **net input**, going into the receiving unit, which is a function of the average of the sending activation `Act` times the weight `Wt` over all the units, with a correction factor for the expected activity level in the layer, `Alpha`: diff --git a/ch2/detector/detector.go b/ch2/detector/detector.go index de5c1b28..eb780748 100644 --- a/ch2/detector/detector.go +++ b/ch2/detector/detector.go @@ -77,31 +77,31 @@ type Sim struct { GbarL float32 `default:"2" min:"0" max:"4" step:"0.05"` // the network -- click to view / edit parameters for layers, paths, etc - Net *leabra.Network `display:"no-inline"` + Net *leabra.Network `new-window:"+" display:"no-inline"` // network parameter management - Params emer.NetParams `display:"inline"` + Params emer.NetParams `display:"-"` // contains looper control loops for running sim - Loops *looper.Manager `display:"no-inline"` + Loops *looper.Manager `display:"-"` // contains computed statistic values - Stats estats.Stats + Stats estats.Stats `display:"-"` // Contains all the logs and information about the logs.' - Logs elog.Logs + Logs elog.Logs `display:"-"` // the training patterns to use - Pats *table.Table `display:"no-inline"` + Patterns *table.Table `new-window:"+" display:"no-inline"` // Environments - Envs env.Envs `display:"no-inline"` + Envs env.Envs `display:"-"` // leabra timing parameters and state - Context leabra.Context + Context leabra.Context `display:"-"` // netview update parameters - ViewUpdate netview.ViewUpdate `display:"inline"` + ViewUpdate netview.ViewUpdate `display:"add-fields"` // manages all the gui elements GUI egui.GUI `display:"-"` @@ -116,7 +116,7 @@ func (ss *Sim) New() { ss.Net = leabra.NewNetwork("Detector") ss.Params.Config(ParamSets, "", "", ss.Net) ss.Stats.Init() - ss.Pats = &table.Table{} + ss.Patterns = &table.Table{} ss.RandSeeds.Init(100) // max 100 runs ss.InitRandSeed(0) ss.Context.Defaults() @@ -131,7 +131,7 @@ func (ss *Sim) Defaults() { // ConfigAll configures all the elements using the standard functions func (ss *Sim) ConfigAll() { - ss.OpenPats() + ss.OpenPatterns() ss.ConfigEnv() ss.ConfigNet(ss.Net) ss.ConfigLogs() @@ -148,7 +148,7 @@ func (ss *Sim) ConfigEnv() { } tst.Name = etime.Test.String() - tst.Config(table.NewIndexView(ss.Pats)) + tst.Config(table.NewIndexView(ss.Patterns)) tst.Sequential = true tst.Init(0) @@ -174,7 +174,7 @@ func (ss *Sim) ConfigNet(net *leabra.Network) { func (ss *Sim) InitWeights(net *leabra.Network) { net.InitWeights() digit := 8 - pats := ss.Pats + pats := ss.Patterns dpat := pats.Tensor("Input", digit) recv := net.LayerByName("RecvNeuron") pthi, _ := recv.RecvPathBySendName("Input") @@ -280,11 +280,11 @@ func (ss *Sim) NewRun() { } ///////////////////////////////////////////////////////////////////////// -// Pats +// Patterns -func (ss *Sim) OpenPats() { - dt := ss.Pats - dt.SetMetaData("name", "DigitPats") +func (ss *Sim) OpenPatterns() { + dt := ss.Patterns + dt.SetMetaData("name", "Digits") dt.SetMetaData("desc", "Digit testing patterns") err := dt.OpenFS(patsfs, "digits.tsv", table.Tab) if err != nil { diff --git a/ch2/neuron/neuron.go b/ch2/neuron/neuron.go index 753cf400..41f168ed 100644 --- a/ch2/neuron/neuron.go +++ b/ch2/neuron/neuron.go @@ -13,11 +13,13 @@ import ( "fmt" "log" "reflect" + "time" "cogentcore.org/core/core" "cogentcore.org/core/icons" "cogentcore.org/core/math32/minmax" "cogentcore.org/core/plot/plotcore" + "cogentcore.org/core/system" "cogentcore.org/core/tree" "github.com/emer/emergent/v2/egui" "github.com/emer/emergent/v2/elog" @@ -95,28 +97,25 @@ type Sim struct { UpdateInterval int `min:"1" def:"10"` // the network -- click to view / edit parameters for layers, paths, etc - Net *leabra.Network `display:"no-inline"` + Net *leabra.Network `display:"-"` SpikeParams spike.ActParams `view:"no-inline"` // testing trial-level log data -- click to see record of network's response to each input // leabra timing parameters and state - Context leabra.Context + Context leabra.Context `display:"-"` // contains computed statistic values - Stats estats.Stats + Stats estats.Stats `display:"-"` // logging - Logs elog.Logs `display:"no-inline"` + Logs elog.Logs `display:"-"` // all parameter management - Params emer.NetParams `display:"inline"` - - // current cycle of updating - Cycle int `edit:"-"` + Params emer.NetParams `display:"-"` // netview update parameters - ViewUpdate netview.ViewUpdate `display:"inline"` + ViewUpdate netview.ViewUpdate `display:"add-fields"` // manages all the gui elements GUI egui.GUI `display:"-"` @@ -137,7 +136,6 @@ func (ss *Sim) Defaults() { ss.SpikeParams.Defaults() ss.Params.Config(ParamSets, "", "", ss.Net) ss.UpdateInterval = 10 - ss.Cycle = 0 ss.Spike = true ss.GbarE = 0.3 ss.GbarL = 0.3 @@ -294,6 +292,7 @@ func (ss *Sim) SpikeVsRate() { // ss.KNaAdapt = false tcl := ss.Logs.Table(etime.Test, etime.Cycle) svr := ss.Logs.MiscTable("SpikeVsRate") + svp := ss.GUI.Plots[etime.ScopeKey("SpikeVsRate")] for gbarE := 0.1; gbarE <= 0.7; gbarE += 0.025 { ss.GbarE = float32(gbarE) spike := float64(0) @@ -319,6 +318,9 @@ func (ss *Sim) SpikeVsRate() { } act := tcl.Float("Act", 159) rate += act + if core.TheApp.Platform() == system.Web { + time.Sleep(time.Millisecond) // critical to prevent hanging! + } } if ss.GUI.StopNow { break @@ -329,10 +331,13 @@ func (ss *Sim) SpikeVsRate() { svr.SetFloat("GBarE", row, gbarE) svr.SetFloat("Spike", row, spike) svr.SetFloat("Rate", row, rate) + svp.GoUpdatePlot() row++ } ss.Defaults() - ss.GUI.Plots[etime.ScopeKey("SpikeVsRate")].UpdatePlot() + svp.GoUpdatePlot() + ss.GUI.IsRunning = false + ss.GUI.UpdateWindow() } ///////////////////////////////////////////////////////////////////////// @@ -483,7 +488,8 @@ func (ss *Sim) ConfigGUI() { Tooltip: "Generate a plot of actual spiking rate vs computed NXX1 rate code.", Active: egui.ActiveStopped, Func: func() { - ss.SpikeVsRate() + ss.GUI.IsRunning = true + go ss.SpikeVsRate() ss.GUI.UpdateWindow() }, }) diff --git a/go.mod b/go.mod index 2fd02617..c41e985d 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/CompCogNeuro/sims/v2 go 1.22 require ( - cogentcore.org/core v0.3.3-0.20240820000827-b7efbcd96c73 - github.com/emer/emergent/v2 v2.0.0-dev0.1.0.0.20240820174009-40d67f5b7c88 + cogentcore.org/core v0.3.3-0.20240821175244-e58d15222272 + github.com/emer/emergent/v2 v2.0.0-dev0.1.0.0.20240820233032-1964b3fa466c github.com/emer/leabra/v2 v2.0.0-20240820174545-ce22f6a30ef6 ) diff --git a/go.sum b/go.sum index ff6593bb..dc95b15d 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -cogentcore.org/core v0.3.3-0.20240820000827-b7efbcd96c73 h1:/49imHmv8zOd6La/MEmmPCeOEbCMLt+S9eSrQhepNds= -cogentcore.org/core v0.3.3-0.20240820000827-b7efbcd96c73/go.mod h1:dg3uRsPcd8S1ZYvRD2TztCtjopRkrB5V/lbl54xsQd4= +cogentcore.org/core v0.3.3-0.20240821175244-e58d15222272 h1:Rg4+pPgZmyuwdVIPlvInNnub4eF4CN0e6n4vRepfj3M= +cogentcore.org/core v0.3.3-0.20240821175244-e58d15222272/go.mod h1:dg3uRsPcd8S1ZYvRD2TztCtjopRkrB5V/lbl54xsQd4= github.com/Bios-Marcel/wastebasket v0.0.4-0.20240213135800-f26f1ae0a7c4 h1:6lx9xzJAhdjq0LvVfbITeC3IH9Fzvo1aBahyPu2FuG8= github.com/Bios-Marcel/wastebasket v0.0.4-0.20240213135800-f26f1ae0a7c4/go.mod h1:FChzXi1izqzdPb6BiNZmcZLGyTYiT61iGx9Rxx9GNeI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -34,8 +34,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/emer/emergent/v2 v2.0.0-dev0.1.0.0.20240820174009-40d67f5b7c88 h1:XpAZVlv6MAq7IbCXvPV0O7D4c+uOQBw4KDXNP2+hkCA= -github.com/emer/emergent/v2 v2.0.0-dev0.1.0.0.20240820174009-40d67f5b7c88/go.mod h1:xSMtRuFkyD27pk5+o9BupztSxz/B2rwVL8AGmTFK/6U= +github.com/emer/emergent/v2 v2.0.0-dev0.1.0.0.20240820233032-1964b3fa466c h1:pynKWFRyQILIElBZZdgMeBG4OxPwgTMkk6rGcLeGfQk= +github.com/emer/emergent/v2 v2.0.0-dev0.1.0.0.20240820233032-1964b3fa466c/go.mod h1:xSMtRuFkyD27pk5+o9BupztSxz/B2rwVL8AGmTFK/6U= github.com/emer/leabra/v2 v2.0.0-20240820174545-ce22f6a30ef6 h1:6/d/+nNg8p2pT9LhS/QS+OdzNH6liwv/TnHCgLkkjH4= github.com/emer/leabra/v2 v2.0.0-20240820174545-ce22f6a30ef6/go.mod h1:b5WyOi8t/rW/zV5ixq/dZ/EO0QzmJ4U8XbtGtKfzpd0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=