Penalize solutions without the full set of predictors #1029
albertbuchard
started this conversation in
General
Replies: 2 comments 10 replies
|
This is likely the top FAQ at this point, I really need to make an FAQ page :) Check out some of the discussion here: #273 (comment) I think there's a discussion somewhere here where I give a fast loss function for this exact purpose, but can't find it at the moment. If you Google around and find it, can you link it here? |
1 reply
|
Actually I think your loss function looks okay. I think it's slow because of the recursive closure function, which makes the compiler do dynamic dispatch (makes it unable to compile it, so you get Python-level speeds). I would do function feature_absent_penalty(ex, dataset::Dataset{T,L}, options) where {T,L}
# Base MSE
pred, ok = eval_tree_array(ex, dataset.X, options)
if !ok
return L(Inf)
end
base = sum(i -> (pred[i] - dataset.y[i])^2, eachindex(pred)) / dataset.n
# Count distinct variable leaves
total_vars = 8 # TODO
used = sizehint!(Set{Int}(), total_vars)
foreach(ex) do node # faster version of 'for node in ex'
if node.degree == 0 && !node.constant
push!(used, node.feature)
end
end
miss = max(0, total_vars - length(used))
return L(base + coeff * miss)
end |
9 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Hi,
I’m trying to implement an efficient way to penalize the number of predictors used in a solution. The goal is to encourage solutions that make use of all predictors. My buddy Chat and I came up with the following approach:
This works, but I lose about an order of magnitude in iteration speed when running on the full dataset (from ~1e6 it/s down to ~1e5 it/s).
I don’t know the internals of the codebase, but I looked through DynamicExpressions.jl and couldn’t find any precomputed property that tracks the number of variables actually used in the final expression. Is there such a magic feature, function or property that I could use instead of traversing the tree at every evaluation?
I’d be very open to suggestions or pointers—thanks!
All reactions