Transformer

The transformer is the component that applies a per-feature value-space transform before normalization, compressing the dynamic range of features that span many orders of magnitude (for example mapping a charge into log space). Like the normalizer it is a pure, invertible value map: it changes values without changing tensor shape, and it normalizes targets only when the task requests it.

Usage

The transformer occupies the components.transformer slot.

components:
  transformer:
    name: standard
    kwargs:
      transforms:
        energy: { space: log, base: 10 }

How it Works

The transformer assigns each feature column a transform space and applies the corresponding mapping, vectorized across columns. Columns with no explicit configuration are left in linear space (untouched). The transform composes with the normalizer: the transformer reshapes the value distribution, then the normalizer scales it.

Variants

  • Standard: per-column selection of a linear, log, or inverse-hyperbolic-sine space.

Registering a new transformer

A transformer is a subclass of Transformer that declares a name and version and implements two methods:

transform(self, t, /, role, *, inverse) -> Tensor

Map the values of t for the given column role, returning a tensor of the same shape; undo the mapping when inverse is True.

_build_spec_list(self, role) -> list[TransformerSpec]

Describe, per column, which space applies. The base caches this and wraps transform with shape and finiteness checks.

from typing import Any, ClassVar

from torch import Tensor

from icegraph.common.data import ColumnarRole
from icegraph.common.tensors import SegmentedTensor
from icegraph.engine.components.transformer import Transformer, TransformerFactory
from icegraph.engine.components.transformer.types import TransformerSpec

from .config import MyTransformerConfig

class MyTransformer(Transformer[MyTransformerConfig]):
    name: ClassVar[str] = "my-transformer"
    version: ClassVar[int] = 1

    @classmethod
    def validate_config(cls, config: dict[str, Any]) -> MyTransformerConfig:
        return MyTransformerConfig(**config)

    def build(self) -> None:
        ...

    def transform(self, t: SegmentedTensor, /, role: ColumnarRole, *, inverse: bool) -> Tensor:
        ...  # return the mapped values, same shape as t.data

    def _build_spec_list(self, role: ColumnarRole) -> list[TransformerSpec]:
        ...

TransformerFactory.register(MyTransformer)