IsPartOfA
- class hybrid_learning.fuzzy_logic.predicates.custom_ops.IsPartOfA(in_key, *, kernel_size=10, thresh=0.1, logical_and=None, conv_hang_front=True, **other_setts)[source]
Bases:
TorchOperationUnary predicate that calculates for each pixel location whether it is part of an object segmentation. The predicate accepts as input the segmentation mask information for objects (encoding the predicate “pixel
pis aA” =IsA(p)). It returns a mask that for each pixel holds the truth value, whether that pixel is part of an object, i.e. at each pixel positionpthe output is\[\begin{split}\exists p_o: \text{IsA}(p_o) \wedge \text{IsPartOf}(p, p_o) \\ = \max_{p_o} \text{IsA}(p_o) \wedge \text{IsPartOf}(p, p_o)\end{split}\]It accepts 1D or 2D object masks of the shape
[[batch x [channels x]] height x] width, in any format that can be parsed to atorch.Tensor.Fuzzification
As fuzzification of the exists quantifier,
maxis used. Thelogical_anddefines the fuzzification ofAND. The values of the predicateIsA(.)are given by the pixel values of the input segmentation mask. The fuzzyIsPartOfrelation is chosen to calculate as a Gaussian distance, with a threshold of valuethreshand distancethresh_radius=int(kernel_size - 1) / 2for better computational performance:\[\begin{split}d(p, p') = \exp(- \frac{\|p - p'\|_2^2}{2 \sigma^2}) \\ \text{IsPartOf}(p, p') := \begin{cases} d(p, p') \text{if} \|p, p'\|_1 <= \text{thresh\_radius} \\ 0 \text{else} \end{cases}\end{split}\]with \(\sigma\) chosen such that \(d(p, p') = \text{thresh}\) for \(\|p - p'\|_2 = \text{thresh\_radius}\). The per-pixel values of the
IsPartOfpredicate are stored in the_ispartof_valuesmask which is then convoluted with theIsAvalues.Note
An even
kernel_sizewill have the same_ispartof_valuespixel values as the oddkernel_size-1, only with a row and a column added (on top/left forconv_hang_frontTrue, else on bottom/right).Choosing the right ``kernel_size``
The shape of the used Gaussian can be defined by a pair of x-y-values
(r, t). The Gaussian then looks like\[G_{r,t}(x) = \exp\left(- \frac{ x^2 }{ \frac{r^2}{- \ln(t)}}} \right)\]As
thresh_radius,int(kernel_size - 1) / 2is used, which also serves as the cutoff distance. To choose thekernel_sizesuch that (1) the point(r, t)lies on the Gaussian, and (2) thekernel_sizecuts at thresholdthresh, solve \(G_{r,t}(\frac{\text{k}-1}{2}) = \text{thresh}\) for \(k\) and getskernel_size=int(k). E.g. to match the constraints that at 4 pixel shift (r=4), \(G(r)\) should still be 0.8, and the kernel should only cut off at a threshold of 0.1, thekernel_sizemust be2*int(12.4) + 1=25.Visualization example
Visualization of the different logics:
>>> import hybrid_learning.fuzzy_logic as fl >>> import torch, torchvision.transforms.functional as F, matplotlib.pyplot as plt >>> # Builder for IsPartOf >>> P = fl.predicates.custom_ops.IsPartOfA.with_(kernel_size=10, thresh=0.01, conv_hang_front=False) >>> # The sample input mask >>> t = torch.zeros([1, 1, 11, 11]) >>> t[:, :, 4, 4], t[:, :, 5, 8] = 0.75, 0.5 >>> # The tensors to compare >>> figs = dict(segmask=t) # input >>> for logic in (fl.LukasiewiczLogic(), fl.ProductLogic(), fl.GoedelLogic()): ... title = f'IsPartOfA ({logic.__class__.__name__.replace("Logic", "")})' ... p = P("pedestrian", logical_and=logic.logical_('AND')) ... figs[title] = p({"pedestrian": t})[p.out_key] >>> # Plot >>> fig, axes = plt.subplots(1, len(figs), figsize=(len(figs)*3, 3), squeeze=False) >>> for i, (title, tens) in enumerate(figs.items()): ... shown_img = axes[0, i].imshow(F.to_pil_image(tens.view(t.size()[2:]))) ... _ = axes[0, i].set_title(title) >>> plt.subplots_adjust(bottom=0.1, right=0.8, top=0.9) >>> cax = plt.axes([.85, .25, 0.01, 0.5]) >>> _ = plt.colorbar(shown_img, cax=cax, orientation='vertical') >>> plt.show()
Public Data Attributes:
The string symbol of this class (override for sub-classes).
The arity of the operation.
The size of the kernel to use.
The value the Gaussian should have at
1/2 kernel_size.Whether the cutoff modelled by the
IsPartOfAconvolution should hang in the front dimensions in case of unequal padding.Settings to reproduce the instance.
Defaults used for settings.
Inherited from : py: class:Merge
The string symbol of this class (override for sub-classes).
The arity of the operation.
IS_COMMUTATIVEWhether instances are equivalent to ones with permuted
in_keys.is_variadicWhether the instance is variadic.
Settings to reproduce the instance.
Defaults used for settings.
pretty_op_symbName of the operation symbol suitable for filenames etc.
childrenThe input keys which are child operations.
all_childrenAll children operations in the flattened computational tree, sorted depth first.
constsThe constant string keys in the input keys.
operation_keysThe list of keys used for this parent operation in original order (constants and children output keys).
all_in_keysAll string input keys both of self and of all child operations.
all_out_keysOutput keys of self and all child operations.
Inherited from : py: class:DictTransform
Settings to reproduce the instance.
Inherited from : py: class:Transform
IDENTITY_CLASSThe identity class or classes for composition / addition.
Settings to reproduce the instance.
Public Methods:
torch_operation(mask)Calculate value of IsPartOfA predicate for given object segmentation mask.
Inherited from : py: class:TorchOperation
operation(annotation_vals)Calculate the predicate output.
Inherited from : py: class:Merge
to_infix_notation([sort_key, ...])Return an infix str encoding equal for differently sorted operations.
to_str(**infix_notation_kwargs)Alias for
to_infix_notation().to_pretty_str(**infix_notation_kwargs)Same as
to_str()but using pretty operation names suitable for filenames etc.to_repr([settings, defaults, sort_key, ...])Return str representation which can be used to reproduce and compare the instance.
treerecurse_replace_keys(**replace_map)Return a new formula with all occurences of variables in
replace_mapreplaced and else identical settings.treerecurse(fun)Apply the given function recursively to this and all children instances.
apply_to(annotations[, keep_keys])Apply this operation to the
annotationsdict.variadic_apply_to(annotations)Return the result of operation on the values/items of a mapping or sequence of arbitrary length.
operation(annotation_vals)Calculate the predicate output.
Inherited from : py: class:DictTransform
apply_to(annotations[, keep_keys])Apply this operation to the
annotationsdict.Inherited from : py: class:Transform
apply_to(annotations[, keep_keys])Apply this operation to the
annotationsdict.Special Methods:
__init__(in_key, *[, kernel_size, thresh, ...])Init.
Inherited from : py: class:Merge
__init__(in_key, *[, kernel_size, thresh, ...])Init.
__str__()Return str(self).
__repr__()Call
to_repr()without sorting.__eq__(other)Two merge operations are considered equal, if their normalized representations coincide.
__copy__()Return a deep copy of self using settings.
__call__(annotations[, keep_keys])Call method modifying a given dictionary.
Inherited from : py: class:DictTransform
__call__(annotations[, keep_keys])Call method modifying a given dictionary.
Inherited from : py: class:Transform
__repr__()Call
to_repr()without sorting.__eq__(other)Two merge operations are considered equal, if their normalized representations coincide.
__copy__()Return a deep copy of self using settings.
__add__(other)Return a flat composition of
selfwithother.__radd__(other)Return a flat composition of
otherandself.__call__(annotations[, keep_keys])Call method modifying a given dictionary.
- Parameters
- __init__(in_key, *, kernel_size=10, thresh=0.1, logical_and=None, conv_hang_front=True, **other_setts)[source]
Init.
The parameters
kernel_sizeandthreshare specifiers for the distance function encoding the is-part-of relation. Thelogical_andis the logicalANDcallable that accepts a list of two tensors with values in [0, 1] and returns their pixel-wise logicalAND. Thein_keyis the key of the fuzzy mask which encodes the per-pixel membership degree to the class of interest. E.g. if “is part of a pedestrian” should be calculated,"pedestrian"is a good choice.
- static create_ispartof_kernel(kernel_size, thresh, thresh_radius=None, conv_hang_front=True)[source]
Create the kernel tensor defining the
IsPartOfrelation. For details see_ispartof_values.
- torch_operation(mask)[source]
Calculate value of IsPartOfA predicate for given object segmentation mask. Allowed mask shapes (1D-4D):
([[batch, [1,]] height,] width)The output shape is that of the input mask. Invalid shapes raise aValueError.The device of
maskis used for calculations and will be the device of the output tensor. As a side effect, the internal storage of theIsPartOfvalues is moved to that device, assuming that the device of inputs does not change frequently.
- property conv_hang_front: bool
Whether the cutoff modelled by the
IsPartOfAconvolution should hang in the front dimensions in case of unequal padding. Internals: To achieve hanging towards the back, the padding must be chosen to hang front.
- property kernel_size: int
The size of the kernel to use. The standard deviation of the gaussian is determined using this as radius and
thresh.
- logical_and: Callable[[List[Tensor]], Tensor]
Callable accepting a list of two tensors with values in [0, 1] and returning their pixel-wise logical
AND. Mandatory argument.
- property setting_defaults
Defaults used for settings.