[MRG+1] Add decision_function for OneVsOneClassifier.

Adding `decision_function` support for the `OneVsOneClassifier`.

This is based off of #1548 and addresses #1523.

- [x] Implement the `decision_function` for `OneVsOneClassifier` 

decision_function returns `votes + scores * (0.4 / max(|scores.max(axis=None)|, |scores.min(axis=None)|))`

As a corner case, when both max and min are same, it simply returns `votes`.

- [x] Add tests for ovo decision function
* Tests `decision_function(X).argmax(axis=1) == predict(X)`
* Tests `decision_function(X).shape == (n_samples, n_classes)`
* Tests `np.round(decision_function(X)) == separately_computed_votes`
* Tests `computed_scores = (decision_function(X) - np.round(decision_function(X)) ) * upscale_factor_derived_from_computed_scores `

- [x] Incorporate the `decision_function` output in `test_ovo_ties`
`ovo_ties` test requires `votes` to assert tie and `scores` to assert if the prediction breaks ties using aggregated decision scores. Both `votes` and `scores` ( individual ) were separately computed till now. These are modified to use `decision_function`
* `votes = round(decision_values)`
* `scaled_aggregated_scores = decision_values - votes`

@arjoly, @amueller, @mblondel  Pl. review when you find time!
yes

On Mon, Dec 15, 2014 at 5:33 PM, ragv <notifications@github.com> wrote:
>
> In doc/modules/multiclass.rst
> <https://github.com/scikit-learn/scikit-learn/pull/3891#discussion-diff-21837065>
> :
>
> > @@ -161,6 +161,17 @@ One-Vs-One
> >
> >  :class:`OneVsOneClassifier` constructs one classifier per pair of classes.
> >  At prediction time, the class which received the most votes is selected.
> > +In the event of a tie (among two classes with an equal number of votes), the
> > +class with the highest score (aggregated from scores of all the individual
> > +classifiers) is selected.
> > +
> > +The ``decision_function`` for ``OneVsOneClassifier`` aggregates all the votes
> > +and adds that to the scores after scaling it to a range of [-0.4, 0.4].
> > +This is done so that ``argmax`` of the decision values along axis=1 will
> > +predict the outcome consistently irrespective of when there is a tie or
> > +otherwise. The reason for scaling the scores is so that it does not mess with
> > +the actual value of the votes.
>
> Thanks for the reviews!! :) Will make the changes...
>
> move this explanation to under def decision_function()
>
> You meant something like this
> <http://scikit-learn.org/stable/modules/generated/sklearn.multiclass.OneVsOneClassifier.html#sklearn.multiclass.OneVsOneClassifier.fit>
> for the decision_function right?
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/scikit-learn/scikit-learn/pull/3891/files#r21837065>.
>


-- 
Godspeed,
Manoj Kumar,
Intern, Telecom ParisTech
Mech Undergrad
http://manojbits.wordpress.com