-
-
Notifications
You must be signed in to change notification settings - Fork 25.8k
MRG adding SomeScore objects for better (?!) grid search interface. #1381
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
Conversation
# construct a scoring object from a simple scoring function | ||
if needs_threshold: | ||
class ScoreObj(object): | ||
greater_is_better = greater_is_better_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the trailing _
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum ok namespace conflict issue...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah didn't know what would happen and wanted to be on the safe side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would simply use objects rather than classes. The factory would than become the init of a class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that. I would prefer that as it is somewhat "flatter".
Would this mean that there is one instance per score? I.e. this namespace contains an object called AUCScore
?
How would you handle the case where there are additional parameters, such as fbeta
or precision@k?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this mean that there is one instance per score? I.e. this namespace
contains an object called AUCScore?
Yes, or rather auc_score (object, no class, thus no CamelCase)
How would you handle the case where there are additional parameters, such as
fbeta or precision@k?
Indeed, with additional parameters, having only one global instance of
the scorer will be a problem. One way to solve it would be to teach the
user to use the ScorerDecorator, that could provide support for
additional arguments. I could do something like
GridSearchCV(..., score_type=AsScorer(fbeta_score, args=dict(beta=3)))
(I just decided that I really didn't like the ScorerDecorator name :} ).
By the way, generating classes the way you do it will pose problems, as
they won't pickle (they are defined in a closure).
I am going to have to run to bed right now, I fear. Will keep on thinking
tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will hit the sack soon, too. (I don't like ScorerDecorator either ;).
I think we can get somewhere here :)
The AsScorer(fbeta_score, args=dict(beta=3))
is a bit to verbose for me still. Maybe **kwargs
?
Good night!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The AsScorer(fbeta_score, args=dict(beta=3)) is a bit to verbose for me still.
Maybe **kwargs?
Possibly. I have no love for **kwargs, but it might be a usecase.
ping @GaelVaroquaux |
Looking at it right now :) |
Thanks :) I put some more info in the description above in case you didn't notice. |
|
return ScoreObj | ||
|
||
|
||
def _score_obj_from_string(score_func): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should just be a dictionary, IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed.
|
In general, I think that I like the approach. It feels like some aspects could be simplified by working a bit more on the details, but I think that the general idea is good. With regards to the API change, I think that your idea of introducing a name change is a good one, to make the transition more smooth and more explicit. Maybe I don't think that I like the classes exposed in metrics: R2Score, MSEScore, ... First, I'd use objects rather than classes. There is no need to introduce classes, IMHO. This would also enable you to get rid of the factory. Second, I think that we should push people to use strings most of the time, just like we are doing with kernels. I think that my favorite strategy would be:
Once this it all done, I have the feeling that it should lead to fairly simple code. |
ps: thanks for the immediate feedback :) |
On Sun, Nov 18, 2012 at 02:32:12PM -0800, Andreas Mueller wrote:
I'd like to completely remove 'greater_is_better' from GridSearchCV. What I have in mind is, in the scorer object: def __call__(self, estimator, X, y): y_pred = estimator.predict(X) if not self.great_is_better: return -score_func(y, y_pred) return score_func(y, y_pred) |
As the user shouldn't be using this object herself, this is probably fine. |
I am not getting the meaning of your remark (I am tired :$ ). |
Could be tiredness on my side, too. |
OK, I thought that you might mean this. I agree with you on both sides: |
On the other hand, this shows up in the |
Yes, but the absolute rule is that bigger is better. We don't want to |
Sorry for the misclick.... This button needs a confirm popup or something... |
order to evaluate the performance of prediction (high is good). | ||
If None is passed, the score of the estimator is maximized. | ||
score_func: string or object, optional | ||
Either one of ["zero-one", "f1", "auc"] for classification, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather use "zero_one"
(underscore instead of dash) as I think is more common in the rest of the project.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we should stop using auc
in our public API but instead used roc_auc
. "Area Under Curve" is ambiguous as we have roc_auc
and precision_recall_auc
that are both valid yet different scoring metrics for classification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we should stop using auc in our public API but instead used
roc_auc. "Area Under Curve" is ambiguous as we have roc_auc and
precision_recall_auc that are both valid yet different scoring metrics
for classification.
+1
@amueller I cannot find the comment / discussion where I advertised the use of parameterized Scorer classes instead of simple functions or objects. I think you started this PR in reaction to that. I would like to re-read my own arguments as I think I forgot some of them. |
This was on the ML. I'll try to find it. Yes, this PR is the result of the discussion, as I think your idea seemed the best consensus. |
Ok and I usual I cannot find this email using google... Sourceforge mailing list archives are really really bad... |
Thanks @amueller! @GaelVaroquaux can you please re-read this message and the following discussion. I really like this explicit is better than implicit design. |
I will also reread the discussion. it has been a while ;) |
About AUC: isn't "area under precision-recall curve" the same as average precision and called ap? |
This is starting to get some shape. TODO
|
@ogrisel There is a behavior that I find quite weird here. It is possible to use a score function for unsupervised learning but I don't understand what is happening. See this commit: fde6ba1 Btw, in GridSearchCV, the |
Yes using an external If we are to make some standard assumptions on the unsupervised models attributes (e.g. such as |
Plus I don't like capitalized first letters in titles
…ng and license note.
…section to docstrings of cross_val_score, GridSearchCV and permutation_test_score
running tests and building docs again, then it should be good :) |
I agree. 👍 for merge if the tests pass and the doc build with the latest renamings. |
I added a small remark on smoke testing the repr, and after that, I am 👍 for merge. Great job! |
Added a smoketest, whatsnew references are ok, tests run, doc build runs. |
waiting for travis, then merging. |
Thanks for the reviews, guys :) |
🍻 wohooo! |
🍻 |
This is hopefully my last shot at adding more advanced score functions, as discussed in the other PRs and the ML.
Compare to #1198 and #1014.
This is sort of a draft (again) and it would be great if I could get some feedback before going further.
This PR basically implements a new interface in GridSearchCV using callable score objects with an
(estimator, X, y)
signature. To create these objects I introduced an internal factory-style function.
The idea would be to either pass a string or a callable object to GridSearchCV.
At the moment, I complicated things a bit by keepingscore_func
as the parameter name inGridSearchCV
. I think it might be better to deprecate it and add a newscore
parameter.I am not sure if I am entirely happy with this. The factory seems a bit overly complicated, but maybe that is a matter of taste. Alternative suggestions welcome. It feels a bit as if decorators would be a more natural.I am happy now.