# rexnetv1

Python API: `luxonis_train.nodes.backbones.rexnetv1`

The ReXNet-lite backbone and the linear bottleneck it repeats.

## Classes

### LinearBottleneck

Inverted residual block of ReXNet with a linear projection.

When `t` is not `1`, the block first expands the channels with a `1x1` convolution. It then applies a depthwise convolution and
projects to `channels` with a `1x1` convolution. The expansion and the depthwise convolution end with `ReLU6`. The projection has
no activation. Each convolution has a batch norm.

When `stride` is `1` and `in_channels <= channels`, the block adds its input to the first `in_channels` output channels. The other
output channels get no shortcut.

> **Example**
> ```pycon
>>> import torch
>>> block = LinearBottleneck(8, 12, t=6)
>>> block(torch.zeros(1, 8, 4, 4)).shape
torch.Size([1, 12, 4, 4])
>>> strided = LinearBottleneck(8, 12, t=6, stride=2)
>>> strided(torch.zeros(1, 8, 4, 4)).shape
torch.Size([1, 12, 2, 2])
```

#### Methods

##### init

```python
def __init__(in_channels: int, channels: int, t: int, kernel_size: int = 3, stride: int = 1):
```

Build the expansion, the depthwise, and the projection layers.

Parameters

 * `in_channels` (`int`): Number of input channels.
 * `channels` (`int`): Number of output channels.
 * `t` (`int`): Expansion factor. The depthwise convolution has `in_channels * t` channels. For `1`, the block has no expansion convolution.
 * `kernel_size` (`int`): Size of the depthwise kernel. The padding is `kernel_size // 2`.
 * `stride` (`int`): Stride of the depthwise convolution.

##### forward

```python
def forward(x: Tensor) -> Tensor:
```

Apply the layers and add the partial shortcut.

Parameters

 * `x` (`Tensor`): Input of shape `[B, in_channels, H, W]`.

Returns

 * `Tensor`: Output of shape `[B, channels, H', W']`. The stride of the depthwise convolution sets `H'` and `W'`. With the shortcut, the first `in_channels` channels hold the sum of the input and the projection.

#### Attributes

##### out

The expansion, depthwise, and projection layers.

### ReXNetV1_lite

Lite ReXNetV1 backbone for lightweight convolutional features.

ReXNet (Rank Expansion Networks) makes the channel counts of its blocks grow linearly with the depth. The lite version has no squeeze-and-excitation blocks, and `ReLU6` is its only activation. The node is a stack of 18 modules: a `3x3` stem with stride 2, 16 [LinearBottleneck](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/backbones/rexnetv1.md) blocks in six stages, and a `1x1` convolution. With the default parameters, this convolution has 1280 channels.

 * `Inputs:`: * `inputs` (`Tensor`): [B, C, H, W]
 * `Outputs:`: * `features` (`list[Tensor]`): one per `out_indices`; by default strides 2, 8, 16, 32 with 16, 56, 120, 1280 channels

> **References**
> * Source: Adapted from [clovaai/rexnet](https://github.com/clovaai/rexnet) (MIT). Paper: [Rethinking Channel Dimensions for Efficient Model Design](https://arxiv.org/abs/2007.00992).
 * License: [MIT](https://github.com/clovaai/rexnet/blob/master/LICENSE). Copyright 2021-present NAVER Corp.

> **Notes**
> The stem always expects 3 input channels. It does not read `in_channels`. `out_indices` selects outputs by module index: `0` is the stem, `1` to `16` are the bottlenecks, and `17` is the final `1x1` convolution.

 * `Variants:`: None. Configure the node through `params`.

> **Example**
> A node entry in the `model.nodes` section of a config:

```yaml
- name: ReXNetV1_lite
```

 * `Compatible with:`: * Attach index: `-1`, the last output of the input node

#### Methods

##### init

```python
def __init__(fix_head_stem: bool = False, divisible_value: int = 8, input_ch: int = 16, final_ch: int = 164, multiplier: float =
1.0, kernel_sizes: int | list[int] = 3, out_indices: list[int] | None = None, **kwargs):
```

Build the stem, the 16 bottlenecks, and the final convolution.

The six stages have 1, 2, 2, 3, 3, and 5 bottlenecks. Their first bottlenecks have the strides 1, 2, 2, 2, 1, and 2 in stage order. The other bottlenecks have the stride 1. The bottlenecks of the first stage have no expansion. The other bottlenecks expand the channels by a factor of 6.

The output channels of the bottlenecks grow in 15 equal steps from `input_ch` to `input_ch + final_ch`. `multiplier` scales these counts. A `multiplier` below `1` scales only the growth, not `input_ch`. The stem has 32 channels. A `multiplier` above `1` gives the stem `32 * multiplier` channels and the final convolution `int(1280 * multiplier)` channels, unless `fix_head_stem` is `True`. The constructor rounds the channel counts of the stem and the bottlenecks up to a multiple of `divisible_value`.

Parameters

 * `fix_head_stem` (`bool`): Whether to keep the stem at 32 channels and the final convolution at 1280 channels. It changes the network only for a `multiplier` above `1`.
 * `divisible_value` (`int`): The number that the channel counts of the stem and the bottlenecks are multiples of.
 * `input_ch` (`int`): The output channels of the first bottleneck, before `multiplier`.
 * `final_ch` (`int`): The channel growth from the first to the last bottleneck, before `multiplier`. It is not the channel count of the last bottleneck.
 * `multiplier` (`float`): The scale of the channel counts.
 * `kernel_sizes` (`int | list[int]`): The size of the depthwise kernels. A list gives one size for each of the six stages.
 * `out_indices` (`list[int] | None`): The indices of the modules whose outputs [forward](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/backbones/rexnetv1.md) returns. `0` is the stem, `1` to `16` are the bottlenecks, and `17` is the final convolution. `None` or an empty list selects `[1, 4, 10, 17]`.
 * `**kwargs`: Keyword arguments forwarded to [BaseNode](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/base_node.md).

Raises

 * `ValueError`: When `kernel_sizes` is a list that does not have exactly six values.

##### forward

```python
def forward(inputs: Tensor) -> list[Tensor]:
```

Run all 18 modules and collect the selected outputs.

> **Example**
> ```pycon
>>> import torch
>>> from luxonis_train.nodes import ReXNetV1_lite
>>> node = ReXNetV1_lite()
>>> [tuple(t.shape) for t in node(torch.zeros(1, 3, 64, 64))]
[(1, 16, 32, 32), (1, 56, 8, 8), (1, 120, 4, 4), (1, 1280, 2, 2)]
```

Parameters

 * `inputs` (`Tensor`): Image batch of shape `[B, 3, H, W]`.

Returns

 * `list[Tensor]`: The outputs of the modules whose index is in `out_indices`, in module order. An index outside `0` to `17`
   selects nothing. The default indices give the strides 2, 8, 16, and 32, with 16, 56, 120, and 1280 channels.

#### Attributes

##### features
