Skip to content

Commit

Permalink
pcore-ds logging and working nominally but not learning.. clearly a b…
Browse files Browse the repository at this point in the history
…ug somewhere!
  • Loading branch information
rcoreilly committed Dec 18, 2024
1 parent b2e45e0 commit d57dbd2
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 45 deletions.
10 changes: 5 additions & 5 deletions examples/pcore-ds/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type ParamConfig struct {
// RunConfig has config parameters related to running the sim.
type RunConfig struct {

// GPU uses the GPU for computation; only for testing in this model -- not faster.
// GPU uses the GPU for computation.
GPU bool `default:"true"`

// NData is the number of data-parallel items to process in parallel per trial.
Expand All @@ -82,14 +82,14 @@ type RunConfig struct {
Run int `default:"0"`

// Runs is the total number of runs to do when running Train, starting from Run.
Runs int `default:"1" min:"1"`
Runs int `default:"25" 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.
// Sequences is the total number of sequences per epoch.
// Should be an even multiple of NData.
Trials int `default:"128"`
Sequences int `default:"128"`

// Cycles is the total number of cycles per trial: at least 200.
Cycles int `default:"200"`
Expand Down
4 changes: 2 additions & 2 deletions examples/pcore-ds/enumgen.go

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

File renamed without changes.
107 changes: 70 additions & 37 deletions examples/pcore-ds/pcore_ds.go → examples/pcore-ds/pcore-ds.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ const (
type Levels int32 //enums:enum
const (
Cycle Levels = iota
Theta
Trial
Sequence
Epoch
Run
Expt
Expand Down Expand Up @@ -383,33 +383,31 @@ func (ss *Sim) ConfigLoops() {
ls := looper.NewStacks()

ev := ss.Envs.ByModeDi(Train, 0).(*MotorSeqEnv)
trials := int(math32.IntMultipleGE(float32(ss.Config.Run.Trials), float32(ss.Config.Run.NData)))
seqs := int(math32.IntMultipleGE(float32(ss.Config.Run.Sequences), float32(ss.Config.Run.NData)))
cycles := ss.Config.Run.Cycles
plusPhase := ss.Config.Run.PlusCycles
nThetas := ev.SeqLen + 1 // 1 reward at end
seqLen := ev.SeqLen + 1 // 1 reward at end

ls.AddStack(Train, Trial).
AddLevel(Expt, 1).
AddLevel(Run, ss.Config.Run.Runs).
AddLevel(Epoch, ss.Config.Run.Epochs).
AddLevelIncr(Trial, trials, ss.Config.Run.NData).
AddLevel(Theta, nThetas).
AddLevelIncr(Sequence, seqs, ss.Config.Run.NData).
AddLevel(Trial, seqLen).
AddLevel(Cycle, cycles)

ls.AddStack(Test, Trial).
AddLevel(Epoch, 1).
AddLevelIncr(Trial, trials, ss.Config.Run.NData).
AddLevel(Theta, nThetas).
AddLevelIncr(Sequence, seqs, ss.Config.Run.NData).
AddLevel(Trial, seqLen).
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) {
trial := ls.Stacks[mode].Loops[Trial].Counter.Cur
theta := ls.Stacks[mode].Loops[Theta].Counter.Cur
ss.ApplyInputs(mode.(Modes), trial, theta)
ls.AddOnStartToLoop(Trial, "ApplyInputs", func(mode enums.Enum) {
ss.ApplyInputs(mode.(Modes))
})

for mode, st := range ls.Stacks {
Expand Down Expand Up @@ -440,7 +438,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 All @@ -454,8 +452,10 @@ func (ss *Sim) ConfigLoops() {

// ApplyInputs applies input patterns from given environment for given mode.
// Any other start-of-trial logic can also be put here.
func (ss *Sim) ApplyInputs(mode Modes, trial, theta int) {
func (ss *Sim) ApplyInputs(mode Modes) {
net := ss.Net
ss.Net.InitExt()

ndata := int(net.Context().NData)
curModeDir := ss.Current.RecycleDir(mode.String())
lays := []string{"State", "S1", "Target", "SNc"}
Expand Down Expand Up @@ -667,7 +667,7 @@ func (ss *Sim) StatsStart(lmd, ltm enums.Enum) {
func (ss *Sim) StatsStep(lmd, ltm enums.Enum) {
mode := lmd.(Modes)
level := ltm.(Levels)
if level == Cycle {
if level < Trial {
return
}
ss.RunStats(mode, level, Step)
Expand Down Expand Up @@ -714,10 +714,12 @@ func (ss *Sim) StatsInit() {
}
if ss.GUI.Tabs != nil {
_, idx := ss.GUI.Tabs.CurrentTab()
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Train, Trial))
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Train, Sequence))
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Train, Epoch))
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Train, Run))
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Train, Trial))
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Test, Trial))
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Test, Sequence))
ss.GUI.Tabs.PlotTensorFS(axon.StatsNode(ss.Stats, Test, Epoch))
ss.GUI.Tabs.SelectTabIndex(idx)
}
Expand All @@ -732,36 +734,38 @@ func (ss *Sim) ConfigStats() {

ss.SetRunName()

// note: Trial level is not recorded, only the sequence

// last arg(s) are levels to exclude
counterFunc := axon.StatLoopCounters(ss.Stats, ss.Current, ss.Loops, net, Theta, Cycle)
counterFunc := axon.StatLoopCounters(ss.Stats, ss.Current, ss.Loops, net, Sequence, 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, Theta, Cycle)
runNameFunc := axon.StatRunName(ss.Stats, ss.Current, ss.Loops, net, Sequence, 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, Theta)
trialNameFunc := axon.StatTrialName(ss.Stats, ss.Current, ss.Loops, net, Trial)
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
trialNameFunc(mode, level, phase == Start)
})
perTrlFunc := axon.StatPerTrialMSec(ss.Stats, Train, Theta)
perTrlFunc := axon.StatPerTrialMSec(ss.Stats, Train, Sequence)
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
perTrlFunc(mode, level, phase == Start)
})

// up to a point, it is good to use loops over stats in one function,
// to reduce repetition of boilerplate.
statNames := []string{"Action", "Target", "Correct", "NCorrect", "Rew", "RewPred", "RPE", "RewEpc"}
// trialstats are only reported for di = 0
trialStats := []string{"Action", "Target", "Correct"}
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
for si, name := range statNames {
if level != Trial {
return
}
for si, name := range trialStats {
modeDir := ss.Stats.RecycleDir(mode.String())
curModeDir := ss.Current.RecycleDir(mode.String())
levelDir := modeDir.RecycleDir(level.String())
subDir := modeDir.RecycleDir((level - 1).String()) // note: will fail for Cycle
di := 0 //
tsr := levelDir.Float64(name)
ndata := int(ss.Net.Context().NData)
var stat float64
if phase == Start {
tsr.SetNumRows(0)
plot.SetFirstStylerTo(tsr, func(s *plot.Style) {
Expand All @@ -772,18 +776,48 @@ func (ss *Sim) ConfigStats() {
})
continue
}
ev := ss.Envs.ByModeDi(mode, di).(*MotorSeqEnv)
var stat float32
switch name {
case "Action":
stat = float32(ev.CurAction)
case "Target":
stat = float32(ev.Target)
case "Correct":
stat = num.FromBool[float32](ev.Correct)
}
curModeDir.Float32(name, 1).SetFloat1D(float64(stat), di)
tsr.AppendRowFloat(float64(stat))
}
})

seqStats := []string{"NCorrect", "Rew", "RewPred", "RPE", "RewEpc"}
ss.AddStat(func(mode Modes, level Levels, phase StatsPhase) {
if level <= Trial {
return
}
for _, name := range seqStats {
modeDir := ss.Stats.RecycleDir(mode.String())
curModeDir := ss.Current.RecycleDir(mode.String())
levelDir := modeDir.RecycleDir(level.String())
subDir := modeDir.RecycleDir((level - 1).String()) // note: will fail for Cycle
tsr := levelDir.Float64(name)
ndata := int(ss.Net.Context().NData)
var stat float64
if phase == Start {
tsr.SetNumRows(0)
plot.SetFirstStylerTo(tsr, func(s *plot.Style) {
s.Range.SetMin(0).SetMax(1)
s.On = true
})
continue
}
switch level {
case Theta:
case Sequence:
for di := range ndata {
ev := ss.Envs.ByModeDi(mode, di).(*MotorSeqEnv)
var stat float32
switch name {
case "Action":
stat = float32(ev.CurAction)
case "Target":
stat = float32(ev.Target)
case "Correct":
stat = num.FromBool[float32](ev.Correct)
case "NCorrect":
stat = float32(ev.PrevNCorrect)
case "Rew":
Expand All @@ -802,7 +836,6 @@ func (ss *Sim) ConfigStats() {
}
}
})

}

// StatCounters returns counters string to show at bottom of netview.
Expand All @@ -819,12 +852,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{"Action", "Target", "Correct"}
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
2 changes: 1 addition & 1 deletion examples/pcore-ds/typegen.go

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

File renamed without changes.

0 comments on commit d57dbd2

Please sign in to comment.