6. Building a Quantifier#

This guide explains how to create custom quantifiers in MLQuantify by extending the base classes and using the provided utilities.

6.1. General Quantifiers#

To build a custom quantifier, inherit from BaseQuantifier and implement the following methods:

  • fit: Train the quantifier on the provided training data (features and labels)

  • predict: Estimate class prevalences on test data using the learned model

Example:

from mlquantify.base import BaseQuantifier
import numpy as np

class MyQuantifier(BaseQuantifier):
    def __init__(self, param1=42, param2='default'):
        self.param1 = param1
        self.param2 = param2

    def fit(self, X, y):
        self.classes_ = np.unique(y)
        # Add your training logic here
        return self

    def predict(self, X):
        _, counts = np.unique(self.classes_, return_counts=True)
        prevalence = counts / counts.sum()
        return prevalence

6.2. Aggregative Quantifiers#

Aggregative quantifiers combine predictions from a base learner. Inherit from both AggregativeQuantifierMixin and BaseQuantifier to create one.

Required methods:

  • fit: Train the quantifier and its base learner

  • predict: Generate individual predictions

  • aggregate: Convert individual predictions into prevalence estimates

Important

  • Place AggregativeQuantifierMixin first in the inheritance list for proper method resolution

  • Include a learner attribute for automatic parameter handling

Example:

from mlquantify.base import BaseQuantifier
from mlquantify.mixins import AggregativeQuantifierMixin
import numpy as np

class MyAggregativeQuantifier(AggregativeQuantifierMixin, BaseQuantifier):
    def __init__(self, learner, param1=42, param2='default'):
        self.learner = learner
        self.param1 = param1
        self.param2 = param2

    def fit(self, X, y):
        self.classes_ = np.unique(y)
        self.learner.fit(X, y)
        return self

    def predict(self, X):
        return self.learner.predict(X)

    def aggregate(self, individual_predictions):
        _, counts = np.unique(individual_predictions, return_counts=True)
        prevalence = counts / counts.sum()
        return prevalence

6.3. Aggregation Types#

Specify the prediction type by inheriting from one of these mixins:

  • CrispLearnerMixin: For hard/crisp predictions (class labels)

  • SoftLearnerMixin: For soft/probabilistic predictions (class probabilities)

Note

These mixins only work with AggregativeQuantifierMixin and require a learner attribute.

6.4. Binary Quantifiers#

Use the @define_binary decorator to adapt multiclass quantifiers for binary problems. The decorator automatically modifies fit, predict, and aggregate methods.

Multiclass strategies:

  • 'ovr' (One-vs-Rest): Treat each class as positive vs. all others

  • 'ovo' (One-vs-One): Compare each pair of classes

Example:

from mlquantify.base import BaseQuantifier
from mlquantify.multiclass import define_binary
import numpy as np

@define_binary
class MyBinaryQuantifier(BaseQuantifier):
    def __init__(self, strategy='ovo', param1=42):
        self.strategy = strategy
        self.param1 = param1

    def fit(self, X, y):
        self.classes_ = np.unique(y)
        return self

    def predict(self, X):
        # Binary prediction logic
        return np.array([0.5, 0.5])  # Example prevalence

6.5. Validation Utilities#

The mlquantify.utils module provides validation functions to ensure data consistency:

  • validate_data: Validate input features and labels

  • validate_prevalences: Validate prevalence estimates

  • validate_predictions: Validate learner predictions (for aggregative quantifiers)

  • _fit_context: Context manager for fitting with automatic parameter validation, with an option to skip multiple validations during fitting if in a loop.

Example:

from mlquantify.utils import (
    validate_data,
    validate_prevalences,
    validate_predictions,
    _fit_context
)
from mlquantify.base import BaseQuantifier
from mlquantify.mixins import SoftLearnerMixin, AggregativeQuantifierMixin

class MyQuantifier(SoftLearnerMixin, AggregativeQuantifierMixin, BaseQuantifier):
    def __init__(self, learner, param1=42):
        self.learner = learner
        self.param1 = param1

    @_fit_context(prefer_skip_validation=True)
    def fit(self, X, y):
        X, y = validate_data(X, y)
        # Training logic
        return self

    def predict(self, X):
        X = validate_data(X)
        # Prediction logic
        return predictions

    def aggregate(self, individual_predictions):
        individual_predictions = validate_predictions(
            individual_predictions, self.classes_
        )
        # Aggregation logic
        return prevalence

6.6. Parameter Constraints#

Ensure parameter validity using the mlquantify.utils module:

  1. Apply the @_fit_context decorator to the fit method

  2. Use constraint validators from mlquantify.utils to check parameter types and values

These validators will raise informative errors when parameters don’t meet expectations.

See also

Example:

from mlquantify.base import BaseQuantifier
from mlquantify.utils import (
    _fit_context,
    Interval,
    Options
)
import numpy as np

class MyQuantifier(BaseQuantifier):
    _param_constraints = {
        'param1': [Interval(0, None, inclusive_left=False)],
        'param2': [Options(['default', 'option1', 'option2'])],
        'param3': "array-like"
    }

    def __init__(self, param1=42, param2='default', param3=None):
        self.param1 = param1
        self.param2 = param2
        self.param3 = param3

    @_fit_context(prefer_skip_validation=True)
    def fit(self, X, y):
        self.classes_ = np.unique(y)
        # Training logic
        return self