-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Major revision to simplify; in particular, to remove obsfit
, obspredict
, obstransform
#30
Conversation
Interesting PR @ablaom, the changes seem overall to move in a promising direction! Quick consideration regarding
Looking at a rough learnAPI MWE for EvoTrees lead me to the question of how to integrate support for LearnAPI through the ecosystem. Current drawbacks in see in MLJ are:
Use of package extensionmay address the above concerns. It makes the usage of a specific ML interface both an opt-in, and very lightweight/lightweight to the user. And maybe most importantly, it can make it easy for an algo to be compatible with multiple interfaces (ex: a times-series specialized interface). Note that I used the single data argument to fit in a little different fashion as instead of passing a tuple
Here I understand that this kwarg could still be used, like I did in the EvoTree test implementation, but without having it as a default/recommended default, I think it increases the risk of seeing various usage patterns to emerge.
LearnAPI.target(::Ridge, data) where data is a table input other than by making an assumption about the the target name write in the algo implementation, which is obviously problematic.
An example of the potential pattern dissemination from using a tuple as a data input is the convenience method where
If the fit interface was strict about the 1 arg data input, I see potential for reserving an optional additional arg for an eval data. Otherwise, such eval data will be passed as a kwargs and potentially subject to the same ambiguity about the nature of that data (tuple, single table), while not benefiting from the dispatch that exists only AFAIK on the positional args.
Regarding the handling of iterative models, with eval data, early stopping, etc., I remain unclear as what should be the story, other than for the hints on the above reserved positional args for train and eval data. The current design in EvoTrees works ok in practice, but it remains debatable whether early-stopping-rounds and or metric functions should be part of the algo's hyper-params struct, or just be kwarg to fit function, or part of a specialized early tracking struct. Not sure that I grasped well the Device / accelerator: did you have a take on how to specify the device on which to perform computation? My personal experience has been positive with the EvoTrees / NeuroTrees approach where a |
Thanks @jeremiedb for spending time wading through the PR and trying it out with EvoTrees. I've made some tweaks. Note that I've changed I've also detailed tentative contracts for new update methods (see also #13).
Yes, we have that now:
It should even be possible to simultaneously support both skit-learn style input
I don't see how one can completely dispense with a base package. Look at the success of Tables.jl. A base API package is useful. MLJModelInterface is not perfect, but it is lightweight. LearnAPI.jl has zero dependencies, and basically zero functionality (a few signature fallbacks aside)
There is no type hierarchy in LearnAPI.jl and no base algorithm type to subtype.
Do you mean "If the fit interface was not strict about the 1 arg data input"? Although I favour external out-of-sample evaluation of some kind (see below) the current
Since there are multiple arguments, a fallback now calls I'm not sure if this has any benefit over specifying Returning to the idea of externally (but efficiently) monitoring out-of-sample loss, you say:
I am keen to ensure this kind of thing can work. Could you please detail what
Maybe the cross-validation example in the doc page for
An expert on this kind of thing, @jpsamaroo, suggested dispatching on types provided by I'm going to merge this PR to make the docs more generally available for feedback. I'm not |
Acked-by: Anthony D. Blaom <[email protected]>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #30 +/- ##
==========================================
- Coverage 65.81% 62.65% -3.17%
==========================================
Files 9 10 +1
Lines 117 83 -34
==========================================
- Hits 77 52 -25
+ Misses 40 31 -9 ☔ View full report in Codecov by Sentry. |
This is a substantial revision aimed at simplification, whose most important goal was to provide a cleaner opt-out for the
obs
business.The methods
obsfit
,obspredict
,obstransform
were previously introduced to avoid type ambiguities when trying to overload the existing methodsfit
,predict
,transform
to accept the output ofobs
in practice. The issue has been resolved by requiring primary implementations offit
,predict
andtransform
to accept a singledata
argument. For example, an implementation now implementsfit(algorithm, (X, y))
instead offit(algorithm, X, y)
. However the latter method is still provided as a convenience method, which means the previous user interface is preserved.Other changes include:
The
obs
signatures have been simplified: instead ofobs(::typeof(fit), algorithm, data)
, etc, we haveobs(algorithm, data)
(for observations passed tofit
) andobs(model, data)
(for observations passed topredict
ortransform
).Simplification of the requirements of an "algorithm": Each algorithm comes with an overloading of a new method (trait)
LearnAPI.constructor(algorithm)
returning a keyword constructor, and the algorithm qualifies if it can be recovered from its constructor (which also gives a way to make mutated copies) and that is all. See the new docs for details. There are other reasons for adding theconstructor
trait.The traits
position_of_target
andpostion_of_weights
are replaced by cleaner and more general methodstarget(algorithm, data)
andweights(algorithm, data)
to do the extraction. (The methodstarget(algorithm)
andweights(algorithm)
, taking valuestrue
orfalse
, replace the traits themselves.)Adds some new
KindsOfProxy
types and re-organises them under three abstract subtypes. In particular, we now have types applying to ordinary distribution-fitting algorithms.Adds the
training_predictions
accessor function; see my Julia Discourse comment after "...but I think we can handle itusing the proposed API if we add one accessor function." addressing an issue raised by @jeremiedb.
Adds a new trait
data_interface
indicating the observation accesss implemented for data output byobs
. The fallback is for the MLUtils.jl interface, but another option is a plainiterate
interface (think data loaders).Resolves Add new KindOfProxy: LabelAmbiguousFuzzy #29, Add
fit_transform
? #18To do:
Consider dropping some of the traits governing the form of method output/input. Perhaps it is enough to stick to
scitype
(not bothscitype
ortypeof
) and to only worry about the types of individual observations, and not about containers.The only traits dealing with the type of input and output that I've kept are
fit_observation_scitype
,target_observation_scitype
(andkinds_of_proxy
which articulates the supported forms ofpredict
output - point predictions, distributions, etc)To do:
update
,update_observations
andupdate_features