network_evaluator (faber_tweann v2.4.0)
View SourceSynchronous neural network evaluator for inference.
This module provides synchronous (blocking) forward propagation for neural networks. Unlike the process-based cortex/neuron approach used during training, this is designed for fast inference in real-time applications like games.
Usage
Create a network from a genotype: {ok, Network} = network_evaluator:from_genotype(AgentId)
Or create a simple feedforward network: Network = network_evaluator:create_feedforward(42, [16, 8], 6)
Evaluate: Outputs = network_evaluator:evaluate(Network, Inputs)
Summary
Functions
Compile network for NIF acceleration.
Create a CfC feedforward network with random weights and CfC neuron metadata.
Create a feedforward network with random weights.
Create a feedforward network with specified activation.
Create a feedforward network with separate output activation.
Evaluate the network with given inputs.
Evaluate with reward-modulated (three-factor) plasticity.
Evaluate with online Hebbian plasticity (memory-by-learning).
Evaluate the network with stateful CfC processing.
Deserialize a network from binary.
Load a network from a genotype stored in ETS, weights included.
Deserialize a network from a JSON-compatible map.
Get the hidden layer activation function from a network.
Read the CfC internal state (the memory carrier); undefined for a plain net.
Get the layer list from a network.
Get neuron metadata from a CfC network.
Get the output layer activation function from a network.
Get network topology information for visualization.
Get visualization data for rendering the network.
Get all weights from the network as a flat list.
Reset internal state of a CfC network to zeros.
Set neuron metadata on a network.
Set weights from a flat list.
Strip the compiled_ref from a network to release NIF memory.
Serialize a network to binary using Erlang term format.
Serialize a network to a JSON-compatible map.
Types
Functions
Compile network for NIF acceleration.
If the NIF is loaded, compiles the network to a flat representation that can be evaluated much faster. Falls back to Erlang evaluation if NIF is not available.
WARNING: Use sparingly! Each compiled network holds a Rust ResourceArc reference that keeps native memory alive. During neuroevolution, do NOT compile networks automatically (especially in create_feedforward or set_weights) as this causes massive memory leaks - one compiled_ref per offspring per generation accumulates unboundedly.
Only call this when you need maximum performance for a specific network that will be evaluated many times (e.g., the final champion network).
-spec create_cfc_feedforward(pos_integer(), [pos_integer()], pos_integer(), atom(), atom() | undefined) -> network().
Create a CfC feedforward network with random weights and CfC neuron metadata.
Same layer structure as create_feedforward but hidden neurons are CfC type. Output neurons remain standard. CfC neurons use evaluate_cfc for temporal adaptation with learnable time constants.
-spec create_feedforward(pos_integer(), [pos_integer()], pos_integer()) -> network().
Create a feedforward network with random weights.
-spec create_feedforward(pos_integer(), [pos_integer()], pos_integer(), atom()) -> network().
Create a feedforward network with specified activation.
-spec create_feedforward(pos_integer(), [pos_integer()], pos_integer(), atom(), atom() | undefined) -> network().
Create a feedforward network with separate output activation.
Hidden layers use Activation, output layer uses OutputActivation. If OutputActivation is undefined, all layers use Activation.
Evaluate the network with given inputs.
Performs synchronous forward propagation through all layers. Uses NIF acceleration if available and network was compiled.
-spec evaluate_with_neuromod(network(), [float()], {float(), float(), float(), float(), float()} | {oja, float()} | {pc, [[[{float(), float(), float(), float()}]]], float()}, float()) -> {[float()], network()}.
Evaluate with reward-modulated (three-factor) plasticity.
Identical to evaluate_with_plasticity/3, but every weight change is gated by a neuromodulatory signal M (typically a reward): dW = M * Eta * (...). This is the third factor of the classic pre x post x neuromodulator rule -- the piece a fixed Hebbian rule lacks. M scales the rule's learning rate, so M = 0 freezes learning, M above zero reinforces the just-active pathway, M below zero reverses it. Works for the global ABCD, Oja, and per-connection rule shapes alike (M multiplies the whole update).
-spec evaluate_with_plasticity(network(), [float()], {float(), float(), float(), float(), float()} | {oja, float()} | {pc, [[[{float(), float(), float(), float()}]]], float()}) -> {[float()], network()}.
Evaluate with online Hebbian plasticity (memory-by-learning).
Forward pass, then update every weight by a Hebbian rule using the pre- and post-synaptic activations of each layer. Three rule shapes are supported: {A,B,C,D,Eta} global ABCD-Hebbian, ONE rule for all synapses: dW = Eta * (A*pre*post + B*pre + C*post + D) {oja, Eta} Oja's self-normalising rule: dW = Eta*post*(pre-post*w) {pc, CoeffLayers, Eta} PER-CONNECTION ABCD: each synapse has its OWN {A,B,C,D} (CoeffLayers mirrors the weight structure), Eta shared. Weights are clamped to [-10, 10]. The evolutionary search tunes the RULE, not the weights, so the network adapts its own weights within an episode. Global ABCD is the special case of per-connection where all synapses share coefficients -- per-connection is strictly more expressive. Biases are not plastic.
Evaluate the network with stateful CfC processing.
For standard feedforward networks (no neuron_meta), behaves identically to evaluate/2 but returns {Outputs, Network} tuple.
For CfC networks, each CfC neuron updates its internal state based on the input-dependent time constant, enabling temporal reasoning.
Deserialize a network from binary.
Load a network from a genotype stored in ETS, weights included.
Faithful or nothing. A genotype whose topology cannot be represented as a stack of dense layers returns {error, {not_layerable, Why}} naming what stopped it, rather than an approximation reported as success.
Until ROADMAP 8a this function counted the neurons, invented a layer shape and filled it with random weights, while its own doc claimed to read the weights from Mnesia. There is no Mnesia and there were no weights. See genotype_to_network for the five conditions that make a genotype unconvertible.
Note this drops per-synapse tuning state (delta, learning rate, parameters), because the evaluator has nowhere to hold it. A converted network is an inference artifact, not a resumable genotype.
Deserialize a network from a JSON-compatible map.
Accepts the format produced by to_json/1.
Get the hidden layer activation function from a network.
See get_layers/1 for why callers outside this module should use accessors.
Read the CfC internal state (the memory carrier); undefined for a plain net.
Get the layer list from a network.
Accessor for consumers outside this module. Use this rather than destructuring the network tuple directly, so that adding fields to the network record cannot silently break callers.
-spec get_neuron_meta(network()) -> [layer_meta()] | undefined.
Get neuron metadata from a CfC network.
Returns undefined for standard feedforward networks.
Get the output layer activation function from a network.
Returns undefined when the output layer uses the same activation as the hidden layers.
Get network topology information for visualization.
Returns a map with layer sizes for rendering the network structure.
Get visualization data for rendering the network.
Combines topology, weights, and activations into a format suitable for frontend visualization.
Get all weights from the network as a flat list.
Useful for evolution - can be mutated and set back.
Reset internal state of a CfC network to zeros.
Call this at the start of each episode to prevent state leakage between independent evaluation sequences (e.g., between game rounds).
-spec set_neuron_meta(network(), [layer_meta()] | undefined) -> network().
Set neuron metadata on a network.
Used by mutation operators to update CfC parameters (tau, state_bound).
Set weights from a flat list.
The list must have the same number of elements as returned by get_weights/1. NOTE: Does NOT compile for NIF - this prevents memory leaks during evolution.
Strip the compiled_ref from a network to release NIF memory.
IMPORTANT: Call this before storing networks long-term (archives, events) to prevent NIF ResourceArc references from accumulating and causing memory leaks. The compiled_ref is a Rust ResourceArc that holds native memory - keeping references alive prevents the memory from being freed.
The network can be recompiled on-demand when needed for evaluation.
Serialize a network to binary using Erlang term format.
This is more compact than JSON and preserves exact floating point values. Use this for Erlang-to-Erlang transfer or storage.
Serialize a network to a JSON-compatible map.
The output format is suitable for JSON encoding and can be loaded in other runtimes (Python, JavaScript, etc.) for inference.
Format: A map with keys "version", "activation", and "layers". The layers list contains maps with "weights" and "biases" keys.