> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/sdgm/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/sdgm/_mcp/server.

# Encoder Selection

> Choose column encoders by semantic type and customize their model plan settings

Start with Kumo's inferred encoders. Override a column only when it needs a specific transformation or feature representation.
First check each column's semantic type (`stype`): an integer category needs `"categorical"`, not `"numerical"`.
Kumo selects encoders from semantic types and column statistics, so an explicit constructor can replace a useful inferred configuration.
An override changes the encoding, not the semantic type or the graph's relationships.
Set column types when preparing [Tables](/kumo-engine/1.0.0/user-code-guide/set-up-a-graph/tables#inspect-and-adjust-column-types), then follow [Graphs](/kumo-engine/1.0.0/user-code-guide/set-up-a-graph/graphs#create-a-graph) to connect the tables and create a snapshot.
Apply optional encoder overrides through `plan.column_processing` before training.
The examples below assume you have created a `plan` as shown in the [Model Plan Guide](/kumo-engine/1.0.0/user-code-guide/train-a-model/model-plan-guide#create-and-use-a-plan).

## Supported Encoders

Import encoders from `kumoapi.encoder` and `Stype` from `kumoapi.typing`.

| Semantic type       | Inferred choices                                                    | When to consider an override                                                                                                                                     |
| ------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `numerical`         | `Numerical`, `MaxLogNumerical`, `MinLogNumerical`                   | Keep the statistics-based scaling or tail transform unless you need a specific scale or missing-value meaning.                                                   |
| `categorical`, `ID` | `Index`, `Hash`, or `Null`                                          | Use `Index` to retain individual categories or `Hash` to bound representations, accepting collisions. Keep exclusion for identifiers that only identify rows.    |
| `multicategorical`  | `MultiCategorical` or `Null`                                        | Set `min_occ` when rare categories should be treated as missing. Retain the inferred choice unless you need different filtering.                                 |
| `text`              | `TextEmbedding` or `Null`                                           | Override exclusion when meaningful text needs encoding, or select vectors with a suitable vocabulary. Keep exclusion when the values provide little usable text. |
| `timestamp`         | `Datetime`                                                          | Change calendar components when only particular time features are relevant.                                                                                      |
| `sequence`          | `NumericalList` for fixed-length nonempty vectors, otherwise `Null` | Change scaling when the vector's magnitude or direction has a specific meaning. Check vector lengths before overriding exclusion.                                |
| Any type            | `Null` for an effectively empty column                              | Use `Null` to deliberately exclude a feature. An override cannot supply missing information.                                                                     |

`ID` is uppercase. Compatible encoders for each type are listed above; `Null` is also available for every type.
Constructor defaults in the tables below describe explicit instances, not the configuration Kumo will infer.

`Null()` excludes a feature; it does not remove a primary key or foreign key relationship from the graph.
Image encoding is not part of this guide's supported input types.

## Numerical Encoders

| Encoder           | Argument      | Default  | Supported values and meaning                                                                                                                             |
| ----------------- | ------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Numerical`       | `scaler`      | `None`   | `None` for no scaling; `"standard"` for mean/std normalization; `"minmax"` for minimum/range scaling; `"robust"` for median/interquartile-range scaling. |
| `Numerical`       | `na_strategy` | `"mean"` | `"mean"`, `"zero"`, `"separate"`.                                                                                                                        |
| `MaxLogNumerical` | `na_strategy` | `"mean"` | `"mean"`, `"zero"`, `"separate"`. Applies `log(x - min + 1)` using the column minimum.                                                                   |
| `MinLogNumerical` | `na_strategy` | `"mean"` | `"mean"`, `"zero"`, `"separate"`. Applies `log(max + 1 - x)` using the column maximum.                                                                   |

The logarithmic encoders compress a long tail on the corresponding side of the distribution.
They do not accept a `scaler` argument.
The legacy `"raise"` missing-value setting is retained for compatibility and should not be used in new plans.

## Categorical and ID Encoders

| Encoder | Argument         | Default      | Supported values and meaning                                              |
| ------- | ---------------- | ------------ | ------------------------------------------------------------------------- |
| `Index` | `min_occ`        | `1`          | Positive integer. Values occurring fewer times are treated as missing.    |
| `Index` | `na_strategy`    | `"separate"` | `"zero"`, `"separate"`, `"most_frequent"`.                                |
| `Hash`  | `num_components` | Required     | Positive integer. Number of hash buckets, not output embedding dimension. |
| `Hash`  | `na_strategy`    | `"separate"` | `"separate"`, `"most_frequent"`.                                          |

`Index` assigns retained categories their own learned representations.
`Hash` bounds the number of distinct representations, so different values can share a bucket.
The model architecture's channel count controls the representation size.
`Hash` does not accept `min_occ` or `na_strategy="zero"`.

For a categorical `products.brand` column, this example caps hashing at 4096 buckets; that count is illustrative, not an inferred or optimal value:

```python
from kumoapi.encoder import Hash

plan.column_processing.encoder_overrides = {
    **(plan.column_processing.encoder_overrides or {}),
    "products.brand": Hash(num_components=4096),
}
```

## Multicategorical Encoder

| Encoder            | Argument      | Default  | Supported values and meaning                                 |
| ------------------ | ------------- | -------- | ------------------------------------------------------------ |
| `MultiCategorical` | `min_occ`     | `1`      | Positive integer. Minimum count for retaining each category. |
| `MultiCategorical` | `na_strategy` | `"zero"` | `"zero"`, `"separate"`, `"most_frequent"`.                   |

Kumo processes each category in the value and combines the results.
The separator is inferred from column statistics; `MultiCategorical` does not accept a `sep` argument.

## Sequence and Embedding Encoder

Use `NumericalList` for `stype="sequence"`, including vectors computed outside Kumo.

| Argument      | Default  | Supported values and meaning                                                                        |
| ------------- | -------- | --------------------------------------------------------------------------------------------------- |
| `scaler`      | `None`   | `None` for no scaling, `"standard"` for standardization, or `"cosine"` to normalize by vector norm. |
| `na_strategy` | `"zero"` | Only `"zero"`.                                                                                      |

These scaler choices differ from `Numerical`: `"minmax"` and `"robust"` are not sequence scaler options.

## Timestamp Encoder

`Datetime` extracts calendar features from `stype="timestamp"` columns.

| Argument               | Default  | Supported values and meaning                                                                         |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `include_minute`       | `True`   | Boolean. Include minute-of-hour features.                                                            |
| `include_hour`         | `True`   | Boolean. Include hour-of-day features.                                                               |
| `include_day_of_week`  | `True`   | Boolean. Include day-of-week features.                                                               |
| `include_day_of_month` | `True`   | Boolean. Include day-of-month features.                                                              |
| `include_day_of_year`  | `True`   | Boolean. Include day-of-year features.                                                               |
| `include_year`         | `True`   | Boolean. Include year features.                                                                      |
| `num_year_periods`     | `None`   | Positive integer or `None`. Number of year periods; when `None`, infer from the column's year range. |
| `na_strategy`          | `"zero"` | Only `"zero"`.                                                                                       |

## Text Encoder

Use `TextEmbedding` for columns with `stype="text"`, such as product descriptions and reviews.
It looks up pretrained vectors for recognized words in each cell and averages them into a feature vector.
Unknown words are ignored; missing cells and cells with no recognized words produce a zero vector.

| Argument      | Default          | Supported values and meaning                                                             |
| ------------- | ---------------- | ---------------------------------------------------------------------------------------- |
| `model`       | `"glove.6B-50d"` | Name of an installed model or a model registered in the trainer's `EmbeddingModelStore`. |
| `na_strategy` | `"zero"`         | Only `"zero"`.                                                                           |

### Text Embedding Models

The default model is [GloVe](https://nlp.stanford.edu/projects/glove/) 6B with 50 dimensions.
Add its vector package to the Python environment where Kumo Engine runs:

```bash
pip install "kumo-engine[text]"
```

Use the package index configured during [environment setup](/kumo-engine/1.0.0/get-started-with-kumo-engine/prerequisites#python-and-package-access).
That index must provide compatible builds of both Kumo Engine and its optional `kumo-glove-6b-50d` dependency.
Kumo Engine does not download word vectors during training.

Automatic encoder selection can choose `Null()` to exclude text columns whose values are too short or contain too few recognized words.
To encode `products.description` explicitly, merge a text override into your plan before constructing the trainer:

```python
from kumo.engine import Trainer
from kumoapi.encoder import TextEmbedding

plan.column_processing.encoder_overrides = {
    **(plan.column_processing.encoder_overrides or {}),
    "products.description": TextEmbedding(),
}
trainer = Trainer(plan)
```

Replace `products.description` with a text column in your graph.
If training reports a missing embedding model, install its vector package or register it as shown below.
To exclude the column instead, use `Null()` in its encoder override.
Only columns that use `TextEmbedding` require word vectors.

### Use Another GloVe Model

Use another vector vocabulary when it better matches your text; retain the default when you have no specific alternative to evaluate.

<details>
  <summary>
    Download and register another GloVe model
  </summary>

  Download one of the supported original GloVe release archives from the [GloVe project](https://nlp.stanford.edu/projects/glove/).
  Pass the unchanged `.zip` file to `GloVeVectors`; it also accepts a directory of previously converted files.

  | Archive                 | Dimensions                                    |
  | ----------------------- | --------------------------------------------- |
  | `glove.6B.zip`          | 50, 100, 200, 300. Pass `dim=` to select one. |
  | `glove.42B.300d.zip`    | 300.                                          |
  | `glove.840B.300d.zip`   | 300.                                          |
  | `glove.twitter.27B.zip` | 25, 50, 100, 200. Pass `dim=` to select one.  |

  For example, download `glove.42B.300d.zip`, replace the path below with its local path, and register it as `"descriptions"`:

  ```python
  from kumo.engine import EmbeddingModelStore, GloVeVectors, Trainer
  from kumoapi.encoder import TextEmbedding

  store = EmbeddingModelStore()
  store.add("descriptions", GloVeVectors("/path/to/glove.42B.300d.zip"))
  plan.column_processing.encoder_overrides = {
      **(plan.column_processing.encoder_overrides or {}),
      "products.description": TextEmbedding(model="descriptions"),
  }
  trainer = Trainer(plan, embedding_models=store)
  ```

  The registration name is your choice and must match the encoder's `model` value.
  Installed models, including the default from the `text` extra, are also available in the store.
  An archive is converted on first use into `~/.cache/kumo/embeddings`.
  Pass a writable `cache_dir=` to `GloVeVectors` to use another directory, and keep the model files accessible to training and prediction workers.
</details>

### Reload a Trained Text Model

A saved model still needs the word vectors used during training.
For the default model, keep the text package installed in the prediction environment.
For a registered model, recreate the store with the same vectors and pass it when loading:

```python
trainer = Trainer.load(bundle_dir, embedding_models=store)
```

Replace `bundle_dir` with your saved model bundle directory.
Kumo matches the vectors by model identity, so the registration name can change but the vectors and tokenization must match.

### Custom Word Vectors

Use custom vectors when you already have a vocabulary and embeddings suited to your text. Keep an installed model when you do not need a custom vocabulary or tokenizer.

<details>
  <summary>
    Implement a custom token embedding model
  </summary>

  To register your own word vectors, implement the `TokenEmbeddingModel` interface in an importable Python module.
  The following two vectors only illustrate the protocol; they are not a useful pretrained language model.
  Save this as `example_vectors.py` in your application package, available to every training and prediction worker:

  ```python
  """Tiny illustrative vectors. This is not a pretrained language model."""
  import hashlib
  import json

  import numpy as np
  import pandas as pd


  class ExampleVectors:
      family = "example-words/1"
      dim = 2
      label = "Two illustrative word vectors"
      tokenizer_version = "lower-whitespace-drop-unknown/1"

      def vocabulary(self):
          return pd.Index(["red", "shoe"])

      def vectors(self):
          return np.array([[1.0, 0.0], [0.0, 1.0]], dtype=np.float32)

      def tokenize(self, texts):
          lookup = {word: row for row, word in enumerate(self.vocabulary())}
          rowptr, rows = [0], []
          for text in texts:
              if isinstance(text, str):
                  rows.extend(lookup[word] for word in text.lower().split()
                              if word in lookup)
              rowptr.append(len(rows))
          return np.array(rowptr, dtype=np.int64), np.array(rows, dtype=np.int64)

      def fingerprint(self):
          metadata = json.dumps([self.tokenizer_version,
                                 self.vocabulary().tolist()]).encode("utf-8")
          return hashlib.sha256(metadata + self.vectors().astype("<f4").tobytes()).hexdigest()
  ```

  The vocabulary order matches the vector rows. `vectors()` returns a `float32` matrix with shape `(vocabulary_size, dim)`.
  For each input cell, `tokenize()` returns its vocabulary row indices between consecutive `rowptr` offsets.
  Unknown words and null cells contribute no tokens.
  For `pd.Series(["Red shoe", None, "sock"])`, this example returns `rowptr=[0, 2, 2, 2]` and `rows=[0, 1]`.

  Register the importable model and merge the text override into your existing plan:

  ```python
  from kumo.engine import EmbeddingModelStore, Trainer
  from kumoapi.encoder import TextEmbedding
  from example_vectors import ExampleVectors

  store = EmbeddingModelStore()
  store.add("example", ExampleVectors())
  plan.column_processing.encoder_overrides = {
      **(plan.column_processing.encoder_overrides or {}),
      "products.description": TextEmbedding(model="example"),
  }
  trainer = Trainer(plan, embedding_models=store)
  ```

  Use the `products.description` column from the preceding example or replace it with a text column in your graph.
  Keep the module importable after restart; defining the class only in a notebook does not make it available to worker processes.
  For large models, load vectors lazily from accessible files instead of storing them all in the pickled object.
  The model identity includes its `family`, dimension, and fingerprint.
  Update the fingerprint whenever vectors, vocabulary order, or tokenization behavior changes.
  When loading a saved model, supply the same model identity through `Trainer.load(bundle_dir, embedding_models=store)`.
  Changing the registration name alone does not change that identity.
</details>

## Encoder Overrides

Set `encoder_overrides` to a dictionary of case-sensitive `"table.column"` names and encoder instances.
Use the table names in your graph, not a warehouse's fully qualified table path.
Leave it as `None` to retain inferred encoders.

For a graph containing `products.price`, `products.category`, and `products.description`, with semantic types numerical, categorical, and text respectively:

```python
from kumoapi.encoder import Index, Null, Numerical

plan.column_processing.encoder_overrides = {
    "products.price": Numerical(scaler="minmax", na_strategy="zero"),
    "products.category": Index(min_occ=2),
    "products.description": Null(),
}
```

This scales prices, imputes missing prices with zero, groups rare categories as missing, and excludes descriptions from input features.
Assigning this dictionary replaces any earlier encoder overrides.
To retain earlier overrides, merge them into the new dictionary.

### Transform a Regression Target

Use the special key `"train_table.TARGET"` to override the generated target encoder.
This controls the value the model learns to predict, rather than an input feature such as `products.price`.
For a scalar numerical regression target with a long upper tail:

```python
from kumoapi.encoder import MaxLogNumerical

plan.column_processing.encoder_overrides = {
    **(plan.column_processing.encoder_overrides or {}),
    "train_table.TARGET": MaxLogNumerical(),
}
```

Pass this plan to `Trainer` before fitting your regression training table.
The transform uses `log(x - min + 1)`, where `min` comes from the target statistics.
Values below that fitted minimum are clamped to the same transformed value as the minimum, so decoding cannot recover those lower values.
Kumo reverses the target transform when producing regression predictions, so `TARGET_PRED` is in the original target units. Do not exponentiate it again.
Keep the saved model's target encoder when reloading. This example does not apply to categorical, list, or forecasting targets, and a logarithmic transform does not guarantee better predictions.

## Missing Values

Set `plan.column_processing.na_strategy` to choose missing-value defaults by semantic type.
Kumo applies each default to compatible inferred feature encoders of that type.
Leave a type out of the dictionary to keep its inferred strategy.
Use `encoder_overrides` for column-specific exceptions.

Before constructing `Trainer(plan)`, this example sets numerical features to zero imputation while using mean imputation for `products.price`:

```python
from kumoapi.encoder import Numerical
from kumoapi.typing import Stype

plan.column_processing.na_strategy = {Stype.numerical: "zero"}
plan.column_processing.encoder_overrides = {
    **(plan.column_processing.encoder_overrides or {}),
    "products.price": Numerical(na_strategy="mean"),
}
```

Replace `products.price` with a numerical column in your graph.
The dictionary merge preserves other encoder overrides; the `na_strategy` assignment replaces any earlier type-wide defaults.
Choose strategies supported by the semantic type and encoder:

| Strategy          | Meaning                                                                                         |
| ----------------- | ----------------------------------------------------------------------------------------------- |
| `"zero"`          | Fill missing numerical values with zero or use a zero feature vector, depending on the encoder. |
| `"mean"`          | Impute missing numerical values with the column mean.                                           |
| `"separate"`      | Preserve missingness as a separate learnable signal.                                            |
| `"most_frequent"` | Use the most frequent category.                                                                 |

### Precedence

A per-column override replaces the inferred encoder, including its missing-value configuration.
The type-wide default does not apply to a column with an explicit override.
If you omit `na_strategy` from an explicit `Numerical()` instance, it uses `"mean"` even when the type-wide numerical default is `"zero"`.

A [warm start](/kumo-engine/1.0.0/user-code-guide/train-a-model/training#start-a-new-run-from-a-trained-model) reuses the source checkpoint's fitted encoders ahead of both settings.
Changing the destination plan's missing-value defaults or overrides does not replace those fitted encoders.
Use a fresh training run to fit different encoders.

### Unsupported Strategies

An invalid type/strategy combination, such as `"most_frequent"` for `Stype.numerical`, fails model plan validation.
Assignment to the public plan alone does not establish that the combination is valid.
Use the supported values in the encoder tables above.

A strategy can be valid for a semantic type but unsupported by a particular inferred encoder.
For example, `Stype.categorical: "zero"` works with `Index`, but an inferred `Hash` encoder keeps its default strategy and emits a warning naming the column and allowed strategies.
Choose one of those strategies or use a compatible explicit encoder override.
Encoders without a missing-value option, such as `Null`, are left unchanged without this warning.

## Check Your Configuration

Inspect `plan.as_json()` before passing the plan to `Trainer`.
Encoder constructors reject unsupported arguments and invalid option values.
During plan validation, Kumo checks that override columns exist and that each encoder supports the column's semantic type.
If it reports an invalid column name, use the case-sensitive table and column names in the graph.
If it reports an incompatible encoder, correct the semantic type or select a compatible encoder from the table above.
For a missing text model, install the text extra, register the required model, or exclude the affected text column with `Null()`.

When your graph snapshot and plan are ready, follow [Training](/kumo-engine/1.0.0/user-code-guide/train-a-model/training#train-a-model) to fit the model. Return to the [Model Plan Guide](/kumo-engine/1.0.0/user-code-guide/train-a-model/model-plan-guide) for architecture and optimization settings.