Skip to content

Commit

Permalink
update econfig/README.md with examples for Env, Network params as map…
Browse files Browse the repository at this point in the history
…, updated example config file.
  • Loading branch information
rcoreilly committed Apr 3, 2024
1 parent f405fb4 commit 7626834
Showing 1 changed file with 118 additions and 37 deletions.
155 changes: 118 additions & 37 deletions econfig/README.md
Expand Up @@ -36,25 +36,37 @@ Docs: [GoDoc](https://pkg.go.dev/github.com/emer/emergent/econfig)

* To enable include file processing, add a `Includes []string` field and a `func (cfg *Config) IncludesPtr() *[]string { return &cfg.Includes }` method. The include file(s) are read first before the current one. A stack of such includes is created and processed in the natural order encountered, so each includer is applied after the includees, recursively. Note: use `--config` to specify the first config file read -- the `Includes` field is excluded from arg processing because it would be processed _after_ the point where include files are processed.

* `Field map[string]any` -- allows raw parsing of values that can be applied later. Use this for `Network`, `Env` etc fields.
* `Field map[string]any` -- allows raw parsing of values that can be applied later. Use this for `Network`, `Env` etc fields. Here are some examples:

```toml
[Env.Env]
"NItems" = 10
"NTrials" = 10
```

```toml
[Params.Network]
"#Output:Layer.Inhib.Layer.Gi" = 0.7
"Prjn:Prjn.Learn.LRate.Base" = 0.05
```

* Field tag `def:"value"`, used in the [GoGi](https://cogentcore.org/core/gi/v2) GUI, sets the initial default value and is shown for the `-h` or `--help` usage info.

* [kit](https://cogentcore.org/core/ki) registered "enum" `const` types, with names automatically parsed from string values (including bit flags). Must use the [goki stringer](https://github.com/goki/stringer) version to generate `FromString()` method, and register the type like this: `var KitTestEnum = kit.Enums.AddEnum(TestEnumN, kit.NotBitFlag, nil)` -- see [enum.go](enum.go) file for example.

# `def` Default Tags
# `default` Default Tags

The [GoGi](https://cogentcore.org/core/gi/v2) GUI processes `def:"value"` struct tags to highlight values that are not at their defaults. econfig uses these same tags to auto-initialize fields as well, ensuring that the tag and the actual initial value are the same. The value for strings or numbers is just the string representation. For more complex types, here ar some examples:
The [Cogent Core](https://cogentcore.org/core) GUI processes `default:"value"` struct tags to highlight values that are not at their defaults. econfig uses these same tags to auto-initialize fields as well, ensuring that the tag and the actual initial value are the same. The value for strings or numbers is just the string representation. For more complex types, here ar some examples:

* `struct`: specify using standard Go literal expression as a string, with single-quotes `'` used instead of double-quotes around strings, such as the name of the fields:
+ `evec.Vec2i`: `def:"{'X':10,'Y':10}"`
+ `evec.Vec2i`: `default:"{'X':10,'Y':10}"`

* `slice`: comma-separated list of values in square braces -- use `'` for internal string boundaries:
+ `[]float32`: `def:"[1, 2.14, 3.14]"`
+ `[]string`: `def:"{'A', 'bbb bbb', 'c c c'}"`
+ `[]float32`: `default:"[1, 2.14, 3.14]"`
+ `[]string`: `default:"{'A', 'bbb bbb', 'c c c'}"`

* `map`: comma-separated list of key:value in curly braces -- use `'` for internal string boundaries:
+ `map[string]float32`: `def:"{'key1': 1, 'key2': 2.14, 'key3': 3.14]"`
+ `map[string]float32`: `default:"{'key1': 1, 'key2': 2.14, 'key3': 3.14]"`

# Standard Config Example

Expand All @@ -63,48 +75,117 @@ Here's the `Config` struct from [axon/examples/ra25](https://github.com/emer/axo
```Go
// ParamConfig has config parameters related to sim params
type ParamConfig struct {
Network map[string]any `desc:"network parameters"`
Set string `desc:"ParamSet name to use -- must be valid name as listed in compiled-in params or loaded params"`
File string `desc:"Name of the JSON file to input saved parameters from."`
Tag string `desc:"extra tag to add to file names and logs saved from this run"`
Note string `desc:"user note -- describe the run params etc -- like a git commit message for the run"`
SaveAll bool `desc:"Save a snapshot of all current param and config settings in a directory named params_<datestamp> then quit -- useful for comparing to later changes and seeing multiple views of current params"`

// network parameters
Network map[string]any

// size of hidden layer -- can use emer.LaySize for 4D layers
Hidden1Size evec.Vec2i `default:"{'X':10,'Y':10}" nest:"+"`

// size of hidden layer -- can use emer.LaySize for 4D layers
Hidden2Size evec.Vec2i `default:"{'X':10,'Y':10}" nest:"+"`

// Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params
Sheet string

// extra tag to add to file names and logs saved from this run
Tag string

// user note -- describe the run params etc -- like a git commit message for the run
Note string

// Name of the JSON file to input saved parameters from.
File string `nest:"+"`

// Save a snapshot of all current param and config settings in a directory named params_<datestamp> (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params
SaveAll bool `nest:"+"`

// for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.
Good bool `nest:"+"`
}

// RunConfig has config parameters related to running the sim
type RunConfig struct {
GPU bool `def:"true" desc:"use the GPU for computation -- generally faster even for small models if NData ~16"`
Threads int `def:"0" desc:"number of parallel threads for CPU computation -- 0 = use default"`
Run int `def:"0" desc:"starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1"`
Runs int `def:"5" min:"1" desc:"total number of runs to do when running Train"`
Epochs int `def:"100" desc:"total number of epochs per run"`
NZero int `def:"2" desc:"stop run after this number of perfect, zero-error epochs"`
NTrials int `def:"32" desc:"total number of trials per epoch. Should be an even multiple of NData."`
NData int `def:"16" min:"1" desc:"number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning."`
TestInterval int `def:"5" desc:"how often to run through all the test patterns, in terms of training epochs -- can use 0 or -1 for no testing"`
PCAInterval int `def:"5" desc:"how frequently (in epochs) to compute PCA on hidden representations to measure variance?"`
StartWts string `desc:"if non-empty, is the name of weights file to load at start of first run -- for testing"`

// use the GPU for computation -- generally faster even for small models if NData ~16
GPU bool `default:"true"`

// number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning.
NData int `default:"16" min:"1"`

// number of parallel threads for CPU computation -- 0 = use default
NThreads int `default:"0"`

// starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1
Run int `default:"0"`

// total number of runs to do when running Train
NRuns int `default:"5" min:"1"`

// total number of epochs per run
NEpochs int `default:"100"`

// stop run after this number of perfect, zero-error epochs
NZero int `default:"2"`

// total number of trials per epoch. Should be an even multiple of NData.
NTrials int `default:"32"`

// how often to run through all the test patterns, in terms of training epochs -- can use 0 or -1 for no testing
TestInterval int `default:"5"`

// how frequently (in epochs) to compute PCA on hidden representations to measure variance?
PCAInterval int `default:"5"`

// if non-empty, is the name of weights file to load at start of first run -- for testing
StartWts string
}

// LogConfig has config parameters related to logging data
type LogConfig struct {
SaveWts bool `desc:"if true, save final weights after each run"`
Epoch bool `def:"true" desc:"if true, save train epoch log to file, as .epc.tsv typically"`
Run bool `def:"true" desc:"if true, save run log to file, as .run.tsv typically"`
Trial bool `def:"false" desc:"if true, save train trial log to file, as .trl.tsv typically. May be large."`
TestEpoch bool `def:"false" desc:"if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there."`
TestTrial bool `def:"false" desc:"if true, save testing trial log to file, as .tst_trl.tsv typically. May be large."`
NetData bool `desc:"if true, save network activation etc data from testing trials, for later viewing in netview"`

// if true, save final weights after each run
SaveWts bool

// if true, save train epoch log to file, as .epc.tsv typically
Epoch bool `default:"true" nest:"+"`

// if true, save run log to file, as .run.tsv typically
Run bool `default:"true" nest:"+"`

// if true, save train trial log to file, as .trl.tsv typically. May be large.
Trial bool `default:"false" nest:"+"`

// if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there.
TestEpoch bool `default:"false" nest:"+"`

// if true, save testing trial log to file, as .tst_trl.tsv typically. May be large.
TestTrial bool `default:"false" nest:"+"`

// if true, save network activation etc data from testing trials, for later viewing in netview
NetData bool
}

// Config is a standard Sim config -- use as a starting point.
type Config struct {
Includes []string `desc:"specify include files here, and after configuration, it contains list of include files added"`
GUI bool `def:"true" desc:"open the GUI -- does not automatically run -- if false, then runs automatically and quits"`
Debug bool `desc:"log debugging information"`
Params ParamConfig `view:"add-fields" desc:"parameter related configuration options"`
Run RunConfig `view:"add-fields" desc:"sim running related configuration options"`
Log LogConfig `view:"add-fields" desc:"data logging related configuration options"`

// specify include files here, and after configuration, it contains list of include files added
Includes []string

// open the GUI -- does not automatically run -- if false, then runs automatically and quits
GUI bool `default:"true"`

// log debugging information
Debug bool

// parameter related configuration options
Params ParamConfig `view:"add-fields"`

// sim running related configuration options
Run RunConfig `view:"add-fields"`

// data logging related configuration options
Log LogConfig `view:"add-fields"`
}

func (cfg *Config) IncludesPtr() *[]string { return &cfg.Includes }
Expand Down

0 comments on commit 7626834

Please sign in to comment.