ronantakizawa/codereview-bench huggingface dataset:
Repository: scikit-learn/scikit-learn
File: sklearn/utils/tests/test_tags.py (Python)

Code before:
)
from sklearn.utils.estimator_checks import (
    check_estimator_tags_renamed,
    check_valid_tag_types,
)


class EmptyClassifier(ClassifierMixin, BaseEstimator):
    pass


class EmptyTransformer(TransformerMixin, BaseEstimator):
    pass


class EmptyRegressor(RegressorMixin, BaseEstimator):
    pass


def test_type_error_is_thrown_for_class_vs_instance():
    """Test that a clearer error is raised if a class is passed instead of an instance.

    Related to the discussion in
    https://github.com/scikit-learn/scikit-learn/issues/32394#issuecomment-3375647854.
    """
    est = EmptyClassifier
    match = re.escape(
        "Expected an estimator instance (EmptyClassifier()), "
        "got estimator class instead (EmptyClassifier)."
    )
    with pytest.raises(TypeError, match=match):
        get_tags(est)


@pytest.mark.parametrize(
    "estimator, value",
    [
        [EmptyClassifier(), True],
        [EmptyTransformer(), False],
        [EmptyRegressor(), True],
        [BaseEstimator(), False],
    ],
)
def test_requires_y(estimator, value):
    assert get_tags(estimator).target_tags.required == value


def test_no___sklearn_tags__with_more_tags():
    """Test that calling `get_tags` on a class that defines `_more_tags` but not
    `__sklearn_tags__` raises an error.
    """

Review comment (suggestion):
Should it be called "cls", because it's a class rather than an estimator? (feel free to discard, as this is a cosmetic comment)

Code after:
)
from sklearn.utils.estimator_checks import (
    check_estimator_tags_renamed,
    check_valid_tag_types,
)


class EmptyClassifier(ClassifierMixin, BaseEstimator):
    pass


class EmptyTransformer(TransformerMixin, BaseEstimator):
    pass


class EmptyRegressor(RegressorMixin, BaseEstimator):
    pass


def test_type_error_is_thrown_for_class_vs_instance():
    """Test that a clearer error is raised if a class is passed instead of an instance.

    Related to the discussion in
    https://github.com/scikit-learn/scikit-learn/issues/32394#issuecomment-3375647854.
    """
    estimator_class = EmptyClassifier
    match = re.escape(
        "Expected an estimator instance (EmptyClassifier()), "
        "got estimator class instead (EmptyClassifier)."
    )
    with pytest.raises(TypeError, match=match):
        get_tags(estimator_class)


@pytest.mark.parametrize(
    "estimator, value",
    [
        [EmptyClassifier(), True],
        [EmptyTransformer(), False],
        [EmptyRegressor(), True],
        [BaseEstimator(), False],
    ],
)
def test_requires_y(estimator, value):
    assert get_tags(estimator).target_tags.required == value


def test_no___sklearn_tags__with_more_tags():
    """Test that calling `get_tags` on a class that defines `_more_tags` but not
    `__sklearn_tags__` raises an error.
    """
Repository: scikit-learn/scikit-learn
File: sklearn/preprocessing/_label.py (Python)

Code before:
        if sparse_output:
            Y = sp.csr_matrix(y)
            if pos_label != 1:
                data = xp.full_like(Y.data, pos_label)
                Y.data = data
        else:
            if sp.issparse(y):
                y = y.toarray()

            Y = xp.asarray(y, device=device_, copy=True)
            if pos_label != 1:
                Y[Y != 0] = pos_label

    else:
        raise ValueError(
            "%s target data is not supported with label binarization" % y_type
        )

    if not sparse_output:
        if neg_label != 0:
            Y[Y == 0] = neg_label

        if pos_switch:
            Y[Y == pos_label] = 0

        Y = xp.astype(Y, int_dtype_)
    else:
        Y.data = Y.data.astype(int, copy=False)

    # preserve label ordering
    if xp.any(classes != sorted_class):
        indices = xp.searchsorted(sorted_class, classes)
        Y = Y[:, indices]

    if y_type == "binary":
        if sparse_output:
            Y = Y[:, [-1]]
        else:
            Y = xp.reshape(Y[:, -1], (-1, 1))

    return Y


def _inverse_binarize_multiclass(y, classes, xp=None):
    """Inverse label binarization transformation for multiclass.

    Multiclass uses the maximal score instead of a threshold.
    """
    if sp.issparse(y):
        classes = np.asarray(classes)
        # Find the argmax for each row in y where y is a CSR matrix

Review comment (suggestion):
```suggestion
        Y = xp.astype(Y, int_dtype_, copy=False)
```

Code after:

    elif y_type == "multilabel-indicator":
        if sparse_output:
            Y = sp.csr_matrix(y)
            if pos_label != 1:
                data = xp.full_like(Y.data, pos_label)
                Y.data = data
        else:
            if sp.issparse(y):
                y = y.toarray()

            Y = xp.asarray(y, device=device_, copy=True)
            if pos_label != 1:
                Y[Y != 0] = pos_label

    else:
        raise ValueError(
            "%s target data is not supported with label binarization" % y_type
        )

    if not sparse_output:
        if neg_label != 0:
            Y[Y == 0] = neg_label

        if pos_switch:
            Y[Y == pos_label] = 0

        Y = xp.astype(Y, int_dtype_, copy=False)
    else:
        Y.data = Y.data.astype(int, copy=False)

    # preserve label ordering
    if xp.any(classes != sorted_class):
        indices = xp.searchsorted(sorted_class, classes)
        Y = Y[:, indices]

    if y_type == "binary":
        if sparse_output:
            Y = Y[:, [-1]]
        else:
            Y = xp.reshape(Y[:, -1], (-1, 1))

    return Y


def _inverse_binarize_multiclass(y, classes, xp=None):
    """Inverse label binarization transformation for multiclass.

    Multiclass uses the maximal score instead of a threshold.
    """
    if sp.issparse(y):
Repository: scikit-learn/scikit-learn
File: sklearn/metrics/cluster/tests/test_common.py (Python)

Code before:

    metric_np = metric(a_np, b_np, **metric_kwargs)

    # When array API dispatch is disabled, and np.asarray works (for example PyTorch
    # with CPU device), calling the metric function with such numpy compatible inputs
    # should work (albeit by implicitly converting to numpy arrays instead of
    # dispatching to the array library).
    try:
        np.asarray(a_xp)
        np.asarray(b_xp)
        numpy_as_array_works = True
    except (TypeError, RuntimeError, ValueError):
        # PyTorch with CUDA device and CuPy raise TypeError consistently.
        # array-api-strict chose to raise RuntimeError instead. NumPy raises
        # a ValueError if the `__array__` dunder does not return an array.
        # Exception type may need to be updated in the future for other libraries.
        numpy_as_array_works = False

    def _check_metric_matches(metric_a, metric_b, convert_a=False):
        if convert_a:
            metric_a = _convert_to_numpy(xp.asarray(metric_a), xp)
        assert_allclose(metric_a, metric_b, atol=_atol_for_type(dtype_name))

    if numpy_as_array_works:
        metric_xp = metric(a_xp, b_xp, **metric_kwargs)

        # Handle cases where multiple return values are not of the same shape,
        # e.g. precision_recall_curve:
        _check_metric_matches(metric_xp, metric_np)

        metric_xp_mixed_1 = metric(a_np, b_xp, **metric_kwargs)
        _check_metric_matches(metric_xp_mixed_1, metric_np)

        metric_xp_mixed_2 = metric(a_xp, b_np, **metric_kwargs)
        _check_metric_matches(metric_xp_mixed_2, metric_np)

    with config_context(array_api_dispatch=True):
        metric_xp = metric(a_xp, b_xp, **metric_kwargs)
        _check_metric_matches(metric_xp, metric_np, convert_a=True)


def check_array_api_unsupervised_metric(metric, array_namespace, device, dtype_name):
    y_pred = np.array([1, 0, 1, 0, 1, 1, 0])
    X = np.random.randint(10, size=(7, 10))

    check_array_api_metric(
        metric,
        array_namespace,
        device,
        dtype_name,
        a_np=X,

Review comment (suggestion):
I copied this logic (and modified it slightly) from `sklearn/metrics/tests/test_common.py`. 

If other cluster algorithms become array API compliant, this should make it simpler to test.

Code after:
        a_np=X,
        b_np=y_pred,
    )


array_api_metric_checkers = {
    calinski_harabasz_score: [
        check_array_api_unsupervised_metric,
    ]
}


def yield_metric_checker_combinations(metric_checkers=array_api_metric_checkers):
    for metric, checkers in metric_checkers.items():
        for checker in checkers:
            yield metric, checker


@pytest.mark.parametrize(
    "array_namespace, device, dtype_name",
    yield_namespace_device_dtype_combinations(),
    ids=_get_namespace_device_dtype_ids,
)
@pytest.mark.parametrize("metric, check_func", yield_metric_checker_combinations())
def test_array_api_compliance(metric, array_namespace, device, dtype_name, check_func):
    check_func(metric, array_namespace, device, dtype_name)
Repository: scikit-learn/scikit-learn
File: build_tools/update_environments_and_lock_files.py (Python)

Code before:
            "meson-python",
        ],
        # Python version from the python3 APT package in the debian-32 docker
        # image.
        "python_version": "3.12.5",
    },
    {
        "name": "ubuntu_atlas",
        "type": "pip",
        "tag": "main-ci",
        "folder": "build_tools/azure",
        "pip_dependencies": [
            "cython",
            "joblib",
            "threadpoolctl",
            "pytest",
            "pytest-xdist",
            "ninja",
            "meson-python",
        ],
        "package_constraints": {
            "joblib": "min",
            "threadpoolctl": "min",
            "cython": "min",
        },
        "python_version": "3.10.4",
    },
]


def execute_command(command_list):
    logger.debug(" ".join(command_list))
    proc = subprocess.Popen(
        command_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )

    out, err = proc.communicate()
    out, err = out.decode(errors="replace"), err.decode(errors="replace")

    if proc.returncode != 0:
        command_str = " ".join(command_list)
        raise RuntimeError(
            "Command exited with non-zero exit code.\n"
            "Exit code: {}\n"
            "Command:\n{}\n"
            "stdout:\n{}\n"
            "stderr:\n{}\n".format(proc.returncode, command_str, out, err)
        )
    logger.log(TRACE, out)
    return out


Review comment (suggestion):
@DeaMariaLeon could you regenerate the ubuntu_atlas lock-file in a follow-up PR? I am reasonably sure it would work without problems but the CI will tell us :wink:.

Code after:
            "meson-python",
        ],
        # Python version from the python3 APT package in the debian-32 docker
        # image.
        "python_version": "3.12.5",
    },
    {
        "name": "ubuntu_atlas",
        "type": "pip",
        "tag": "main-ci",
        "folder": "build_tools/azure",
        "pip_dependencies": [
            "cython",
            "joblib",
            "threadpoolctl",
            "pytest",
            "pytest-xdist",
            "ninja",
            "meson-python",
        ],
        "package_constraints": {
            "joblib": "min",
            "threadpoolctl": "min",
            "cython": "min",
        },
        "python_version": "3.12.3",
    },
]


def execute_command(command_list):
    logger.debug(" ".join(command_list))
    proc = subprocess.Popen(
        command_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )

    out, err = proc.communicate()
    out, err = out.decode(errors="replace"), err.decode(errors="replace")

    if proc.returncode != 0:
        command_str = " ".join(command_list)
        raise RuntimeError(
            "Command exited with non-zero exit code.\n"
            "Exit code: {}\n"
            "Command:\n{}\n"
            "stdout:\n{}\n"
            "stderr:\n{}\n".format(proc.returncode, command_str, out, err)
        )
    logger.log(TRACE, out)
    return out
Repository: scikit-learn/scikit-learn
File: sklearn/linear_model/tests/test_sgd.py (Python)

Code before:
    """Check that SGDOneClassSVM has the correct estimator type.

    Non-regression test for if the mixin was not on the left.
    """
    sgd_ocsvm = SGDOneClassSVM()
    assert get_tags(sgd_ocsvm).estimator_type == "outlier_detector"


def test_sgd_one_class_svm_formulation_with_scipy_minimize():
    """
    Test that the objective formulation of `SGDOneClassSVM` is appropriate by
    checking that the converged parameters are close enough to the ones output
    by scipy's `minimize` function using "L-BFGS-B".
    """
    nu = 0.5
    hinge_threshold = 1.0
    n_samples, n_features = 300, 20
    random_seed = 42

    def objective_and_grad(w, X, y, alpha):
        weights = w[:-1]
        intercept = w[-1]
        p = X @ weights + intercept
        z = p * y
        n_samples, n_features = X.shape
        sum_loss = np.where(z <= hinge_threshold, hinge_threshold - z, 0.0).sum()
        avg_loss = sum_loss / n_samples
        reg = 0.5 * alpha * np.dot(weights, weights)
        obj = avg_loss + reg + (intercept * alpha)
        grad_pointwise = np.where(z <= hinge_threshold, -y, 0.0)
        grad_pointwise /= n_samples
        grad = np.empty_like(w)
        grad[:n_features] = X.T @ grad_pointwise + alpha * weights
        grad[-1] = grad_pointwise.sum() + alpha
        return obj, grad

    rng = np.random.RandomState(random_seed)
    X = rng.rand(n_samples, n_features)
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective_and_grad,
        w0,
        method="L-BFGS-B",
        jac=True,
        args=(X, y, nu),
        options={"maxiter": 100},
    )
    w_out = scipy_output.x
    expected_coef = w_out[:-1]
    expected_offset = 1 - w_out[-1]

Review comment (suggestion):
```suggestion
        sum_loss = np.maximum(hinge_threshold - z, 0.0).sum()
```

Code after:
        reg = 0.5 * alpha * weights @ weights
        obj = avg_loss + reg + intercept * alpha
        return obj

    X, _ = make_blobs(
        n_samples=n_samples,
        n_features=n_features,
        random_state=random_seed,
    )
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective,
        w0,
        method="Nelder-Mead",
        args=(X, y, nu),
        options={"maxiter": 1000},
    )
    w_out = scipy_output.x
    expected_coef = w_out[:-1]
    expected_offset = 1 - w_out[-1]

    model = SGDOneClassSVM(
        nu=nu,
        learning_rate="constant",
        max_iter=4000,
        tol=None,
        eta0=1e-4,
        random_state=random_seed,
    )
    model.fit(X, y)

    assert_allclose(model.coef_, expected_coef, rtol=5e-3)
    assert_allclose(model.offset_, expected_offset, rtol=1e-2)
Repository: scikit-learn/scikit-learn
File: sklearn/linear_model/tests/test_sgd.py (Python)

Code before:
    Non-regression test for if the mixin was not on the left.
    """
    sgd_ocsvm = SGDOneClassSVM()
    assert get_tags(sgd_ocsvm).estimator_type == "outlier_detector"


def test_sgd_one_class_svm_formulation_with_scipy_minimize():
    """
    Test that the objective formulation of `SGDOneClassSVM` is appropriate by
    checking that the converged parameters are close enough to the ones output
    by scipy's `minimize` function using "L-BFGS-B".
    """
    nu = 0.5
    hinge_threshold = 1.0
    n_samples, n_features = 300, 20
    random_seed = 42

    def objective_and_grad(w, X, y, alpha):
        weights = w[:-1]
        intercept = w[-1]
        p = X @ weights + intercept
        z = p * y
        n_samples, n_features = X.shape
        sum_loss = np.where(z <= hinge_threshold, hinge_threshold - z, 0.0).sum()
        avg_loss = sum_loss / n_samples
        reg = 0.5 * alpha * np.dot(weights, weights)
        obj = avg_loss + reg + (intercept * alpha)
        grad_pointwise = np.where(z <= hinge_threshold, -y, 0.0)
        grad_pointwise /= n_samples
        grad = np.empty_like(w)
        grad[:n_features] = X.T @ grad_pointwise + alpha * weights
        grad[-1] = grad_pointwise.sum() + alpha
        return obj, grad

    rng = np.random.RandomState(random_seed)
    X = rng.rand(n_samples, n_features)
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective_and_grad,
        w0,
        method="L-BFGS-B",
        jac=True,
        args=(X, y, nu),
        options={"maxiter": 100},
    )
    w_out = scipy_output.x
    expected_coef = w_out[:-1]
    expected_offset = 1 - w_out[-1]

    model = SGDOneClassSVM(

Review comment (suggestion):
```suggestion
        reg = 0.5 * alpha * weights @ weights
```

Code after:
        return obj

    X, _ = make_blobs(
        n_samples=n_samples,
        n_features=n_features,
        random_state=random_seed,
    )
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective,
        w0,
        method="Nelder-Mead",
        args=(X, y, nu),
        options={"maxiter": 1000},
    )
    w_out = scipy_output.x
    expected_coef = w_out[:-1]
    expected_offset = 1 - w_out[-1]

    model = SGDOneClassSVM(
        nu=nu,
        learning_rate="constant",
        max_iter=4000,
        tol=None,
        eta0=1e-4,
        random_state=random_seed,
    )
    model.fit(X, y)

    assert_allclose(model.coef_, expected_coef, rtol=5e-3)
    assert_allclose(model.offset_, expected_offset, rtol=1e-2)
Repository: scikit-learn/scikit-learn
File: sklearn/linear_model/tests/test_sgd.py (Python)

Code before:
    sgd_64.fit(X_64, Y_64)

    sgd_32 = SGDEstimator(max_iter=22, shuffle=False)
    sgd_32.fit(X_32, Y_32)

    assert_allclose(sgd_64.coef_, sgd_32.coef_)


def test_sgd_one_class_svm_estimator_type():
    """Check that SGDOneClassSVM has the correct estimator type.

    Non-regression test for if the mixin was not on the left.
    """
    sgd_ocsvm = SGDOneClassSVM()
    assert get_tags(sgd_ocsvm).estimator_type == "outlier_detector"


def test_sgd_one_class_svm_formulation_with_scipy_minimize():
    """
    Test that the objective formulation of `SGDOneClassSVM` is appropriate by
    checking that the converged parameters are close enough to the ones output
    by scipy's `minimize` function using "L-BFGS-B".
    """
    nu = 0.5
    hinge_threshold = 1.0
    n_samples, n_features = 300, 20
    random_seed = 42

    def objective_and_grad(w, X, y, alpha):
        weights = w[:-1]
        intercept = w[-1]
        p = X @ weights + intercept
        z = p * y
        n_samples, n_features = X.shape
        sum_loss = np.where(z <= hinge_threshold, hinge_threshold - z, 0.0).sum()
        avg_loss = sum_loss / n_samples
        reg = 0.5 * alpha * np.dot(weights, weights)
        obj = avg_loss + reg + (intercept * alpha)
        grad_pointwise = np.where(z <= hinge_threshold, -y, 0.0)
        grad_pointwise /= n_samples
        grad = np.empty_like(w)
        grad[:n_features] = X.T @ grad_pointwise + alpha * weights
        grad[-1] = grad_pointwise.sum() + alpha
        return obj, grad

    rng = np.random.RandomState(random_seed)
    X = rng.rand(n_samples, n_features)
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective_and_grad,

Review comment (suggestion):
```suggestion
    n_samples, n_features = 300, 3
```

Code after:
    n_samples, n_features = 300, 3
    random_seed = 42

    def objective(w, X, y, alpha):
        weights = w[:-1]
        intercept = w[-1]
        p = X @ weights + intercept
        z = p * y
        avg_loss = np.mean(np.maximum(hinge_threshold - z, 0.0))
        reg = 0.5 * alpha * weights @ weights
        obj = avg_loss + reg + intercept * alpha
        return obj

    X, _ = make_blobs(
        n_samples=n_samples,
        n_features=n_features,
        random_state=random_seed,
    )
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective,
        w0,
        method="Nelder-Mead",
        args=(X, y, nu),
        options={"maxiter": 1000},
    )
    w_out = scipy_output.x
    expected_coef = w_out[:-1]
    expected_offset = 1 - w_out[-1]

    model = SGDOneClassSVM(
        nu=nu,
        learning_rate="constant",
        max_iter=4000,
        tol=None,
        eta0=1e-4,
        random_state=random_seed,
    )
    model.fit(X, y)

    assert_allclose(model.coef_, expected_coef, rtol=5e-3)
    assert_allclose(model.offset_, expected_offset, rtol=1e-2)
Repository: scikit-learn/scikit-learn
File: sklearn/linear_model/tests/test_sgd.py (Python)

Code before:
    """
    sgd_ocsvm = SGDOneClassSVM()
    assert get_tags(sgd_ocsvm).estimator_type == "outlier_detector"


def test_sgd_one_class_svm_formulation_with_scipy_minimize():
    """
    Test that the objective formulation of `SGDOneClassSVM` is appropriate by
    checking that the converged parameters are close enough to the ones output
    by scipy's `minimize` function using "L-BFGS-B".
    """
    nu = 0.5
    hinge_threshold = 1.0
    n_samples, n_features = 300, 20
    random_seed = 42

    def objective_and_grad(w, X, y, alpha):
        weights = w[:-1]
        intercept = w[-1]
        p = X @ weights + intercept
        z = p * y
        n_samples, n_features = X.shape
        sum_loss = np.where(z <= hinge_threshold, hinge_threshold - z, 0.0).sum()
        avg_loss = sum_loss / n_samples
        reg = 0.5 * alpha * np.dot(weights, weights)
        obj = avg_loss + reg + (intercept * alpha)
        grad_pointwise = np.where(z <= hinge_threshold, -y, 0.0)
        grad_pointwise /= n_samples
        grad = np.empty_like(w)
        grad[:n_features] = X.T @ grad_pointwise + alpha * weights
        grad[-1] = grad_pointwise.sum() + alpha
        return obj, grad

    rng = np.random.RandomState(random_seed)
    X = rng.rand(n_samples, n_features)
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective_and_grad,
        w0,
        method="L-BFGS-B",
        jac=True,
        args=(X, y, nu),
        options={"maxiter": 100},
    )
    w_out = scipy_output.x
    expected_coef = w_out[:-1]
    expected_offset = 1 - w_out[-1]

    model = SGDOneClassSVM(
        nu=nu,

Review comment (suggestion):
```suggestion
        obj = avg_loss + reg + intercept * alpha
```

Code after:

    X, _ = make_blobs(
        n_samples=n_samples,
        n_features=n_features,
        random_state=random_seed,
    )
    y = np.ones(n_samples, dtype=X.dtype)
    w0 = np.zeros(n_features + 1)
    scipy_output = minimize(
        objective,
        w0,
        method="Nelder-Mead",
        args=(X, y, nu),
        options={"maxiter": 1000},
    )
    w_out = scipy_output.x
    expected_coef = w_out[:-1]
    expected_offset = 1 - w_out[-1]

    model = SGDOneClassSVM(
        nu=nu,
        learning_rate="constant",
        max_iter=4000,
        tol=None,
        eta0=1e-4,
        random_state=random_seed,
    )
    model.fit(X, y)

    assert_allclose(model.coef_, expected_coef, rtol=5e-3)
    assert_allclose(model.offset_, expected_offset, rtol=1e-2)