Skip to content

Commit

Permalink
pfcmaint actually working with ndata > 1 -- have to just do flat tria…
Browse files Browse the repository at this point in the history
…ls relative to env steps
  • Loading branch information
rcoreilly committed Dec 18, 2024
1 parent acc3039 commit b2e45e0
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 61 deletions.
38 changes: 6 additions & 32 deletions examples/pcore-ds/pcore_ds.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,19 +733,19 @@ func (ss *Sim) ConfigStats() {
ss.SetRunName()

// last arg(s) are levels to exclude
counterFunc := axon.StatLoopCounters(ss.Stats, ss.Current, ss.Loops, net, Trial, Cycle)
counterFunc := axon.StatLoopCounters(ss.Stats, ss.Current, ss.Loops, net, Theta, Cycle)
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
counterFunc(mode, level, phase == Start)
})
runNameFunc := axon.StatRunName(ss.Stats, ss.Current, ss.Loops, net, Trial, Cycle)
runNameFunc := axon.StatRunName(ss.Stats, ss.Current, ss.Loops, net, Theta, Cycle)
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
runNameFunc(mode, level, phase == Start)
})
trialNameFunc := axon.StatTrialName(ss.Stats, ss.Current, ss.Loops, net, Trial)
trialNameFunc := axon.StatTrialName(ss.Stats, ss.Current, ss.Loops, net, Theta)
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
trialNameFunc(mode, level, phase == Start)
})
perTrlFunc := axon.StatPerTrialMSec(ss.Stats, Train, Trial)
perTrlFunc := axon.StatPerTrialMSec(ss.Stats, Train, Theta)
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
perTrlFunc(mode, level, phase == Start)
})
Expand Down Expand Up @@ -773,7 +773,7 @@ func (ss *Sim) ConfigStats() {
continue
}
switch level {
case Trial:
case Theta:
for di := range ndata {
ev := ss.Envs.ByModeDi(mode, di).(*MotorSeqEnv)
var stat float32
Expand All @@ -796,33 +796,7 @@ func (ss *Sim) ConfigStats() {
curModeDir.Float32(name, ndata).SetFloat1D(float64(stat), di)
tsr.AppendRowFloat(float64(stat))
}
case Epoch:
stat = stats.StatMean.Call(subDir.Value(name)).Float1D(0)
tsr.AppendRowFloat(stat)
// if mode == Train {
// break
// }
// if si == 0 {
// stats.Groups(curModeDir, subDir.Value("TrialName"))
// break
// }
// stats.GroupStats(curModeDir, stats.StatMean, subDir.Value(name))
// // note: results go under Group name: TrialName
// gp := curModeDir.RecycleDir("Stats/TrialName/" + name).Value("Mean")
// plot.SetFirstStylerTo(gp, func(s *plot.Style) {
// if si >= 2 && si <= 3 {
// s.On = true
// }
// })
// if si == len(statNames)-1 {
// nrows := gp.DimSize(0)
// row := curModeDir.RecycleDir("Stats").Int("Row", nrows)
// for i := range nrows {
// row.Set(i, i)
// }
// ss.GUI.Tabs.PlotTensorFS(curModeDir.RecycleDir("Stats"))
// }
case Run:
default:
stat = stats.StatMean.Call(subDir.Value(name)).Float1D(0)
tsr.AppendRowFloat(stat)
}
Expand Down
6 changes: 3 additions & 3 deletions examples/pfcmaint/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type RunConfig struct {
// NData is the number of data-parallel items to process in parallel per trial.
// Is significantly faster for both CPU and GPU. Results in an effective
// mini-batch of learning.
NData int `default:"16" min:"1"`
NData int `default:"2" min:"1"`

// NThreads is the number of parallel threads for CPU computation;
// 0 = use default.
Expand All @@ -79,11 +79,11 @@ type RunConfig struct {
Runs int `default:"1" min:"1"`

// Epochs is the total number of epochs per run.
Epochs int `default:"30"`
Epochs int `default:"50"`

// Trials is the total number of trials per epoch.
// Should be an even multiple of NData.
Trials int `default:"64"`
Trials int `default:"128"`

// Cycles is the total number of cycles per trial: at least 200.
Cycles int `default:"200"`
Expand Down
10 changes: 5 additions & 5 deletions examples/pfcmaint/enumgen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions examples/pfcmaint/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,14 @@ var LayerParams = axon.LayerSheets{
// Base is always applied, and others can be optionally selected to apply on top of that.
var PathParams = axon.PathSheets{
"Base": {
{Sel: "Path", Doc: "",
Set: func(pt *axon.PathParams) {
pt.Learn.LRate.Base = 0.01
}},
{Sel: ".PFCPath", Doc: "",
Set: func(pt *axon.PathParams) {
pt.PathScale.Abs = 1.0
pt.Learn.LRate.Base = 0.01
}},
{Sel: "#GPiToPFCThal", Doc: "",
Set: func(pt *axon.PathParams) {
Expand Down
34 changes: 17 additions & 17 deletions examples/pfcmaint/pfcmaint.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const (
type Levels int32 //enums:enum
const (
Cycle Levels = iota
Theta
Trial
Epoch
Run
Expand Down Expand Up @@ -149,8 +148,8 @@ func (ss *Sim) Run() {
func (ss *Sim) ConfigEnv() {
// Can be called multiple times -- don't re-create
newEnv := (len(ss.Envs) == 0)

for di := 0; di < ss.Config.Run.NData; di++ {
ndata := ss.Config.Run.NData
for di := 0; di < ndata; di++ {
var trn, tst *PFCMaintEnv
if newEnv {
trn = &PFCMaintEnv{}
Expand All @@ -166,14 +165,14 @@ func (ss *Sim) ConfigEnv() {
if ss.Config.Env.Env != nil {
reflectx.SetFieldsFromMap(trn, ss.Config.Env.Env)
}
trn.Config(etime.Train, 73+int64(di)*73)
trn.Config(etime.Train, di, ndata, 73) // same seeds so same pats

tst.Name = env.ModeDi(etime.Test, di)
tst.Defaults()
if ss.Config.Env.Env != nil {
reflectx.SetFieldsFromMap(tst, ss.Config.Env.Env)
}
tst.Config(etime.Test, 181+int64(di)*181)
tst.Config(etime.Test, di, ndata, 181)

trn.Init(0)
tst.Init(0)
Expand Down Expand Up @@ -275,7 +274,6 @@ func (ss *Sim) NetViewUpdater(mode enums.Enum) *axon.NetViewUpdate {
func (ss *Sim) ConfigLoops() {
ls := looper.NewStacks()

ev := ss.Envs.ByModeDi(Train, 0).(*PFCMaintEnv)
trials := int(math32.IntMultipleGE(float32(ss.Config.Run.Trials), float32(ss.Config.Run.NData)))
cycles := ss.Config.Run.Cycles
plusPhase := ss.Config.Run.PlusCycles
Expand All @@ -284,22 +282,20 @@ func (ss *Sim) ConfigLoops() {
AddLevel(Run, ss.Config.Run.Runs).
AddLevel(Epoch, ss.Config.Run.Epochs).
AddLevelIncr(Trial, trials, ss.Config.Run.NData).
AddLevel(Theta, ev.NTrials).
AddLevel(Cycle, cycles)

ls.AddStack(Test, Trial).
AddLevel(Epoch, 1).
AddLevelIncr(Trial, trials, ss.Config.Run.NData).
AddLevel(Theta, ev.NTrials).
AddLevel(Cycle, cycles)

axon.LooperStandard(ls, ss.Net, ss.NetViewUpdater, 50, cycles-plusPhase, cycles-1, Cycle, Theta, Train) // note: Theta
axon.LooperStandard(ls, ss.Net, ss.NetViewUpdater, 50, cycles-plusPhase, cycles-1, Cycle, Trial, Train)

ls.Stacks[Train].OnInit.Add("Init", func() { ss.Init() })

ls.AddOnStartToLoop(Theta, "ApplyInputs", func(mode enums.Enum) {
ls.AddOnStartToLoop(Trial, "ApplyInputs", func(mode enums.Enum) {
trial := ls.Stacks[mode].Loops[Trial].Counter.Cur
theta := ls.Stacks[mode].Loops[Theta].Counter.Cur
theta := ls.Stacks[mode].Loops[Trial].Counter.Cur
ss.ApplyInputs(mode.(Modes), trial, theta)
})

Expand All @@ -314,7 +310,7 @@ func (ss *Sim) ConfigLoops() {
})

if ss.Config.GUI {
axon.LooperUpdateNetView(ls, Cycle, Theta, ss.NetViewUpdater)
axon.LooperUpdateNetView(ls, Cycle, Trial, ss.NetViewUpdater)

ls.Stacks[Train].OnInit.Add("GUI-Init", func() { ss.GUI.UpdateWindow() })
ls.Stacks[Test].OnInit.Add("GUI-Init", func() { ss.GUI.UpdateWindow() })
Expand Down Expand Up @@ -503,30 +499,34 @@ func (ss *Sim) ConfigStats() {
itemly := ss.Net.LayerByName("ItemP")
timely := ss.Net.LayerByName("TimeP")
for di := range ndata {
ev := ss.Envs.ByModeDi(mode, di).(*PFCMaintEnv)
var stat float64
switch name {
case "ItemP_CorSim":
stat = 1.0 - float64(axon.LayerStates.Value(int(itemly.Index), int(di), int(axon.LayerPhaseDiff)))
case "TimeP_CorSim":
stat = 1.0 - float64(axon.LayerStates.Value(int(timely.Index), int(di), int(axon.LayerPhaseDiff)))
}
if ev.Trial.Prev == 0 { // unpredictable
stat = 1
}
curModeDir.Float64(name, ndata).SetFloat1D(stat, di)
tsr.AppendRowFloat(stat)
}
case Epoch, Run:
default:
stat = stats.StatMean.Call(subDir.Value(name)).Float1D(0)
tsr.AppendRowFloat(stat)
}
}
})

prevCorFunc := axon.StatPrevCorSim(ss.Stats, ss.Current, net, Theta, "ItemP", "TimeP")
prevCorFunc := axon.StatPrevCorSim(ss.Stats, ss.Current, net, Trial, "ItemP", "TimeP")
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
prevCorFunc(mode, level, phase == Start)
})

lays := net.LayersByClass("PFC")
actGeFunc := axon.StatLayerActGe(ss.Stats, net, Train, Theta, lays...)
actGeFunc := axon.StatLayerActGe(ss.Stats, net, Train, Trial, lays...)
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
actGeFunc(mode, level, phase == Start)
})
Expand All @@ -547,12 +547,12 @@ func (ss *Sim) StatCounters(mode, level enums.Enum) string {
return counters
}
counters += fmt.Sprintf(" TrialName: %s", curModeDir.StringValue("TrialName").String1D(di))
statNames := []string{"Gated"}
statNames := []string{"ItemP_CorSim", "TimeP_CorSim"}
if level == Cycle || curModeDir.Node(statNames[0]) == nil {
return counters
}
for _, name := range statNames {
counters += fmt.Sprintf(" %s: %.4g", name, curModeDir.Float32(name).Float1D(di))
counters += fmt.Sprintf(" %s: %.4g", name, curModeDir.Value(name).Float1D(di))
}
return counters
}
Expand Down
26 changes: 22 additions & 4 deletions examples/pfcmaint/pfcmaint_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package pfcmaint

import (
"fmt"
"log/slog"

"cogentcore.org/core/base/randx"
"cogentcore.org/core/tensor"
Expand All @@ -30,9 +31,18 @@ type PFCMaintEnv struct {
// trial counter is for the maint step within item
Trial env.Counter `display:"inline"`

// number of different items to maintain
// Di is the data parallel index.
Di int

// ndata is number of data parallel total.
NData int

// number of different items to maintain.
NItems int

// StartItem is item we start on, based on Di, NData.
StartItem int

// number of trials to maintain
NTrials int

Expand Down Expand Up @@ -73,15 +83,22 @@ func (ev *PFCMaintEnv) Defaults() {
}

// Config configures the world
func (ev *PFCMaintEnv) Config(mode etime.Modes, rndseed int64) {
func (ev *PFCMaintEnv) Config(mode etime.Modes, di, ndata int, rndseed int64) {
ev.Mode = mode
ev.Di = di
ev.NData = ndata
ev.RandSeed = rndseed
ev.Rand.NewRand(ev.RandSeed)
ev.States = make(map[string]*tensor.Float32)
ev.States["Item"] = tensor.NewFloat32(ev.NUnitsY, ev.NUnitsX)
ev.States["Time"] = tensor.NewFloat32(ev.NUnitsY, ev.NTrials)
ev.States["GPi"] = tensor.NewFloat32(ev.NUnitsY, ev.NUnitsX)
ev.Sequence.Max = ev.NItems
if ev.NItems%ndata != 0 {
slog.Error("PFCMaintEnv: Number of items must be evenly divisible by NData", "NItems:", ev.NItems, "NData:", ndata)
}
nper := ev.NItems / ndata
ev.Sequence.Max = nper
ev.StartItem = ev.Di * nper
ev.Trial.Max = ev.NTrials
ev.ConfigPats()
}
Expand Down Expand Up @@ -136,7 +153,8 @@ func (ev *PFCMaintEnv) RenderState(item, trial int) {

// Step does one step -- must set Trial.Cur first if doing testing
func (ev *PFCMaintEnv) Step() bool {
ev.RenderState(ev.Sequence.Cur, ev.Trial.Cur)
item := ev.StartItem + ev.Sequence.Cur
ev.RenderState(item, ev.Trial.Cur)
ev.Sequence.Same()
if ev.Trial.Incr() {
ev.Sequence.Incr()
Expand Down

0 comments on commit b2e45e0

Please sign in to comment.