diff --git a/sklearn/cross_validation.py b/sklearn/cross_validation.py index df042e2b6a5ac..01251a072e8ea 100644 --- a/sklearn/cross_validation.py +++ b/sklearn/cross_validation.py @@ -1184,9 +1184,9 @@ def _fit_and_score(estimator, X, y, scorer, train, test, verbose, parameters, estimator.fit(X_train, **fit_params) else: estimator.fit(X_train, y_train, **fit_params) - test_score = _score(estimator, X_test, y_test, scorer) + test_score = scorer(estimator, X_test, y_test) if return_train_score: - train_score = _score(estimator, X_train, y_train, scorer) + train_score = scorer(estimator, X_train, y_train) scoring_time = time.time() - start_time @@ -1235,18 +1235,6 @@ def _safe_split(estimator, X, y, indices, train_indices=None): return X_subset, y_subset -def _score(estimator, X_test, y_test, scorer): - """Compute the score of an estimator on a given test set.""" - if y_test is None: - score = scorer(estimator, X_test) - else: - score = scorer(estimator, X_test, y_test) - if not isinstance(score, numbers.Number): - raise ValueError("scoring must return a number, got %s (%s) instead." - % (str(score), type(score))) - return score - - def _permutation_test_score(estimator, X, y, cv, scorer): """Auxiliary function for permutation_test_score""" avg_score = [] diff --git a/sklearn/feature_selection/rfe.py b/sklearn/feature_selection/rfe.py index 01c99ceb526f4..05f376250c024 100644 --- a/sklearn/feature_selection/rfe.py +++ b/sklearn/feature_selection/rfe.py @@ -13,7 +13,7 @@ from ..base import clone from ..base import is_classifier from ..cross_validation import _check_cv as check_cv -from ..cross_validation import _safe_split, _score +from ..cross_validation import _safe_split from .base import SelectorMixin from ..metrics.scorer import check_scoring @@ -342,7 +342,7 @@ def fit(self, X, y): mask = np.where(ranking_ <= k + 1)[0] estimator = clone(self.estimator) estimator.fit(X_train[:, mask], y_train) - score = _score(estimator, X_test[:, mask], y_test, scorer) + score = scorer(estimator, X_test[:, mask], y_test) if self.verbose > 0: print("Finished fold with %d / %d feature ranks, score=%f" diff --git a/sklearn/learning_curve.py b/sklearn/learning_curve.py index 7989bc3534658..a650a11f75af3 100644 --- a/sklearn/learning_curve.py +++ b/sklearn/learning_curve.py @@ -10,7 +10,7 @@ from .cross_validation import _check_cv from .utils import check_arrays from .externals.joblib import Parallel, delayed -from .cross_validation import _safe_split, _score, _fit_and_score +from .cross_validation import _safe_split, _fit_and_score from .metrics.scorer import check_scoring @@ -204,18 +204,22 @@ def _incremental_fit_estimator(estimator, X, y, classes, train, test, """Train estimator on training subsets incrementally and compute scores.""" train_scores, test_scores = [], [] partitions = zip(train_sizes, np.split(train, train_sizes)[:-1]) + for n_train_samples, partial_train in partitions: train_subset = train[:n_train_samples] X_train, y_train = _safe_split(estimator, X, y, train_subset) X_partial_train, y_partial_train = _safe_split(estimator, X, y, partial_train) X_test, y_test = _safe_split(estimator, X, y, test, train_subset) + if y_partial_train is None: estimator.partial_fit(X_partial_train, classes=classes) else: estimator.partial_fit(X_partial_train, y_partial_train, classes=classes) - train_scores.append(_score(estimator, X_train, y_train, scorer)) - test_scores.append(_score(estimator, X_test, y_test, scorer)) + + train_scores.append(scorer(estimator, X_train, y_train)) + test_scores.append(scorer(estimator, X_test, y_test)) + return np.array((train_scores, test_scores)).T diff --git a/sklearn/metrics/scorer.py b/sklearn/metrics/scorer.py index 18d629b04908a..beae0ee27c56d 100644 --- a/sklearn/metrics/scorer.py +++ b/sklearn/metrics/scorer.py @@ -20,6 +20,7 @@ from abc import ABCMeta, abstractmethod from warnings import warn +import numbers import numpy as np @@ -127,6 +128,10 @@ def _evaluate_scorers(estimator, X, y, scorers): else: score = scorer.score_func(y, y_pred, **scorer.kwargs) + if not isinstance(score, numbers.Number): + raise ValueError("scoring must return a number, got %s (%s)" + " instead." % (str(score), type(score))) + sign = 1 if scorer.greater_is_better else -1 scores.append(sign * score) @@ -146,9 +151,12 @@ def get_scorer(scoring): return scorer -def _passthrough_scorer(estimator, *args, **kwargs): +def _default_scorer(estimator, X, y, *args, **kwargs): """Function that wraps estimator.score""" - return estimator.score(*args, **kwargs) + if y is None: + return estimator.score(X, *args, **kwargs) + else: + return estimator.score(X, y, *args, **kwargs) def check_scoring(estimator, scoring=None, allow_none=False, loss_func=None, @@ -204,7 +212,7 @@ def check_scoring(estimator, scoring=None, allow_none=False, loss_func=None, scorer = get_scorer(scoring) return scorer elif hasattr(estimator, 'score'): - return _passthrough_scorer + return _default_scorer elif not has_scoring: if allow_none: return None