Skip to content

Commit

Permalink
Merge pull request #866 from JuliaAI/dev
Browse files Browse the repository at this point in the history
For a 0.21.1 release
  • Loading branch information
ablaom authored Nov 15, 2022
2 parents 9e12621 + a85f959 commit c5d755e
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 115 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MLJBase"
uuid = "a7f614a8-145f-11e9-1d2a-a57a1082229d"
authors = ["Anthony D. Blaom <[email protected]>"]
version = "0.21.0"
version = "0.21.1"

[deps]
CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597"
Expand Down
4 changes: 2 additions & 2 deletions src/machines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ Additional keys, `machines` and `fitted_params_given_machine`, give a
list of *all* machines in the underlying network, and a dictionary of
fitted parameters keyed on those machines.
```
See also [`report`](@ref)
"""
function fitted_params(mach::Machine)
Expand Down Expand Up @@ -858,7 +858,7 @@ Additional keys, `machines` and `report_given_machine`, give a
list of *all* machines in the underlying network, and a dictionary of
reports keyed on those machines.
```
See also [`fitted_params`](@ref)
"""
function report(mach::Machine)
Expand Down
6 changes: 4 additions & 2 deletions src/operations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ERR_ROWS_NOT_ALLOWED = ArgumentError(
"Calling `transform(mach, rows=...)` or "*
"`predict(mach, rows=...)` when "*
"`mach.model isa Static` is not allowed, as no data "*
"is bound to `mach` in this case. Specify a explicit "*
"is bound to `mach` in this case. Specify an explicit "*
"data or node, as in `transform(mach, X)`, or "*
"`transform(mach, X1, X2, ...)`. "
)
Expand Down Expand Up @@ -240,7 +240,9 @@ for (operation, fallback) in [(:predict_mode, :mode),
if $(QuoteNode(operation)) in MLJBase.operations(fitresult)
return output_and_report(fitresult, $(QuoteNode(operation)), Xnew)
end
return $(fallback).(predict(m, fitresult, Xnew))
# The following line retuns a `Tuple` since `m` is a `NetworkComposite`
predictions, report = predict(m, fitresult, Xnew)
return $(fallback).(predictions), report
end
end |> eval
end
66 changes: 59 additions & 7 deletions test/_models/Transformers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
export FeatureSelector,
UnivariateStandardizer, Standardizer,
UnivariateBoxCoxTransformer,
OneHotEncoder, UnivariateDiscretizer
OneHotEncoder, UnivariateDiscretizer, Averager

using Statistics

Expand Down Expand Up @@ -568,16 +568,62 @@ function MLJBase.transform(transformer::OneHotEncoder, fitresult, X)
return MLJBase.table(named_cols, prototype=X)
end

"""
Averager(; mix = 0.5)
Static Unsupervised mode for computing the weighted sum of two vectors with weight `mix`.
"""
mutable struct Averager <: Static
mix::Float64
end

function MLJBase.clean!(model::Averager)
warning = ""
if model.mix > 1 || model.mix < 0
warning *= "Need `0 ≤ mix ≤ 1`. Resetting `mix=0.5`` "
model.mix = 0.5
end
return warning
end

function Averager(; mix=0.0)
model = Averager(mix)
message = MLJBase.clean!(model)
isempty(message) || @warn message
return model
end

function MLJBase.transform(m::Averager, _, y1, y2)
if !(y1 isa AbstractVector && y2 isa AbstractVector)
throw(
ArgumentError(
"Both inputs to the `Averager` transform must be "*
"instances of `AbstractVector`"
)
)
end
average = ((1 - m.mix) .* y1) .+ (m.mix .* y2)
return average
end

##
## Metadata for all built-in transformers
##

metadata_pkg.((FeatureSelector, UnivariateStandardizer,
UnivariateDiscretizer, Standardizer,
UnivariateBoxCoxTransformer, OneHotEncoder),
name="MLJBase",
julia=true,
license="MIT")
metadata_pkg.(
(
FeatureSelector,
UnivariateStandardizer,
UnivariateDiscretizer,
Standardizer,
UnivariateBoxCoxTransformer,
OneHotEncoder,
Averager
),
name="MLJBase",
julia=true,
license="MIT"
)

metadata_model(FeatureSelector,
input=MLJBase.Table,
Expand Down Expand Up @@ -614,3 +660,9 @@ metadata_model(OneHotEncoder,
output=MLJBase.Table,
weights=false,
path="MLJBase.OneHotEncoder")

metadata_model(Averager,
output=AbstractVector{MLJBase.Continuous},
weights=false,
path="MLJBase.Averager"
)
204 changes: 102 additions & 102 deletions test/_models/simple_composite_model.jl
Original file line number Diff line number Diff line change
@@ -1,117 +1,117 @@
export SimpleDeterministicCompositeModel, SimpleDeterministicNetworkCompositeModel
export SimpleDeterministicCompositeModel, SimpleDeterministicNetworkCompositeModel,
SimpleProbabilisticCompositeModel, SimpleProbabilisticNetworkCompositeModel

using MLJBase

"""
SimpleDeterministicCompositeModel(;regressor=ConstantRegressor(),
transformer=FeatureSelector())
Construct a composite model consisting of a transformer
(`Unsupervised` model) followed by a `Deterministic` model. Mainly
intended for internal testing .
"""
mutable struct SimpleDeterministicCompositeModel{L<:Deterministic,
T<:Unsupervised} <: DeterministicComposite
model::L
transformer::T

const COMPOSITE_MODELS = [
:SimpleDeterministicCompositeModel,
:SimpleProbabilisticCompositeModel,
:SimpleDeterministicNetworkCompositeModel,
:SimpleProbabilisticNetworkCompositeModel
]
const REGRESSORS = Dict(
:SimpleDeterministicCompositeModel => :DeterministicConstantRegressor,
:SimpleDeterministicNetworkCompositeModel => :DeterministicConstantRegressor,
:SimpleProbabilisticCompositeModel => :ConstantRegressor,
:SimpleProbabilisticNetworkCompositeModel => :ConstantRegressor,
)

const REGRESSOR_SUPERTYPES = Dict(
:SimpleDeterministicCompositeModel => :Deterministic,
:SimpleDeterministicNetworkCompositeModel => :Deterministic,
:SimpleProbabilisticCompositeModel => :Probabilistic,
:SimpleProbabilisticNetworkCompositeModel => :Probabilistic,
)

const COMPOSITE_SUPERTYPES = Dict(
:SimpleDeterministicCompositeModel => :DeterministicComposite,
:SimpleDeterministicNetworkCompositeModel => :DeterministicNetworkComposite,
:SimpleProbabilisticCompositeModel => :ProbabilisticComposite,
:SimpleProbabilisticNetworkCompositeModel => :ProbabilisticNetworkComposite,
)


for model in COMPOSITE_MODELS
regressor = REGRESSORS[model]
regressor_supertype = REGRESSOR_SUPERTYPES[model]
composite_supertype = COMPOSITE_SUPERTYPES[model]
quote
"""
(model)(; regressor=$($(regressor))(), transformer=FeatureSelector())
Construct a composite model consisting of a transformer
(`Unsupervised` model) followed by a `$($(regressor_supertype))` model. Mainly
intended for internal testing .
"""
mutable struct $(model){
L<:$(regressor_supertype),
T<:Unsupervised
} <: $(composite_supertype)
model::L
transformer::T
end

function $(model)(;
model=$(regressor)(), transformer=FeatureSelector()
)
composite = $(model)(model, transformer)
message = MLJBase.clean!(composite)
isempty(message) || @warn message
return composite
end

MLJBase.metadata_pkg(
$(model);
package_url = "https://github.com/alan-turing-institute/MLJBase.jl",
is_pure_julia = true,
is_wrapper = true
)

MLJBase.input_scitype(::Type{<:$(model){L,T}}) where {L,T} =
MLJBase.input_scitype(T)
MLJBase.target_scitype(::Type{<:$(model){L,T}}) where {L,T} =
MLJBase.target_scitype(L)

end |> eval
end

function SimpleDeterministicCompositeModel(;
model=DeterministicConstantRegressor(),
transformer=FeatureSelector())
## FIT METHODS
for model in COMPOSITE_MODELS[1:2]
@eval function MLJBase.fit(
composite::$(model), verbosity::Integer, Xtrain, ytrain
)
X = source(Xtrain) # instantiates a source node
y = source(ytrain)

composite = SimpleDeterministicCompositeModel(model, transformer)
t = machine(composite.transformer, X)
Xt = transform(t, X)

message = MLJBase.clean!(composite)
isempty(message) || @warn message
l = machine(composite.model, Xt, y)
yhat = predict(l, Xt)

return composite
mach = machine($(REGRESSOR_SUPERTYPES[model])(), X, y; predict=yhat)

return!(mach, composite, verbosity)
end
end

MLJBase.is_wrapper(::Type{<:SimpleDeterministicCompositeModel}) = true
for model in COMPOSITE_MODELS[3:4]
@eval function MLJBase.prefit(
composite::$(model),
verbosity::Integer,
Xtrain,
ytrain
)
X = source(Xtrain) # instantiates a source node
y = source(ytrain)

function MLJBase.fit(composite::SimpleDeterministicCompositeModel,
verbosity::Integer, Xtrain, ytrain)
X = source(Xtrain) # instantiates a source node
y = source(ytrain)
t = machine(:transformer, X)
Xt = transform(t, X)

t = machine(composite.transformer, X)
Xt = transform(t, X)
l = machine(:model, Xt, y)
yhat = predict(l, Xt)

l = machine(composite.model, Xt, y)
yhat = predict(l, Xt)

mach = machine(Deterministic(), X, y; predict=yhat)

return!(mach, composite, verbosity)
(predict=yhat,)
end
end

MLJBase.load_path(::Type{<:SimpleDeterministicCompositeModel}) =
"MLJBase.SimpleDeterministicCompositeModel"
MLJBase.package_uuid(::Type{<:SimpleDeterministicCompositeModel}) = ""
MLJBase.package_url(::Type{<:SimpleDeterministicCompositeModel}) =
"https://github.com/alan-turing-institute/MLJBase.jl"
MLJBase.is_pure_julia(::Type{<:SimpleDeterministicCompositeModel}) = true
MLJBase.input_scitype(::Type{<:SimpleDeterministicCompositeModel{L,T}}) where {L,T} =
MLJBase.input_scitype(T)
MLJBase.target_scitype(::Type{<:SimpleDeterministicCompositeModel{L,T}}) where {L,T} =
MLJBase.target_scitype(L)

"""
SimpleDeterministicCompositeNetworkModel(;regressor=ConstantRegressor(),
transformer=FeatureSelector())
Construct a composite model consisting of a transformer
(`Unsupervised` model) followed by a `Deterministic` model. Mainly
intended for internal testing .
"""
mutable struct SimpleDeterministicNetworkCompositeModel{L<:Deterministic,
T<:Unsupervised} <: DeterministicNetworkComposite
model::L
transformer::T

end

function SimpleDeterministicNetworkCompositeModel(;
model=DeterministicConstantRegressor(),
transformer=FeatureSelector())

composite = SimpleDeterministicNetworkCompositeModel(model, transformer)

message = MLJBase.clean!(composite)
isempty(message) || @warn message

return composite

end

MLJBase.is_wrapper(::Type{<:SimpleDeterministicNetworkCompositeModel}) = true

function MLJBase.prefit(composite::SimpleDeterministicNetworkCompositeModel,
verbosity::Integer, Xtrain, ytrain)
X = source(Xtrain) # instantiates a source node
y = source(ytrain)

t = machine(:transformer, X)
Xt = transform(t, X)

l = machine(:model, Xt, y)
yhat = predict(l, Xt)

(predict=yhat,)
end

MLJBase.load_path(::Type{<:SimpleDeterministicNetworkCompositeModel}) =
"MLJBase.SimpleDeterministicNetworkCompositeModel"
MLJBase.package_uuid(::Type{<:SimpleDeterministicNetworkCompositeModel}) = ""
MLJBase.package_url(::Type{<:SimpleDeterministicNetworkCompositeModel}) =
"https://github.com/alan-turing-institute/MLJBase.jl"
MLJBase.is_pure_julia(::Type{<:SimpleDeterministicNetworkCompositeModel}) = true
MLJBase.input_scitype(::Type{<:SimpleDeterministicNetworkCompositeModel{L,T}}) where {L,T} =
MLJBase.input_scitype(T)
MLJBase.target_scitype(::Type{<:SimpleDeterministicNetworkCompositeModel{L,T}}) where {L,T} =
MLJBase.target_scitype(L)
Loading

0 comments on commit c5d755e

Please sign in to comment.