Skip to content
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

fix bug in TuneWrapper for param in used in predict function, issue 2472 #2479

Merged
merged 11 commits into from
Apr 15, 2019

Conversation

berndbischl
Copy link
Member

@berndbischl berndbischl commented Nov 9, 2018

fixes issue #2472

unit tests are missing. please help and merge

R/TuneWrapper.R Outdated
predictLearner(lrn, .model$learner.model$next.model, .newdata, ...)
arglist = list(.learner = lrn, .model = .model$learner.model$next.model, .newdata = .newdata)
arglist = insert(arglist, list(...))
arglist = insert(arglist, .model$learner.model$opt.result$x)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably only insert the parameters that have when %in% c("predict", "both").

Maybe one could just copy the lines from predict.R, if we are sure there are no other wrappers that introduce a discrepancy between the par.vals of a learner and the ... parameters on purpose.

@jakob-r jakob-r self-assigned this Nov 12, 2018
@jakob-r
Copy link
Member

jakob-r commented Nov 12, 2018

Some notes regarding my observation:

  • setHyperPars within predictLearner is without effect because they will never be requested. The hyperparams got extracted in predict.(WrappedModel) and are put into ....
  • We don't know if the par.vals got changed after the training of the TuneWrapped Learner.
  • We will always overwrite the existing par.vals with the ones from the learner.
  • We assume that the user does not change par.vals and between training and predict. This holds especially as in most cases both is done internally in one step.

@mb706
Copy link
Contributor

mb706 commented Nov 12, 2018

setHyperPars within predictLearner is without effect because they will never be requested. The hyperparams got extracted in predict.(WrappedModel) and are put into ....

we should probably not rely on this; right now the parameter values are given both inside the ... and as part of the .learner object; its probably good to make sure they agree.

We don't know if the par.vals got changed after the training of the TuneWrapped Learner.

How would that happen (assuming the user does not directly modify the model$learner object, in which case, too bad)?

We will always overwrite the existing par.vals with the ones from the learner.

You mean the ones being tuned over? It might be worth considering to remove the parameters found in the tuning param set from the wrapped learner's param set, so the user gets an error message when he tries to set a param that will be overwritten later.

We assume that the user does not change par.vals and between training and predict. This holds especially as in most cases both is done internally in one step.

I'm confused again, how would that happen? Does any part of mlr support that?

@jakob-r
Copy link
Member

jakob-r commented Nov 12, 2018

setHyperPars within predictLearner is without effect because they will never be requested. The hyperparams got extracted in predict.(WrappedModel) and are put into ....

we should probably not rely on this; right now the parameter values are given both inside the ... and as part of the .learner object; its probably good to make sure they agree.

That is the architecture of mlr at the moment and we are relying on it everywhere. In train and predict the parameters are read and put into the arguments.
This is probably not the best design but keeping the arguments and the par.vals "in sync" would only be a lot of effort.

We don't know if the par.vals got changed after the training of the TuneWrapped Learner.

How would that happen (assuming the user does not directly modify the model$learner object, in which case, too bad)?

Like that, yes., ? mod = train(...); setHyperPars(mod$learner, ...); predict(mod, ...)

We will always overwrite the existing par.vals with the ones from the learner.

You mean the ones being tuned over? It might be worth considering to remove the parameters found in the tuning param set from the wrapped learner's param set, so the user gets an error message when he tries to set a param that will be overwritten later.

A warning somewhere might be useful. But I am afraid we would generate warnings for cases where we have set the par.vals in the definition of the learner. This can entail a lot of work.

We assume that the user does not change par.vals and between training and predict. This holds especially as in most cases both is done internally in one step.

I'm confused again, how would that happen? Does any part of mlr support that?
See above.

My suggestion: We should merge this PR asap and can add convenience later.

@mb706
Copy link
Contributor

mb706 commented Nov 12, 2018

That is the architecture of mlr at the moment and we are relying on it everywhere. In train and predict the parameters are read and put into the arguments.

Do you consider this to be a bug?

mod = train(...); setHyperPars(mod$learner, ...); predict(mod, ...)

has "model$learner <- [something]" ever been documented as supported behaviour? If the user modifies internals of objects then of course he can break things without bounds, I thought of mod$learner as such an internal.

@berndbischl
Copy link
Member Author

i do not understand the unit test. can you please add at least some comments?
how the test is setup and why you expect certain things?

@berndbischl
Copy link
Member Author

also please note: a PR for fixing a certain bug is probably not the best place to dicuss general architecture questions. please move this to a clean issue if you want to discuss this...

@jakob-r
Copy link
Member

jakob-r commented Nov 12, 2018

Do you consider this to be a bug?

I would not call it a bug as it's just affecting some error message. But the whole code is strange. How do we know that it's really the wrong family that leads to NAs? But this is another issue and should not be discussed here.

i do not understand the unit test.

Better now?

@jakob-r
Copy link
Member

jakob-r commented Nov 13, 2018

@berndbischl ping

R/TuneWrapper.R Outdated
@@ -74,8 +74,16 @@ trainLearner.TuneWrapper = function(.learner, .task, .subset = NULL, ...) {

#' @export
predictLearner.TuneWrapper = function(.learner, .model, .newdata, ...) {
lrn = setHyperPars(.learner$next.learner, par.vals = .model$learner.model$opt.result$x)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI I am relatively sure that removing this line (and not putting .learner = lrn further down etc) will break things.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean .learner$next.learner? That moved to another line. But I added setHyperPars now again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2a0d9d0 is exactly what I meant, with .learner = lrn I meant the list entry ".learner" 👍

@pat-s
Copy link
Member

pat-s commented Apr 11, 2019

@jakob-r If the build passes, can this be merged? I would add an entry to NEWS.md

@pat-s pat-s merged commit 7ea4a57 into master Apr 15, 2019
@pat-s pat-s deleted the fix_2472 branch April 15, 2019 18:27
vrodriguezf pushed a commit to vrodriguezf/mlr that referenced this pull request Jan 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants