From f7aca9585c42dfc8be7b631ea6a9d33e29ab6153 Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Fri, 14 Aug 2020 12:36:22 +1200 Subject: [PATCH 01/10] "Bump version to 0.14.8" --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index b8abe02a..72e0bd9a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MLJBase" uuid = "a7f614a8-145f-11e9-1d2a-a57a1082229d" authors = ["Anthony D. Blaom "] -version = "0.14.7" +version = "0.14.8" [deps] CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597" From e0d124afacf40d21e982e20b5bf41a12162c1b29 Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Fri, 14 Aug 2020 13:23:08 +1200 Subject: [PATCH 02/10] eliminate mention of `Scientific` type --- src/MLJBase.jl | 2 +- test/_models/Constant.jl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/MLJBase.jl b/src/MLJBase.jl index a24aeb1b..601eac31 100644 --- a/src/MLJBase.jl +++ b/src/MLJBase.jl @@ -101,7 +101,7 @@ export matrix, int, classes, decoder, table, nrows, selectrows, selectcols, select # re-exports from (MLJ)ScientificTypes -export Scientific, Found, Unknown, Known, Finite, Infinite, +export Unknown, Known, Finite, Infinite, OrderedFactor, Multiclass, Count, Continuous, Textual, Binary, ColorImage, GrayImage, Image, Table export scitype, scitype_union, elscitype, nonmissing, trait diff --git a/test/_models/Constant.jl b/test/_models/Constant.jl index 263536f8..94d06ee7 100644 --- a/test/_models/Constant.jl +++ b/test/_models/Constant.jl @@ -112,28 +112,28 @@ metadata_pkg.((ConstantRegressor, ConstantClassifier, is_wrapper=false) metadata_model(ConstantRegressor, - input=MLJBase.Table(MLJBase.Scientific), + input=MLJBase.Table, target=AbstractVector{MLJBase.Continuous}, weights=false, descr="Constant regressor (Probabilistic).", path="MLJModels.ConstantRegressor") metadata_model(DeterministicConstantRegressor, - input=MLJBase.Table(MLJBase.Scientific), + input=MLJBase.Table, target=AbstractVector{MLJBase.Continuous}, weights=false, descr="Constant regressor (Deterministic).", path="MLJModels.DeterministicConstantRegressor") metadata_model(ConstantClassifier, - input=MLJBase.Table(MLJBase.Scientific), + input=MLJBase.Table, target=AbstractVector{<:MLJBase.Finite}, weights=true, descr="Constant classifier (Probabilistic).", path="MLJModels.ConstantClassifier") metadata_model(DeterministicConstantClassifier, - input=MLJBase.Table(MLJBase.Scientific), + input=MLJBase.Table, target=AbstractVector{<:MLJBase.Finite}, weights=false, descr="Constant classifier (Deterministic).", From 92b9d7234b4f9b2f770420bc4563a8fdeed66497 Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Fri, 14 Aug 2020 16:07:45 +1200 Subject: [PATCH 03/10] revert CI 1.5 -> 1.4 until StableRNGs issue is resolved --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 03a498a3..afa9ea81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ env: - JULIA_NUM_THREADS=30 julia: - 1.0 - - 1.5 + - 1.4 - nightly jobs: allow_failures: From 4d2e83a5a516f23c2ddd6fbccd183d908b8c4569 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Tue, 18 Aug 2020 15:55:18 +0000 Subject: [PATCH 04/10] Make some code more concise This makes the `predict_mode`, `predict_mean`, and `predict_median` code more concise in the case of surrogate and composite models. --- src/operations.jl | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/operations.jl b/src/operations.jl index d49ae317..512660ad 100644 --- a/src/operations.jl +++ b/src/operations.jl @@ -106,29 +106,16 @@ for operation in [:predict, :transform, :inverse_transform] eval(ex) end -function predict_mode(m::Union{ProbabilisticComposite,ProbabilisticSurrogate}, - fitresult, - Xnew) - if haskey(fitresult, :predict_mode) - return fitresult.predict_mode(Xnew) - end - return mode.(predict(m, fitresult, Xnew)) -end - -function predict_mean(m::Union{ProbabilisticComposite,ProbabilisticSurrogate}, - fitresult, - Xnew) - if haskey(fitresult, :predict_mean) - return fitresult.predict_mean(Xnew) - end - return mean.(predict(m, fitresult, Xnew)) -end - -function predict_median(m::Union{ProbabilisticComposite,ProbabilisticSurrogate}, - fitresult, - Xnew) - if haskey(fitresult, :predict_median) - return fitresult.predict_median(Xnew) +for (operation, fallback) in [(:predict_mode, :mode), (:predict_mean, :mean), (:predict_median, :median)] + ex = quote + function $(operation)(m::Union{ProbabilisticComposite,ProbabilisticSurrogate}, + fitresult, + Xnew) + if haskey(fitresult, $(QuoteNode(operation))) + return fitresult.$(operation)(Xnew) + end + return $(fallback).(predict(m, fitresult, Xnew)) + end end - return median.(predict(m, fitresult, Xnew)) + eval(ex) end From 440839f084c1b14dfaf5d447ff47d300016c906f Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Wed, 19 Aug 2020 10:57:17 +1200 Subject: [PATCH 05/10] rm multiple listings in implemented_methods trait --- src/interface/model_api.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/model_api.jl b/src/interface/model_api.jl index 11d4164a..d88adfa7 100644 --- a/src/interface/model_api.jl +++ b/src/interface/model_api.jl @@ -33,7 +33,7 @@ predict_median(m, fitresult, Xnew, ::Val{<:BadMedianTypes}) = # not in MLJModelInterface as methodswith requires InteractiveUtils MLJModelInterface.implemented_methods(::FI, M::Type{<:MLJType}) = - getfield.(methodswith(M), :name) + getfield.(methodswith(M), :name) |> unique # serialization fallbacks: # Here `file` can be `String` or `IO` (eg, `file=IOBuffer()`). From 5aeb3c0d504ecf20454c46d4c03a8a808a68cc6d Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Tue, 18 Aug 2020 15:33:27 +0000 Subject: [PATCH 06/10] Add the `:predict_joint` operation, and add composite and surrogate types for `JointProbabilistic` --- src/composition/abstract_types.jl | 10 ++++++++-- src/operations.jl | 12 ++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/composition/abstract_types.jl b/src/composition/abstract_types.jl index 00b7fe12..9c176864 100644 --- a/src/composition/abstract_types.jl +++ b/src/composition/abstract_types.jl @@ -1,6 +1,7 @@ # true composite models: abstract type DeterministicComposite <: Deterministic end abstract type ProbabilisticComposite <: Probabilistic end +abstract type JointProbabilisticComposite <: JointProbabilistic end abstract type IntervalComposite <: Interval end abstract type UnsupervisedComposite <: Unsupervised end abstract type StaticComposite <: Static end @@ -8,24 +9,27 @@ abstract type StaticComposite <: Static end # surrogate composite models: struct DeterministicSurrogate <: Deterministic end struct ProbabilisticSurrogate <: Probabilistic end +struct JointProbabilisticSurrogate <: JointProbabilistic end struct IntervalSurrogate <: Interval end struct UnsupervisedSurrogate <: Unsupervised end struct StaticSurrogate <: Static end Deterministic() = DeterministicSurrogate() Probabilistic() = ProbabilisticSurrogate() +JointProbabilistic() = JointProbabilisticSurrogate() Interval() = IntervalSurrogate() Unsupervised() = UnsupervisedSurrogate() Static() = StaticSurrogate() const SupervisedComposite = - Union{DeterministicComposite,ProbabilisticComposite,IntervalComposite} + Union{DeterministicComposite,ProbabilisticComposite,JointProbabilisticComposite,IntervalComposite} const SupervisedSurrogate = - Union{DeterministicSurrogate,ProbabilisticSurrogate,IntervalSurrogate} + Union{DeterministicSurrogate,ProbabilisticSurrogate,JointProbabilisticSurrogate,IntervalSurrogate} const Surrogate = Union{DeterministicSurrogate, ProbabilisticSurrogate, + JointProbabilisticSurrogate, IntervalSurrogate, UnsupervisedSurrogate, StaticSurrogate} @@ -35,10 +39,12 @@ const Composite = Union{SupervisedComposite,UnsupervisedComposite, for T in [:DeterministicComposite, :ProbabilisticComposite, + :JointProbabilisticComposite, :IntervalComposite, :UnsupervisedComposite, :StaticComposite, :DeterministicSurrogate, + :JointProbabilisticSurrogate, :ProbabilisticSurrogate, :IntervalSurrogate, :UnsupervisedSurrogate, diff --git a/src/operations.jl b/src/operations.jl index 512660ad..9dc51f55 100644 --- a/src/operations.jl +++ b/src/operations.jl @@ -22,7 +22,7 @@ ## TODO: need to add checks on the arguments of ## predict(::Machine, ) and transform(::Machine, ) -const OPERATIONS = (:predict, :predict_mean, :predict_mode, :predict_median, +const OPERATIONS = (:predict, :predict_mean, :predict_mode, :predict_median, :predict_joint, :transform, :inverse_transform) for operation in OPERATIONS @@ -70,19 +70,19 @@ for operation in OPERATIONS ex = quote # 1. operations on machines, given *concrete* data: - function $operation(mach::Machine, Xraw) + function $operation(mach::Machine, Xraw; kwargs...) if mach.state > 0 return $(operation)(mach.model, mach.fitresult, - Xraw) + Xraw; kwargs...) else error("$mach has not been trained.") end end - function $operation(mach::Machine{<:Static}, Xraw, Xraw_more...) + function $operation(mach::Machine{<:Static}, Xraw, Xraw_more...; kwargs...) isdefined(mach, :fitresult) || (mach.fitresult = nothing) return $(operation)(mach.model, mach.fitresult, - Xraw, Xraw_more...) + Xraw, Xraw_more...; kwargs...) end # 2. operations on machines, given *dynamic* data (nodes): @@ -98,7 +98,7 @@ end ## SURROGATE AND COMPOSITE MODELS -for operation in [:predict, :transform, :inverse_transform] +for operation in [:predict, :predict_joint, :transform, :inverse_transform] ex = quote $operation(model::Union{Composite,Surrogate}, fitresult,X) = fitresult.$operation(X) From b5fd923585a9f06e34a44af789b92b28b935bb39 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Fri, 21 Aug 2020 04:02:10 +0000 Subject: [PATCH 07/10] Remove kwargs --- src/operations.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/operations.jl b/src/operations.jl index 9dc51f55..1ae621ba 100644 --- a/src/operations.jl +++ b/src/operations.jl @@ -70,19 +70,19 @@ for operation in OPERATIONS ex = quote # 1. operations on machines, given *concrete* data: - function $operation(mach::Machine, Xraw; kwargs...) + function $operation(mach::Machine, Xraw) if mach.state > 0 return $(operation)(mach.model, mach.fitresult, - Xraw; kwargs...) + Xraw) else error("$mach has not been trained.") end end - function $operation(mach::Machine{<:Static}, Xraw, Xraw_more...; kwargs...) + function $operation(mach::Machine{<:Static}, Xraw, Xraw_more...) isdefined(mach, :fitresult) || (mach.fitresult = nothing) return $(operation)(mach.model, mach.fitresult, - Xraw, Xraw_more...; kwargs...) + Xraw, Xraw_more...) end # 2. operations on machines, given *dynamic* data (nodes): From b663e41ae669f0840b5620eab6429514815ef5b8 Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Fri, 21 Aug 2020 12:41:35 +1200 Subject: [PATCH 08/10] improve error message for exception thrown by composite models #358 improve error message for exception thrown by composite models #358 re-instate tests --- src/composition/learning_networks/nodes.jl | 42 +++++++----- src/machines.jl | 70 +++++++++++++------- src/sources.jl | 35 ++++++++++ test/composition/learning_networks/nodes.jl | 51 +++++++++++--- test/composition/models/_wrapped_function.jl | 1 + test/composition/models/pipelines.jl | 9 +++ 6 files changed, 156 insertions(+), 52 deletions(-) diff --git a/src/composition/learning_networks/nodes.jl b/src/composition/learning_networks/nodes.jl index b0c30aec..ba927a50 100644 --- a/src/composition/learning_networks/nodes.jl +++ b/src/composition/learning_networks/nodes.jl @@ -103,24 +103,34 @@ color(N::Node) = (N.machine.frozen ? :red : :green) # constructor for static operations: Node(operation, args::AbstractNode...) = Node(operation, nothing, args...) -# make nodes callable: -(y::Node)(; rows=:) = - (y.operation)(y.machine, [arg(rows=rows) for arg in y.args]...) -function (y::Node)(Xnew) - length(y.origins) == 1 || - error("Node $y has multiple origins and cannot be called "* +_check(y::Node) = nothing +_check(y::Node{Nothing}) = length(y.origins) == 1 ? nothing : + error("Node $y has multiple origins and cannot be called "* "on new data. ") - return (y.operation)(y.machine, [arg(Xnew) for arg in y.args]...) -end -# and for the special case of static operations: -(y::Node{Nothing})(; rows=:) = - (y.operation)([arg(rows=rows) for arg in y.args]...) -function (y::Node{Nothing})(Xnew) - length(y.origins) == 1 || - error("Node $y has multiple origins and cannot be called "* - "on new data. ") - return (y.operation)([arg(Xnew) for arg in y.args]...) +# make nodes callable: +(y::Node)(; rows=:) = _apply((y, y.machine); rows=rows) +(y::Node)(Xnew) = (_check(y); _apply((y, y.machine), Xnew)) +(y::Node{Nothing})(; rows=:) = _apply((y, ); rows=rows) +(y::Node{Nothing})(Xnew)= (_check(y); _apply((y, ), Xnew)) + +function _apply(y_plus, input...; kwargs...) + y = y_plus[1] + mach = y_plus[2:end] # in static case this is () + raw_args = map(y.args) do arg + arg(input...; kwargs...) + end + try + (y.operation)(mach..., raw_args...) + catch exception + @error "Failed "* + "to apply the operation `$(y.operation)` to the machine "* + "$(y.machine), which receives it's data arguments from one or more "* + "nodes in a learning network. Possibly, one of these nodes "* + "is delivering data that is incompatible with the machine's model.\n"* + diagnostics(y, input...; kwargs...) + throw(exception) + end end ScientificTypes.elscitype(N::Node) = Unknown diff --git a/src/machines.jl b/src/machines.jl index 9f743026..59be05d1 100644 --- a/src/machines.jl +++ b/src/machines.jl @@ -49,20 +49,23 @@ end # makes sense if they are actually source nodes. function check(model::Supervised, args... ; full=false) + + nowarns = true + nargs = length(args) if nargs == 2 X, y = args elseif nargs > 2 - supports_weights(model) || - @info("$(typeof(model)) does not support sample weights and " * - "the supplied weights will be ignored in training.\n" * - "However, supplied weights will be passed to " * - "weight-supporting measures on calls to `evaluate!` " * + supports_weights(model) || elscitype(args[3]) <: Unknown || + @info("$(typeof(model)) does not support sample weights and "* + "the supplied weights will be ignored in training.\n"* + "However, supplied weights will be passed to "* + "weight-supporting measures on calls to `evaluate!` "* "and in tuning. ") X, y, w = args else - throw(ArgumentError("Use `machine(model, X, y)` or " * - "`machine(model, X, y, w)` for a supervised " * + throw(ArgumentError("Use `machine(model, X, y)` or "* + "`machine(model, X, y, w)` for a supervised "* "model.")) end @@ -70,39 +73,41 @@ function check(model::Supervised, args... ; full=false) # checks on input type: input_scitype(model) <: Unknown || elscitype(X) <: input_scitype(model) || - @warn "The scitype of `X`, in `machine(model, X, ...)` " - "is incompatible with " * - "`model`:\nscitype(X) = $(elscitype(X))\n" * - "input_scitype(model) = $(input_scitype(model))." + (@warn("The scitype of `X`, in `machine(model, X, ...)` "* + "is incompatible with "* + "`model=$model`:\nscitype(X) = $(elscitype(X))\n"* + "input_scitype(model) = $(input_scitype(model))."); nowarns=false) # checks on target type: target_scitype(model) <: Unknown || elscitype(y) <: target_scitype(model) || - @warn "The scitype of `y`, in `machine(model, X, y, ...)` " * - "is incompatible with " * - "`model`:\nscitype(y) = $(elscitype(y))\n" * - "target_scitype(model) = $(target_scitype(model))." + (@warn("The scitype of `y`, in `machine(model, X, y, ...)` "* + "is incompatible with "* + "`model=$model`:\nscitype(y) = $(elscitype(y))\ntarget_scitype(model) "* + "= $(target_scitype(model))."); nowarns=false) # checks on dimension matching: X() === nothing || # model fits a distribution to y nrows(X()) == nrows(y()) || throw(DimensionMismatch("Differing number of observations "* "in input and target. ")) - if nargs > 2 - w.data isa AbstractVector{<:Real} || w.data === nothing || + if nargs > 2 && !(w.data isa Nothing) + w.data isa AbstractVector{<:Real} || throw(ArgumentError("Weights must be real.")) nrows(w()) == nrows(y()) || throw(DimensionMismatch("Weights and target "* "differ in length.")) end end - return nothing + return nowarns end function check(model::Unsupervised, args...; full=false) + nowarns = true + nargs = length(args) nargs <= 1 || - throw(ArgumentError("Wrong number of arguments. Use " * + throw(ArgumentError("Wrong number of arguments. Use "* "`machine(model, X)` for an unsupervised model, "* "or `machine(model)` if there are no training "* "arguments (`Static` transformers).) ")) @@ -111,11 +116,11 @@ function check(model::Unsupervised, args...; full=false) # check input scitype input_scitype(model) <: Unknown || elscitype(X) <: input_scitype(model) || - @warn "The scitype of `X`, in `machine(model, X)` is "* - "incompatible with `model`:\nscitype(X) = $(elscitype(X))\n" * - "input_scitype(model) = $(input_scitype(model))." + (@warn("The scitype of `X`, in `machine(model, X)` is "* + "incompatible with `model=$model`:\nscitype(X) = $(elscitype(X))\n"* + "input_scitype(model) = $(input_scitype(model))."); nowarns=false) end - return nothing + return nowarns end @@ -414,7 +419,22 @@ function fit_only!(mach::Machine; rows=nothing, verbosity=1, force=false) # fit the model: fitlog(mach, :train, verbosity) mach.fitresult, mach.cache, mach.report = - fit(mach.model, verbosity, raw_args...) + try + fit(mach.model, verbosity, raw_args...) + catch exception + @error "Problem fitting the machine $mach, "* + "possibly because an upstream node in a learning "* + "network is providing data of incompatible scitype. " + _sources = sources(glb(mach.args...)) + length(_sources) > 2 || + mach.model isa Composite || + all((!isempty).(_sources)) || + @warn "Some learning network source nodes are empty. " + @info "Running type checks... " + check(mach.model, source.(raw_args)... ; full=true) && + @info "Type checks okay. " + throw(exception) + end elseif mach.model != mach.old_model # update the model: fitlog(mach, :update, verbosity) @@ -448,7 +468,7 @@ end fit!(mach::Machine, rows=nothing, verbosity=1, force=false) Fit the machine `mach`. In the case that `mach` has `Node` arguments, -first train all other machines on which `mach` depends. +first train all other machines on which `mach` depends. To attempt to fit a machine without touching any other machine, use `fit_only!`. For more on the internal logic of fitting see diff --git a/src/sources.jl b/src/sources.jl index be378d24..19167a58 100644 --- a/src/sources.jl +++ b/src/sources.jl @@ -76,6 +76,41 @@ function (X::Source)(; rows=:) end (X::Source)(Xnew) = Xnew +# return a string of diagnostics for the call `X(input...; kwargs...)` +diagnostic_table_sources(X::AbstractNode) = + "Learning network sources:\n"* + "source\tscitype\n"* + "-------------------------------------------\n"* + reduce(*, ("$s\t$(scitype(s()))\n" for s in sources(X))) + +function diagnostics(X::AbstractNode, input...; kwargs...) + raw_args = map(X.args) do arg + arg(input...; kwargs...) + end + _sources = sources(X) + scitypes = scitype.(raw_args) + mach = X.machine + model = mach.model + _input = input_scitype(model) + _target = target_scitype(model) + _output = output_scitype(model) + + table1 = "Incoming data:\n"* + "arg of $(X.operation)\tscitype\n"* + "-------------------------------------------\n"* + reduce(*, ("$(X.args[j])\t$(scitypes[j])\n" for j in eachindex(X.args))) + + table2 = diagnostic_table_sources(X) + return """ + Model ($model): + input_scitype = $_input + target_scitype =$_target + output_scitype =$_output + + $table1 + $table2""" +end + """ rebind!(s, X) diff --git a/test/composition/learning_networks/nodes.jl b/test/composition/learning_networks/nodes.jl index 07aea74e..753f11c6 100644 --- a/test/composition/learning_networks/nodes.jl +++ b/test/composition/learning_networks/nodes.jl @@ -12,12 +12,41 @@ seed!(1234) @load KNNRegressor +@load DecisionTreeClassifier -@testset "network #1" begin +N =100 +X = (x1=rand(N), x2=rand(N), x3=rand(N)); +y = 2X.x1 - X.x2 + 0.05*rand(N); - N =100 - X = (x1=rand(N), x2=rand(N), x3=rand(N)); - y = 2X.x1 - X.x2 + 0.05*rand(N); +@testset "error messages for invalid learning networks" begin + + Xs = source(X) + ys = source(y) + mach1 = machine(Standardizer(), Xs) + W = transform(mach1, Xs) + fit!(W) + @test_logs((:error, r"Failed"), @test_throws Exception W(34)) + + mach2 = machine(DecisionTreeClassifier(), W, ys) + yhat = predict(mach2, W) + @test_logs((:error, r"because an upstream"), + (:info, r"Running type checks"), + (:warn, r"^The scitype of"), + (:error, r"^Problem fitting"), + @test_throws Exception fit!(yhat, verbosity=-1)) + + Xs = source() + mach1 = machine(Standardizer(), Xs) + W = transform(mach1, Xs) + @test_logs((:error, r"^Problem"), + (:warn, r"are empty"), + (:info, r"Running"), + (:warn, r"^The scitype of "), + (:error, r"^Problem"), + @test_throws Exception fit!(W, verbosity=-1)) +end + +@testset "network #1" begin knn_ = KNNRegressor(K=7) @@ -170,11 +199,11 @@ end # error handling: MLJBase.rebind!(X, "junk") - @test_logs((:info, r"Not"), - (:info, r"Not"), - (:error, r"Problem"), - (:error, r"Problem"), - @test_throws Exception fit!(yhat)) + @test_logs((:error, r""), + (:error, r""), + (:error, r""), + (:error, r""), + @test_throws Exception fit!(yhat, verbosity=-1)) end @@ -326,7 +355,7 @@ end @testset "@node" begin X1 = source(4) X2 = source(5) - X = source(1:10) + Xp = source(1:10) add(a, b, c) = a + b + c N = @node add(X1, 1, X2) @@ -335,7 +364,7 @@ end N = @node tuple(X1, 5, X1) @test N() == (4, 5, 4) - Y = @node selectrows(X, 3:4) + Y = @node selectrows(Xp, 3:4) @test Y() == 3:4 @test Y([:one, :two, :three, :four]) == [:three, :four] diff --git a/test/composition/models/_wrapped_function.jl b/test/composition/models/_wrapped_function.jl index 65d3c21d..c015ea45 100644 --- a/test/composition/models/_wrapped_function.jl +++ b/test/composition/models/_wrapped_function.jl @@ -1,3 +1,4 @@ + module TestPipelineStatic using Test diff --git a/test/composition/models/pipelines.jl b/test/composition/models/pipelines.jl index beb5d7cd..9096296b 100644 --- a/test/composition/models/pipelines.jl +++ b/test/composition/models/pipelines.jl @@ -460,6 +460,15 @@ fit!(mach) @test p isa ProbabilisticComposite pdf(predict(mach, X)[1], 'f') ≈ 4/7 +# test invalid replacement of classifier with regressor throws +# informative error message: +p.constant_classifier = ConstantRegressor() +@test_logs((:error, r"^Problem"), + (:info, r"^Running type"), + (:warn, r"The scitype of"), + (:error, r"Problem"), + @test_throws Exception fit!(mach, verbosity=-1)) + # test a simple deterministic classifier pipeline: X = MLJBase.table(rand(rng,7,3)) y = categorical(collect("ffmmfmf")) From acb36a3bed3de0312260ccdd352d05e9b7909f5b Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Fri, 21 Aug 2020 16:46:20 +1200 Subject: [PATCH 09/10] "Bump version to 0.14.9" --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 72e0bd9a..d2e361c3 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MLJBase" uuid = "a7f614a8-145f-11e9-1d2a-a57a1082229d" authors = ["Anthony D. Blaom "] -version = "0.14.8" +version = "0.14.9" [deps] CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597" From e07cdb046500ca9101d3bb8083d12094f4a7bcaf Mon Sep 17 00:00:00 2001 From: "Anthony D. Blaom" Date: Fri, 21 Aug 2020 16:48:02 +1200 Subject: [PATCH 10/10] revert version to 0.14.8 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index d2e361c3..72e0bd9a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MLJBase" uuid = "a7f614a8-145f-11e9-1d2a-a57a1082229d" authors = ["Anthony D. Blaom "] -version = "0.14.9" +version = "0.14.8" [deps] CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597"