activation
torch_to_nnef.op.aten.activation
clamp
Map PyTorch: 'aten:clamp' to NNEF.
PyTorch's clamp(input, min=None, max=None) skips a bound when it
is None (the unset sentinel): NOT when it is 0.0. The earlier
if X.data: truthy check evaluated to False for the literal 0.0,
silently dropping min=0 / max=0 clamps and producing wrong
output for any input crossing the unset bound. Same root pattern as
the flatten or 0/-1 bug. Use explicit is None checks.
elu
Map PyTorch: 'aten:elu' to NNEF.
PyTorch's aten::elu(self, alpha=1, scale=1, input_scale=1) takes
three scalar parameters. NNEF's standard elu fragment is
hard-coded to alpha=1, so we emit a custom elu fragment (see
torch_to_nnef/op/fragment/elu.nnef) that exposes alpha as an
attribute. scale and input_scale are not part of the NNEF op
surface; the emitter raises on non-default values for those (rare in
practice: the common form is F.elu(x, alpha=k)).
erf
Op should be added to tract-nnef eventualy.
gelu
Map PyTorch: 'aten:gelu' to NNEF.
hardsigmoid
Map PyTorch: 'aten:hardsigmoid' to NNEF.
PyTorch ref: y = clamp((x + 3) / 6, 0, 1). Tract has no native
op for this, so we emit a custom fragment built from min/max
and arithmetic primitives.
mish
Map PyTorch: 'aten:mish' to NNEF.
PyTorch ref: y = x * tanh(softplus(x)). Tract has no native
op so we emit a fragment built from softplus/tanh/mul.
prelu
Map PyTorch: 'aten:prelu' to NNEF.
PyTorch's PReLU(num_parameters=C) stores the slope as a 1-D tensor
of shape (C,) and applies it along the channel axis (dim=1) of an
input shaped (B, C, *spatial). NNEF broadcasts left-aligned
(prepends 1s), so a raw (C,) weight would broadcast to the
trailing axis instead of the channel axis: i.e. wrong.
Pre-unsqueeze the weight to (C, 1, 1, ...) so left-alignment
yields (1, C, 1, 1, ...) and broadcast lands on the channel axis.
Same pattern as group_norm/batch_norm scale/offset. The single-slope
case (num_parameters=1 -> shape (1,)) is left untouched
since broadcasting is then trivially correct.
softplus
Map PyTorch: 'aten:softplus' to NNEF.
Note: numerical stability applied in PyTorch is not done in NNEF vanilla implementation, nor case beta != 1.
PyTorch ref
y = (1/beta) * log(exp(beta * x) + 1) if ((beta * x) < thresh) else x
NNEF ref
y = log(exp(x) + 1.0)