JuliaAI / MLJBase.jl

Core functionality for the MLJ machine learning framework
MIT License
160 stars 46 forks source link

Add facility to specify a default logger different from `nothing` #926

Open ablaom opened 11 months ago

ablaom commented 11 months ago

This could be provided as either part of #925 or as a follow-up PR.

The idea is to define a global variable DEFAULT_LOGGER and to make the default value of the logger keyword option in evaluate! equal to DEFAULT_LOGGER, rather than nothing. (And later, do the same for TunedModel and IteratedModel; see https://github.com/alan-turing-institute/MLJ.jl/issues/1029.)

In __init__ the DEFAULT_LOGGER would be set to nothing but MLJBase will provide a public method default_logger to set and inspect the value. For example:

# inspecting:
julia> default_logger()
nothing

# changing:
using MLFlow
julia> default_logger(MLFlowLogger())
MLFlowLogger(MLFlow(
    baseuri = "http://127.0.0.1:5000", 
    apiversion = 2.0
), "MLJ experiment", nothing)

The required code can be modelled exactly on the DEFAULT_RESOURCE global variable (see src/init.jl) and the default_resource setter/getter (see src/MLJBase.jl).

To do after this integration:

@pebeto

pebeto commented 11 months ago

Does this change replace our keyword argument in evaluate! and save?

ablaom commented 11 months ago

Yes, everywhere we have a keyword argument logger=nothing , we need to change to logger=default_logger(). At present, that's just evaluate!.

In the case of MLJBase.save, there is nothing in MLJBase that connects save to logging. That happens only in MLJFlow.jl, where MLJBase.save(::MLFlowLogger, ::Machine) is overloaded. I suppose we could arrange that MLBase.save(mach) saves the machine to the default logger, ie, do something like this in MLJBase:

const ERR_INVALID_DEFAULT_LOGGER = ArgumentError(
    "`default_logger()` is currently `nothing`. Either specify an explicit path or stream as "
    "target of the save, or use `default_logger(logger)` to change the default logger. "
)
"""
    <new doc string>
"""
MLJBase.save(mach::Machine) = MLJBase(default_logger, mach)
MLJBase.save(::Nothing, ::Machine) = throw(ERR_INVALID_DEFAULT_LOGGER)

What do you think?

pebeto commented 11 months ago

Awesome, how it could be used by MLJTuning and MLJIteration? Are we going to call to certain functions defined by us inside that packages?