Files
2026-07-13 12:49:22 +08:00

114 lines
3.4 KiB
Python

"""
Helper functions internally used in cleanlab.regression.
"""
import numpy as np
import pandas as pd
from numpy.typing import ArrayLike
from typing import Tuple, Union
def assert_valid_prediction_inputs(
labels: ArrayLike,
predictions: ArrayLike,
method: str,
) -> Tuple[np.ndarray, np.ndarray]:
"""Checks that ``labels``, ``predictions``, ``method`` are correctly formatted."""
# Load array_like input as numpy array. If not raise error.
try:
labels = np.asarray(labels)
except:
raise ValueError(f"labels must be array_like.")
try:
predictions = np.asarray(predictions)
except:
raise ValueError(f"predictions must be array_like.")
# Check if labels and predictions are 1-D and numeric
valid_labels = check_dimension_and_datatype(check_input=labels, text="labels")
valid_predictions = check_dimension_and_datatype(check_input=predictions, text="predictions")
# Check if number of examples are same.
assert (
valid_labels.shape == valid_predictions.shape
), f"Number of examples in labels {labels.shape} and predictions {predictions.shape} are not same."
# Check if inputs have missing values
check_missing_values(valid_labels, text="labels")
check_missing_values(valid_predictions, text="predictions")
# Check if method is among allowed scoring method
scoring_methods = ["residual", "outre"]
if method not in scoring_methods:
raise ValueError(f"Specified method '{method}' must be one of: {scoring_methods}.")
# return 1-D numpy array
return valid_labels, valid_predictions
def assert_valid_regression_inputs(
X: Union[np.ndarray, pd.DataFrame],
y: ArrayLike,
) -> Tuple[np.ndarray, np.ndarray]:
"""
Checks that regression inputs are properly formatted and returns the inputs in numpy array format.
"""
try:
X = np.asarray(X)
except:
raise ValueError(f"X must be array_like.")
y = check_dimension_and_datatype(y, "y")
check_missing_values(y, text="y")
if len(X) != len(y):
raise ValueError("X and y must have same length.")
return X, y
def check_dimension_and_datatype(check_input: ArrayLike, text: str) -> np.ndarray:
"""
Raises errors related to:
1. If input is empty
2. If input is not 1-D
3. If input is not numeric
If all the checks are passed, it returns the squeezed 1-D array required by the main algorithm.
"""
try:
check_input = np.asarray(check_input)
except:
raise ValueError(f"{text} could not be converted to numpy array, check input.")
# Check if input is empty
if not check_input.size:
raise ValueError(f"{text} cannot be empty array.")
# Remove axis with length one
check_input = np.squeeze(check_input)
# Check if input is 1-D
if check_input.ndim != 1:
raise ValueError(
f"Expected 1-Dimensional inputs for {text}, got {check_input.ndim} dimensions."
)
# Check if datatype is numeric
if not np.issubdtype(check_input.dtype, np.number):
raise ValueError(
f"Expected {text} to contain numeric values, got values of type {check_input.dtype}."
)
return check_input
def check_missing_values(check_input: np.ndarray, text: str):
"""Raise error if there are any missing values in Numpy array."""
if np.isnan(check_input).any():
raise ValueError(f"{text} cannot contain missing values.")