{"action":"created","comment":{"url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments/33763342","id":33763342,"diff_hunk":"@@ -0,0 +1,717 @@\n+\n+\"\"\"Test the partition  module\"\"\"\n+from __future__ import division\n+import warnings\n+\n+import numpy as np\n+from scipy.sparse import coo_matrix\n+from scipy import stats\n+\n+from sklearn.utils.testing import assert_true\n+from sklearn.utils.testing import assert_equal\n+from sklearn.utils.testing import assert_almost_equal\n+from sklearn.utils.testing import assert_raises\n+from sklearn.utils.testing import assert_greater\n+from sklearn.utils.testing import assert_not_equal\n+from sklearn.utils.testing import assert_array_almost_equal\n+from sklearn.utils.testing import assert_array_equal\n+from sklearn.utils.testing import assert_warns_message\n+from sklearn.utils.testing import ignore_warnings\n+from sklearn.utils.mocking import MockDataFrame\n+\n+from sklearn.model_selection import (\n+    cross_val_score, KFold, StratifiedKFold, LeaveOneOut, LeaveOneLabelOut,\n+    LeavePOut, LeavePLabelOut, ShuffleSplit, StratifiedShuffleSplit,\n+    PredefinedSplit, check_cv, train_test_split)\n+from sklearn.model_selection.split import _safe_split, _validate_shuffle_split\n+\n+from sklearn.datasets import load_digits\n+from sklearn.datasets import load_iris\n+\n+from sklearn.externals import six\n+from sklearn.externals.six.moves import zip\n+\n+from sklearn.svm import SVC\n+from sklearn.preprocessing import MultiLabelBinarizer\n+\n+with warnings.catch_warnings(record=True):\n+    from sklearn import cross_validation as cval\n+\n+\n+class MockClassifier(object):\n+    \"\"\"Dummy classifier to test the cross-validation\"\"\"\n+\n+    def __init__(self, a=0, allow_nd=False):\n+        self.a = a\n+        self.allow_nd = allow_nd\n+\n+    def fit(self, X, Y=None, sample_weight=None, class_prior=None,\n+            sparse_sample_weight=None, sparse_param=None, dummy_int=None,\n+            dummy_str=None, dummy_obj=None, callback=None):\n+        \"\"\"The dummy arguments are to test that this fit function can\n+        accept non-array arguments through cross-validation, such as:\n+            - int\n+            - str (this is actually array-like)\n+            - object\n+            - function\n+        \"\"\"\n+        self.dummy_int = dummy_int\n+        self.dummy_str = dummy_str\n+        self.dummy_obj = dummy_obj\n+        if callback is not None:\n+            callback(self)\n+\n+        if self.allow_nd:\n+            X = X.reshape(len(X), -1)\n+        if X.ndim >= 3 and not self.allow_nd:\n+            raise ValueError('X cannot be d')\n+        if sample_weight is not None:\n+            assert_true(sample_weight.shape[0] == X.shape[0],\n+                        'MockClassifier extra fit_param sample_weight.shape[0]'\n+                        ' is {0}, should be {1}'.format(sample_weight.shape[0],\n+                                                        X.shape[0]))\n+        if class_prior is not None:\n+            assert_true(class_prior.shape[0] == len(np.unique(y)),\n+                        'MockClassifier extra fit_param class_prior.shape[0]'\n+                        ' is {0}, should be {1}'.format(class_prior.shape[0],\n+                                                        len(np.unique(y))))\n+        if sparse_sample_weight is not None:\n+            fmt = ('MockClassifier extra fit_param sparse_sample_weight'\n+                   '.shape[0] is {0}, should be {1}')\n+            assert_true(sparse_sample_weight.shape[0] == X.shape[0],\n+                        fmt.format(sparse_sample_weight.shape[0], X.shape[0]))\n+        if sparse_param is not None:\n+            fmt = ('MockClassifier extra fit_param sparse_param.shape '\n+                   'is ({0}, {1}), should be ({2}, {3})')\n+            assert_true(sparse_param.shape == P_sparse.shape,\n+                        fmt.format(sparse_param.shape[0],\n+                                   sparse_param.shape[1],\n+                                   P_sparse.shape[0], P_sparse.shape[1]))\n+        return self\n+\n+    def predict(self, T):\n+        if self.allow_nd:\n+            T = T.reshape(len(T), -1)\n+        return T[:, 0]\n+\n+    def score(self, X=None, Y=None):\n+        return 1. / (1 + np.abs(self.a))\n+\n+    def get_params(self, deep=False):\n+        return {'a': self.a, 'allow_nd': self.allow_nd}\n+\n+\n+X = np.ones((10, 2))\n+X_sparse = coo_matrix(X)\n+W_sparse = coo_matrix((np.array([1]), (np.array([1]), np.array([0]))),\n+                      shape=(10, 1))\n+P_sparse = coo_matrix(np.eye(5))\n+y = np.arange(10) // 2\n+\n+\n+@ignore_warnings\n+def test_cross_val_generator_with_default_indices():\n+    X = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])\n+    y = np.array([1, 1, 2, 2])\n+    labels = np.array([1, 2, 3, 4])\n+    loo = LeaveOneOut()\n+    lpo = LeavePOut(2)\n+    kf = KFold(2)\n+    skf = StratifiedKFold(2)\n+    lolo = LeaveOneLabelOut()\n+    lopo = LeavePLabelOut(2)\n+    ss = ShuffleSplit()\n+    ps = PredefinedSplit()\n+    for i, cv in enumerate([loo, lpo, kf, skf, lolo, lopo, ss, ps]):\n+        print(cv)\n+        for train, test in cv.split(X, y, labels):\n+            assert_not_equal(np.asarray(train).dtype.kind, 'b')\n+            assert_not_equal(np.asarray(train).dtype.kind, 'b')\n+\n+\n+def check_valid_split(train, test, n_samples=None):\n+    # Use python sets to get more informative assertion failure messages\n+    train, test = set(train), set(test)\n+\n+    # Train and test split should not overlap\n+    assert_equal(train.intersection(test), set())\n+\n+    if n_samples is not None:\n+        # Check that the union of train an test split cover all the indices\n+        assert_equal(train.union(test), set(range(n_samples)))\n+\n+\n+def check_cv_coverage(cv, X, y, labels, expected_n_iter=None, n_samples=None):\n+    # Check that a all the samples appear at least once in a test fold\n+    if expected_n_iter is not None:\n+        assert_equal(cv.n_splits(X, y, labels), expected_n_iter)\n+    else:\n+        expected_n_iter = cv.n_splits(X, y, labels)\n+\n+    collected_test_samples = set()\n+    iterations = 0\n+    for train, test in cv.split(X, y, labels):\n+        check_valid_split(train, test, n_samples=n_samples)\n+        iterations += 1\n+        collected_test_samples.update(test)\n+\n+    # Check that the accumulated test samples cover the whole dataset\n+    assert_equal(iterations, expected_n_iter)\n+    if n_samples is not None:\n+        assert_equal(collected_test_samples, set(range(n_samples)))\n+\n+\n+def test_kfold_valueerrors():\n+    X1 = np.array([[1, 2], [3, 4], [5, 6]])\n+    X2 = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])\n+    # Check that errors are raised if there is not enough samples\n+    assert_raises(ValueError, next, KFold(4).split(X1))\n+\n+    # Check that a warning is raised if the least populated class has too few\n+    # members.\n+    y = np.array([3, 3, -1, -1, 2])\n+\n+    skf_3 = StratifiedKFold(3)\n+    assert_warns_message(Warning, \"The least populated class\",\n+                         next, skf_3.split(X2, y))\n+\n+    # Check that despite the warning the folds are still computed even\n+    # though all the classes are not necessarily represented at on each\n+    # side of the split at each split\n+    with warnings.catch_warnings():\n+        check_cv_coverage(skf_3, X2, y, labels=None, expected_n_iter=3,\n+                          n_samples=len(y))\n+\n+    # Error when number of folds is <= 1\n+    assert_raises(ValueError, KFold, 0)\n+    assert_raises(ValueError, KFold, 1)\n+    assert_raises(ValueError, StratifiedKFold, 0)\n+    assert_raises(ValueError, StratifiedKFold, 1)\n+\n+    # When n_folds is not integer:\n+    assert_raises(ValueError, KFold, 1.5)\n+    assert_raises(ValueError, StratifiedKFold, 1.5)\n+\n+\n+def test_kfold_indices():\n+    # Check all indices are returned in the test folds\n+    X1 = np.ones((300, 2))\n+    kf = KFold(3)\n+    check_cv_coverage(kf, X1, y=None, labels=None, expected_n_iter=3,\n+                      n_samples=300)\n+\n+    # Check all indices are returned in the test folds even when equal-sized\n+    # folds are not possible\n+    X2 = np.ones((17, 2))\n+    kf = KFold(3)\n+    check_cv_coverage(kf, X2, y=None, labels=None, expected_n_iter=3,\n+                      n_samples=17)\n+\n+\n+def test_kfold_no_shuffle():\n+    # Manually check that KFold preserves the data ordering on toy datasets\n+    X2 = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]\n+\n+    splits = KFold(2).split(X2[:-1])\n+    train, test = next(splits)\n+    assert_array_equal(test, [0, 1])\n+    assert_array_equal(train, [2, 3])\n+\n+    train, test = next(splits)\n+    assert_array_equal(test, [2, 3])\n+    assert_array_equal(train, [0, 1])\n+\n+    splits = KFold(2).split(X2)\n+    train, test = next(splits)\n+    assert_array_equal(test, [0, 1, 2])\n+    assert_array_equal(train, [3, 4])\n+\n+    train, test = next(splits)\n+    assert_array_equal(test, [3, 4])\n+    assert_array_equal(train, [0, 1, 2])\n+\n+\n+def test_stratified_kfold_no_shuffle():\n+    # Manually check that StratifiedKFold preserves the data ordering as much\n+    # as possible on toy datasets in order to avoid hiding sample dependencies\n+    # when possible\n+    X, y = np.ones((4, 2)), [1, 1, 0, 0]\n+    splits = StratifiedKFold(2).split(X, y)\n+    train, test = next(splits)\n+    assert_array_equal(test, [0, 2])\n+    assert_array_equal(train, [1, 3])\n+\n+    train, test = next(splits)\n+    assert_array_equal(test, [1, 3])\n+    assert_array_equal(train, [0, 2])\n+\n+    splits = StratifiedKFold(2).split(np.ones((7, 2)), [1, 1, 1, 0, 0, 0, 0])\n+    train, test = next(splits)\n+    assert_array_equal(test, [0, 1, 3, 4])\n+    assert_array_equal(train, [2, 5, 6])\n+\n+    train, test = next(splits)\n+    assert_array_equal(test, [2, 5, 6])\n+    assert_array_equal(train, [0, 1, 3, 4])\n+\n+\n+def test_stratified_kfold_ratios():\n+    # Check that stratified kfold preserves label ratios in individual splits\n+    # Repeat with shuffling turned off and on\n+    n_samples = 1000\n+    X = np.ones(n_samples)\n+    labels = np.array([4] * int(0.10 * n_samples) +\n+                      [0] * int(0.89 * n_samples) +\n+                      [1] * int(0.01 * n_samples))\n+\n+    for cv in [StratifiedKFold(5, shuffle=s) for s in (True, False)]:\n+        for train, test in cv.split(X, y=labels):\n+            assert_almost_equal(np.sum(labels[train] == 4) / len(train), 0.10,\n+                                2)\n+            assert_almost_equal(np.sum(labels[train] == 0) / len(train), 0.89,\n+                                2)\n+            assert_almost_equal(np.sum(labels[train] == 1) / len(train), 0.01,\n+                                2)\n+            assert_almost_equal(np.sum(labels[test] == 4) / len(test), 0.10, 2)\n+            assert_almost_equal(np.sum(labels[test] == 0) / len(test), 0.89, 2)\n+            assert_almost_equal(np.sum(labels[test] == 1) / len(test), 0.01, 2)\n+\n+\n+def test_kfold_balance():\n+    # Check that KFold returns folds with balanced sizes\n+    for i in range(11, 17):\n+        kf = KFold(5).split(X=np.ones(i))\n+        sizes = []\n+        for _, test in kf:\n+            sizes.append(len(test))\n+\n+        assert_true((np.max(sizes) - np.min(sizes)) <= 1)\n+        assert_equal(np.sum(sizes), i)\n+\n+\n+def test_stratifiedkfold_balance():\n+    # Check that KFold returns folds with balanced sizes (only when\n+    # stratification is possible)\n+    # Repeat with shuffling turned off and on\n+    labels = [0] * 3 + [1] * 14\n+    X = np.ones(17)\n+\n+    for cv in [StratifiedKFold(3, shuffle=s) for s in (True, False)]:\n+        for i in range(11, 17):\n+            skf = cv.split(X[:i], y=labels[:i])\n+            sizes = []\n+            for _, test in skf:\n+                sizes.append(len(test))\n+\n+            assert_true((np.max(sizes) - np.min(sizes)) <= 1)\n+            assert_equal(np.sum(sizes), i)\n+\n+\n+def test_shuffle_kfold():\n+    # Check the indices are shuffled properly, and that all indices are\n+    # returned in the different test folds\n+    kf = KFold(3, shuffle=True, random_state=0)\n+    ind = np.arange(300)\n+\n+    all_folds = None\n+    for train, test in kf.split(X=np.ones(300)):\n+        sorted_array = np.arange(100)\n+        assert_true(np.any(sorted_array != ind[train]))\n+        sorted_array = np.arange(101, 200)\n+        assert_true(np.any(sorted_array != ind[train]))\n+        sorted_array = np.arange(201, 300)\n+        assert_true(np.any(sorted_array != ind[train]))\n+        if all_folds is None:\n+            all_folds = ind[test].copy()\n+        else:\n+            all_folds = np.concatenate((all_folds, ind[test]))\n+\n+    all_folds.sort()\n+    assert_array_equal(all_folds, ind)\n+\n+\n+def test_shuffle_stratifiedkfold():\n+    # Check that shuffling is happening when requested, and for proper\n+    # sample coverage\n+    X_40 = np.ones(40)\n+    labels = [0] * 20 + [1] * 20\n+    kf0 = StratifiedKFold(5, shuffle=True, random_state=0)\n+    kf1 = StratifiedKFold(5, shuffle=True, random_state=1)\n+    for (_, test0), (_, test1) in zip(kf0.split(X_40, y=labels),\n+                                      kf1.split(X_40, y=labels)):\n+        assert_true(set(test0) != set(test1))\n+    check_cv_coverage(kf0, X_40, y=labels, labels=None,\n+                      expected_n_iter=5, n_samples=40)\n+\n+\n+def test_kfold_can_detect_dependent_samples_on_digits():  # see #2372\n+    # The digits samples are dependent: they are apparently grouped by authors\n+    # although we don't have any information on the groups segment locations\n+    # for this data. We can highlight this fact be computing k-fold cross-\n+    # validation with and without shuffling: we observe that the shuffling case\n+    # wrongly makes the IID assumption and is therefore too optimistic: it\n+    # estimates a much higher accuracy (around 0.96) than than the non\n+    # shuffling variant (around 0.86).\n+\n+    digits = load_digits()\n+    X, y = digits.data[:800], digits.target[:800]\n+    model = SVC(C=10, gamma=0.005)\n+\n+    cv = KFold(n_folds=5, shuffle=False)\n+    mean_score = cross_val_score(model, X, y, cv=cv).mean()\n+    assert_greater(0.88, mean_score)\n+    assert_greater(mean_score, 0.85)\n+\n+    # Shuffling the data artificially breaks the dependency and hides the\n+    # overfitting of the model with regards to the writing style of the authors\n+    # by yielding a seriously overestimated score:\n+\n+    cv = KFold(5, shuffle=True, random_state=0)\n+    mean_score = cross_val_score(model, X, y, cv=cv).mean()\n+    assert_greater(mean_score, 0.95)\n+\n+    cv = KFold(5, shuffle=True, random_state=1)\n+    mean_score = cross_val_score(model, X, y, cv=cv).mean()\n+    assert_greater(mean_score, 0.95)\n+\n+    # Similarly, StratifiedKFold should try to shuffle the data as little\n+    # as possible (while respecting the balanced class constraints)\n+    # and thus be able to detect the dependency by not overestimating\n+    # the CV score either. As the digits dataset is approximately balanced\n+    # the estimated mean score is close to the score measured with\n+    # non-shuffled KFold\n+\n+    cv = StratifiedKFold(5)\n+    mean_score = cross_val_score(model, X, y, cv=cv).mean()\n+    assert_greater(0.88, mean_score)\n+    assert_greater(mean_score, 0.85)\n+\n+\n+def test_shuffle_split():\n+    X_10 = np.ones(10)\n+    ss1 = ShuffleSplit(test_size=0.2, random_state=0).split(X_10)\n+    ss2 = ShuffleSplit(test_size=2, random_state=0).split(X_10)\n+    ss3 = ShuffleSplit(test_size=np.int32(2), random_state=0).split(X_10)\n+    for typ in six.integer_types:\n+        ss4 = ShuffleSplit(test_size=typ(2), random_state=0).split(X_10)\n+    for t1, t2, t3, t4 in zip(ss1, ss2, ss3, ss4):\n+        assert_array_equal(t1[0], t2[0])\n+        assert_array_equal(t2[0], t3[0])\n+        assert_array_equal(t3[0], t4[0])\n+        assert_array_equal(t1[1], t2[1])\n+        assert_array_equal(t2[1], t3[1])\n+        assert_array_equal(t3[1], t4[1])\n+\n+\n+def test_stratified_shuffle_split_init():\n+    X = np.arange(7)\n+    y = np.asarray([0, 1, 1, 1, 2, 2, 2])\n+    # Check that error is raised if there is a class with only one sample\n+    assert_raises(ValueError, next,\n+                  StratifiedShuffleSplit(3, 0.2).split(X=np.ones(7), y=y))\n+\n+    # Check that error is raised if the test set size is smaller than n_classes\n+    assert_raises(ValueError, next, StratifiedShuffleSplit(3, 2).split(X, y))\n+    # Check that error is raised if the train set size is smaller than\n+    # n_classes\n+    assert_raises(ValueError, next,\n+                  StratifiedShuffleSplit(3, 3, 2).split(X, y))\n+\n+    X = np.arange(9)\n+    y = np.asarray([0, 0, 0, 1, 1, 1, 2, 2, 2])\n+    # Check that errors are raised if there is not enough samples\n+    assert_raises(ValueError, StratifiedShuffleSplit, 3, 0.5, 0.6)\n+    assert_raises(ValueError, next,\n+                  StratifiedShuffleSplit(3, 8, 0.6).split(X, y))\n+    assert_raises(ValueError, next,\n+                  StratifiedShuffleSplit(3, 0.6, 8).split(X, y))\n+\n+    # Train size or test size too small\n+    assert_raises(ValueError, next,\n+                  StratifiedShuffleSplit(train_size=2).split(X, y))\n+    assert_raises(ValueError, next,\n+                  StratifiedShuffleSplit(test_size=2).split(X, y))\n+\n+\n+def test_stratified_shuffle_split_iter():\n+    ys = [np.array([1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3]),\n+          np.array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]),\n+          np.array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2]),\n+          np.array([1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4]),\n+          np.array([-1] * 800 + [1] * 50)\n+          ]\n+\n+    for y in ys:\n+        sss = StratifiedShuffleSplit(6, test_size=0.33,\n+                                     random_state=0).split(np.ones(len(y)), y)\n+        for train, test in sss:\n+            assert_array_equal(np.unique(y[train]), np.unique(y[test]))\n+            # Checks if folds keep classes proportions\n+            p_train = (np.bincount(np.unique(y[train], return_inverse=True)[1])\n+                       / float(len(y[train])))\n+            p_test = (np.bincount(np.unique(y[test], return_inverse=True)[1])\n+                      / float(len(y[test])))\n+            assert_array_almost_equal(p_train, p_test, 1)\n+            assert_equal(y[train].size + y[test].size, y.size)\n+            assert_array_equal(np.lib.arraysetops.intersect1d(train, test), [])\n+\n+\n+def test_stratified_shuffle_split_even():\n+    # Test the StratifiedShuffleSplit, indices are drawn with a\n+    # equal chance\n+    n_folds = 5\n+    n_iter = 1000\n+\n+    def assert_counts_are_ok(idx_counts, p):\n+        # Here we test that the distribution of the counts\n+        # per index is close enough to a binomial\n+        threshold = 0.05 / n_splits\n+        bf = stats.binom(n_splits, p)\n+        for count in idx_counts:\n+            p = bf.pmf(count)\n+            assert_true(p > threshold,\n+                        \"An index is not drawn with chance corresponding \"\n+                        \"to even draws\")\n+\n+    for n_samples in (6, 22):\n+        labels = np.array((n_samples // 2) * [0, 1])\n+        splits = StratifiedShuffleSplit(n_iter=n_iter,\n+                                        test_size=1. / n_folds,\n+                                        random_state=0)\n+\n+        train_counts = [0] * n_samples\n+        test_counts = [0] * n_samples\n+        n_splits = 0\n+        for train, test in splits.split(X=np.ones(n_samples), y=labels):\n+            n_splits += 1\n+            for counter, ids in [(train_counts, train), (test_counts, test)]:\n+                for id in ids:\n+                    counter[id] += 1\n+        assert_equal(n_splits, n_iter)\n+\n+        n_train, n_test = _validate_shuffle_split(n_samples,\n+                                                  test_size=1./n_folds,\n+                                                  train_size=1.-(1./n_folds))\n+\n+        assert_equal(len(train), n_train)\n+        assert_equal(len(test), n_test)\n+        assert_equal(len(set(train).intersection(test)), 0)\n+\n+        label_counts = np.unique(labels)\n+        assert_equal(splits.test_size, 1.0 / n_folds)\n+        assert_equal(n_train + n_test, len(labels))\n+        assert_equal(len(label_counts), 2)\n+        ex_test_p = float(n_test) / n_samples\n+        ex_train_p = float(n_train) / n_samples\n+\n+        assert_counts_are_ok(train_counts, ex_train_p)\n+        assert_counts_are_ok(test_counts, ex_test_p)\n+\n+\n+def test_predefinedsplit_with_kfold_split():\n+    X_10 = np.ones(10)\n+    # Check that PredefinedSplit can reproduce a split generated by Kfold.\n+    folds = -1 * np.ones(10)\n+    kf_train = []\n+    kf_test = []\n+    for i, (train_ind, test_ind) in \\\n+            enumerate(KFold(5, shuffle=True).split(X=np.ones(10))):\n+        kf_train.append(train_ind)\n+        kf_test.append(test_ind)\n+        folds[test_ind] = i\n+    ps_train = []\n+    ps_test = []\n+    ps = PredefinedSplit()\n+    for train_ind, test_ind in ps.split(X=X_10, labels=folds):\n+        ps_train.append(train_ind)\n+        ps_test.append(test_ind)\n+    assert_array_equal(ps_train, kf_train)\n+    assert_array_equal(ps_test, kf_test)\n+\n+\n+def test_leave_label_out_changing_labels():\n+    # Check that LeaveOneLabelOut and LeavePLabelOut work normally if\n+    # the labels variable is changed before calling __iter__\n+    labels = np.array([0, 1, 2, 1, 1, 2, 0, 0])\n+    X = np.ones(len(labels))\n+    labels_changing = np.array(labels, copy=True)\n+    lolo = LeaveOneLabelOut().split(X, labels=labels)\n+    lolo_changing = LeaveOneLabelOut().split(X, labels=labels)\n+    lplo = LeavePLabelOut(p=2).split(X, labels=labels)\n+    lplo_changing = LeavePLabelOut(p=2).split(X, labels=labels)\n+    labels_changing[:] = 0\n+    for llo, llo_changing in [(lolo, lolo_changing), (lplo, lplo_changing)]:\n+        for (train, test), (train_chan, test_chan) in zip(llo, llo_changing):\n+            assert_array_equal(train, train_chan)\n+            assert_array_equal(test, test_chan)\n+\n+\n+def test_train_test_split_errors():\n+    assert_raises(ValueError, train_test_split)\n+    assert_raises(ValueError, train_test_split, range(3), train_size=1.1)\n+    assert_raises(ValueError, train_test_split, range(3), test_size=0.6,\n+                  train_size=0.6)\n+    assert_raises(ValueError, train_test_split, range(3),\n+                  test_size=np.float32(0.6), train_size=np.float32(0.6))\n+    assert_raises(ValueError, train_test_split, range(3),\n+                  test_size=\"wrong_type\")\n+    assert_raises(ValueError, train_test_split, range(3), test_size=2,\n+                  train_size=4)\n+    assert_raises(TypeError, train_test_split, range(3),\n+                  some_argument=1.1)\n+    assert_raises(ValueError, train_test_split, range(3), range(42))\n+\n+\n+def test_train_test_split():\n+    X = np.arange(100).reshape((10, 10))\n+    X_s = coo_matrix(X)\n+    y = np.arange(10)\n+\n+    # simple test\n+    split = train_test_split(X, y, test_size=None, train_size=.5)\n+    X_train, X_test, y_train, y_test = split\n+    assert_equal(len(y_test), len(y_train))\n+    # test correspondence of X and y\n+    assert_array_equal(X_train[:, 0], y_train * 10)\n+    assert_array_equal(X_test[:, 0], y_test * 10)\n+\n+    # don't convert lists to anything else by default\n+    split = train_test_split(X, X_s, y.tolist())\n+    X_train, X_test, X_s_train, X_s_test, y_train, y_test = split\n+    assert_true(isinstance(y_train, list))\n+    assert_true(isinstance(y_test, list))\n+\n+    # allow nd-arrays\n+    X_4d = np.arange(10 * 5 * 3 * 2).reshape(10, 5, 3, 2)\n+    y_3d = np.arange(10 * 7 * 11).reshape(10, 7, 11)\n+    split = train_test_split(X_4d, y_3d)\n+    assert_equal(split[0].shape, (7, 5, 3, 2))\n+    assert_equal(split[1].shape, (3, 5, 3, 2))\n+    assert_equal(split[2].shape, (7, 7, 11))\n+    assert_equal(split[3].shape, (3, 7, 11))\n+\n+    # test stratification option\n+    y = np.array([1, 1, 1, 1, 2, 2, 2, 2])\n+    for test_size, exp_test_size in zip([2, 4, 0.25, 0.5, 0.75],\n+                                        [2, 4, 2, 4, 6]):\n+        train, test = train_test_split(y, test_size=test_size,\n+                                       stratify=y,\n+                                       random_state=0)\n+        assert_equal(len(test), exp_test_size)\n+        assert_equal(len(test) + len(train), len(y))\n+        # check the 1:1 ratio of ones and twos in the data is preserved\n+        assert_equal(np.sum(train == 1), np.sum(train == 2))\n+\n+\n+def train_test_split_pandas():\n+    # check train_test_split doesn't destroy pandas dataframe\n+    types = [MockDataFrame]\n+    try:\n+        from pandas import DataFrame\n+        types.append(DataFrame)\n+    except ImportError:\n+        pass\n+    for InputFeatureType in types:\n+        # X dataframe\n+        X_df = InputFeatureType(X)\n+        X_train, X_test = train_test_split(X_df)\n+        assert_true(isinstance(X_train, InputFeatureType))\n+        assert_true(isinstance(X_test, InputFeatureType))\n+\n+\n+def train_test_split_mock_pandas():\n+    # X mock dataframe\n+    X_df = MockDataFrame(X)\n+    X_train, X_test = train_test_split(X_df)\n+    assert_true(isinstance(X_train, MockDataFrame))\n+    assert_true(isinstance(X_test, MockDataFrame))\n+    X_train_arr, X_test_arr = train_test_split(X_df)\n+\n+\n+def test_shufflesplit_errors():\n+    assert_raises(ValueError, ShuffleSplit, test_size=2.0)\n+    assert_raises(ValueError, ShuffleSplit, test_size=1.0)\n+    assert_raises(ValueError, ShuffleSplit, test_size=0.1, train_size=0.95)\n+    assert_raises(ValueError, next, ShuffleSplit(test_size=11).split(X))\n+    assert_raises(ValueError, next, ShuffleSplit(test_size=10).split(X))\n+    assert_raises(ValueError, next, ShuffleSplit(test_size=8,\n+                                                 train_size=3).split(X))\n+    assert_raises(ValueError, ShuffleSplit, test_size=None, train_size=None)\n+    assert_raises(ValueError, next, ShuffleSplit(train_size=1j).split(X))\n+\n+\n+def test_shufflesplit_reproducible():\n+    # Check that iterating twice on the ShuffleSplit gives the same\n+    # sequence of train-test when the random_state is given\n+    ss = ShuffleSplit(random_state=21)\n+    assert_array_equal(list(a for a, b in ss.split(X)),\n+                       list(a for a, b in ss.split(X)))\n+\n+\n+def test_safe_split_with_precomputed_kernel():\n+    clf = SVC()\n+    clfp = SVC(kernel=\"precomputed\")\n+\n+    iris = load_iris()\n+    X, y = iris.data, iris.target\n+    K = np.dot(X, X.T)\n+\n+    cv = ShuffleSplit(test_size=0.25, random_state=0)\n+    tr, te = list(cv.split(X))[0]\n+\n+    X_tr, y_tr = _safe_split(clf, X, y, tr)\n+    K_tr, y_tr2 = _safe_split(clfp, K, y, tr)\n+    assert_array_almost_equal(K_tr, np.dot(X_tr, X_tr.T))\n+\n+    X_te, y_te = _safe_split(clf, X, y, te, tr)\n+    K_te, y_te2 = _safe_split(clfp, K, y, te, tr)\n+    assert_array_almost_equal(K_te, np.dot(X_te, X_tr.T))\n+\n+\n+def test_train_test_split_allow_nans():\n+    # Check that train_test_split allows input data with NaNs\n+    X = np.arange(200, dtype=np.float64).reshape(10, -1)\n+    X[2, :] = np.nan\n+    y = np.repeat([0, 1], X.shape[0] / 2)\n+    train_test_split(X, y, test_size=0.2, random_state=42)\n+\n+\n+def test_check_cv_return_types():\n+    X = np.ones((9, 2))\n+    cv = check_cv(3, classifier=False)\n+    # Use numpy.testing.assert_equal which recursively compares\n+    # lists of lists\n+    np.testing.assert_equal(list(KFold(3).split(X)), list(cv.split(X)))\n+\n+    y_binary = np.array([0, 1, 0, 1, 0, 0, 1, 1, 1])\n+    cv = check_cv(3, y_binary, classifier=True)\n+    np.testing.assert_equal(list(StratifiedKFold(3).split(X, y_binary)),\n+                            list(cv.split(X, y_binary)))\n+\n+    y_multiclass = np.array([0, 1, 0, 1, 2, 1, 2, 0, 2])\n+    cv = check_cv(3, y_multiclass, classifier=True)\n+    np.testing.assert_equal(list(StratifiedKFold(3).split(X, y_multiclass)),\n+                            list(cv.split(X, y_multiclass)))\n+\n+    X = np.ones((5, 2))\n+    y_seq_of_seqs = [[], [1, 2], [3], [0, 1, 3], [2]]\n+\n+    with warnings.catch_warnings(record=True):\n+        # deprecated sequence of sequence format\n+        cv = check_cv(3, y_seq_of_seqs, classifier=True)\n+    np.testing.assert_equal(list(KFold(3).split(X)), list(cv.split(X)))\n+\n+    y_indicator_matrix = MultiLabelBinarizer().fit_transform(y_seq_of_seqs)\n+    cv = check_cv(3, y_indicator_matrix, classifier=True)\n+    np.testing.assert_equal(list(KFold(3).split(X)), list(cv.split(X)))\n+\n+    y_multioutput = np.array([[1, 2], [0, 3], [0, 0], [3, 1], [2, 0]])\n+    cv = check_cv(3, y_multioutput, classifier=True)\n+    np.testing.assert_equal(list(KFold(3).split(X)), list(cv.split(X)))\n+\n+    # Check if the old style classes are wrapped to have a split method","path":"sklearn/model_selection/tests/test_split.py","position":712,"original_position":712,"commit_id":"e4e3290a8b4f066151e90498554b135c4184cbc4","original_commit_id":"e4e3290a8b4f066151e90498554b135c4184cbc4","user":{"login":"rvraghav93","id":9487348,"avatar_url":"https://avatars.githubusercontent.com/u/9487348?v=3","gravatar_id":"","url":"https://api.github.com/users/rvraghav93","html_url":"https://github.com/rvraghav93","followers_url":"https://api.github.com/users/rvraghav93/followers","following_url":"https://api.github.com/users/rvraghav93/following{/other_user}","gists_url":"https://api.github.com/users/rvraghav93/gists{/gist_id}","starred_url":"https://api.github.com/users/rvraghav93/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rvraghav93/subscriptions","organizations_url":"https://api.github.com/users/rvraghav93/orgs","repos_url":"https://api.github.com/users/rvraghav93/repos","events_url":"https://api.github.com/users/rvraghav93/events{/privacy}","received_events_url":"https://api.github.com/users/rvraghav93/received_events","type":"User","site_admin":false},"body":"okay :)","created_at":"2015-07-02T10:01:04Z","updated_at":"2015-07-02T10:01:04Z","html_url":"https://github.com/scikit-learn/scikit-learn/pull/4294#discussion_r33763342","pull_request_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294","_links":{"self":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments/33763342"},"html":{"href":"https://github.com/scikit-learn/scikit-learn/pull/4294#discussion_r33763342"},"pull_request":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294"}}},"pull_request":{"url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294","id":29984425,"html_url":"https://github.com/scikit-learn/scikit-learn/pull/4294","diff_url":"https://github.com/scikit-learn/scikit-learn/pull/4294.diff","patch_url":"https://github.com/scikit-learn/scikit-learn/pull/4294.patch","issue_url":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/4294","number":4294,"state":"open","locked":false,"title":"[WIP] Reorganize grid_search, cross_validation and learning_curve into model_selection","user":{"login":"rvraghav93","id":9487348,"avatar_url":"https://avatars.githubusercontent.com/u/9487348?v=3","gravatar_id":"","url":"https://api.github.com/users/rvraghav93","html_url":"https://github.com/rvraghav93","followers_url":"https://api.github.com/users/rvraghav93/followers","following_url":"https://api.github.com/users/rvraghav93/following{/other_user}","gists_url":"https://api.github.com/users/rvraghav93/gists{/gist_id}","starred_url":"https://api.github.com/users/rvraghav93/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rvraghav93/subscriptions","organizations_url":"https://api.github.com/users/rvraghav93/orgs","repos_url":"https://api.github.com/users/rvraghav93/repos","events_url":"https://api.github.com/users/rvraghav93/events{/privacy}","received_events_url":"https://api.github.com/users/rvraghav93/received_events","type":"User","site_admin":false},"body":"fixes #1848, #2904 \r\n<hr>\r\n**TODO**\r\n- [x] Reorganize the classes / functions into the `model_selection` module.\r\n- [x] Remove all deprecation from new style classes.\r\n- [x] Use split in all the files that use cv ? (or fix `check_cv` so both old style and new style classes can be used)\r\n- [x] Refactor the tests.\r\n- [x] Fix all the imports\r\n- [x] Make all the general tests pass\r\n- [x] Make all the `model_selction` tests pass\r\n- [x] Clean up the old style classes to use as much from the new members as possible. (duplicate as little code as possible) - https://github.com/rvraghav93/scikit-learn/pull/2\r\n- [ ] Clean up the documentation - https://github.com/rvraghav93/scikit-learn/pull/3\r\n- [ ]  Fix the examples - https://github.com/rvraghav93/scikit-learn/pull/4\r\n\r\n<hr>\r\n**MINOR**\r\n- [ ] Rename `p` to a better name.\r\n- [x] Rename `_check_is_partition`-->`_check_is_permutation`?\r\n- [x] Remove `_empty_mask`\r\n- [x] As Joel said [here](https://github.com/scikit-learn/scikit-learn/pull/4621/files#r33238307), use binomial coefficient instead of factorial.\r\n\r\n<hr>\r\n**NOTE:**\r\nThe current implementation will still not support nesting `EstimatorCV` inside `GridSearchCV`... This will become possible only after allowing `sample_properties` to pass from `GridSearchCV` to `EstimatorCV`...\r\n<hr>\r\n**PRs whose changes to g_s / c_v / l_c have been manually incorporated into this:**\r\n\r\n#4714 - Svm decision function shape - 1 commit\r\n#4829 - merge _check_cv into check_cv ... -  1 commit\r\n#4857 - Document missing attribute `random_state` in `RandomizedSearchCV` - 1 commit\r\n#4840 - FIX avoid memory cost when sampling from large parameter grids - 1 commit\r\n<hr>\r\nThis PR is slightly based upon @pignacio's work in #3340.\r\n<hr>\r\n\r\n**Other model selection issues to be tackled after this PR is merged**\r\n\r\n(I am just listing all the issues/improvements that are out of scope for this PR but related to the `model_selection`)\r\n\r\n* General tests for CV objects\r\n* Whether `_permutation_test_score` can be replaced by `cross_val_score`?\r\n\r\n<hr>\r\n\r\n**Unresolved issues**\r\n\r\n* How to design `PredefinedSplit` in the context of data independent cv objects.","created_at":"2015-02-25T12:54:52Z","updated_at":"2015-07-02T10:01:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ad9f5095628f3f5bfaa57af50b54d20826fe9d04","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294/commits","review_comments_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294/comments","review_comment_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments{/number}","comments_url":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/4294/comments","statuses_url":"https://api.github.com/repos/scikit-learn/scikit-learn/statuses/e4e3290a8b4f066151e90498554b135c4184cbc4","head":{"label":"rvraghav93:model_selection","ref":"model_selection","sha":"e4e3290a8b4f066151e90498554b135c4184cbc4","user":{"login":"rvraghav93","id":9487348,"avatar_url":"https://avatars.githubusercontent.com/u/9487348?v=3","gravatar_id":"","url":"https://api.github.com/users/rvraghav93","html_url":"https://github.com/rvraghav93","followers_url":"https://api.github.com/users/rvraghav93/followers","following_url":"https://api.github.com/users/rvraghav93/following{/other_user}","gists_url":"https://api.github.com/users/rvraghav93/gists{/gist_id}","starred_url":"https://api.github.com/users/rvraghav93/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rvraghav93/subscriptions","organizations_url":"https://api.github.com/users/rvraghav93/orgs","repos_url":"https://api.github.com/users/rvraghav93/repos","events_url":"https://api.github.com/users/rvraghav93/events{/privacy}","received_events_url":"https://api.github.com/users/rvraghav93/received_events","type":"User","site_admin":false},"repo":{"id":26038110,"name":"scikit-learn","full_name":"rvraghav93/scikit-learn","owner":{"login":"rvraghav93","id":9487348,"avatar_url":"https://avatars.githubusercontent.com/u/9487348?v=3","gravatar_id":"","url":"https://api.github.com/users/rvraghav93","html_url":"https://github.com/rvraghav93","followers_url":"https://api.github.com/users/rvraghav93/followers","following_url":"https://api.github.com/users/rvraghav93/following{/other_user}","gists_url":"https://api.github.com/users/rvraghav93/gists{/gist_id}","starred_url":"https://api.github.com/users/rvraghav93/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rvraghav93/subscriptions","organizations_url":"https://api.github.com/users/rvraghav93/orgs","repos_url":"https://api.github.com/users/rvraghav93/repos","events_url":"https://api.github.com/users/rvraghav93/events{/privacy}","received_events_url":"https://api.github.com/users/rvraghav93/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rvraghav93/scikit-learn","description":"scikit-learn: machine learning in Python","fork":true,"url":"https://api.github.com/repos/rvraghav93/scikit-learn","forks_url":"https://api.github.com/repos/rvraghav93/scikit-learn/forks","keys_url":"https://api.github.com/repos/rvraghav93/scikit-learn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rvraghav93/scikit-learn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rvraghav93/scikit-learn/teams","hooks_url":"https://api.github.com/repos/rvraghav93/scikit-learn/hooks","issue_events_url":"https://api.github.com/repos/rvraghav93/scikit-learn/issues/events{/number}","events_url":"https://api.github.com/repos/rvraghav93/scikit-learn/events","assignees_url":"https://api.github.com/repos/rvraghav93/scikit-learn/assignees{/user}","branches_url":"https://api.github.com/repos/rvraghav93/scikit-learn/branches{/branch}","tags_url":"https://api.github.com/repos/rvraghav93/scikit-learn/tags","blobs_url":"https://api.github.com/repos/rvraghav93/scikit-learn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rvraghav93/scikit-learn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rvraghav93/scikit-learn/git/refs{/sha}","trees_url":"https://api.github.com/repos/rvraghav93/scikit-learn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rvraghav93/scikit-learn/statuses/{sha}","languages_url":"https://api.github.com/repos/rvraghav93/scikit-learn/languages","stargazers_url":"https://api.github.com/repos/rvraghav93/scikit-learn/stargazers","contributors_url":"https://api.github.com/repos/rvraghav93/scikit-learn/contributors","subscribers_url":"https://api.github.com/repos/rvraghav93/scikit-learn/subscribers","subscription_url":"https://api.github.com/repos/rvraghav93/scikit-learn/subscription","commits_url":"https://api.github.com/repos/rvraghav93/scikit-learn/commits{/sha}","git_commits_url":"https://api.github.com/repos/rvraghav93/scikit-learn/git/commits{/sha}","comments_url":"https://api.github.com/repos/rvraghav93/scikit-learn/comments{/number}","issue_comment_url":"https://api.github.com/repos/rvraghav93/scikit-learn/issues/comments{/number}","contents_url":"https://api.github.com/repos/rvraghav93/scikit-learn/contents/{+path}","compare_url":"https://api.github.com/repos/rvraghav93/scikit-learn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rvraghav93/scikit-learn/merges","archive_url":"https://api.github.com/repos/rvraghav93/scikit-learn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rvraghav93/scikit-learn/downloads","issues_url":"https://api.github.com/repos/rvraghav93/scikit-learn/issues{/number}","pulls_url":"https://api.github.com/repos/rvraghav93/scikit-learn/pulls{/number}","milestones_url":"https://api.github.com/repos/rvraghav93/scikit-learn/milestones{/number}","notifications_url":"https://api.github.com/repos/rvraghav93/scikit-learn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rvraghav93/scikit-learn/labels{/name}","releases_url":"https://api.github.com/repos/rvraghav93/scikit-learn/releases{/id}","created_at":"2014-11-01T00:56:31Z","updated_at":"2015-05-03T17:08:25Z","pushed_at":"2015-07-01T08:48:28Z","git_url":"git://github.com/rvraghav93/scikit-learn.git","ssh_url":"git@github.com:rvraghav93/scikit-learn.git","clone_url":"https://github.com/rvraghav93/scikit-learn.git","svn_url":"https://github.com/rvraghav93/scikit-learn","homepage":"http://scikit-learn.org","size":64882,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"scikit-learn:master","ref":"master","sha":"c66a8391efc270e362e058bc8d04b29a3b09698c","user":{"login":"scikit-learn","id":365630,"avatar_url":"https://avatars.githubusercontent.com/u/365630?v=3","gravatar_id":"","url":"https://api.github.com/users/scikit-learn","html_url":"https://github.com/scikit-learn","followers_url":"https://api.github.com/users/scikit-learn/followers","following_url":"https://api.github.com/users/scikit-learn/following{/other_user}","gists_url":"https://api.github.com/users/scikit-learn/gists{/gist_id}","starred_url":"https://api.github.com/users/scikit-learn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scikit-learn/subscriptions","organizations_url":"https://api.github.com/users/scikit-learn/orgs","repos_url":"https://api.github.com/users/scikit-learn/repos","events_url":"https://api.github.com/users/scikit-learn/events{/privacy}","received_events_url":"https://api.github.com/users/scikit-learn/received_events","type":"Organization","site_admin":false},"repo":{"id":843222,"name":"scikit-learn","full_name":"scikit-learn/scikit-learn","owner":{"login":"scikit-learn","id":365630,"avatar_url":"https://avatars.githubusercontent.com/u/365630?v=3","gravatar_id":"","url":"https://api.github.com/users/scikit-learn","html_url":"https://github.com/scikit-learn","followers_url":"https://api.github.com/users/scikit-learn/followers","following_url":"https://api.github.com/users/scikit-learn/following{/other_user}","gists_url":"https://api.github.com/users/scikit-learn/gists{/gist_id}","starred_url":"https://api.github.com/users/scikit-learn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scikit-learn/subscriptions","organizations_url":"https://api.github.com/users/scikit-learn/orgs","repos_url":"https://api.github.com/users/scikit-learn/repos","events_url":"https://api.github.com/users/scikit-learn/events{/privacy}","received_events_url":"https://api.github.com/users/scikit-learn/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scikit-learn/scikit-learn","description":"scikit-learn: machine learning in Python","fork":false,"url":"https://api.github.com/repos/scikit-learn/scikit-learn","forks_url":"https://api.github.com/repos/scikit-learn/scikit-learn/forks","keys_url":"https://api.github.com/repos/scikit-learn/scikit-learn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scikit-learn/scikit-learn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scikit-learn/scikit-learn/teams","hooks_url":"https://api.github.com/repos/scikit-learn/scikit-learn/hooks","issue_events_url":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/events{/number}","events_url":"https://api.github.com/repos/scikit-learn/scikit-learn/events","assignees_url":"https://api.github.com/repos/scikit-learn/scikit-learn/assignees{/user}","branches_url":"https://api.github.com/repos/scikit-learn/scikit-learn/branches{/branch}","tags_url":"https://api.github.com/repos/scikit-learn/scikit-learn/tags","blobs_url":"https://api.github.com/repos/scikit-learn/scikit-learn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scikit-learn/scikit-learn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scikit-learn/scikit-learn/git/refs{/sha}","trees_url":"https://api.github.com/repos/scikit-learn/scikit-learn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scikit-learn/scikit-learn/statuses/{sha}","languages_url":"https://api.github.com/repos/scikit-learn/scikit-learn/languages","stargazers_url":"https://api.github.com/repos/scikit-learn/scikit-learn/stargazers","contributors_url":"https://api.github.com/repos/scikit-learn/scikit-learn/contributors","subscribers_url":"https://api.github.com/repos/scikit-learn/scikit-learn/subscribers","subscription_url":"https://api.github.com/repos/scikit-learn/scikit-learn/subscription","commits_url":"https://api.github.com/repos/scikit-learn/scikit-learn/commits{/sha}","git_commits_url":"https://api.github.com/repos/scikit-learn/scikit-learn/git/commits{/sha}","comments_url":"https://api.github.com/repos/scikit-learn/scikit-learn/comments{/number}","issue_comment_url":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/comments{/number}","contents_url":"https://api.github.com/repos/scikit-learn/scikit-learn/contents/{+path}","compare_url":"https://api.github.com/repos/scikit-learn/scikit-learn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scikit-learn/scikit-learn/merges","archive_url":"https://api.github.com/repos/scikit-learn/scikit-learn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scikit-learn/scikit-learn/downloads","issues_url":"https://api.github.com/repos/scikit-learn/scikit-learn/issues{/number}","pulls_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls{/number}","milestones_url":"https://api.github.com/repos/scikit-learn/scikit-learn/milestones{/number}","notifications_url":"https://api.github.com/repos/scikit-learn/scikit-learn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scikit-learn/scikit-learn/labels{/name}","releases_url":"https://api.github.com/repos/scikit-learn/scikit-learn/releases{/id}","created_at":"2010-08-17T09:43:38Z","updated_at":"2015-07-02T08:58:34Z","pushed_at":"2015-07-02T09:33:59Z","git_url":"git://github.com/scikit-learn/scikit-learn.git","ssh_url":"git@github.com:scikit-learn/scikit-learn.git","clone_url":"https://github.com/scikit-learn/scikit-learn.git","svn_url":"https://github.com/scikit-learn/scikit-learn","homepage":"http://scikit-learn.org","size":125816,"stargazers_count":6578,"watchers_count":6578,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3937,"mirror_url":null,"open_issues_count":693,"forks":3937,"open_issues":693,"watchers":6578,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294"},"html":{"href":"https://github.com/scikit-learn/scikit-learn/pull/4294"},"issue":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/4294"},"comments":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/4294/comments"},"review_comments":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294/comments"},"review_comment":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4294/commits"},"statuses":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/statuses/e4e3290a8b4f066151e90498554b135c4184cbc4"}}}}