Convolution and pooling
Generated by tools/gen_example_pages.py from mnd_scripts/examples/example_conv_pool.mnd — the output below is a real run, not a transcription. Regenerating the page reruns it.
spatial operators (conv2d, maxpool2d, avgpool2d) and shape operators (concat) — and the OBJECT-PARAMETER syntax { key: value } that configures them.
The program#
# ============================================================================
# example_conv_pool.mnd
# ----------------------------------------------------------------------------
# FUNCTIONALITY: spatial operators (conv2d, maxpool2d, avgpool2d) and shape
# operators (concat) -- and the OBJECT-PARAMETER syntax `{ key: value }` that
# configures them.
#
# THE ONE RULE THAT TRIPS EVERYONE UP: object params are an ARGUMENT, and in a
# postfix language every argument precedes its operator.
#
# RIGHT: img {kernel_size: 2, stride: 2} maxpool2d pooled =
# WRONG: img maxpool2d {kernel_size: 2, stride: 2} pooled =
#
# The wrong form still parses -- the block just becomes a dangling term that no
# operator ever consumes -- so the operator silently falls back to its defaults
# (and for pooling, a default kernel_size of 0, which is a run-time error).
# Read the params as "with these settings, do this", left to right.
#
# Named params are resolved to integers at graph-build time and folded into the
# 24-bit IR immediate the worker decodes, which is why they must be compile-time
# constants rather than runtime values.
#
# conv2d 2 ops {stride, padding} input rank-2 [H,W] or rank-3
# [C,H,W]; WEIGHT IS RANK-4
# [Cout, Cin, KH, KW]
# maxpool2d 1 op {kernel_size, stride} stride defaults to kernel_size
# avgpool2d 1 op {kernel_size, stride} integer mean, truncated
# concat 2 ops {axis}
#
# RUN: ../maned-run examples/example_conv_pool.mnd
# ============================================================================
mnd::quantmax=1000;
mnd::quantmin=-1000;
mnd::quantres=0;
in::img = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]; # 4x4 [H,W]
# One output channel, one input channel, 2x2 kernel -> shape [1,1,2,2].
# This is a diagonal-difference detector.
in::kernel = [[[[1,0],[0,-1]]]];
in::a = [[1,2],[3,4]];
in::b = [[5,6],[7,8]];
profile::img;
calc::lambda_flow vision(img, kernel, a, b) {
# --- convolution, stride 1, no padding: 4x4 -> [1,3,3] ----------------
img kernel {stride: 1, padding: 0} conv2d features =
# --- same kernel, stride 2: 4x4 -> [1,2,2] ----------------------------
img kernel {stride: 2, padding: 0} conv2d strided =
# --- padding widens the output back out --------------------------------
img kernel {stride: 1, padding: 1} conv2d padded =
# --- pooling: 4x4 -> 2x2 ------------------------------------------------
img {kernel_size: 2, stride: 2} maxpool2d pooled_max =
img {kernel_size: 2, stride: 2} avgpool2d pooled_avg =
# stride omitted defaults to kernel_size (non-overlapping windows)
img {kernel_size: 2} maxpool2d pooled_default_stride =
# overlapping windows: kernel 2, stride 1 -> 3x3
img {kernel_size: 2, stride: 1} maxpool2d pooled_overlap =
# --- concatenation along either axis -----------------------------------
a b {axis: 0} concat stacked_rows = # 2x2 + 2x2 -> 4x2
a b {axis: 1} concat stacked_cols = # 2x2 + 2x2 -> 2x4
# --- a small pipeline: convolve, rectify, pool ------------------------
# `padded` carries both signs (the zero-pad border makes the detector fire
# asymmetrically), so relu actually has something to clamp.
padded relu rectified =
rectified {kernel_size: 2, stride: 1} maxpool2d pipeline_out =
} return features, strided, padded,
pooled_max, pooled_avg, pooled_default_stride, pooled_overlap,
stacked_rows, stacked_cols, rectified, pipeline_out;
The run#
$ maned-run mnd_scripts/examples/example_conv_pool.mnd
Matrix Profile: img
------------------------------------------------
[basic_id]
type matrix
field real
dtype int
[dimensions] exact
shape 4 x 4
order 4
is_square true
is_rectangular false
[structure] exact
is_diagonal false
is_identity false
is_zero_matrix false
is_upper_triangular false
is_lower_triangular false
is_bidiagonal false
is_lower_bidiagonal false
is_upper_bidiagonal false
is_tridiagonal false
is_band_matrix false
bandwidth_lower 3
bandwidth_upper 3
is_sparse false
non_zero_elements 16
zero_elements 0
sparsity_ratio 0/16 (0)
[symmetry] exact
is_symmetric false
is_skew_symmetric false
is_hermitian false
is_orthogonal false
is_normal false
[linear_algebra]
trace 34
determinant 0
rank 2
is_full_rank false
is_invertible false
is_singular true
[spectral] approximate (QR iteration)
eigenvalues -2.209, 0, 0, 36.21
multiplicity -2.209 (alg 1, geo 1), 0 (alg 2, geo 2), 36.21 (alg 1, geo 1)
spectral_radius 36.21
all_eigenvalues_positive false
is_diagonalizable true
is_defective false
jordan_blocks -2.209^1, 0^1, 0^1, 36.21^1
[numerical] approximate
condition_number inf
condition_status singular
is_numerically_stable false
[positivity]
(definiteness) not_applicable (matrix is not symmetric)
is_positive_definite false
is_positive_semidefinite false
is_negative_definite false
is_negative_semidefinite false
is_indefinite false
[special_properties]
is_nilpotent false
is_idempotent false
is_involutory false
[decompositions]
supports_lu true
supports_qr true
supports_svd true
supports_cholesky false
supports_eigendecomp true
supports_jordan true
[computational] rule
storage_format dense_row_major
linear_solver lu, qr
eigen_solver qr, schur_decomposition
fpga_friendly false
cache_friendly true
gpu_friendly true
tensor_core_friendly false
[geometric_interpretation] rule
represents_scaling true
represents_shear true
represents_rotation false
represents_projection false
[dynamic_interpretation] rule
has_coupled_modes false
dynamic_modes all modes independent
[taxonomy]
inherits square_matrix, dense_matrix, singular_matrix, diagonalizable_matrix
implies -
forbids symmetric, diagonal, orthogonal, spd, invertible, defective
------------------------------------------------
flow 'vision' outputs:
features : [1x3x3] = [-5, -5, -5, -5, -5, -5, -5, -5, -5]
strided : [1x2x2] = [-5, -5, -5, -5]
padded : [1x5x5] = [-1, -2, -3, -4, 0, -5, -5, -5, -5, 4, -9, -5, -5, -5, 8, -13, -5, -5, -5, 12, 0, 13, 14, 15, 16]
pooled_max : [2x2] = [6, 8, 14, 16]
pooled_avg : [2x2] = [3, 5, 11, 13]
pooled_default_stride : [2x2] = [6, 8, 14, 16]
pooled_overlap : [3x3] = [6, 7, 8, 10, 11, 12, 14, 15, 16]
stacked_rows : [4x2] = [1, 2, 3, 4, 5, 6, 7, 8]
stacked_cols : [2x4] = [1, 2, 5, 6, 3, 4, 7, 8]
rectified : [1x5x5] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 8, 0, 0, 0, 0, 12, 0, 13, 14, 15, 16]
pipeline_out : [1x4x4] = [0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 12, 13, 14, 15, 16]
Next#
- Language guide — every operation the examples use, in the full table.
- RPN syntax specification — the normative rules.