a preprocessing layer which encodes integer features this layer provides options for condensing data into a categorical encoding when the total number of tokens are known in advance it accepts integer values as inputs and it outputs a dense or sparse representation of those inputs for integer inputs where the total number of tokens is not known use keras layers integerlookup instead note this layer is safe to use inside a tf data pipeline independently of which backend you re using examples onehot encoding data layer keras layers categoryencoding numtokens4 outputmodeonehot layer3 2 0 1 array0 0 0 1 0 0 1 0 1 0 0 0 0 1 0 0 multihot encoding data layer keras layers categoryencoding numtokens4 outputmodemultihot layer0 1 0 0 1 2 3 1 array1 1 0 0 1 0 0 0 0 1 1 0 0 1 0 1 using weighted inputs in count mode layer keras layers categoryencoding numtokens4 outputmodecount countweights np array 1 2 1 1 2 3 4 2 layer0 1 0 0 1 2 3 1 countweightscountweights array0 1 0 2 0 0 0 2 0 0 0 0 0 2 0 3 0 0 0 2 0 0 4 args numtokens the total number of tokens the layer should support all inputs to the layer must integers in the range 0 value numtokens or an error will be thrown outputmode specification for the output of the layer values can be onehot multihot or count configuring the layer as follows onehot encodes each individual element in the input into an array of numtokens size containing a 1 at the element index if the last dimension is size 1 will encode on that dimension if the last dimension is not size 1 will append a new dimension for the encoded output multihot encodes each sample in the input into a single array of numtokens size containing a 1 for each vocabulary term present in the sample treats the last dimension as the sample dimension if input shape is samplelength output shape will be numtokens count like multihot but the int array contains a count of the number of times the token at that index appeared in the sample for all output modes currently only output up to rank 2 is supported defaults to multihot call arguments inputs a 1d or 2d tensor of integer inputs countweights a tensor in the same shape as inputs indicating the weight for each sample value when summing up in count mode not used in multihot or onehot modes support deprecated names for outputmodes outputmode must be one of count onehot multihot a preprocessing layer which encodes integer features this layer provides options for condensing data into a categorical encoding when the total number of tokens are known in advance it accepts integer values as inputs and it outputs a dense or sparse representation of those inputs for integer inputs where the total number of tokens is not known use keras layers integerlookup instead note this layer is safe to use inside a tf data pipeline independently of which backend you re using examples one hot encoding data layer keras layers categoryencoding num_tokens 4 output_mode one_hot layer 3 2 0 1 array 0 0 0 1 0 0 1 0 1 0 0 0 0 1 0 0 multi hot encoding data layer keras layers categoryencoding num_tokens 4 output_mode multi_hot layer 0 1 0 0 1 2 3 1 array 1 1 0 0 1 0 0 0 0 1 1 0 0 1 0 1 using weighted inputs in count mode layer keras layers categoryencoding num_tokens 4 output_mode count count_weights np array 1 2 1 1 2 3 4 2 layer 0 1 0 0 1 2 3 1 count_weights count_weights array 0 1 0 2 0 0 0 2 0 0 0 0 0 2 0 3 0 0 0 2 0 0 4 args num_tokens the total number of tokens the layer should support all inputs to the layer must integers in the range 0 value num_tokens or an error will be thrown output_mode specification for the output of the layer values can be one_hot multi_hot or count configuring the layer as follows one_hot encodes each individual element in the input into an array of num_tokens size containing a 1 at the element index if the last dimension is size 1 will encode on that dimension if the last dimension is not size 1 will append a new dimension for the encoded output multi_hot encodes each sample in the input into a single array of num_tokens size containing a 1 for each vocabulary term present in the sample treats the last dimension as the sample dimension if input shape is sample_length output shape will be num_tokens count like multi_hot but the int array contains a count of the number of times the token at that index appeared in the sample for all output modes currently only output up to rank 2 is supported defaults to multi_hot call arguments inputs a 1d or 2d tensor of integer inputs count_weights a tensor in the same shape as inputs indicating the weight for each sample value when summing up in count mode not used in multi_hot or one_hot modes support deprecated names for output_modes output_mode must be one of count one_hot multi_hot
from keras import backend
from keras.api_export import keras_export
from keras.layers.preprocessing.tf_data_layer import TFDataLayer
from keras.utils import backend_utils


@keras_export("keras.layers.CategoryEncoding")
class CategoryEncoding(TFDataLayer):
    

    def __init__(self, num_tokens=None, output_mode="multi_hot", **kwargs):
        super().__init__(**kwargs)

        
        if output_mode == "binary":
            output_mode = "multi_hot"

        
        if output_mode not in ("count", "one_hot", "multi_hot"):
            raise ValueError(f"Unknown arg for output_mode: {output_mode}")

        if num_tokens is None:
            raise ValueError(
                "num_tokens must be set to use this layer. If the "
                "number of tokens is not known beforehand, use the "
                "IntegerLookup layer instead."
            )
        if num_tokens < 1:
            raise ValueError(
                f"`num_tokens` must be >= 1. Received: num_tokens={num_tokens}."
            )
        self.num_tokens = num_tokens
        self.output_mode = output_mode
        self._allow_non_tensor_positional_args = True
        self._convert_input_args = False

    def _count(self, inputs, axis=-1):
        reduction_axis = 1 if len(inputs.shape) > 1 else 0
        outputs = self.backend.numpy.sum(
            self.backend.nn.one_hot(
                inputs, self.num_tokens, axis=axis, dtype=self.dtype
            ),
            axis=reduction_axis,
        )
        return outputs

    def _encode(self, inputs):
        if self.output_mode == "multi_hot":
            outputs = self.backend.nn.multi_hot(
                inputs, self.num_tokens, dtype=self.dtype
            )
        elif self.output_mode == "one_hot":
            outputs = self.backend.nn.one_hot(
                inputs, self.num_tokens, dtype=self.dtype
            )
        elif self.output_mode == "count":
            outputs = self._count(inputs)

        return outputs

    def compute_output_shape(self, input_shape):
        if self.output_mode == "one_hot":
            if input_shape[-1] != 1:
                return tuple(input_shape + (self.num_tokens,))
            else:
                return tuple(input_shape[:-1] + (self.num_tokens,))
        return tuple(input_shape[:-1] + (self.num_tokens,))

    def get_config(self):
        config = {
            "num_tokens": self.num_tokens,
            "output_mode": self.output_mode,
        }
        base_config = super().get_config()
        return {**base_config, **config}

    def call(self, inputs):
        outputs = self._encode(inputs)

        if (
            self.backend._backend != "tensorflow"
            and not backend_utils.in_tf_graph()
        ):
            outputs = backend.convert_to_tensor(outputs)
        return outputs