Documentation ¶
Overview ¶
Package neat provides an implementation of NeuroEvolution of Augmenting Topologies (NEAT) as a plug-and-play framework, which can be used by simply adding and appropriate configuration and an evaluation function.
NEAT ¶
NEAT (NeuroEvolution of Augmenting Topologies) is a neuroevolution algorithm by Dr. Kenneth O. Stanley which evolves not only neural networks' weights but also their topologies. This method starts the evolution process with genomes with minimal structure, then complexifies the structure of each genome as it progresses. You can read the original paper from here: http://nn.cs.utexas.edu/downloads/papers/stanley.ec02.pdf
Example ¶
This NEAT package is as simple as plug and play. All you have to do is to create a new instance of NEAT, given the configuration from a JSON file, for which the template is provided below, and an evaluation method of a neural network, and run.
{ "experimentName": "XOR Test", "verbose": true, "numInputs": 3, "numOutputs": 1, "numGenerations": 50, "populationSize": 100, "initFitness": 9999.0, "minimizeFitness": true, "survivalRate": 0.5, "stagnationLimit": 5, "ratePerturb": 0.2, "rateAddNode": 0.2, "rateAddConn": 0.2, "rateMutateChild": 0.5, "distanceThreshold": 20.0, "coeffUnmatching": 1.0, "coeffMatching": 1.0 }
Now that you have the configuration JSON file is ready as `config.json`, we can start experiment with NEAT. Below is an example XOR experiment.
package main import ( "log" "math" // Import NEAT package after installing the package through // the instruction provided above. "github.com/jinyeom/neat" ) func main() { // First, create a new instance of Config from the JSON file created above. // If there's a file import error, the program will crash. config, err := neat.NewConfigJSON("config.json") if err != nil{ log.Fatal(err) } // Then, we can define the evaluation function, which is a type of function // which takes a neural network, evaluates its performance, and returns some // score that indicates its performance. This score is essentially a // genome's fitness score. With the configuration and the evaluation // function we defined, we can create a new instance of NEAT and start the // evolution process. neat.New(config, neat.XORTest()).Run() }
Index ¶
- Variables
- func Compatibility(g0, g1 *Genome, c0, c1 float64) float64
- func NewNetwork(g *Genome)
- type ActivationFunc
- func Abs() *ActivationFunc
- func Cos() *ActivationFunc
- func Cube() *ActivationFunc
- func Exp() *ActivationFunc
- func Gaussian(mean, stdev float64) *ActivationFunc
- func Identity() *ActivationFunc
- func Linear() *ActivationFunc
- func Log() *ActivationFunc
- func RandActivationFunc() *ActivationFunc
- func ReLU() *ActivationFunc
- func Sigmoid() *ActivationFunc
- func Sin() *ActivationFunc
- func Sine() *ActivationFunc
- func Square() *ActivationFunc
- func Tanh() *ActivationFunc
- type ComparisonFunc
- type Config
- type ConnGene
- type ConnectionGene
- func (c *ConnectionGene) Disable()
- func (c *ConnectionGene) Dst() *NodeGene
- func (c *ConnectionGene) Enable()
- func (c *ConnectionGene) Expressed() bool
- func (c *ConnectionGene) Id() int
- func (c *ConnectionGene) Src() *NodeGene
- func (c *ConnectionGene) String() string
- func (c *ConnectionGene) Weight() float64
- type EvaluationFunc
- type Genome
- func (g *Genome) Connect(srcId, dstId int) error
- func (g *Genome) ConnenctionGenes() []*ConnectionGene
- func (g *Genome) Copy() *Genome
- func (g *Genome) Evaluate(evaluate EvaluationFunc)
- func (g *Genome) ExportJSON(format bool) error
- func (g *Genome) MutateAddConn(rate float64)
- func (g *Genome) MutateAddNode(rate float64, activation *ActivationFunc)
- func (g *Genome) MutatePerturb(rate float64)
- func (g *Genome) NodeGenes() []*NodeGene
- func (g *Genome) Push(nodeType NodeType, activation ActivationFunc) *NodeGene
- func (g *Genome) String() string
- type NEAT
- type Network
- type NeuralNetwork
- type Neuron
- type NodeGene
- type NodeType
- type Species
- type Statistics
Constants ¶
This section is empty.
Variables ¶
var ( // ActivationSet is a set of functions that can be used as activation // functions by neurons. ActivationSet = map[string]*ActivationFunc{ "linear": Linear(), "sigmoid": Sigmoid(), "tanh": Tanh(), "sin": Sin(), "cos": Cos(), "relu": ReLU(), "log": Log(), "exp": Exp(), "abs": Abs(), "square": Square(), "cube": Cube(), "gaussian": Gaussian(0.0, 1.0), } )
Functions ¶
func Compatibility ¶
Compatibility computes the compatibility distance between two argument genomes.
Compatibility distance of two genomes is utilized for differentiating their species during speciation. The distance is computed as follows:
d = c0 * U + c1 * W
c0, c1, are hyperparameter coefficients, and U, W are respectively number of unmatching genes, and the average weight differences of matching genes. This approach is a slightly modified version of Dr. Kenneth Stanley's original approach in which unmatching genes are separated into excess and disjoint genes.
func NewNetwork ¶
func NewNetwork(g *Genome)
Types ¶
type ActivationFunc ¶
type ActivationFunc int
const ( Linear ActivationFunc = iota Sigmoid Tanh ReLU Sine Gaussian )
func Abs ¶
func Abs() *ActivationFunc
Abs returns the absolute value function as an activation function.
func Exp ¶
func Exp() *ActivationFunc
Exp returns the exponential function as an activation function.
func Gaussian ¶
func Gaussian(mean, stdev float64) *ActivationFunc
Gaussian returns the Gaussian function as an activation function, given a mean and a standard deviation.
func Identity ¶
func Identity() *ActivationFunc
Identity returns the identity function as an activation function. This function is only used for sensor nodes.
func RandActivationFunc ¶
func RandActivationFunc() *ActivationFunc
func ReLU ¶
func ReLU() *ActivationFunc
ReLU returns a rectifier linear unit as an activation function.
func Sigmoid ¶
func Sigmoid() *ActivationFunc
Sigmoid returns the sigmoid function as an activation function.
func Square ¶
func Square() *ActivationFunc
Square returns the square function as an activation function.
type ComparisonFunc ¶
type ComparisonFunc func(g0, g1 *Genome) bool
ComparisonFunc is a type of function that returns a boolean value that indicates whether the first argument genome is better than the second one in terms of its fitness.
func NewComparisonFunc ¶
func NewComparisonFunc(minimize bool) ComparisonFunc
NewComparisonFunc returns a new comparison function, given an indicator of whether the fitness is better when minimized.
type Config ¶
type Config struct { // general settings ExperimentName string `json:"experimentName"` // name of the experiment Verbose bool `json:"verbose"` // verbose mode (terminal) // neural network settings NumInputs int `json:"numInputs"` // number of inputs NumOutputs int `json:"numOutputs"` // number of outputs FullyConnected bool `json:"fullyConnected"` // initially fully connected // evolution settings NumGenerations int `json:"numGenerations"` // number of generations PopulationSize int `json:"populationSize"` // size of population InitFitness float64 `json:"initFitness"` // initial fitness score MinimizeFitness bool `json:"minimizeFitness"` // true if minimizing fitness SurvivalRate float64 `json:"survivalRate"` // survival rate StagnationLimit int `json:"stagnationLimit"` // limit of stagnation // mutation rates settings RatePerturb float64 `json:"ratePerturb"` // by perturbing weights RateAddNode float64 `json:"rateAddNode"` // by adding a node RateAddConn float64 `json:"rateAddConn"` // by adding a connection RateMutateChild float64 `json:"rateMutateChild"` // mutation of a child // compatibility distance coefficient settings DistanceThreshold float64 `json:"distanceThreshold"` // distance threshold CoeffUnmatching float64 `json:"coeffUnmatching"` // unmatching genes CoeffMatching float64 `json:"coeffMatching"` // matching genes // CPPN settings CPPNActivations []string `json:"cppnActivations"` // additional activations }
Config consists of all hyperparameter settings for NEAT. It can be imported from a JSON file.
func NewConfigJSON ¶
NewConfigJSON creates a new instance of Config, given the name of a JSON file that consists of the hyperparameter settings.
type ConnGene ¶
type ConnGene struct { From int `json:"from"` // input node To int `json:"to"` // output node Weight float64 `json:"weight"` // connection weight Disabled bool `json:"disabled"` // true if disabled }
ConnGene is an implementation of a connection between two nodes in the graph representation of a genome. Each connection includes its input node, output node, connection weight, and an indication of whether this connection is disabled
func NewConnGene ¶
NewConnGene returns a new instance of ConnGene, given the input and output node genes. By default, the connection is enabled.
type ConnectionGene ¶
type ConnectionGene struct {
// contains filtered or unexported fields
}
func NewConnectionGene ¶
func NewConnectionGene(innovID int, src, dst *NodeGene) *ConnectionGene
func (*ConnectionGene) Disable ¶
func (c *ConnectionGene) Disable()
func (*ConnectionGene) Dst ¶
func (c *ConnectionGene) Dst() *NodeGene
func (*ConnectionGene) Enable ¶
func (c *ConnectionGene) Enable()
func (*ConnectionGene) Expressed ¶
func (c *ConnectionGene) Expressed() bool
func (*ConnectionGene) Id ¶
func (c *ConnectionGene) Id() int
func (*ConnectionGene) Src ¶
func (c *ConnectionGene) Src() *NodeGene
func (*ConnectionGene) String ¶
func (c *ConnectionGene) String() string
func (*ConnectionGene) Weight ¶
func (c *ConnectionGene) Weight() float64
type EvaluationFunc ¶
type EvaluationFunc func(*NeuralNetwork) float64
EvaluationFunc is a type of function that evaluates an argument neural network and returns a its fitness (performance) score.
func PoleBalancingTest ¶
func PoleBalancingTest(randomStart bool, maxTime int) EvaluationFunc
PoleBalancingTest returns the pole balancing task as an evaluation function. The fitness is measured with how long the network can balanced the pole, given a max time. Suggested max time is 120000 ticks.
func XORTest ¶
func XORTest() EvaluationFunc
XORTest returns an XOR test as an evaluation function. The fitness is measured with the total error, which should be minimized.
type Genome ¶
type Genome struct {
// contains filtered or unexported fields
}
func Crossover ¶
Crossover returns a new child genome by performing crossover between the two argument genomes.
innovations is a temporary dictionary for the child genome's connection genes; it essentially stores all connection genes that will be contained in the child genome.
Initially, all of one parent genome's connections are recorded to innovations. Then, as the other parent genome's connections are added, it checks if each connection already exists; if it does, swap with the other parent's connection by 50% chance. Otherwise, append the new connection.
func NewFCGenome ¶
NewFCGenome returns an instance of initial Genome with fully connected input and output layers.
func (*Genome) ConnenctionGenes ¶
func (g *Genome) ConnenctionGenes() []*ConnectionGene
func (*Genome) Evaluate ¶
func (g *Genome) Evaluate(evaluate EvaluationFunc)
Evaluate takes an evaluation function and evaluates its fitness. Only perform the evaluation if it hasn't yet. If the lamarckian indicator is true, encode the phenotype neural network back into the genome.
func (*Genome) ExportJSON ¶
ExportJSON exports a JSON file that contains this genome's information. If the argument format indicator is true, the exported JSON file will be formatted with indentations.
func (*Genome) MutateAddConn ¶
func (g *Genome) MutateAddConn(rate float64)
MutateAddConn mutates the genome by adding a connection.
func (*Genome) MutateAddNode ¶
func (g *Genome) MutateAddNode(rate float64, activation *ActivationFunc)
MutateAddNode mutates the genome by adding a node with the argument activation function.
func (*Genome) MutatePerturb ¶
func (g *Genome) MutatePerturb(rate float64)
MutatePerturb mutates the genome by perturbation of its weights by the argument rate.
type NEAT ¶
type NEAT struct { Config *Config // configuration Population []*Genome // population of genome Species []*Species // species of subpopulation of genomes Activations []*ActivationFunc // set of activation functions Evaluation EvaluationFunc // evaluation function Comparison ComparisonFunc // comparison function Best *Genome // best genome Statistics *Statistics // statistics // contains filtered or unexported fields }
NEAT is the implementation of NeuroEvolution of Augmenting Topology (NEAT).
func New ¶
func New(config *Config, evaluation EvaluationFunc) *NEAT
New creates a new instance of NEAT with provided argument configuration and an evaluation function.
func (*NEAT) Evaluate ¶
func (n *NEAT) Evaluate()
Evaluate evaluates fitness of every genome in the population. After the evaluation, their fitness scores are recored in each genome.
func (*NEAT) Reproduce ¶
func (n *NEAT) Reproduce()
Reproduce performs reproduction of genomes in each species. Reproduction is performed under the assumption of speciation being already executed. The number of eliminated genomes in each species is determined by rate of elimination specified in n.Config; after some number of genomes are eliminated, the empty space is filled with resulting genomes of crossover among surviving genomes. If the number of eliminated genomes is 0 or less then 2 genomes survive, every member survives and mutates.
func (*NEAT) Speciate ¶
func (n *NEAT) Speciate()
Speciate performs speciation of each genome. The speciation mechanism is as follows (from http://nn.cs.utexas.edu/downloads/papers/stanley.phd04.pdf):
The Genome Loop: Take next genome g from P The Species Loop: If all species in S have been checked: create new species snew and place g in it Else: get next species s from S If g is compatible with s: add g to s If g has not been placed: Species Loop If not all genomes in G have been placed: Genome Loop Else STOP
type NeuralNetwork ¶
type NeuralNetwork struct { Neurons []*Neuron // all neurons in the network // contains filtered or unexported fields }
NeuralNetwork is an implementation of the phenotype neural network that is decoded from a genome.
func NewNeuralNetwork ¶
func NewNeuralNetwork(g *Genome) *NeuralNetwork
NewNeuralNetwork returns a new instance of NeuralNetwork given a genome to decode from.
func (*NeuralNetwork) FeedForward ¶
func (n *NeuralNetwork) FeedForward(inputs []float64) ([]float64, error)
FeedForward propagates inputs signals from input neurons to output neurons, and return output signals.
func (*NeuralNetwork) String ¶
func (n *NeuralNetwork) String() string
String returns the string representation of NeuralNetwork.
type Neuron ¶
type Neuron struct { ID int // neuron ID Type string // neuron type Signal float64 // signal held by this neuron Synapses map[*Neuron]float64 // synapse from input neurons Activation *ActivationFunc // activation function // contains filtered or unexported fields }
Neuron is an implementation of a single neuron of a neural network.
type NodeGene ¶
type NodeGene struct {
// contains filtered or unexported fields
}
func NewNodeGene ¶
func NewNodeGene(id int, ntype string, activation *ActivationFunc) *NodeGene
NewNodeGene returns a new instance of NodeGene, given its ID, its type, and the activation function of this node.
func (*NodeGene) Activation ¶
func (n *NodeGene) Activation() ActivationFunc
func (*NodeGene) Copy ¶
func (n *NodeGene) Copy() *NodeGene
Copy returns a deep copy of this node gene.
type Species ¶
type Species struct { ID int // species ID Stagnation int // number of generations of stagnation Representative *Genome // genome that represents this species (permanent) BestFitness float64 // best fitness score in this species Members []*Genome // member genomes }
Species is an implementation of species, or niche for speciation of genomes that are differentiated by their toplogical differences, measured with compatibility distance. Each species is created with a new genome that is not compatible with other genomes in the population, i.e., when a genome is not compatible with any other species.
func NewSpecies ¶
NewSpecies creates and returns a new instance of Species, given an initial genome that will also become the new species' representative.
func (*Species) ExplicitFitnessSharing ¶
func (s *Species) ExplicitFitnessSharing()
ExplicitFitnessSharing adjust this species' members fitness via explicit fitness sharing.
type Statistics ¶
type Statistics struct { NumSpecies []int // number of species in each generation MinFitness []float64 // minimum fitness in each generation MaxFitness []float64 // maximum fitness in each generation AvgFitness []float64 // average fitness in each generation }
Statistics is a data structure that records statistical information of each generation during the evolutionary process.
func NewStatistics ¶
func NewStatistics(numGenerations int) *Statistics
NewStatistics returns a new instance of Statistics.
func (*Statistics) Update ¶
func (s *Statistics) Update(currGen int, n *NEAT)
Update the statistics of current generation