Running drift checks on a feature column that had no data in a
particular monitoring window (upstream pipeline failed). Instead of
a meaningful error I got a ZeroDivisionError buried several frames
deep inside get_binned_data, which took a while to trace back.
After digging into it there are actually a few related issues across
the divergence-based stat tests.
Empty input series
psi_stat_test, kl_div_stat_test, jensenshannon_stat_test and
hellinger_stat_test all behave differently when given an empty series:
- psi_stat_test and kl_div_stat_test raise ZeroDivisionError
- jensenshannon_stat_test raises ZeroDivisionError or silently
returns (0.0, False) depending on which series is empty
- hellinger_stat_test silently returns (nan, False) or (1.0, True)
depending on feature type, no exception at all
Quick repro:
import pandas as pd
from evidently.legacy.core import ColumnType
from evidently.legacy.calculations.stattests import psi_stat_test
psi_stat_test(pd.Series([], dtype=float), pd.Series([1.0, 2.0, 3.0]), ColumnType.Numerical, 0.1)
get_one_column_drift already guards against this at the higher level
but the individual functions are all in all with no documented
precondition on input size.
Both series empty crashes differently
When both series are empty, get_binned_data hits a different failure
path - the feel_zeroes block calls min() on an empty array:
ValueError: min() arg is an empty sequence
So the same input produces two different exceptions depending on
which series is empty vs both being empty.
Out of range values silently bucketed into boundary bin
When current data is completely outside the reference data range,
numpy histogram silently dumps all values into the last bin instead
of indicating that the distributions don't overlap at all:
import pandas as pd
from evidently.legacy.core import ColumnType
from evidently.legacy.calculations.stattests import psi_stat_test
ref = pd.Series(list(range(1, 50)))
cur = pd.Series([1000.0] * 49)
print(psi_stat_test(ref, cur, ColumnType.Numerical, 0.1))
Drift is detected but the score is computed on wrong bin counts
since all current values land in the last bin. No warning is raised.
All four tests are publicly exported with no documented precondition
on input size or range, so users have no way to know these inputs
are unsupported.
Thanks !!!
Running drift checks on a feature column that had no data in a
particular monitoring window (upstream pipeline failed). Instead of
a meaningful error I got a ZeroDivisionError buried several frames
deep inside get_binned_data, which took a while to trace back.
After digging into it there are actually a few related issues across
the divergence-based stat tests.
Empty input series
psi_stat_test, kl_div_stat_test, jensenshannon_stat_test and
hellinger_stat_test all behave differently when given an empty series:
returns (0.0, False) depending on which series is empty
depending on feature type, no exception at all
Quick repro:
import pandas as pd
from evidently.legacy.core import ColumnType
from evidently.legacy.calculations.stattests import psi_stat_test
psi_stat_test(pd.Series([], dtype=float), pd.Series([1.0, 2.0, 3.0]), ColumnType.Numerical, 0.1)
get_one_column_drift already guards against this at the higher level
but the individual functions are all in all with no documented
precondition on input size.
Both series empty crashes differently
When both series are empty, get_binned_data hits a different failure
path - the feel_zeroes block calls min() on an empty array:
ValueError: min() arg is an empty sequence
So the same input produces two different exceptions depending on
which series is empty vs both being empty.
Out of range values silently bucketed into boundary bin
When current data is completely outside the reference data range,
numpy histogram silently dumps all values into the last bin instead
of indicating that the distributions don't overlap at all:
import pandas as pd
from evidently.legacy.core import ColumnType
from evidently.legacy.calculations.stattests import psi_stat_test
ref = pd.Series(list(range(1, 50)))
cur = pd.Series([1000.0] * 49)
print(psi_stat_test(ref, cur, ColumnType.Numerical, 0.1))
Drift is detected but the score is computed on wrong bin counts
since all current values land in the last bin. No warning is raised.
All four tests are publicly exported with no documented precondition
on input size or range, so users have no way to know these inputs
are unsupported.
Thanks !!!