Skip to main content

HomOps Reference

HomAvgPool

Average-pool packed feature maps as a depthwise convolution.

ApML
RunsServer (HomConv subclass)
Changes shapeSame as HomConv - (C, H*W) metadata; stride gates slots
Changes scaleYes - via HomConv packed mul
Levels spentSame as HomConv
RotatesYes - kernel tap alignments
KeysRotation key

What it does

HomAvgPool implements average pooling as a depthwise HomConv: in_channels = out_channels = groups = channels, padding = 0, and a kernel fixed to all ones divided by kH * kW. The average kernel is set in the constructor; you do not call set_data.
It replaces the old Unfold → Reshape → MatMul → Reshape pipeline. Reach for it when you need encrypted AvgPool2d-style downsampling on packed square feature maps. It is not separately registered: it serializes as Conv with the avg kernel as plaintext data.

Signature

HomAvgPool(
    channels,                           # required
    kernel_size,                        # int | (h, w)
    stride,                             # int | (h, w)
    dilation=(1, 1),
)
OP_TYPE is inherited from HomConv (HomOpType.Conv). The constructor builds the depthwise avg kernel and calls set_data for you.

Parameters

ParameterTypeDefaultDescription
channelsintrequiredNumber of channels (= groups; depthwise).
kernel_sizeint | (h, w)requiredPool window; normalized by HomConv.
strideint | (h, w)requiredPool stride.
dilationint | (h, w)(1, 1)Dilation applied to the averaging kernel; default (1, 1).
Fixed / inherited
FieldValue
padding0
groupschannels
biasFalse (HomConv default)
kernel_shape(C, 1, kH, kW)
Weights1/(kH*kW) everywhere - set automatically

Requirements

  • Same as HomConv. Rotation keys, square packing (C, H*W) with H == W, and internal_n ≥ H*W.
  • No user set_data. The average kernel is attached in init.
  • Identity tap. With padding=0, the identity rotation is the tap at offset 0; typical kernels include that relative (0, 0) tap.
These surface as compilation errors; see Compilation errors.

Shape effect

Same as HomConv: (C, H*W)(C, H*W) in deploy metadata; stride zeros non-selected spatial slots inside the vector. Clear / post reshape typically restores (C, H_out, W_out) with standard avg-pool geometry:
H_out = floor((H - kH) / stride_h) + 1 (and the same for W), when padding is 0.

Scale effect / Level budget / Keys

Inherited from HomConv: packed mul (and its typical mod-switch), rotation keys, no square key.

Example

2×2 average pool with stride 2 on a 3×32×32 map:
pipeline.pyPYTHON
from lattica_build.operators import HomReshape, HomAvgPool
from lattica_build.base_classes.hom_pipeline import HomomorphicPipeline

INPUT_SHAPE = (3, 32, 32)

pipeline = HomomorphicPipeline(
    client_pre=[HomReshape((3, 32 * 32))],
    hom=HomAvgPool(channels=3, kernel_size=2, stride=2),
    client_post=[HomReshape(INPUT_SHAPE)],
    n_axis=1,
    input_shape=INPUT_SHAPE,
)

See also

  • HomConv - base conv; depthwise pattern is groups=in_channels