{"action":"created","comment":{"url":"https://api.github.com/repos/GPflow/GPflow/pulls/comments/211109172","pull_request_review_id":147464997,"id":211109172,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxMTEwOTE3Mg==","diff_hunk":"@@ -251,5 +251,57 @@ def _get_tensor_safe(name, index, graph):\n     except KeyError:\n         return None\n \n+\n+def swap_final_dims(X: tf.Tensor):\n+    \"\"\"\n+    equivalent to np.swapaxes(X, -2, -1)\n+    \"\"\"\n+    K = tf.rank(X)\n+    num_broadcasting_dims = tf.reduce_max([K - 2, 0])\n+    perm = tf.concat([tf.range(num_broadcasting_dims), [K - 1, K - 2]], 0)\n+    return tf.transpose(X, perm)\n+\n+\n+def slice_final_dim(X: tf.Tensor, sl: slice, dim: int):\n+    \"\"\"\n+    Takes the slice sl from the final dimension of X\n+    If the slice is the whole of the final dimension (i.e. sl=slice(0, dim)) then there is nothing to do\n+    NB tensorflow does not support slicing with step!=1, so raise error if this is attempted\n+    \"\"\"\n+    if (sl.start is None) and (sl.step is None) and (sl.stop == dim):  # nothing to do\n+        return X\n+    else:\n+        if sl.step and (sl.step != 1):\n+            raise NotImplementedError('only slices with step=1 supported by tensorflow')\n+\n+        start = 1 if sl.start is None else sl.start\n+\n+        begin = tf.concat([tf.zeros([tf.rank(X) - 1], dtype=settings.int_type),\n+                           tf.reshape(start, [1])], 0)\n+\n+        size = tf.concat([tf.shape(X)[:-1], tf.reshape(sl.stop - start, [1])], 0)\n+\n+        return tf.slice(X, begin, size)\n+\n+\n+def tile_over_new_axis(X : tf.Tensor, repeats : tf.Tensor, axis : int):\n+    \"\"\"\n+    Inserts a new axis and tiles k times\n+    e.g. if X.shape = [S, N, D], and axis=-2 then this is equivalent to\n+     tf.tile(X[:, :, None, :], [1, 1, repeats, 1])","path":"gpflow/misc.py","position":41,"original_position":41,"commit_id":"64cfc3c40ee1f2f7159e9d6e41c917a9c12ac9d0","original_commit_id":"64cfc3c40ee1f2f7159e9d6e41c917a9c12ac9d0","user":{"login":"awav","id":24483645,"node_id":"MDQ6VXNlcjI0NDgzNjQ1","avatar_url":"https://avatars0.githubusercontent.com/u/24483645?v=4","gravatar_id":"","url":"https://api.github.com/users/awav","html_url":"https://github.com/awav","followers_url":"https://api.github.com/users/awav/followers","following_url":"https://api.github.com/users/awav/following{/other_user}","gists_url":"https://api.github.com/users/awav/gists{/gist_id}","starred_url":"https://api.github.com/users/awav/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/awav/subscriptions","organizations_url":"https://api.github.com/users/awav/orgs","repos_url":"https://api.github.com/users/awav/repos","events_url":"https://api.github.com/users/awav/events{/privacy}","received_events_url":"https://api.github.com/users/awav/received_events","type":"User","site_admin":false},"body":"* Formatting issues - space before \"tf.tile\" and \"supports negative ...\"\r\n* Would be nice to have docstrings for parameters","created_at":"2018-08-19T17:14:31Z","updated_at":"2018-08-19T17:25:40Z","html_url":"https://github.com/GPflow/GPflow/pull/829#discussion_r211109172","pull_request_url":"https://api.github.com/repos/GPflow/GPflow/pulls/829","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/GPflow/GPflow/pulls/comments/211109172"},"html":{"href":"https://github.com/GPflow/GPflow/pull/829#discussion_r211109172"},"pull_request":{"href":"https://api.github.com/repos/GPflow/GPflow/pulls/829"}}},"pull_request":{"url":"https://api.github.com/repos/GPflow/GPflow/pulls/829","id":209369179,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA5MzY5MTc5","html_url":"https://github.com/GPflow/GPflow/pull/829","diff_url":"https://github.com/GPflow/GPflow/pull/829.diff","patch_url":"https://github.com/GPflow/GPflow/pull/829.patch","issue_url":"https://api.github.com/repos/GPflow/GPflow/issues/829","number":829,"state":"open","locked":false,"title":"support broadcasting","user":{"login":"hughsalimbeni","id":4891485,"node_id":"MDQ6VXNlcjQ4OTE0ODU=","avatar_url":"https://avatars2.githubusercontent.com/u/4891485?v=4","gravatar_id":"","url":"https://api.github.com/users/hughsalimbeni","html_url":"https://github.com/hughsalimbeni","followers_url":"https://api.github.com/users/hughsalimbeni/followers","following_url":"https://api.github.com/users/hughsalimbeni/following{/other_user}","gists_url":"https://api.github.com/users/hughsalimbeni/gists{/gist_id}","starred_url":"https://api.github.com/users/hughsalimbeni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hughsalimbeni/subscriptions","organizations_url":"https://api.github.com/users/hughsalimbeni/orgs","repos_url":"https://api.github.com/users/hughsalimbeni/repos","events_url":"https://api.github.com/users/hughsalimbeni/events{/privacy}","received_events_url":"https://api.github.com/users/hughsalimbeni/received_events","type":"User","site_admin":false},"body":"# Broadcasting over leading dimensions \r\nThis PR modifies the kernels and conditionals to support broadcasting over (arbitrarily many) extra leading dimensions, similar to most of the tensorflow ops. So e.g. `kern.K(X)` now supports `X` being shape `[S, ..., T, N, D]`, and returns  `[S, ..., T, N, N]`\r\n\r\nThe purpose of this PR is to facilitate models that need multiple, potentially correlated, samples. \r\n\r\n## Summary of new supported operations:\r\n\r\n`kern.K(X)` supports `X` of shape  `[..., N, D]` and returns `[..., N, N]`\r\n`kern.K(X, X2)` supports `X`, `X2` of shape  `[..., T, N, D]`, `[..., T, M, D]` and returns `[..., N, M]`, where the leading dimensions must match \r\n`kern.Kdiag(X)` supports `X` of shape  `[..., N, D]` and returns `[..., N]`\r\n\r\n`conditionals.conditional(Xnew, X, kern, f, full_cov=False, q_sqrt=None)` supports `Xnew` of shape [..., N, D] and returns `[..., N, Dy]`, `[..., Dy, N, N]`\r\n\r\n## Why not use multioutput?\r\n\r\nSuppose a model has `Dy` independent GPs and we want to compute the full covariance between `S` different sets of inputs, each of size `N`. To use the multioutput framework for this we would need to have a `Dy * S`-output kernel, but `S` is not a parameter of our model so this is unsatisfactory. Also, if we actually have dependent GPs then the correlation structure is very tricky in the flattened version, but is straightforward using broadcasting over the leading dimensions. \r\n\r\n\r\n","created_at":"2018-08-19T16:54:11Z","updated_at":"2018-08-19T17:25:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"352ba480c2b51e6d30d9f8cb9fdc32861d0a79da","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/GPflow/GPflow/pulls/829/commits","review_comments_url":"https://api.github.com/repos/GPflow/GPflow/pulls/829/comments","review_comment_url":"https://api.github.com/repos/GPflow/GPflow/pulls/comments{/number}","comments_url":"https://api.github.com/repos/GPflow/GPflow/issues/829/comments","statuses_url":"https://api.github.com/repos/GPflow/GPflow/statuses/64cfc3c40ee1f2f7159e9d6e41c917a9c12ac9d0","head":{"label":"GPflow:broadcasting","ref":"broadcasting","sha":"64cfc3c40ee1f2f7159e9d6e41c917a9c12ac9d0","user":{"login":"GPflow","id":16667412,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NjY3NDEy","avatar_url":"https://avatars2.githubusercontent.com/u/16667412?v=4","gravatar_id":"","url":"https://api.github.com/users/GPflow","html_url":"https://github.com/GPflow","followers_url":"https://api.github.com/users/GPflow/followers","following_url":"https://api.github.com/users/GPflow/following{/other_user}","gists_url":"https://api.github.com/users/GPflow/gists{/gist_id}","starred_url":"https://api.github.com/users/GPflow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GPflow/subscriptions","organizations_url":"https://api.github.com/users/GPflow/orgs","repos_url":"https://api.github.com/users/GPflow/repos","events_url":"https://api.github.com/users/GPflow/events{/privacy}","received_events_url":"https://api.github.com/users/GPflow/received_events","type":"Organization","site_admin":false},"repo":{"id":49643229,"node_id":"MDEwOlJlcG9zaXRvcnk0OTY0MzIyOQ==","name":"GPflow","full_name":"GPflow/GPflow","owner":{"login":"GPflow","id":16667412,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NjY3NDEy","avatar_url":"https://avatars2.githubusercontent.com/u/16667412?v=4","gravatar_id":"","url":"https://api.github.com/users/GPflow","html_url":"https://github.com/GPflow","followers_url":"https://api.github.com/users/GPflow/followers","following_url":"https://api.github.com/users/GPflow/following{/other_user}","gists_url":"https://api.github.com/users/GPflow/gists{/gist_id}","starred_url":"https://api.github.com/users/GPflow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GPflow/subscriptions","organizations_url":"https://api.github.com/users/GPflow/orgs","repos_url":"https://api.github.com/users/GPflow/repos","events_url":"https://api.github.com/users/GPflow/events{/privacy}","received_events_url":"https://api.github.com/users/GPflow/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GPflow/GPflow","description":"Gaussian processes in TensorFlow","fork":false,"url":"https://api.github.com/repos/GPflow/GPflow","forks_url":"https://api.github.com/repos/GPflow/GPflow/forks","keys_url":"https://api.github.com/repos/GPflow/GPflow/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GPflow/GPflow/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GPflow/GPflow/teams","hooks_url":"https://api.github.com/repos/GPflow/GPflow/hooks","issue_events_url":"https://api.github.com/repos/GPflow/GPflow/issues/events{/number}","events_url":"https://api.github.com/repos/GPflow/GPflow/events","assignees_url":"https://api.github.com/repos/GPflow/GPflow/assignees{/user}","branches_url":"https://api.github.com/repos/GPflow/GPflow/branches{/branch}","tags_url":"https://api.github.com/repos/GPflow/GPflow/tags","blobs_url":"https://api.github.com/repos/GPflow/GPflow/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GPflow/GPflow/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GPflow/GPflow/git/refs{/sha}","trees_url":"https://api.github.com/repos/GPflow/GPflow/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GPflow/GPflow/statuses/{sha}","languages_url":"https://api.github.com/repos/GPflow/GPflow/languages","stargazers_url":"https://api.github.com/repos/GPflow/GPflow/stargazers","contributors_url":"https://api.github.com/repos/GPflow/GPflow/contributors","subscribers_url":"https://api.github.com/repos/GPflow/GPflow/subscribers","subscription_url":"https://api.github.com/repos/GPflow/GPflow/subscription","commits_url":"https://api.github.com/repos/GPflow/GPflow/commits{/sha}","git_commits_url":"https://api.github.com/repos/GPflow/GPflow/git/commits{/sha}","comments_url":"https://api.github.com/repos/GPflow/GPflow/comments{/number}","issue_comment_url":"https://api.github.com/repos/GPflow/GPflow/issues/comments{/number}","contents_url":"https://api.github.com/repos/GPflow/GPflow/contents/{+path}","compare_url":"https://api.github.com/repos/GPflow/GPflow/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GPflow/GPflow/merges","archive_url":"https://api.github.com/repos/GPflow/GPflow/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GPflow/GPflow/downloads","issues_url":"https://api.github.com/repos/GPflow/GPflow/issues{/number}","pulls_url":"https://api.github.com/repos/GPflow/GPflow/pulls{/number}","milestones_url":"https://api.github.com/repos/GPflow/GPflow/milestones{/number}","notifications_url":"https://api.github.com/repos/GPflow/GPflow/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GPflow/GPflow/labels{/name}","releases_url":"https://api.github.com/repos/GPflow/GPflow/releases{/id}","deployments_url":"https://api.github.com/repos/GPflow/GPflow/deployments","created_at":"2016-01-14T11:29:24Z","updated_at":"2018-08-18T16:39:02Z","pushed_at":"2018-08-19T16:54:12Z","git_url":"git://github.com/GPflow/GPflow.git","ssh_url":"git@github.com:GPflow/GPflow.git","clone_url":"https://github.com/GPflow/GPflow.git","svn_url":"https://github.com/GPflow/GPflow","homepage":"","size":30414,"stargazers_count":741,"watchers_count":741,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":217,"mirror_url":null,"archived":false,"open_issues_count":55,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":217,"open_issues":55,"watchers":741,"default_branch":"master"}},"base":{"label":"GPflow:master","ref":"master","sha":"2c4cf398a248242298fd1c45125392839fe90b05","user":{"login":"GPflow","id":16667412,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NjY3NDEy","avatar_url":"https://avatars2.githubusercontent.com/u/16667412?v=4","gravatar_id":"","url":"https://api.github.com/users/GPflow","html_url":"https://github.com/GPflow","followers_url":"https://api.github.com/users/GPflow/followers","following_url":"https://api.github.com/users/GPflow/following{/other_user}","gists_url":"https://api.github.com/users/GPflow/gists{/gist_id}","starred_url":"https://api.github.com/users/GPflow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GPflow/subscriptions","organizations_url":"https://api.github.com/users/GPflow/orgs","repos_url":"https://api.github.com/users/GPflow/repos","events_url":"https://api.github.com/users/GPflow/events{/privacy}","received_events_url":"https://api.github.com/users/GPflow/received_events","type":"Organization","site_admin":false},"repo":{"id":49643229,"node_id":"MDEwOlJlcG9zaXRvcnk0OTY0MzIyOQ==","name":"GPflow","full_name":"GPflow/GPflow","owner":{"login":"GPflow","id":16667412,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE2NjY3NDEy","avatar_url":"https://avatars2.githubusercontent.com/u/16667412?v=4","gravatar_id":"","url":"https://api.github.com/users/GPflow","html_url":"https://github.com/GPflow","followers_url":"https://api.github.com/users/GPflow/followers","following_url":"https://api.github.com/users/GPflow/following{/other_user}","gists_url":"https://api.github.com/users/GPflow/gists{/gist_id}","starred_url":"https://api.github.com/users/GPflow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GPflow/subscriptions","organizations_url":"https://api.github.com/users/GPflow/orgs","repos_url":"https://api.github.com/users/GPflow/repos","events_url":"https://api.github.com/users/GPflow/events{/privacy}","received_events_url":"https://api.github.com/users/GPflow/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GPflow/GPflow","description":"Gaussian processes in TensorFlow","fork":false,"url":"https://api.github.com/repos/GPflow/GPflow","forks_url":"https://api.github.com/repos/GPflow/GPflow/forks","keys_url":"https://api.github.com/repos/GPflow/GPflow/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GPflow/GPflow/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GPflow/GPflow/teams","hooks_url":"https://api.github.com/repos/GPflow/GPflow/hooks","issue_events_url":"https://api.github.com/repos/GPflow/GPflow/issues/events{/number}","events_url":"https://api.github.com/repos/GPflow/GPflow/events","assignees_url":"https://api.github.com/repos/GPflow/GPflow/assignees{/user}","branches_url":"https://api.github.com/repos/GPflow/GPflow/branches{/branch}","tags_url":"https://api.github.com/repos/GPflow/GPflow/tags","blobs_url":"https://api.github.com/repos/GPflow/GPflow/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GPflow/GPflow/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GPflow/GPflow/git/refs{/sha}","trees_url":"https://api.github.com/repos/GPflow/GPflow/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GPflow/GPflow/statuses/{sha}","languages_url":"https://api.github.com/repos/GPflow/GPflow/languages","stargazers_url":"https://api.github.com/repos/GPflow/GPflow/stargazers","contributors_url":"https://api.github.com/repos/GPflow/GPflow/contributors","subscribers_url":"https://api.github.com/repos/GPflow/GPflow/subscribers","subscription_url":"https://api.github.com/repos/GPflow/GPflow/subscription","commits_url":"https://api.github.com/repos/GPflow/GPflow/commits{/sha}","git_commits_url":"https://api.github.com/repos/GPflow/GPflow/git/commits{/sha}","comments_url":"https://api.github.com/repos/GPflow/GPflow/comments{/number}","issue_comment_url":"https://api.github.com/repos/GPflow/GPflow/issues/comments{/number}","contents_url":"https://api.github.com/repos/GPflow/GPflow/contents/{+path}","compare_url":"https://api.github.com/repos/GPflow/GPflow/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GPflow/GPflow/merges","archive_url":"https://api.github.com/repos/GPflow/GPflow/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GPflow/GPflow/downloads","issues_url":"https://api.github.com/repos/GPflow/GPflow/issues{/number}","pulls_url":"https://api.github.com/repos/GPflow/GPflow/pulls{/number}","milestones_url":"https://api.github.com/repos/GPflow/GPflow/milestones{/number}","notifications_url":"https://api.github.com/repos/GPflow/GPflow/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GPflow/GPflow/labels{/name}","releases_url":"https://api.github.com/repos/GPflow/GPflow/releases{/id}","deployments_url":"https://api.github.com/repos/GPflow/GPflow/deployments","created_at":"2016-01-14T11:29:24Z","updated_at":"2018-08-18T16:39:02Z","pushed_at":"2018-08-19T16:54:12Z","git_url":"git://github.com/GPflow/GPflow.git","ssh_url":"git@github.com:GPflow/GPflow.git","clone_url":"https://github.com/GPflow/GPflow.git","svn_url":"https://github.com/GPflow/GPflow","homepage":"","size":30414,"stargazers_count":741,"watchers_count":741,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":217,"mirror_url":null,"archived":false,"open_issues_count":55,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":217,"open_issues":55,"watchers":741,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GPflow/GPflow/pulls/829"},"html":{"href":"https://github.com/GPflow/GPflow/pull/829"},"issue":{"href":"https://api.github.com/repos/GPflow/GPflow/issues/829"},"comments":{"href":"https://api.github.com/repos/GPflow/GPflow/issues/829/comments"},"review_comments":{"href":"https://api.github.com/repos/GPflow/GPflow/pulls/829/comments"},"review_comment":{"href":"https://api.github.com/repos/GPflow/GPflow/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/GPflow/GPflow/pulls/829/commits"},"statuses":{"href":"https://api.github.com/repos/GPflow/GPflow/statuses/64cfc3c40ee1f2f7159e9d6e41c917a9c12ac9d0"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"awav"}}