tf.keras.quantizers.unpack_int4

Unpack a packed int4 back to an int8 tensor in the range [-8, 7].

This function reverses the packing performed by `pack_int4`, restoring
the original int8 tensor (values in the range [-8, 7]) from a packed int8
tensor where each element contains two int4 values (one in the lower nibble,
one in the upper nibble).

The function restores the original axis order and removes any
padding that was added during packing.

Args:
    packed: An int8 tensor containing packed int4 values along the
        specified axis. Each int8 value encodes two int4 values.
    orig_len: The original (unpadded) length of the axis that was
        packed. This is used to remove any padding that may have
        been added during packing to ensure an even number of rows.
    axis: The axis along which the tensor was packed. Defaults to 0.
    dtype: The data type of the input and unpacked tensor. Can be
        `"int8"` or `"uint8"`. Defaults to `"int8"`.

Returns:
    unpacked: An int8 tensor with the same shape as the original
        (unpacked) tensor, with values in the range [-8, 7].

Example:

```python
```
>>> import numpy as np
>>> from keras.quantizers import pack_int4, unpack_int4

```

# Example with axis=0
# Original array has shape (3, 2)
```
>>> original_array = np.array([[-3, 7], [2, -8], [1, 0]], dtype=np.int8)

```

# Pack the array along axis 0. Since the length of axis 0 (3) is
# odd, it will be padded to a length of 4. The packed array will
# have a shape of (ceil(3/2), 2) = (2, 2).
```
>>> packed, packed_shape, orig_len = pack_int4(original_array, axis=0)
>>> print("Packed array:

", packed) Packed array: [[ 45 -121] [ 1 0]]

```

# Now, unpack the array back to its original form
```
>>> unpacked = unpack_int4(packed, orig_len, axis=0)
>>> print("Unpacked array:

", unpacked) Unpacked array: [[-3 7] [ 2 -8] [ 1 0]] >>> np.allclose(original_array, unpacked) True

```

# Example with axis=1
# Original array has shape (2, 3)
```
>>> original_array = np.array([[-3, 7, 2], [-8, 1, 0]], dtype=np.int8)

```

# Pack along axis 1. Length of axis 1 (3) is padded to 4.
# The new shape is (2, ceil(3/2)) = (2, 2).
```
>>> packed, packed_shape, orig_len = pack_int4(original_array, axis=1)
>>> print("Packed array:

", packed) Packed array: [[ 125 2] [ 24 0]]

```

# Unpack the array
```
>>> unpacked = unpack_int4(packed, orig_len, axis=1)
>>> print("Unpacked array:

", unpacked) Unpacked array: [[-3 7 2] [-8 1 0]] >>> np.allclose(original_array, unpacked) True

    ```

```