Skip to content

check_observe_transform_equivalence

yohou.testing.check_observe_transform_equivalence(transformer, X, y=None)

Check observe() does not change transform() output for a fitted transformer.

transform() does not consult _X_observed; it transforms the provided DataFrame independently of internal memory. Calling observe() beforehand updates the memory buffer (not the fitted parameters), so starting from the same fitted state, transforming after an observe() call must match transforming without it.

Parameters

Name Type Description Default
transformer BaseActualTransformer

Unfitted transformer

required
X DataFrame

Training data

required
y DataFrame

Target data

None

Raises

Type Description
AssertionError

If observe() changes the transform output

Source Code

Source code in src/yohou/testing/transformer.py
def check_observe_transform_equivalence(transformer, X: pl.DataFrame, y: pl.DataFrame | None = None) -> None:
    """Check observe() does not change transform() output for a fitted transformer.

    ``transform()`` does not consult ``_X_observed``; it transforms the provided
    DataFrame independently of internal memory. Calling ``observe()`` beforehand
    updates the memory buffer (not the fitted parameters), so starting from the
    same fitted state, transforming after an ``observe()`` call must match
    transforming without it.

    Parameters
    ----------
    transformer : BaseActualTransformer
        Unfitted transformer
    X : pl.DataFrame
        Training data
    y : pl.DataFrame, optional
        Target data

    Raises
    ------
    AssertionError
        If observe() changes the transform output

    """
    # Split data so X_second continues immediately after X_first.
    X_first, X_second = train_test_split(X, test_size=0.5, shuffle=False)
    y_first = y.head(len(X_first)) if y is not None else None

    # Both paths share the same fitted parameters (fit on X_first). observe()
    # may only ingest data that continues after the fitted/observed state, so
    # X_second is the natural continuation of X_first.
    # Path 1: fit only.
    transformer1 = clone(transformer)
    transformer1.fit(X_first, y_first)
    X_trans1 = transformer1.transform(X_second)

    # Path 2: fit, then observe (updates memory, not fitted params).
    transformer2 = clone(transformer)
    transformer2.fit(X_first, y_first)
    transformer2.observe(X_second)
    X_trans2 = transformer2.transform(X_second)

    # Results should be equivalent
    assert_frame_equal(X_trans1, X_trans2, rel_tol=1e-6, abs_tol=1e-8)