Custom Attributes and Filter Specs¶
This guide focuses on choosing attributes, grouping them into filter specs, and keeping CFP configurations reproducible.
Attribute Selection¶
Start with the smallest attribute set that expresses the prior you need. For the full attribute list, see Attribute Catalog.
Intent |
Candidate attributes |
|---|---|
Remove small components |
|
Prefer contrast in the tree |
|
Prefer elongated or compact shapes |
|
Use bounding-box geometry |
|
Use tree position |
|
Use contours |
|
Example:
from mtlearn import morphology
from mtlearn.layers import ConnectedFilterPreprocessingLayer
shape_and_contrast = [
morphology.AttributeType.AREA,
morphology.AttributeType.GRAY_HEIGHT,
morphology.AttributeType.COMPACTNESS,
]
Attribute Groups¶
Groups expand to scalar attributes before CFP parameters are created.
shape_spec = {
"name": "shape",
"tree_type": "max-tree",
"attributes": morphology.AttributeGroup.SHAPE,
}
mixed_spec = {
"name": "shape_plus_depth",
"tree_type": "max-tree",
"attributes": [
morphology.AttributeGroup.SHAPE,
morphology.AttributeType.DEPTH_NODE,
],
}
The number of trainable weights for a spec equals the number of scalar attributes after expansion.
layer = ConnectedFilterPreprocessingLayer(
in_channels=1,
filter_specs=[mixed_spec],
scale_mode="minmax01",
)
weights, biases = layer.get_params()
print(weights["shape_plus_depth"].shape)
Naming Specs¶
Use explicit names. They become keys in parameter dictionaries, exported metadata, checkpoint contracts, and inspection output.
filter_specs = [
{
"name": "max_area_contrast",
"tree_type": "max-tree",
"attributes": [
morphology.AttributeType.AREA,
morphology.AttributeType.GRAY_HEIGHT,
],
},
{
"name": "min_area_tophat",
"tree_type": "min-tree",
"attributes": morphology.AttributeType.AREA,
},
]
Avoid relying on generated names such as filter_0 in long-running
experiments because reordering specs changes the meaning of saved weights.
Tree-of-Shapes Specs¶
Tree-of-shapes specs are useful when the same filter should respond to bright and dark structures. Pick interpolation explicitly when reproducibility across experiments matters.
tos_spec = {
"name": "tos_shape",
"tree_type": "tree-of-shapes",
"tos_interpolation": morphology.ToSInterpolation.SelfDual,
"attributes": [
morphology.AttributeType.AREA,
morphology.AttributeType.COMPACTNESS,
],
}
The current CFP validation rejects scalar attributes that are undefined for tree-of-shapes. Broad groups may be expanded with unsupported members removed when the backend exposes a safe group-level fallback.
Config Round Trip¶
Use get_config and from_config to store the layer architecture separately
from trainable weights.
config = layer.get_config()
restored = ConnectedFilterPreprocessingLayer.from_config(config)
This is the same config shape used by checkpoint helpers. It records tree type, attributes, normalization mode, clamp bounds, and hybrid normalization constants.
Practical Checklist¶
Use a small number of specs first; each spec multiplies output channels.
Name every spec before training.
Keep max-tree and min-tree specs separate when polarity matters.
Use tree-of-shapes when polarity should not matter.
For
"hybrid"normalization, build or load dataset stats before training.Inspect one sample before large experiments to confirm attributes and gates.