Skip to content

activation

torch_to_nnef.op.aten.activation

clamp

clamp(g, node, name_to_tensor, **kwargs)

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.

clamp_max

clamp_max(g, node, name_to_tensor, **kwargs)

Map PyTorch: 'aten:clamp_max' to NNEF.

clamp_min

clamp_min(g, node, name_to_tensor, **kwargs)

Map PyTorch: 'aten:clamp_min' to NNEF.

elu

elu(g, node, name_to_tensor, **kwargs)

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

erf(g, node, name_to_tensor, null_ref, inference_target, **kwargs)

Op should be added to tract-nnef eventualy.

gelu

gelu(g, node, name_to_tensor, null_ref, inference_target, **kwargs)

Map PyTorch: 'aten:gelu' to NNEF.

glu

glu(g, node, name_to_tensor, **kwargs)

Map PyTorch: 'aten:glu' to NNEF.

hardsigmoid

hardsigmoid(**kwargs)

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.

hardswish

hardswish(inference_target, **kwargs)

Map PyTorch: 'aten:hardswish' to NNEF.

hardtanh

hardtanh(**kwargs)

Map PyTorch: 'aten:hardtanh' to NNEF.

leaky_relu

leaky_relu(**kwargs)

Map PyTorch: 'aten:leaky_relu' to NNEF.

log_softmax

log_softmax(inference_target, **kwargs)

Map PyTorch: 'aten:log_softmax' to NNEF.

mish

mish(**kwargs)

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

prelu(**kwargs)

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.

relu6

relu6(**kwargs)

Map PyTorch: 'aten:relu6' to NNEF.

selu

selu(**kwargs)

Map PyTorch: 'aten:selu' to NNEF.

silu

silu(**kwargs)

Map PyTorch: 'aten:silu' to NNEF.

softmax

softmax(**kwargs)

Map PyTorch: 'aten:softmax', 'aten:_softmax' to NNEF.

softplus

softplus(**kwargs)

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)

threshold

threshold(**kwargs)

Map PyTorch: 'aten:threshold' to NNEF.

PyTorch ref: y = x if x > threshold else value.