---
title: "ClikaRT::nn::ConvTranspose"
sidebar_label: "ConvTranspose"
description: "N-dimensional transposed-convolution module (learnable upsampling)."
---

<!-- Generated by tools/doxygen2mdx from Doxygen XML. Do not edit. -->

<span class="api-kind api-kind--class">class</span>

**Header:** `ClikaRT/nn/conv_transpose.h`  
**Inherits:** [`ClikaRT::nn::Module`](./Module.md)

A bound, weight-packing transposed convolution, the public face of the runtime's packed conv-transpose, exposed as an `nn::Module` leaf. Unlike the stateless `ops::conv_transpose*` free functions (which re-pack the weight on every call), a `ConvTranspose` binds its weight ONCE and packs it into the backend's kernel layout; every `forward` reuses that packed weight. Build one per layer at load, reuse it every step.

The lifecycle (uniform across every weight-bearing `nn` module):

1. `make(in, out, kernel, options, ...)`, the ONE constructor: declares storage-free `weight` / `bias` slots under their canonical names.
2. `set_weights(w[, b])` (tensors in hand) or `load_state_dict(...)` (a checkpoint, by dotted name) binds the slots.
3. `forward(x)` packs ON FIRST CALL (once, thread-safe), then serves the packed form every step; `LoadOptions::pack_on_load` pays the pack at load time.

Layout: activations are channels-last `[N, D1..Dn, C]`; the weight is INPUT-channel-first `[in_channels, K1..Kn, out_channels/groups]`, the flip of `Conv`'s OHWI, matching the transposed-conv convention. The kernel size vector fixes the spatial rank. Held via `std::shared_ptr` (an `nn::Module` leaf); copy/move are pinned by the base.

N-dimensional transposed-convolution module (learnable upsampling).

Channels-last; the weight is the transpose-flip of [`Conv`](./Conv.md)'s: input-channel-first `[C_in, K.., O/groups]` (`C_in == weight[0]`, `C_out == weight[-1] * groups`), the module form of [`ops::conv_transpose1d`](../ops/conv_transpose1d.md#conv_transpose1d)`/2d/3d`. The module owns its weights: construct with `make(...)`, or declare shapes and bind a checkpoint via [`load_state_dict`](./Module.md#load_state_dict). The first forward packs the weight (or [`LoadOptions::pack_on_load`](./LoadOptions.md#pack_on_load) packs it at the end of the load); the pack is the one resident copy, and [`named_parameters()`](./Module.md#named_parameters) / [`state_dict()`](./Module.md#state_dict) read the weight back from it; `to(dtype)` restores, casts, and re-packs on the next forward.

```cpp
auto up = ClikaRT::nn::ConvTranspose::make(W, b);   // W: [C_in, K.., O/groups]
auto y  = up->forward(x);
```

## Static member functions

### make() {#make}

<div class="api-signature">

`static` `std::shared_ptr<ConvTranspose>` **`make`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::int64_t` `in_channels`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::int64_t` `out_channels`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Span`](../Span.md)`<const std::int64_t>` `kernel`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Span`](../Span.md)`<const std::int64_t>` `stride` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Span`](../Span.md)`<const std::int64_t>` `padding` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Span`](../Span.md)`<const std::int64_t>` `output_padding` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Span`](../Span.md)`<const std::int64_t>` `dilation` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::int64_t` `groups` `=` `1`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`bool` `bias` `=` `false`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::optional<`[`ops::Activation`](../ops/index.md#Activation)`>` `activation` `=` `std::nullopt`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`DataType`](../../index.md#DataType) `dtype` `=` [`DataType::Float32`](../../index.md#DataType),<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Device`](../Device.md) `device` `=` [`Device::cpu`](../Device.md#cpu)`()`<br />
)

</div>

Defaults: `stride` / `padding` / `output_padding` / `dilation` = empty (unit stride, no crop, zero output padding, unit dilation), `groups` = `1`, `bias` = `false` (no bias slot), `activation` = none, [`dtype`](../dtype/index.md) = `Float32`, [`device`](../device-namespace/index.md) = CPU, so the three counts alone make a plain unit-stride transposed convolution.

**Throws**

- `ClikaRT::Error`: as stated above.

<div class="api-declared">

Declared in `ClikaRT/nn/conv_transpose.h`, line 90

</div>

## Member functions

### \~ConvTranspose() {#ConvTranspose}

<div class="api-signature">

**`~ConvTranspose`**() `override`

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/conv_transpose.h`, line 104

</div>

### set\_weights() {#set_weights}

<div class="api-signature">

`void` **`set_weights`**([`Tensor`](../Tensor.md) `weight`, [`OptionalTensor`](../../index.md#OptionalTensor) `bias` `=` `{}`)

</div>

Bind the declared slots positionally: `weight` (input-channel-first `[in, K.., out/groups]`) and, when the module was made with one, `bias` (`[out]`). The declared placement wins (the tensors move to it); shapes must match the declaration. Re-binding after a pack drops the pack; the next [`forward`](./ConvTranspose.md#forward) re-packs from the new weights. Raises [`ClikaRT::Error`](../Error.md) on a geometry mismatch or a bias without a declared bias slot.

<div class="api-declared">

Declared in `ClikaRT/nn/conv_transpose.h`, line 114

</div>

### to\_impl(StreamOrDevice) {#to_impl}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`to_impl`**([`StreamOrDevice`](../StreamOrDevice.md) `where`) `override`

</div>

Move to a placement or cast to a dtype; same contract as [`Conv`](./Conv.md): packed moves rebuild on the target; a dtype cast restores the raw weight from the pack, casts, and re-packs on the next forward.

<div class="api-declared">

Declared in `ClikaRT/nn/conv_transpose.h`, line 121

</div>

### to\_impl(DataType) {#to_impl-2}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`to_impl`**([`DataType`](../../index.md#DataType) `dtype`) `override`

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/conv_transpose.h`, line 122

</div>

### forward() {#forward}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`forward`**([`Tensor`](../Tensor.md) `x`) `const`

</div>

Apply the bound weight: `x` `[N, D1..Dn, in]` -\> `[N, O1..On, out]` (then bias + activation if configured). The first call packs (once, thread-safe); every later call reuses the pack. Raises [`ClikaRT::Error`](../Error.md) on a shape/dtype mismatch or a still-fake slot.

<div class="api-declared">

Declared in `ClikaRT/nn/conv_transpose.h`, line 129

</div>

## Protected member functions

### initialize\_impl() {#initialize_impl}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`initialize_impl`**() `override`

</div>

The pack hook ([`Module::initialize_impl`](./Module.md#initialize_impl)): packs now (idempotent, thread-safe). Every declared slot must hold a real (loaded) tensor; a still-fake slot is a clean error. After the pack the `weight` slot reads back from the pack, the single resident copy; the bias stays bound.

<div class="api-declared">

Declared in `ClikaRT/nn/conv_transpose.h`, line 142

</div>
