{"action":"created","comment":{"url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments/34413554","id":34413554,"diff_hunk":"@@ -0,0 +1,477 @@\n+import numpy as np\n+from scipy import linalg\n+from scipy.special import digamma, gammaln\n+\n+from time import time\n+\n+from ..externals import six\n+from ..utils import check_array\n+from ..utils.validation import check_is_fitted\n+from ..utils.extmath import logsumexp\n+from sklearn.externals.six.moves import zip\n+from sklearn.externals.six import print_\n+from .gaussianmixture import MixtureBase, check_shape\n+\n+\n+def _define_prior_shape(n_components, n_features, precision_type):\n+    lambda_W_prior_shape = {\n+        'full': (n_features, n_features),\n+        'tied': (n_features, n_features),\n+        'diag': (n_features, ),\n+        'spherical': ()}\n+    param_shape = {'weight_alpha_prior': (),\n+                   'mu_beta_prior': (),\n+                   'mu_m_prior': (1, n_features),\n+                   'lambda_nu_prior': (),\n+                   'lambda_W_prior': lambda_W_prior_shape[precision_type]}\n+    return param_shape\n+\n+\n+def _check_weight_prior(weight_alpha_prior, desired_shape):\n+    \"\"\"Check the parameter 'alpha' of the weight Dirichlet distribution\n+\n+    Parameters\n+    ----------\n+    weight_alpha : scalar\n+\n+    Returns\n+    -------\n+    weight_alpha : scalar\n+    \"\"\"\n+    # check shape\n+    check_shape(weight_alpha_prior, desired_shape, 'alpha')\n+    if weight_alpha_prior <= 0:\n+        raise ValueError(\"The parameter 'weight_alpha_prior' should be \"\n+                         \"greater than 0, but got %.5f\" % weight_alpha_prior)\n+    return weight_alpha_prior\n+\n+def _check_mu_prior(mu_m, mu_beta, desired_shape_m, desired_shape_beta):\n+    \"\"\"Check the 'm', the parameter of the Gaussian distribution of the mean\n+\n+    Parameters\n+    ----------\n+    m : array-like, (n_components, n_features)\n+\n+    beta : array-like, (n_components,)\n+\n+    n_components : int\n+\n+    n_features : int\n+\n+    Returns\n+    -------\n+    m : array, (n_components, n_features)\n+\n+    beta : array-like, (n_components,)\n+    \"\"\"\n+    # check value\n+    mu_m = check_array(mu_m, dtype=np.float64, ensure_2d=False)\n+\n+    # check shape\n+    check_shape(mu_m, desired_shape_m, 'mu_m_prior')\n+\n+    # check shape\n+    check_shape(mu_beta, desired_shape_beta, 'mu_beta_prior')\n+    if mu_beta <= 0:\n+        raise ValueError(\"The parameter 'mu_beta_prior' should be \"\n+                         \"greater than 0, but got %.5f\" % mu_beta)\n+    return mu_m, mu_beta\n+\n+\n+def _check_lambda_nu_prior(lambda_nu, desired_shape, n_features, name):\n+    check_shape(lambda_nu, desired_shape, name)\n+    if lambda_nu <= 0:\n+        raise ValueError(\"The parameter 'lambda_nu' should be \"\n+                         \"greater than 0, but got %.5f\" % lambda_nu)\n+    if np.any(np.less_equal(lambda_nu, n_features - 1)):\n+        raise ValueError(\"The parameter '%s' \"\n+                         \"should be greater then %d, but got \"\n+                         \"minimal value %.5f\"\n+                         % (name, n_features - 1, np.min(lambda_nu)))\n+    return lambda_nu\n+\n+def _check_lambda_wishart_prior(lambda_nu, lambda_W,\n+                                desired_shape_nu, desired_shape_W):\n+    # Wishart distribution\n+    lambda_nu = _check_lambda_nu_prior(\n+        lambda_nu, desired_shape_nu, desired_shape_W[0], 'lambda_nu_prior')\n+\n+    lambda_W = check_array(lambda_W, dtype=np.float64, ensure_2d=False)\n+    check_shape(lambda_W, desired_shape_W, 'lambda_W_prior')\n+    if (not np.allclose(lambda_W, lambda_W.T) or\n+            np.any(np.less_equal(linalg.eigvalsh(lambda_W), 0.0))):\n+        raise ValueError(\"The parameter 'W' of Wishart distribution \"\n+                         \"should be symmetric, positive-definite\")\n+    return lambda_nu, lambda_W\n+\n+\n+def _check_lambda_gamma_prior(lambda_nu, lambda_W,\n+                              desired_shape_a, desired_shape_b):\n+    # Gamma distribution\n+    lambda_nu = _check_lambda_nu_prior(lambda_nu, desired_shape_a,\n+                                       1, 'lambda_nu_prior')\n+\n+    lambda_W = check_array(lambda_W, dtype=np.float64, ensure_2d=False)\n+    check_shape(lambda_W, desired_shape_b, 'lambda_W_prior')\n+    if np.any(np.less_equal(lambda_W, 0.0)):\n+        raise ValueError(\"The parameter 'W' of Gamma distributions \"\n+                         \"should be positive\")\n+    return lambda_nu, lambda_W\n+\n+\n+def _check_lambda_prior(lambda_nu, lambda_W, desired_shape_a,\n+                        desired_shape_b, covariance_type):\n+    \"\"\"Check the parameter of the precision distributions\n+\n+    Parameters\n+    ----------\n+    lambda_nu : array-like, shape of (n_components,)\n+\n+    lambda_W : array-like,\n+        'full' : shape of (n_features, n_features)\n+        'tied' : shape of (n_features, n_features)\n+        'diag' : shape of (n_components, n_features)\n+        'spherical' : shape of (n_components,)\n+\n+    n_components : int\n+\n+    n_features : int\n+\n+    covariance_type : string\n+\n+    Returns\n+    -------\n+    lambda_nu : array-like\n+\n+    lambda_W : array-like\n+    \"\"\"\n+\n+    check_covars_functions = {\"full\": _check_lambda_wishart_prior,\n+                              \"tied\": _check_lambda_wishart_prior,\n+                              \"diag\": _check_lambda_gamma_prior,\n+                              \"spherical\": _check_lambda_gamma_prior}\n+    return check_covars_functions[covariance_type](\n+        lambda_nu, lambda_W, desired_shape_a, desired_shape_b)\n+\n+\n+def _dirichlet_log_C(alpha):\n+    \"\"\"The log of the normalization term of Dirichlet distribution\n+    \"\"\"\n+    return gammaln(np.sum(alpha)) - np.sum(gammaln(alpha))\n+\n+def _wishart_log_B(n_dim, nu, inv_W_chol):\n+    \"\"\"The log of the normalization term of Wishart distribution\n+    \"\"\"\n+    log_det_W = - 2 * np.sum(np.log(np.diag(inv_W_chol)))\n+    temp1 = - nu * .5 * log_det_W\n+    temp2 = nu * n_dim * .5 * np.log(2)\n+    temp3 = n_dim * (n_dim - 1) * .25 * np.log(np.pi)\n+    temp4 = np.sum(gammaln((nu + 1 - np.arange(1, n_dim + 1)) * .5))\n+    return temp1 - temp2 - temp3 - temp4\n+\n+def _wishart_entropy(n_dim, nu, inv_W_chol, log_W):\n+    return - np.log(_wishart_log_B(n_dim, nu, inv_W_chol)) - \\\n+           .5 * (nu - n_dim - 1) * log_W + .5 * nu * n_dim\n+\n+class BayesianGaussianMixture(MixtureBase):\n+    def __init__(self, n_components=1, precision_type='full',\n+                 random_state=None, tol=1e-6, min_covar=0,\n+                 n_iter=100, n_init=1, params=None, init_params='kmeans',\n+                 weight_alpha_prior=None,\n+                 mu_m_prior=None, mu_beta_prior=None,\n+                 lambda_nu_prior=None, lambda_W_prior=None,\n+                 verbose=0):\n+        super(BayesianGaussianMixture, self).__init__(\n+            n_components, precision_type, random_state, tol, min_covar,\n+            n_iter, n_init, params, init_params, verbose)\n+        self.precision_type = precision_type\n+        self.weight_alpha_prior = weight_alpha_prior\n+        self.mu_m_prior = mu_m_prior\n+        self.mu_beta_prior = mu_beta_prior\n+        self.lambda_nu_prior = lambda_nu_prior\n+        self.lambda_W_prior = lambda_W_prior\n+\n+    def _check_initial_parameters(self):\n+        param_shape = _define_prior_shape(\n+            self.n_components, self.n_features, self.precision_type)\n+        if self.weight_alpha_prior is not None:\n+            _check_weight_prior(self.weight_alpha_prior,\n+                                param_shape['weight_alpha_prior'])\n+\n+        if self.mu_beta_prior is not None or self.mu_m_prior is not None:\n+            _check_mu_prior(self.mu_m_prior, self.mu_beta_prior,\n+                            param_shape['mu_m_prior'],\n+                            param_shape['mu_beta_prior'])\n+\n+        if self.lambda_nu_prior is not None or self.lambda_W_prior is not None:\n+            _check_lambda_prior(\n+                self.lambda_nu_prior, self.lambda_W_prior,\n+                param_shape['lambda_nu_prior'], param_shape['lambda_W_prior'],\n+                self.precision_type)\n+\n+    def _initialize_weight(self, X, nk, xk, Sk):\n+        if self.weight_alpha_prior is None:\n+            # TODO discuss default value\n+            self.weight_alpha_prior = 1e-3 * np.array(self.n_components)\n+\n+        self.weight_alpha_ = self._estimate_weights(X, nk, xk, Sk)\n+\n+        # for lower bound\n+        self.log_C_alpha_prior = _dirichlet_log_C(np.ones(self.n_components) *\n+                                                  self.weight_alpha_prior)\n+\n+    def _initialize_mu(self, X, nk, xk, Sk):\n+        if self.mu_beta_prior is None:\n+            self.mu_beta_prior = 1\n+            # TODO discuss default value\n+\n+        if self.mu_m_prior is None:\n+            self.mu_m_prior = X.mean(axis=0).reshape(1, -1)\n+            # TODO discuss default value\n+\n+        self.mu_beta_, self.mu_m_ = self._estimate_means(X, nk, xk, Sk)\n+        self.log_beta_prior = self.n_features * np.log(self.mu_beta_prior / (2 * np.pi))\n+\n+    def _initialize_lambda(self, X, nk, xk, Sk):\n+        if self.lambda_nu_prior is None:\n+            self.lambda_nu_prior = self.n_features\n+            # TODO discuss default value\n+\n+        if self.lambda_W_prior is None:\n+            self.lambda_inv_W_prior = np.cov(X.T, bias=1) * self.n_features\n+            # TODO discuss default value\n+            try:\n+                self.lambda_W_prior = np.linalg.inv(self.lambda_inv_W_prior)\n+            except linalg.LinAlgError:\n+                raise ValueError(\"lambda_W_prior must be symmetric, \"\n+                                 \"positive-definite. Check data distribution\")\n+        else:\n+            try:\n+                self.lambda_inv_W_prior = np.linalg.inv(self.lambda_W_prior)\n+            except linalg.LinAlgError:\n+                raise ValueError(\"lambda_W_prior must be symmetric, \"\n+                                 \"positive-definite.\")\n+\n+        self.lambda_nu_, self.lambda_inv_W_ = self._estimate_lambda(\n+            X, nk, xk, Sk)\n+        self.log_B_W_nu_prior = _wishart_log_B(\n+            self.n_features, self.lambda_nu_prior, self.lambda_W_prior)\n+\n+    def _initialize_parameters(self, X, responsibilities, nk, xk, Sk):\n+        self._initialize_weight(X, nk, xk, Sk)\n+        self._initialize_mu(X, nk, xk, Sk)\n+        self._initialize_lambda(X, nk, xk, Sk)\n+\n+    # m step\n+    def _estimate_weights(self, X, nk, xk, Sk):\n+        print 'alpha'\n+        print self.weight_alpha_prior + nk\n+        return self.weight_alpha_prior + nk\n+\n+    def _estimate_means(self, X, nk, xk, Sk):\n+        mu_beta_ = self.mu_beta_prior + nk\n+        mu_m_ = (self.mu_beta_prior * self.mu_m_prior +\n+                      nk[:, np.newaxis] * xk) / mu_beta_[:, np.newaxis]\n+        print 'mu_beta'\n+        print mu_beta_\n+        print 'mu_m'\n+        print mu_m_\n+        return mu_beta_, mu_m_\n+\n+    def _estimate_lambda_full(self, X, nk, xk, Sk):\n+        lambda_nu_ = self.lambda_nu_prior + nk\n+        lambda_inv_W_ = np.empty((self.n_components, self.n_features,\n+                                  self.n_features))\n+        for k in range(self.n_components):\n+            diff = xk[k] - self.mu_m_prior\n+            lambda_inv_W_[k] = (\n+                self.lambda_inv_W_prior + nk[k] * Sk[k] +\n+                (nk[k] * self.mu_beta_prior / self.mu_beta_[k]) *\n+                np.outer(diff, diff))\n+            print 'Wishart Mean'\n+            print np.linalg.inv(lambda_inv_W_[k]) * lambda_nu_[k]\n+        return lambda_nu_, lambda_inv_W_\n+\n+    def _estimate_lambda_tied(self, X, nk, xk, Sk):\n+        pass\n+\n+    def _estimate_lambda_diag(self, X, nk, xk, Sk):\n+        pass\n+\n+    def _estimate_lambda_spherical(self, X, nk, xk, Sk):\n+        pass\n+\n+    def _estimate_lambda(self, X, nk, xk, Sk):\n+        estimate_lambda_functions = {\n+            \"full\": self._estimate_lambda_full,\n+            \"tied\": self._estimate_lambda_tied,\n+            \"diag\": self._estimate_lambda_diag,\n+            \"spherical\": self._estimate_lambda_spherical\n+        }\n+        return estimate_lambda_functions[self.covariance_type](X, nk, xk, Sk)\n+\n+    def _e_step(self, X):\n+        log_prob_comp, log_prob, resp = \\\n+            self._estimate_log_probabilities_responsibilities(X)\n+        lower_bound = self._lower_bound(log_prob_comp, resp)\n+        return lower_bound, resp\n+\n+    def _m_step(self, X, nk, xk, Sk):\n+        self.weight_alpha_ = self._estimate_weights(X, nk, xk, Sk)\n+        self.mu_beta_, self.mu_m_ = self._estimate_means(X, nk, xk, Sk)\n+        self.lambda_nu_, self.lambda_inv_W_ = self._estimate_lambda(\n+            X, nk, xk, Sk)\n+\n+    # e step\n+    def _estimate_weighted_log_probabilities(self, X):\n+        # save ln_weights for computing lower bound\n+        log_weights = self._estimate_log_weights()\n+        _estimate_log_X = {\n+            \"full\": self._estimate_log_X_full,\n+            \"tied\": self._estimate_log_X_tied,\n+            \"diag\": self._estimate_log_X_diag,\n+            \"spherical\": self._estimate_log_X_spherical\n+        }\n+        # save ln_lambda, inv_W_chol for computing lower bound\n+        log_X = _estimate_log_X[self.precision_type](X)\n+        return log_weights + log_X\n+\n+    def _estimate_log_weights(self):\n+        # first item in Equation 3.8\n+        log_weights = (digamma(self.weight_alpha_) -\n+                digamma(np.sum(self.weight_alpha_)))\n+        self.log_weights = log_weights\n+        return log_weights\n+\n+    def _estimate_log_X_full(self, X):\n+        # second item in Equation 3.8\n+        n_samples = X.shape[0]\n+        n_features = self.n_features\n+        ln_W_digamma = np.arange(1, self.n_features + 1)\n+        log_X = np.empty((n_samples, self.n_components))\n+        log_lambda = np.empty((self.n_components, ))\n+        inv_W_chol = np.empty(self.lambda_inv_W_.shape)\n+        for k, (beta, m, nu, inv_W) in enumerate(\n+                zip(self.mu_beta_, self.mu_m_,\n+                    self.lambda_nu_, self.lambda_inv_W_)):\n+            try:\n+                inv_W_chol[k] = linalg.cholesky(inv_W, lower=True)\n+            except linalg.LinAlgError:\n+                raise ValueError(\"'lambda_inv_W_' must be symmetric, \"\n+                                 \"positive-definite\")\n+            ln_inv_W_det = 2. * np.sum(np.log(np.diagonal(inv_W_chol[k])))\n+            log_lambda[k] = (np.sum(digamma(.5 * (nu + 1 - ln_W_digamma))) +\n+                             n_features * np.log(2) - ln_inv_W_det)\n+\n+            W_sol = linalg.solve_triangular(inv_W_chol[k], (X - m).T,\n+                                            lower=True).T\n+            mahala_dist = np.sum(np.square(W_sol), axis=1)\n+            log_X[:, k] = - .5 * (- log_lambda[k] +\n+                                  n_features / beta + nu * mahala_dist)\n+        log_X -= .5 * (n_features * np.log(2 * np.pi))\n+        self.inv_W_chol = inv_W_chol\n+        self.log_lambda = log_lambda","path":"sklearn/mixture/bayesianmixture.py","position":373,"original_position":373,"commit_id":"a3831784f8d090191629ff73dc60b639af2c7ddc","original_commit_id":"a3831784f8d090191629ff73dc60b639af2c7ddc","user":{"login":"xuewei4d","id":1180956,"avatar_url":"https://avatars.githubusercontent.com/u/1180956?v=3","gravatar_id":"","url":"https://api.github.com/users/xuewei4d","html_url":"https://github.com/xuewei4d","followers_url":"https://api.github.com/users/xuewei4d/followers","following_url":"https://api.github.com/users/xuewei4d/following{/other_user}","gists_url":"https://api.github.com/users/xuewei4d/gists{/gist_id}","starred_url":"https://api.github.com/users/xuewei4d/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuewei4d/subscriptions","organizations_url":"https://api.github.com/users/xuewei4d/orgs","repos_url":"https://api.github.com/users/xuewei4d/repos","events_url":"https://api.github.com/users/xuewei4d/events{/privacy}","received_events_url":"https://api.github.com/users/xuewei4d/received_events","type":"User","site_admin":false},"body":"Hi @ogrisel @amueller @vene @lesteve I didn't save resp and other data which could scale along with n_samples, but I did save other temporary data as instance attributes to compute lower bound when doing e_step. I don't know this is good or bad style.  Any comment?  ","created_at":"2015-07-11T15:24:08Z","updated_at":"2015-07-11T15:24:08Z","html_url":"https://github.com/scikit-learn/scikit-learn/pull/4802#discussion_r34413554","pull_request_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4802","_links":{"self":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments/34413554"},"html":{"href":"https://github.com/scikit-learn/scikit-learn/pull/4802#discussion_r34413554"},"pull_request":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4802"}}},"pull_request":{"url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4802","id":36740194,"html_url":"https://github.com/scikit-learn/scikit-learn/pull/4802","diff_url":"https://github.com/scikit-learn/scikit-learn/pull/4802.diff","patch_url":"https://github.com/scikit-learn/scikit-learn/pull/4802.patch","issue_url":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/4802","number":4802,"state":"open","locked":false,"title":"[WIP] Improve GMM API","user":{"login":"xuewei4d","id":1180956,"avatar_url":"https://avatars.githubusercontent.com/u/1180956?v=3","gravatar_id":"","url":"https://api.github.com/users/xuewei4d","html_url":"https://github.com/xuewei4d","followers_url":"https://api.github.com/users/xuewei4d/followers","following_url":"https://api.github.com/users/xuewei4d/following{/other_user}","gists_url":"https://api.github.com/users/xuewei4d/gists{/gist_id}","starred_url":"https://api.github.com/users/xuewei4d/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuewei4d/subscriptions","organizations_url":"https://api.github.com/users/xuewei4d/orgs","repos_url":"https://api.github.com/users/xuewei4d/repos","events_url":"https://api.github.com/users/xuewei4d/events{/privacy}","received_events_url":"https://api.github.com/users/xuewei4d/received_events","type":"User","site_admin":false},"body":"GSoC 2015 project,  Improve GMM API\r\n\r\n1. [x] Completes [derivation report](https://www.dropbox.com/s/8hlbb7dlwllwcry/VBGMM.pdf?dl=0).\r\n2. [x] Adds new classes. One abstract class ```_BasesMixture```. Three derived classes ```GaussianMixture```, ```BayesianGaussianMixture```, ```DirichletProcessGaussianMixture```\r\n3. [ ] Decouples large functions, especially in ```DirichletProcessGaussianMixture``` and ```BayesianGaussianMixture```\r\n4. [x] Removes numerical stability fixes for HMM. It seems that whenever there is a numerical issue, the code always adds 10*EPS in the computation. I think in some cases there is a better way to address the problem, such as normalization the extremely small variables earlier, or we just simply remove ```10*EPS``` which is only for HMM.\r\n5. [ ] Writes updating functions for ```BayesianGaussianMixtureModel``` and ```DirichletProcessGaussianMixtureModel``` according to the report.\r\n6. [x] Provides methods that allow users to initialize the model with user-provided data\r\n7. [x] Corrects kmeans initialization. It is weird when using kmeans initialization, only means is initialized. The weights and covariances are initialized by averaging.\r\n8. [x] Writes several checking functions for the initialization data\r\n9. [x] Adjusts the verbose messages. When ```verbose>1```, it display log-likelihood and time used in the same line of the message ```Iteration x```\r\n10. [ ] ~~Adjusts the time to compute log-likelihood. The code in the current master branch compute the log-likelihood of the model after E-step which is actually the score of the last iteration, and misses the score immediately after the initialization.~~\r\n11. [x] Simplify ```fit_predict```\r\n12. [x] Adds warning for ```params!='wmc'```\r\n13. [ ] Studies and contrasts the convergence of classical MLE / EM GMM with Bayesian GMM against the number of samples and the number of components\r\n14. [ ] Friendly warning and error messages, or automatically addressing if possible (e.g. random re-init of singular components)\r\n15. [ ] Examples that shows how models can over-fit by comparing likelihood on training and validation sets (normalized by\r\nthe number of samples). For instance extend the BIC score example with a cross-validated likelihood plot\r\n16. [ ] Testing on 1-D dimensions\r\n17. [ ] Testing on Degenerating cases\r\n18. [ ] AIC, BIC for VBGMM DPGMM\r\n19. [optional] add a partial_fit function for incremental / out-of-core fitting of (classical) GMM, for instance http://arxiv.org/abs/0712.4273 \r\n20. [optional] ledoit_wolf covariance estimation","created_at":"2015-06-02T15:18:15Z","updated_at":"2015-07-11T15:24:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f006d5d9665acee6a51c95afc4c308c74ce39c6f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4802/commits","review_comments_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4802/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/4802/comments","statuses_url":"https://api.github.com/repos/scikit-learn/scikit-learn/statuses/a3831784f8d090191629ff73dc60b639af2c7ddc","head":{"label":"xuewei4d:gmm_api","ref":"gmm_api","sha":"a3831784f8d090191629ff73dc60b639af2c7ddc","user":{"login":"xuewei4d","id":1180956,"avatar_url":"https://avatars.githubusercontent.com/u/1180956?v=3","gravatar_id":"","url":"https://api.github.com/users/xuewei4d","html_url":"https://github.com/xuewei4d","followers_url":"https://api.github.com/users/xuewei4d/followers","following_url":"https://api.github.com/users/xuewei4d/following{/other_user}","gists_url":"https://api.github.com/users/xuewei4d/gists{/gist_id}","starred_url":"https://api.github.com/users/xuewei4d/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuewei4d/subscriptions","organizations_url":"https://api.github.com/users/xuewei4d/orgs","repos_url":"https://api.github.com/users/xuewei4d/repos","events_url":"https://api.github.com/users/xuewei4d/events{/privacy}","received_events_url":"https://api.github.com/users/xuewei4d/received_events","type":"User","site_admin":false},"repo":{"id":31241818,"name":"scikit-learn","full_name":"xuewei4d/scikit-learn","owner":{"login":"xuewei4d","id":1180956,"avatar_url":"https://avatars.githubusercontent.com/u/1180956?v=3","gravatar_id":"","url":"https://api.github.com/users/xuewei4d","html_url":"https://github.com/xuewei4d","followers_url":"https://api.github.com/users/xuewei4d/followers","following_url":"https://api.github.com/users/xuewei4d/following{/other_user}","gists_url":"https://api.github.com/users/xuewei4d/gists{/gist_id}","starred_url":"https://api.github.com/users/xuewei4d/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuewei4d/subscriptions","organizations_url":"https://api.github.com/users/xuewei4d/orgs","repos_url":"https://api.github.com/users/xuewei4d/repos","events_url":"https://api.github.com/users/xuewei4d/events{/privacy}","received_events_url":"https://api.github.com/users/xuewei4d/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/xuewei4d/scikit-learn","description":"scikit-learn: machine learning in Python","fork":true,"url":"https://api.github.com/repos/xuewei4d/scikit-learn","forks_url":"https://api.github.com/repos/xuewei4d/scikit-learn/forks","keys_url":"https://api.github.com/repos/xuewei4d/scikit-learn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xuewei4d/scikit-learn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xuewei4d/scikit-learn/teams","hooks_url":"https://api.github.com/repos/xuewei4d/scikit-learn/hooks","issue_events_url":"https://api.github.com/repos/xuewei4d/scikit-learn/issues/events{/number}","events_url":"https://api.github.com/repos/xuewei4d/scikit-learn/events","assignees_url":"https://api.github.com/repos/xuewei4d/scikit-learn/assignees{/user}","branches_url":"https://api.github.com/repos/xuewei4d/scikit-learn/branches{/branch}","tags_url":"https://api.github.com/repos/xuewei4d/scikit-learn/tags","blobs_url":"https://api.github.com/repos/xuewei4d/scikit-learn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xuewei4d/scikit-learn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xuewei4d/scikit-learn/git/refs{/sha}","trees_url":"https://api.github.com/repos/xuewei4d/scikit-learn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xuewei4d/scikit-learn/statuses/{sha}","languages_url":"https://api.github.com/repos/xuewei4d/scikit-learn/languages","stargazers_url":"https://api.github.com/repos/xuewei4d/scikit-learn/stargazers","contributors_url":"https://api.github.com/repos/xuewei4d/scikit-learn/contributors","subscribers_url":"https://api.github.com/repos/xuewei4d/scikit-learn/subscribers","subscription_url":"https://api.github.com/repos/xuewei4d/scikit-learn/subscription","commits_url":"https://api.github.com/repos/xuewei4d/scikit-learn/commits{/sha}","git_commits_url":"https://api.github.com/repos/xuewei4d/scikit-learn/git/commits{/sha}","comments_url":"https://api.github.com/repos/xuewei4d/scikit-learn/comments{/number}","issue_comment_url":"https://api.github.com/repos/xuewei4d/scikit-learn/issues/comments{/number}","contents_url":"https://api.github.com/repos/xuewei4d/scikit-learn/contents/{+path}","compare_url":"https://api.github.com/repos/xuewei4d/scikit-learn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xuewei4d/scikit-learn/merges","archive_url":"https://api.github.com/repos/xuewei4d/scikit-learn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xuewei4d/scikit-learn/downloads","issues_url":"https://api.github.com/repos/xuewei4d/scikit-learn/issues{/number}","pulls_url":"https://api.github.com/repos/xuewei4d/scikit-learn/pulls{/number}","milestones_url":"https://api.github.com/repos/xuewei4d/scikit-learn/milestones{/number}","notifications_url":"https://api.github.com/repos/xuewei4d/scikit-learn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xuewei4d/scikit-learn/labels{/name}","releases_url":"https://api.github.com/repos/xuewei4d/scikit-learn/releases{/id}","created_at":"2015-02-24T02:43:56Z","updated_at":"2015-05-07T14:11:26Z","pushed_at":"2015-07-11T15:15:33Z","git_url":"git://github.com/xuewei4d/scikit-learn.git","ssh_url":"git@github.com:xuewei4d/scikit-learn.git","clone_url":"https://github.com/xuewei4d/scikit-learn.git","svn_url":"https://github.com/xuewei4d/scikit-learn","homepage":"http://scikit-learn.org","size":64018,"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":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"scikit-learn:master","ref":"master","sha":"a5feec25bb0e04072030ca8adc46ad151149e9c7","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-11T05:45:13Z","pushed_at":"2015-07-11T15:15:38Z","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":126909,"stargazers_count":6681,"watchers_count":6681,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4015,"mirror_url":null,"open_issues_count":715,"forks":4015,"open_issues":715,"watchers":6681,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4802"},"html":{"href":"https://github.com/scikit-learn/scikit-learn/pull/4802"},"issue":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/4802"},"comments":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/4802/comments"},"review_comments":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/4802/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/4802/commits"},"statuses":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/statuses/a3831784f8d090191629ff73dc60b639af2c7ddc"}}}}