diff --git a/Project.toml b/Project.toml index f56f712..ade32a7 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "EvoTrees" uuid = "f6006082-12f8-11e9-0c9c-0d5d367ab1e5" authors = ["jeremiedb "] -version = "0.16.8" +version = "0.16.9" [deps] BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0" diff --git a/ext/EvoTreesCUDAExt/init.jl b/ext/EvoTreesCUDAExt/init.jl index a3eee50..3315e0e 100644 --- a/ext/EvoTreesCUDAExt/init.jl +++ b/ext/EvoTreesCUDAExt/init.jl @@ -23,7 +23,7 @@ function EvoTrees.init_core(params::EvoTrees.EvoTypes{L}, ::Type{<:EvoTrees.GPU} elseif L == EvoTrees.MLogLoss if eltype(y_train) <: EvoTrees.CategoricalValue target_levels = EvoTrees.CategoricalArrays.levels(y_train) - target_isordered = isordered(y_train) + target_isordered = EvoTrees.isordered(y_train) y = UInt32.(EvoTrees.CategoricalArrays.levelcode.(y_train)) elseif eltype(y_train) <: Integer || eltype(y_train) <: Bool || eltype(y_train) <: String || eltype(y_train) <: Char target_levels = sort(unique(y_train)) diff --git a/ext/EvoTreesCUDAExt/predict.jl b/ext/EvoTreesCUDAExt/predict.jl index e983dd4..7c37923 100644 --- a/ext/EvoTreesCUDAExt/predict.jl +++ b/ext/EvoTreesCUDAExt/predict.jl @@ -150,13 +150,13 @@ function EvoTrees.predict!( end # prediction for EvoTree model -function predict( - m::EvoTree{L,K}, +function EvoTrees._predict( + m::EvoTrees.EvoTree{L,K}, data, ::Type{<:EvoTrees.GPU}; ntree_limit=length(m.trees)) where {L,K} - Tables.istable(data) ? data = Tables.columntable(data) : nothing + EvoTrees.Tables.istable(data) ? data = EvoTrees.Tables.columntable(data) : nothing ntrees = length(m.trees) ntree_limit > ntrees && error("ntree_limit is larger than number of trees $ntrees.") x_bin = CuArray(EvoTrees.binarize(data; fnames=m.info[:fnames], edges=m.info[:edges])) diff --git a/src/models.jl b/src/models.jl index 9e8571a..f840201 100644 --- a/src/models.jl +++ b/src/models.jl @@ -70,6 +70,10 @@ function EvoTreeRegressor(; kwargs...) :rng => 123, ) + args_ignored = setdiff(keys(kwargs), keys(args)) + length(args_ignored) > 0 && + @info "The following kwargs are not supported and will be ignored: $(args_ignored)." + args_override = intersect(keys(args), keys(kwargs)) for arg in args_override args[arg] = kwargs[arg] @@ -163,6 +167,10 @@ function EvoTreeCount(; kwargs...) :rng => 123, ) + args_ignored = setdiff(keys(kwargs), keys(args)) + length(args_ignored) > 0 && + @info "The following kwargs are not supported and will be ignored: $(args_ignored)." + args_override = intersect(keys(args), keys(kwargs)) for arg in args_override args[arg] = kwargs[arg] @@ -231,6 +239,10 @@ function EvoTreeClassifier(; kwargs...) :rng => 123, ) + args_ignored = setdiff(keys(kwargs), keys(args)) + length(args_ignored) > 0 && + @info "The following kwargs are not supported and will be ignored: $(args_ignored)." + args_override = intersect(keys(args), keys(kwargs)) for arg in args_override args[arg] = kwargs[arg] @@ -301,6 +313,10 @@ function EvoTreeMLE(; kwargs...) :rng => 123, ) + args_ignored = setdiff(keys(kwargs), keys(args)) + length(args_ignored) > 0 && + @info "The following kwargs are not supported and will be ignored: $(args_ignored)." + args_override = intersect(keys(args), keys(kwargs)) for arg in args_override args[arg] = kwargs[arg] @@ -387,6 +403,10 @@ function EvoTreeGaussian(; kwargs...) :rng => 123, ) + args_ignored = setdiff(keys(kwargs), keys(args)) + length(args_ignored) > 0 && + @info "The following kwargs are not supported and will be ignored: $(args_ignored)." + args_override = intersect(keys(args), keys(kwargs)) for arg in args_override args[arg] = kwargs[arg] diff --git a/src/predict.jl b/src/predict.jl index 2e2f07d..3b3b6e2 100644 --- a/src/predict.jl +++ b/src/predict.jl @@ -74,16 +74,23 @@ function predict!(pred::Matrix{T}, tree::Tree{L,K}, x_bin::Matrix{UInt8}, featty return nothing end + """ - predict(model::EvoTree, X::AbstractMatrix; ntree_limit = length(model.trees)) + predict(m::EvoTree, data; ntree_limit=length(m.trees), device=:cpu) Predictions from an EvoTree model - sums the predictions from all trees composing the model. Use `ntree_limit=N` to only predict with the first `N` trees. """ -function predict( +function predict(m::EvoTree, data; ntree_limit=length(m.trees), device=:cpu) + @assert Symbol(device) ∈ [:cpu, :gpu] + _device = Symbol(device) == :cpu ? CPU : GPU + _predict(m, data, _device; ntree_limit) +end + +function _predict( m::EvoTree{L,K}, data, - ::Type{<:Device}=CPU; + ::Type{<:CPU}; ntree_limit=length(m.trees)) where {L,K} Tables.istable(data) ? data = Tables.columntable(data) : nothing diff --git a/src/structs.jl b/src/structs.jl index fa7cec1..8394727 100644 --- a/src/structs.jl +++ b/src/structs.jl @@ -87,12 +87,10 @@ struct EvoTree{L,K} trees::Vector{Tree{L,K}} info::Dict end -# (m::EvoTree)(data, device::Type{D}=CPU; ntree_limit=length(m.trees)) where {D<:Device} = -# predict(m, data, device; ntree_limit) -function (m::EvoTree)(data; ntree_limit=length(m.trees), device="cpu") - @assert string(device) ∈ ["cpu", "gpu"] - _device = string(device) == "cpu" ? CPU : GPU - return predict(m, data, _device; ntree_limit) +function (m::EvoTree)(data; ntree_limit=length(m.trees), device=:cpu) + @assert Symbol(device) ∈ [:cpu, :gpu] + _device = Symbol(device) == :cpu ? CPU : GPU + return _predict(m, data, _device; ntree_limit) end _get_struct_loss(::EvoTree{L,K}) where {L,K} = L diff --git a/test/issue-274.jl b/test/issue-274.jl new file mode 100644 index 0000000..d06b0b3 --- /dev/null +++ b/test/issue-274.jl @@ -0,0 +1,9 @@ +using CUDA +using EvoTrees +using CategoricalArrays + +x_train = x=rand(10, 2) +y_train = categorical(rand("abc", 10), ordered=true) +config = EvoTreeClassifier(; device=:gpu, L2=123) +m = fit_evotree(config; x_train, y_train, device=:gpu) +yhat = m(x_train; device=:gpu)