Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion python/cuml/cuml/cluster/dbscan.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ class DBSCAN(Base,

cdef float eps = self.eps
cdef int min_samples = self.min_samples
cdef level_enum verbose = self.verbose
cdef level_enum verbose = self._verbose_level
cdef bool multi_gpu = self._multi_gpu
cdef size_t max_mbytes_per_batch = self.max_mbytes_per_batch or 0

Expand Down
3 changes: 1 addition & 2 deletions python/cuml/cuml/cluster/kmeans.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ from libcpp cimport bool
from pylibraft.common.handle cimport handle_t

cimport cuml.cluster.cpp.kmeans as lib
from cuml.internals.logger cimport level_enum
from cuml.metrics.distance_type cimport DistanceType


Expand All @@ -36,7 +35,7 @@ cdef _kmeans_init_params(kmeans, lib.KMeansParams& params):
params.n_clusters = kmeans.n_clusters
params.max_iter = kmeans.max_iter
params.tol = kmeans.tol
params.verbosity = <level_enum>(<int>kmeans.verbose)
params.verbosity = kmeans._verbose_level
params.metric = DistanceType.L2Expanded
params.batch_samples = int(kmeans.max_samples_per_batch)
params.oversampling_factor = kmeans.oversampling_factor
Expand Down
3 changes: 1 addition & 2 deletions python/cuml/cuml/ensemble/randomforest_common.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ class BaseRandomForestModel(Base, InteropMixin):
"min_impurity_decrease",
"max_batch_size",
"random_state",
"criterion",
Comment thread
jcrist marked this conversation as resolved.
"n_streams",
"oob_score",
"handle",
Expand Down Expand Up @@ -421,7 +420,7 @@ class BaseRandomForestModel(Base, InteropMixin):
cdef uintptr_t y_ptr = y.ptr
cdef int n_rows = X.shape[0]
cdef int n_cols = X.shape[1]
cdef level_enum verbose = <level_enum> self.verbose
cdef level_enum verbose = <level_enum> self._verbose_level
Comment thread
jcrist marked this conversation as resolved.
cdef int n_classes = self.n_classes_ if is_classifier else 0

if self.max_depth <= 0:
Expand Down
4 changes: 2 additions & 2 deletions python/cuml/cuml/experimental/linear_model/lars.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,13 @@ class Lars(Base, RegressorMixin):
larsFit(handle_[0], <float*> X_ptr, n_rows, <int> self.n_cols,
<float*> y_ptr, <float*> beta_ptr, <int*> active_idx_ptr,
<float*> alphas_ptr, &n_active, <float*> Gram_ptr,
max_iter, <float*> coef_path_ptr, self.verbose, ld_X,
max_iter, <float*> coef_path_ptr, self._verbose_level, ld_X,
ld_G, <float> self.eps)
else:
larsFit(handle_[0], <double*> X_ptr, n_rows, <int> self.n_cols,
<double*> y_ptr, <double*> beta_ptr, <int*> active_idx_ptr,
<double*> alphas_ptr, &n_active, <double*> Gram_ptr,
max_iter, <double*> coef_path_ptr, self.verbose,
max_iter, <double*> coef_path_ptr, self._verbose_level,
ld_X, ld_G, <double> self.eps)
self.n_active = n_active
self.n_iter_ = n_active
Expand Down
92 changes: 13 additions & 79 deletions python/cuml/cuml/internals/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
import cuml.internals.input_utils
import cuml.internals.logger as logger
import cuml.internals.nvtx as nvtx
from cuml.internals import api_context_managers
from cuml.internals.global_settings import GlobalSettings
from cuml.internals.input_utils import determine_array_type
from cuml.internals.mixins import TagsMixin
from cuml.internals.output_type import (
Expand All @@ -24,40 +22,6 @@
)


class VerbosityDescriptor:
"""Descriptor for ensuring correct type is used for verbosity

This descriptor ensures that when the 'verbose' attribute of a cuML
estimator is accessed external to the cuML API, an integer is returned
(consistent with Scikit-Learn's API for verbosity). Internal to the API, an
enum is used. Scikit-Learn's numerical values for verbosity are the inverse
of those used by spdlog, so the numerical value is also inverted internal
to the cuML API. This ensures that cuML code treats verbosity values as
expected for an spdlog-based codebase.
"""

def __get__(self, obj, cls=None):
if api_context_managers.in_internal_api():
return logger._verbose_to_level(obj._verbose)
else:
return obj._verbose

def __set__(self, obj, value):
if api_context_managers.in_internal_api():
assert isinstance(value, logger.level_enum), (
"The log level should always be provided as a level_enum, "
"not an integer"
)
obj._verbose = logger._verbose_from_level(value)
else:
if isinstance(value, logger.level_enum):
raise ValueError(
"The log level should always be provided as an integer, "
"not using the enum"
)
obj._verbose = value


class Base(TagsMixin, metaclass=cuml.internals.BaseMetaClass):
"""
Base class for all the ML algos. It handles some of the common operations
Expand Down Expand Up @@ -191,28 +155,10 @@ def __init__(
verbose=False,
output_type=None,
):
"""
Constructor. All children must call init method of this base class.

"""
Comment thread
jcrist marked this conversation as resolved.
self.handle = (
pylibraft.common.handle.Handle() if handle is None else handle
)

# The following manipulation of the root_cm ensures that the verbose
# descriptor sees any set or get of the verbose attribute as happening
# internal to the cuML API. Currently, __init__ calls do not take place
# within an api context manager, so setting "verbose" here would
# otherwise appear to be external to the cuML API. This behavior will
# be corrected with the update of cuML's API context manager
# infrastructure in https://github.com/rapidsai/cuml/pull/6189.
GlobalSettings().prev_root_cm = GlobalSettings().root_cm
GlobalSettings().root_cm = True
self.verbose = logger._verbose_to_level(verbose)
# Please see above note on manipulation of the root_cm. This should be
# rendered unnecessary with https://github.com/rapidsai/cuml/pull/6189.
GlobalSettings().root_cm = GlobalSettings().prev_root_cm

self.verbose = verbose
self.output_type = _check_output_type_str(
cuml.global_settings.output_type
if output_type is None
Expand All @@ -224,8 +170,6 @@ def __init__(
if nvtx_benchmark and nvtx_benchmark.lower() == "true":
self.set_nvtx_annotations()

verbose = VerbosityDescriptor()

def __repr__(self):
"""
Pretty prints the arguments of a class using Scikit-learn standard :)
Expand All @@ -250,6 +194,11 @@ def __repr__(self):
output += " <sk_model_ attribute used>"
return output

@property
def _verbose_level(self):
"""The current `verbose` setting as a `logger.level_enum`"""
return logger._verbose_to_level(self.verbose)

@classmethod
def _get_param_names(cls):
"""
Expand All @@ -267,20 +216,7 @@ def get_params(self, deep=True):
need anything other than what is there in this method, then it doesn't
have to override this method
"""
params = dict()
variables = self._get_param_names()
for key in variables:
var_value = getattr(self, key, None)
# We are currently internal to the cuML API, but the value we
# return will immediately be returned external to the API, so we
# must perform the translation from enum to integer before
# returning the value. Ordinarily, this is handled by
# VerbosityDescriptor for direct access to the verbose
# attribute.
if key == "verbose":
var_value = logger._verbose_from_level(var_value)
params[key] = var_value
return params
return {name: getattr(self, name) for name in self._get_param_names()}

def set_params(self, **params):
"""
Expand All @@ -291,15 +227,13 @@ def set_params(self, **params):
"""
if not params:
return self
variables = self._get_param_names()
valid_params = self._get_param_names()
for key, value in params.items():
if key not in variables:
raise ValueError("Bad param '%s' passed to set_params" % key)
else:
# Switch verbose to enum since we are now internal to cuML API
if key == "verbose":
value = logger._verbose_to_level(value)
setattr(self, key, value)
if key not in valid_params:
raise ValueError(
f"Invalid parameter {key!r} for `{type(self).__name__}`"
)
setattr(self, key, value)
return self

def _set_output_type(self, inp):
Expand Down
71 changes: 9 additions & 62 deletions python/cuml/cuml/internals/logger.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
# SPDX-FileCopyrightText: Copyright (c) 2020-2025, NVIDIA CORPORATION.
# SPDX-License-Identifier: Apache-2.0
#

# distutils: language = c++


import logging
Comment thread
jcrist marked this conversation as resolved.
import sys


Expand All @@ -23,6 +18,7 @@ cdef void _log_callback(int lvl, const char * msg) with gil:
"""
print(msg.decode('utf-8'), end='')


cdef void _log_flush() with gil:
"""
Default spdlogs callback function to flush logs
Expand All @@ -38,12 +34,7 @@ def _verbose_to_level(verbose: bool | int) -> level_enum:
elif verbose is False:
return level_enum.info
else:
return level_enum(6 - verbose)


def _verbose_from_level(level: level_enum) -> int:
"""Convert a `level_enum` back into an equivalent `verbose` parameter value."""
return 6 - int(level)
return level_enum(min(max(6 - verbose, 0), 6))


cdef class LogLevelSetter:
Expand Down Expand Up @@ -179,7 +170,7 @@ def should_log_for(level):
return default_logger().should_log(level)


def _log(level_enum lvl, msg, default_func):
def _log(level_enum lvl, msg):
"""
Internal function to log a message at a given level.

Expand All @@ -189,8 +180,6 @@ def _log(level_enum lvl, msg, default_func):
Logging level to be set.
msg : str
Message to be logged.
default_func : function
Default logging function to be used if GPU build is disabled.
"""
cdef string s = msg.encode("UTF-8")
default_logger().log(lvl, s)
Expand All @@ -200,115 +189,73 @@ def trace(msg):
"""
Logs a trace message, if it is enabled.

Examples
--------

.. code-block:: python

logger.trace("Hello world! This is a trace message")

Parameters
----------
msg : str
Message to be logged.
"""
# No trace level in Python so we use the closest thing, debug.
_log(level_enum.trace, msg, logging.debug)
_log(level_enum.trace, msg)


def debug(msg):
"""
Logs a debug message, if it is enabled.

Examples
--------

.. code-block:: python

logger.debug("Hello world! This is a debug message")

Parameters
----------
msg : str
Message to be logged.
"""
_log(level_enum.debug, msg, logging.debug)
_log(level_enum.debug, msg)


def info(msg):
"""
Logs an info message, if it is enabled.

Examples
--------

.. code-block:: python

logger.info("Hello world! This is a info message")

Parameters
----------
msg : str
Message to be logged.
"""
_log(level_enum.info, msg, logging.info)
_log(level_enum.info, msg)


def warn(msg):
"""
Logs a warning message, if it is enabled.

Examples
--------

.. code-block:: python

logger.warn("Hello world! This is a warning message")

Parameters
----------
msg : str
Message to be logged.
"""
_log(level_enum.warn, msg, logging.warn)
_log(level_enum.warn, msg)


def error(msg):
"""
Logs an error message, if it is enabled.

Examples
--------

.. code-block:: python

logger.error("Hello world! This is a error message")

Parameters
----------
msg : str
Message to be logged.
"""
_log(level_enum.error, msg, logging.error)
_log(level_enum.error, msg)


def critical(msg):
"""
Logs a critical message, if it is enabled.

Examples
--------

.. code-block:: python

logger.critical("Hello world! This is a critical message")

Parameters
----------
msg : str
Message to be logged.
"""
_log(level_enum.critical, msg, logging.critical)
_log(level_enum.critical, msg)


def flush():
Expand Down
2 changes: 1 addition & 1 deletion python/cuml/cuml/linear_model/elastic_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def fit(
max_iter=self.max_iter,
tol=self.tol,
penalty_normalized=False,
verbose=self.verbose,
verbose=self._verbose_level,
handle=self.handle,
)
coef = CumlArray(data=coef.to_output("cupy").flatten())
Expand Down
2 changes: 1 addition & 1 deletion python/cuml/cuml/linear_model/logistic_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def fit(
max_iter=self.max_iter,
tol=self.tol,
linesearch_max_iter=self.linesearch_max_iter,
verbose=self.verbose,
verbose=self._verbose_level,
handle=self.handle,
lbfgs_memory=self.lbfgs_memory,
penalty_normalized=self.penalty_normalized,
Expand Down
Loading