Skip to content

← CNNs from Scratch step 5 of 15

Hard Research

Depthwise Separable Convolution

A depthwise separable convolution splits filtering into two steps. First, each input channel uses its own spatial filter. Then a shared matrix mixes the filtered channels at each position.

Implement depthwise_separable_conv(x, dw_filters, pw_weights) for a one-dimensional signal with no batch axis.

Inputs and output

  • x has shape (C_in, L): input channels by signal length.
  • dw_filters has shape (C_in, K): one length-K filter per input channel.
  • pw_weights has shape (C_out, C_in): one row per output channel.
  • Channel counts are positive and 1 <= K <= L. Inputs share a floating-point dtype and device.
  • Return shape (C_out, L - K + 1), preserving the input dtype and device.

Step 1: filter each channel

Use stride 1, dilation 1 and no padding. At each position i, multiply the K values starting at x[c, i] by dw_filters[c], then sum:

depthwise[c, i] = sum(x[c, i + j] * dw_filters[c, j] for j in range(K))

Use the filter in its given order; do not reverse it. This is the cross-correlation convention used by neural-network convolution layers. Channels stay separate in this step, giving shape (C_in, L - K + 1).

For example, filtering [1, 2, 3, 4] with [1, 0, -1] gives [-2, -2]. When K equals L, there is exactly one output position.

Step 2: mix channels

At every position, combine the filtered channel values using the same pw_weights matrix:

output = pw_weights @ depthwise

This is a pointwise convolution: it mixes channels without looking at neighboring positions. Include no bias, activation or residual addition, and leave the inputs unchanged.

The window below illustrates the first step for one channel. The second step changes the number of channels, not the output length.

Loading visualization…