Generated reference › Activation Function — Machine Learning/Neural Networks
kind: generated#block#machine-learning-neural-networks

Activation Function — Machine Learning/Neural Networks

Machine_Learning/Neural_Networks/Activation_Function · 1 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Activation Function

Machine Learning / Neural Networks

Applies one elementwise nonlinearity to every entry of the input, with no change of shape. This is the activation as its own node, for a graph that places it between layers rather than inside them – a residual branch that adds before activating, layers exported unactivated from the framework, or simply a network you would rather read off the canvas.

The Dense Layer block carries four activations internally; use those when the activation belongs to the layer, and this block when it does not.

Ports

  • u – the input, any size [r,c]. The function is applied to each entry independently.
  • Outputy, the same [r,c]: an elementwise map never changes the signal's dimensions.

Parameters

  • Activation – which function to apply:
    • ReLU – max(0, x). The default, and the usual hidden-layer choice.
    • LeakyReLU – x for x > 0, Leaky Slope·x otherwise; keeps a small gradient on the negative side.
    • ELU – x for x > 0, ELU Alpha·(ex − 1) otherwise; saturates smoothly at −alpha instead of at 0.
    • Tanh – squashes to (−1, 1).
    • Sigmoid – 1 ÷ (1 + e−x), squashes to (0, 1).
    • Softplus – ln(1 + ex), a smooth ReLU.
    • SiLU – x · sigmoid(x), also called swish.
    • GELU – 0.5·x·(1 + tanh(√(2/π)·(x + 0.044715·x³))). See the Notes: this is the tanh approximation, deliberately.
  • Leaky Slope – the negative-side slope used by LeakyReLU only, and ignored by every other setting. Default 0.01, PyTorch's negative_slope.
  • ELU Alpha – the saturation level used by ELU only, and ignored by every other setting. Default 1.0, PyTorch's alpha.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The chosen activation is baked into the body at export time – it is structural, not something to retune on the target – and so are the two slope constants.

The three HDL targets are simulation-only: they carry the function in real arithmetic and quantize only at the port boundary. Six of the eight activations are transcendental and have no place in a Q16.16 datapath; ReLU and LeakyReLU alone would be synthesizable, and a block whose synthesizability changed with a combo value would be worse than one that is honest about the whole of itself.

PLC Structured Text has no TANH, so Tanh and GELU are emitted through 2 ÷ (1 + EXP(−2z)) − 1, which is the same function written in terms of EXP alone.

Simulink bridge

None. Simulink has no single elementwise-activation block to map to: its Deep Learning blocks take a trained network object, and the nearest primitives (Saturation, Math Function, Trigonometric Function) each cover one of these eight at best and none of the others, so no ParamRule could carry the combo across. The bridge reports the block rather than dropping it silently, and it has no parity testbench, which is the documented consequence of Support::None rather than a gap. Code export verification still covers it across all ten languages.

Notes

  • Algebraic and stateless: the output depends only on the current input, so the block cannot break an algebraic loop.
  • Nonlinear, and deliberately carries no state space – every one of the eight is nonlinear, so no A/B/C/D describes it and model reduction correctly refuses the block.
  • GELU is the tanh approximation (nn.GELU(approximate='tanh')), not the exact 0.5·x·(1 + erf(x/√2)). This is a portability decision: erf exists in none of VHDL, Verilog, SystemVerilog or IEC 61131-3, so the exact form could not be exported to four of the ten targets at all. The two differ by up to about 1e-3 of the output; if your trained network used the exact form and that matters, place the difference in your error budget rather than assuming these agree.
  • Every activation is written in an overflow-safe form – the exponent argument is never positive in ELU or Softplus – so a large input saturates rather than producing an infinity or a NaN.

Code facts#

FactValue
registered typeMachine_Learning/Neural_Networks/Activation_Function
familyMachine_Learning/Neural_Networks
solver environment classICoreBlock_0_Machine_Learning_1_Neural_Networks_2_Activation_Function
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Neural_Networks/Activation_Function/ICoreBlock_0_Machine_Learning_1_Neural_Networks_2_Activation_Function.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Neural_Networks/Activation_Function/ICoreBlock_0_Machine_Learning_1_Neural_Networks_2_Activation_Function.h
default size on canvas110 × 80 px
ports at insert1 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2outICoreDoubley

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
ActivationReLU%~%LeakyReLU%~%ELU%~%Tanh%~%Sigmoid%~%Softplus%~%SiLU…
Leaky Slope0.01
ELU Alpha1.0

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): no Simulink equivalent: its Deep Learning blocks take a trained network OBJECT, and no primitive carries an eight-way elementwise activation -- Saturation, Math Function and Trigonometric Function each cover at most one of these and none of the rest, so there is no parameter this combo could map onto

Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Activation Function — one elementwise nonlinearity, eight of them, as its own block Every activation below is written in an OVERFLOW-SAFE, mostly branchless form, and the same form in all ten backends. That is worth stating because the obvious spellings are not safe:

  • ELU as x > 0 ? x : a*(exp(x)-1) is fine with a real branch, but the vectorized

spellings (numpy's where, MATLAB's masking) evaluate BOTH sides, and exp() of a large positive x is +Inf -- which multiplied by the zero mask is NaN, not the value it replaced. Written as max(x,0) + a*(exp(min(x,0)) - 1) it is exact and can never overflow, because the exponent argument is never positive.

  • Softplus as log(1 + exp(x)) overflows to +Inf for x beyond ~709 and returns Inf where

the true answer is x. max(x,0) + log(1 + exp(-|x|)) is the standard stable identity and is what all ten emit.

  • ReLU and LeakyReLU are written with abs() in the HDL bodies -- (x+|x|)/2 and its leaky

generalization -- because a VHDL-2008 conditional expression is NOT a primary and will not parse inside a block body's expression.

The three HDL targets are SIMULATION-ONLY real arithmetic, as with the rest of this family: six of the eight activations are transcendental, and a block whose synthesizability depended on which combo value you picked would be worse than one that says so about the whole of itself.

Sample results#

Activation Function — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleActivation Function — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample0123-2-10123inputoutput
tin ICoreDouble-Out-0out ICoreDouble-Out-0
0-20
0.40.50.5
0.8-20
1.20.50.5
1.6-20
20.50.5
2.4-20
2.80.50.5
3.2-20
3.60.50.5
4-20
4.40.50.5
4.8-20
5.20.50.5

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 1
rampRamp: slope 1 from t = 00 … 5.8
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias0 … 0.9996
stepStep: 0 -> 1 at t = 1 s0 … 1

Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample

Category static · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Machine_Learning__Neural_Networks__Activation_Function.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).