{"action":"created","comment":{"url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments/23132708","id":23132708,"diff_hunk":"@@ -0,0 +1,154 @@\n+# Author: Andrea Bravi <a.bravi@uottawa.ca>\n+# License: 3-clause BSD\n+\n+import numpy as np\n+from ..base import BaseEstimator\n+from .base import SelectorMixin\n+from ..metrics.cluster.supervised import mutual_info_score\n+from ..utils.validation import array2d\n+\n+\n+class MinRedundancyMaxRelevance(BaseEstimator, SelectorMixin):\n+    \"\"\"\n+    Select the subset of features with minimal redundancy and maximal\n+    relevance (mRMR) with the outcome.\n+\n+    IMPORTANT: This version only supports data in categorical or integer form.\n+\n+    Attributes\n+    ----------\n+    k : int, default=2\n+        Number of features to select (selected_features)\n+    mask : list, len=selected_features\n+           Integer list of the features ordered by maximal relevance and\n+           minimal redundancy\n+    score : array, shape=[selected_features]\n+            mRMR score associated to each entry in mask\n+    relevance : array, shape=[n_features]\n+                Relevance of all the features\n+    redundancy : array, shape=[n_features]\n+                 Redundancy of all the features\n+    rule : string, default='diff'\n+           Rule to combine relevance and redundancy, either\n+           'diff' - difference between the two\n+           'prod' - product between the two\n+    X : array, shape=[n_samples, n_features]\n+        Input dataset, must be either integer or categorical\n+    y : array, shape=[n_samples]\n+        Label vector, must be either integer or categorical\n+\n+    References\n+    ----------\n+    .. [1] H. Peng, F. Long, and C. Ding, \"Feature selection based on mutual\n+       information: criteria of max-dependency, max-relevance, and\n+       min-redundancy\", IEEE Transactions on Pattern Analysis and Machine\n+       Intelligence, Vol. 27, No. 8, pp.1226-1238, 2005.\n+    \"\"\"\n+    def __init__(self, k=2, rule='diff'):\n+        \"\"\"\n+        Parameters\n+        ----------\n+        k : int, default=2\n+            Number of features to select\n+        rule : string, default='diff'\n+               Rule to combine relevance and redundancy, either\n+               'diff' - difference between the two\n+               'prod' - product between the two\n+        \"\"\"\n+        self.k = k\n+        self.rule = rule\n+\n+    def fit(self, X, y):\n+        \"\"\"\n+        Parameters\n+        ----------\n+        X : array, shape=[n_samples, n_features]\n+            Input dataset, must be either integer or categorical\n+        y : array, shape=[n_samples]\n+            Label vector, must be either integer or categorical\n+        \"\"\"\n+        X = array2d(X)\n+\n+        self.X = X\n+        self.y = y\n+        self.mask, self.score = self._compute_mRMR(X, y)\n+        return self\n+\n+    def _get_support_mask(self):\n+        \"\"\"\n+        Returns\n+        -------\n+        support : array, dype=bool, shape=[n_features]\n+                  Boolean mask with True the selected features\n+        \"\"\"\n+\n+        support = np.zeros(self.n_features, dtype=bool)\n+        support[self.mask] = True\n+        return support\n+\n+    def _compute_mRMR(self, X, y):\n+        \"\"\"\n+        Parameters\n+        ----------\n+        X : array, shape=[n_samples, n_features]\n+            Input dataset, must be either integer or categorical\n+        y : array, shape=[n_samples]\n+            Label vector, must be either integer or categorical\n+\n+        Returns\n+        -------\n+        mask : list, len=selected_features\n+               Integer list of the features ordered by maximal relevance and\n+               minimal redundancy\n+        score : list, len=selected_features\n+                mRMR score associated to each entry in mask\n+        \"\"\"\n+        M = X.shape[1]  # Number of features\n+\n+        # Computation of relevance and redundancy\n+        relevance = np.zeros(M)\n+        redundancy = np.zeros([M, M])\n+        for m1 in range(0, M):\n+            relevance[m1] = mutual_info_score(X[:, m1], y)\n+            for m2 in range(m1+1, M):\n+                redundancy[m1, m2] = mutual_info_score(X[:, m1],\n+                                                       X[:, m2])\n+                redundancy[m2, m1] = redundancy[m1, m2]\n+\n+        # Sequential search optimization\n+        mask = []\n+        score = []\n+        search_space = range(0, M)\n+\n+        score.append(max(relevance))\n+        ind = int(relevance.argmax(0))  # Optimal feature\n+        mask.append(ind)\n+        search_space.pop(ind)\n+\n+        if self.rule == 'diff':\n+            for m in range(0, self.k-1):","path":"sklearn/feature_selection/multivariate_filtering.py","position":129,"original_position":129,"commit_id":"4b97111c098ba5f76c6f2cd2a2070db3ebe25688","original_commit_id":"4b97111c098ba5f76c6f2cd2a2070db3ebe25688","user":{"login":"jnothman","id":78827,"avatar_url":"https://avatars.githubusercontent.com/u/78827?v=3","gravatar_id":"","url":"https://api.github.com/users/jnothman","html_url":"https://github.com/jnothman","followers_url":"https://api.github.com/users/jnothman/followers","following_url":"https://api.github.com/users/jnothman/following{/other_user}","gists_url":"https://api.github.com/users/jnothman/gists{/gist_id}","starred_url":"https://api.github.com/users/jnothman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jnothman/subscriptions","organizations_url":"https://api.github.com/users/jnothman/orgs","repos_url":"https://api.github.com/users/jnothman/repos","events_url":"https://api.github.com/users/jnothman/events{/privacy}","received_events_url":"https://api.github.com/users/jnothman/received_events","type":"User","site_admin":false},"body":"Rather than repeating yourself with the logic, you could define `rule = np.subtract` or `rule = np.multiply`","created_at":"2015-01-18T11:43:09Z","updated_at":"2015-01-18T11:43:09Z","html_url":"https://github.com/scikit-learn/scikit-learn/pull/2547#discussion_r23132708","pull_request_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/2547","_links":{"self":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/comments/23132708"},"html":{"href":"https://github.com/scikit-learn/scikit-learn/pull/2547#discussion_r23132708"},"pull_request":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/2547"}}},"pull_request":{"url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/2547","id":9338001,"html_url":"https://github.com/scikit-learn/scikit-learn/pull/2547","diff_url":"https://github.com/scikit-learn/scikit-learn/pull/2547.diff","patch_url":"https://github.com/scikit-learn/scikit-learn/pull/2547.patch","issue_url":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/2547","number":2547,"state":"open","locked":false,"title":"Minimum redundancy maximum relevance (mRMR) feature selection","user":{"login":"AndreaBravi","id":5732226,"avatar_url":"https://avatars.githubusercontent.com/u/5732226?v=3","gravatar_id":"","url":"https://api.github.com/users/AndreaBravi","html_url":"https://github.com/AndreaBravi","followers_url":"https://api.github.com/users/AndreaBravi/followers","following_url":"https://api.github.com/users/AndreaBravi/following{/other_user}","gists_url":"https://api.github.com/users/AndreaBravi/gists{/gist_id}","starred_url":"https://api.github.com/users/AndreaBravi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndreaBravi/subscriptions","organizations_url":"https://api.github.com/users/AndreaBravi/orgs","repos_url":"https://api.github.com/users/AndreaBravi/repos","events_url":"https://api.github.com/users/AndreaBravi/events{/privacy}","received_events_url":"https://api.github.com/users/AndreaBravi/received_events","type":"User","site_admin":false},"body":"Hi!\r\n\r\nI have created a new class computing the mRMR filtering feature selection.\r\n\r\npep8, pyflakes and nosetests run succesfully on the submitted code.\r\n\r\nI am planning to create the documentation for this class as soon as I receive your approval.\r\n\r\nThanks!\r\n\r\nAndrea","created_at":"2013-10-23T17:16:03Z","updated_at":"2015-01-18T11:43:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f6b30c9f0338313e7baf218eb09de6f2047caa36","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/2547/commits","review_comments_url":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/2547/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/2547/comments","statuses_url":"https://api.github.com/repos/scikit-learn/scikit-learn/statuses/4b97111c098ba5f76c6f2cd2a2070db3ebe25688","head":{"label":"AndreaBravi:mRMR","ref":"mRMR","sha":"4b97111c098ba5f76c6f2cd2a2070db3ebe25688","user":{"login":"AndreaBravi","id":5732226,"avatar_url":"https://avatars.githubusercontent.com/u/5732226?v=3","gravatar_id":"","url":"https://api.github.com/users/AndreaBravi","html_url":"https://github.com/AndreaBravi","followers_url":"https://api.github.com/users/AndreaBravi/followers","following_url":"https://api.github.com/users/AndreaBravi/following{/other_user}","gists_url":"https://api.github.com/users/AndreaBravi/gists{/gist_id}","starred_url":"https://api.github.com/users/AndreaBravi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndreaBravi/subscriptions","organizations_url":"https://api.github.com/users/AndreaBravi/orgs","repos_url":"https://api.github.com/users/AndreaBravi/repos","events_url":"https://api.github.com/users/AndreaBravi/events{/privacy}","received_events_url":"https://api.github.com/users/AndreaBravi/received_events","type":"User","site_admin":false},"repo":{"id":13725449,"name":"scikit-learn","full_name":"AndreaBravi/scikit-learn","owner":{"login":"AndreaBravi","id":5732226,"avatar_url":"https://avatars.githubusercontent.com/u/5732226?v=3","gravatar_id":"","url":"https://api.github.com/users/AndreaBravi","html_url":"https://github.com/AndreaBravi","followers_url":"https://api.github.com/users/AndreaBravi/followers","following_url":"https://api.github.com/users/AndreaBravi/following{/other_user}","gists_url":"https://api.github.com/users/AndreaBravi/gists{/gist_id}","starred_url":"https://api.github.com/users/AndreaBravi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AndreaBravi/subscriptions","organizations_url":"https://api.github.com/users/AndreaBravi/orgs","repos_url":"https://api.github.com/users/AndreaBravi/repos","events_url":"https://api.github.com/users/AndreaBravi/events{/privacy}","received_events_url":"https://api.github.com/users/AndreaBravi/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/AndreaBravi/scikit-learn","description":"scikit-learn: machine learning in Python","fork":true,"url":"https://api.github.com/repos/AndreaBravi/scikit-learn","forks_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/forks","keys_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/teams","hooks_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/hooks","issue_events_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/issues/events{/number}","events_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/events","assignees_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/assignees{/user}","branches_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/branches{/branch}","tags_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/tags","blobs_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/git/refs{/sha}","trees_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/statuses/{sha}","languages_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/languages","stargazers_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/stargazers","contributors_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/contributors","subscribers_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/subscribers","subscription_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/subscription","commits_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/commits{/sha}","git_commits_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/git/commits{/sha}","comments_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/comments{/number}","issue_comment_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/issues/comments/{number}","contents_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/contents/{+path}","compare_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/merges","archive_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/downloads","issues_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/issues{/number}","pulls_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/pulls{/number}","milestones_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/milestones{/number}","notifications_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/labels{/name}","releases_url":"https://api.github.com/repos/AndreaBravi/scikit-learn/releases{/id}","created_at":"2013-10-20T19:37:29Z","updated_at":"2013-12-27T14:32:58Z","pushed_at":"2013-11-04T23:03:21Z","git_url":"git://github.com/AndreaBravi/scikit-learn.git","ssh_url":"git@github.com:AndreaBravi/scikit-learn.git","clone_url":"https://github.com/AndreaBravi/scikit-learn.git","svn_url":"https://github.com/AndreaBravi/scikit-learn","homepage":"http://scikit-learn.org","size":52280,"stargazers_count":1,"watchers_count":1,"language":"C","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":1,"default_branch":"master"}},"base":{"label":"scikit-learn:master","ref":"master","sha":"3f49cee020a91a0be5d0d5602d29b3eefce9d758","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-01-18T10:38:01Z","pushed_at":"2015-01-18T10:38:01Z","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":108521,"stargazers_count":4861,"watchers_count":4861,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2797,"mirror_url":null,"open_issues_count":558,"forks":2797,"open_issues":558,"watchers":4861,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/2547"},"html":{"href":"https://github.com/scikit-learn/scikit-learn/pull/2547"},"issue":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/2547"},"comments":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/issues/2547/comments"},"review_comments":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/pulls/2547/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/2547/commits"},"statuses":{"href":"https://api.github.com/repos/scikit-learn/scikit-learn/statuses/4b97111c098ba5f76c6f2cd2a2070db3ebe25688"}}}}