Edifice.Convolutional.DenseNet (Edifice v0.2.0)

Copy Markdown View Source

DenseNet (Densely Connected Convolutional Network) implementation.

DenseNet connects each layer to every other layer in a feed-forward fashion. Within a dense block, each layer receives the feature maps of all preceding layers as input (via concatenation), encouraging feature reuse and reducing parameter count compared to traditional CNNs.

Architecture

Input [batch, H, W, C]
      |
+-----v----------+
| Stem            |  7x7 conv stride 2, BN, ReLU, 3x3 max pool
+--+--------------+
   |
+--v--------------+
| Dense Block 1    |  Each layer concatenates all previous feature maps
+--+--------------+
   |
+--v--------------+
| Transition 1     |  1x1 conv (compress) + 2x2 avg pool (downsample)
+--+--------------+
   |
+--v--------------+
| Dense Block 2    |
+--+--------------+
   |
   ... (repeat)
   |
+--v--------------+
| Final BN + ReLU  |
+--+--------------+
   |
+--v--------------+
| Global AvgPool   |
+--+--------------+
   |
+--v--------------+
| Dense            |  num_classes outputs
+-----------------+

Configurations

Modelblock_configgrowth_rateParams
DenseNet-121[6, 12, 24, 16]32~8M
DenseNet-169[6, 12, 32, 32]32~14M
DenseNet-201[6, 12, 48, 32]32~20M
DenseNet-264[6, 12, 64, 48]32~34M

Usage

# DenseNet-121 for CIFAR-10
model = DenseNet.build(
  input_shape: {nil, 32, 32, 3},
  num_classes: 10,
  growth_rate: 32,
  block_config: [6, 12, 24, 16]
)

# Compact DenseNet for small datasets
model = DenseNet.build(
  input_shape: {nil, 32, 32, 3},
  num_classes: 10,
  growth_rate: 12,
  block_config: [4, 8, 12, 8],
  compression: 0.5
)

Summary

Types

Options for build/1.

Functions

Build a DenseNet model.

Build a dense block where each layer receives all previous feature maps.

Get the output size (num_classes) for a DenseNet model.

Build a transition layer between dense blocks.

Types

build_opt()

@type build_opt() ::
  {:block_config, [pos_integer()]}
  | {:bn_size, pos_integer()}
  | {:compression, float()}
  | {:dropout, float()}
  | {:growth_rate, pos_integer()}
  | {:initial_channels, pos_integer()}
  | {:input_shape, tuple()}
  | {:num_classes, pos_integer() | nil}

Options for build/1.

Functions

build(opts \\ [])

@spec build([build_opt()]) :: Axon.t()

Build a DenseNet model.

Options

  • :input_shape - Input shape as {nil, height, width, channels} (required)
  • :num_classes - Number of output classes (default: 10)
  • :growth_rate - Number of new feature maps per dense layer (default: 32)
  • :block_config - List of layer counts per dense block (default: [6, 12, 24, 16])
  • :compression - Compression factor for transitions, 0.0-1.0 (default: 0.5)
  • :initial_channels - Channels after stem conv (default: growth_rate * 2)
  • :dropout - Dropout rate in dense layers (default: 0.0)
  • :bn_size - Bottleneck width multiplier for BN-ReLU-1x1 layers (default: 4)

Returns

An Axon model outputting [batch, num_classes].

dense_block(input, num_layers, opts \\ [])

@spec dense_block(Axon.t(), pos_integer(), keyword()) :: {Axon.t(), pos_integer()}

Build a dense block where each layer receives all previous feature maps.

Within a dense block, layer i receives the concatenation of feature maps from layers 0, 1, ..., i-1 as input. Each layer produces growth_rate new feature maps.

Parameters

  • input - Input Axon node [batch, H, W, C]
  • num_layers - Number of dense layers in this block

Options

  • :growth_rate - New feature maps per layer (default: 32)
  • :num_channels - Current number of input channels (required for tracking)
  • :dropout - Dropout rate (default: 0.0)
  • :bn_size - Bottleneck width multiplier (default: 4)
  • :name - Layer name prefix (default: "dense_block")

Returns

Tuple of {output_node, total_channels} where total_channels is num_channels + num_layers * growth_rate.

output_size(opts \\ [])

@spec output_size(keyword()) :: pos_integer()

Get the output size (num_classes) for a DenseNet model.

transition_layer(input, out_channels, opts \\ [])

@spec transition_layer(Axon.t(), pos_integer(), keyword()) :: Axon.t()

Build a transition layer between dense blocks.

Transitions reduce spatial dimensions (2x downsampling via average pooling) and optionally compress the number of feature maps with a 1x1 convolution.

Parameters

  • input - Input Axon node [batch, H, W, C]
  • out_channels - Number of output channels after compression

Options

  • :name - Layer name prefix (default: "transition")

Returns

An Axon node with shape [batch, H/2, W/2, out_channels].