Repository: JuliaAI/MLJBase.jl
Pull request #658 (2021-10-04 22:52:21)

Extend overloading of `predict_mode`, etc to all models, not just `Supervised`
Resolves first part of  #656.

Used to throw an error:

```julia
using MLJ
model = (@load GMMClusterer)()
X, _ = make_moons()
mach = machine(model, X) |> fit!
julia> predict_mode(mach, rows=1:2)
2-element CategoricalArrays.CategoricalArray{Int64,1,UInt32}:
 2
 1
```

cc @juliohm 




Patch:
diff --git a/src/interface/model_api.jl b/src/interface/model_api.jl
index ed9540a1..c80d3c87 100644
--- a/src/interface/model_api.jl
+++ b/src/interface/model_api.jl
@@ -1,35 +1,31 @@
 # Add fallbacks for predict_* which require mean, mode, median.
 
-const BadModeTypes   = Union{AbstractArray{Continuous},Table(Continuous)}
 const BadMeanTypes   = Union{AbstractArray{<:Finite},Table(Finite)}
 const BadMedianTypes = Union{AbstractArray{<:Finite},Table(Finite)}
 
+const err_wrong_target_scitype(actual_scitype) = ArgumentError(
+    "Attempting to compute mode of predictions made "*
+    "by a model with `$actual_scitype` targets. ")
+
 # mode:
-predict_mode(m::Probabilistic, fitresult, Xnew) =
-    predict_mode(m, fitresult, Xnew, Val(target_scitype(m)))
-predict_mode(m, fitresult, Xnew, ::Any) =
+predict_mode(m, fitresult, Xnew) =
     mode.(predict(m, fitresult, Xnew))
-predict_mode(m, fitresult, Xnew, ::Val{<:BadModeTypes}) =
-    throw(ArgumentError("Attempting to compute mode of predictions made "*
-                        "by a model expecting `Continuous` targets. "))
 
 # mean:
-predict_mean(m::Probabilistic, fitresult, Xnew) =
-    predict_mean(m, fitresult, Xnew, Val(target_scitype(m)))
+predict_mean(m, fitresult, Xnew) =
+    predict_mean(m, fitresult, Xnew, target_scitype(m))
 predict_mean(m, fitresult, Xnew, ::Any) =
     mean.(predict(m, fitresult, Xnew))
-predict_mean(m, fitresult, Xnew, ::Val{<:BadMeanTypes}) =
-    throw(ArgumentError("Attempting to compute mean of predictions made "*
-                        "by a model expecting `Finite` targets. "))
+predict_mean(m, fitresult, Xnew, ::Type{<:BadMeanTypes}) =
+    throw(err_wrong_target_scitype(Finite))
 
 # median:
-predict_median(m::Probabilistic, fitresult, Xnew) =
-    predict_median(m, fitresult, Xnew, Val(target_scitype(m)))
+predict_median(m, fitresult, Xnew) =
+    predict_median(m, fitresult, Xnew, target_scitype(m))
 predict_median(m, fitresult, Xnew, ::Any) =
     median.(predict(m, fitresult, Xnew))
-predict_median(m, fitresult, Xnew, ::Val{<:BadMedianTypes}) =
-    throw(ArgumentError("Attempting to compute median of predictions made "*
-                        "by a model expecting `Finite` targets. "))
+predict_median(m, fitresult, Xnew, ::Type{<:BadMedianTypes}) =
+    throw(err_wrong_target_scitype(Finite))
 
 # not in MLJModelInterface as methodswith requires InteractiveUtils
 MLJModelInterface.implemented_methods(::FI, M::Type{<:MLJType}) =
@@ -48,4 +44,3 @@ for T in (:Supervised, :Unsupervised,
     end
     eval(ex)
 end
-


Test patch:
diff --git a/test/interface/model_api.jl b/test/interface/model_api.jl
index 0eec3d81..9bf3e0bf 100644
--- a/test/interface/model_api.jl
+++ b/test/interface/model_api.jl
@@ -17,14 +17,16 @@ rng = StableRNG(661)
     clf = ConstantClassifier()
     fitresult, _, _ = MLJBase.fit(clf, 1, X, yfinite)
     @test predict_mode(clf, fitresult, X)[1] == 'a'
-    @test_throws ArgumentError predict_mean(clf, fitresult, X)
-    @test_throws ArgumentError predict_median(clf, fitresult, X)
+    @test_throws(MLJBase.err_wrong_target_scitype(MLJBase.Finite),
+                 predict_mean(clf, fitresult, X))
+    @test_throws(MLJBase.err_wrong_target_scitype(MLJBase.Finite),
+                 predict_median(clf, fitresult, X))
 
     rgs = ConstantRegressor()
     fitresult, _, _ = MLJBase.fit(rgs, 1, X, ycont)
     @test predict_mean(rgs, fitresult, X)[1] == 3
     @test predict_median(rgs, fitresult, X)[1] == 3
-    @test_throws ArgumentError predict_mode(rgs, fitresult, X)
+    @test predict_mode(rgs, fitresult, X)[1] == 3
 end
 
 mutable struct UnivariateFiniteFitter <: MLJModelInterface.Probabilistic