{"action":"created","comment":{"url":"https://api.github.com/repos/rlworkgroup/garage/pulls/comments/243149700","pull_request_review_id":186840801,"id":243149700,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0MzE0OTcwMA==","diff_hunk":"@@ -0,0 +1,220 @@\n+\"\"\"Gaussian MLP Model.\"\"\"\n+import numpy as np\n+import tensorflow as tf\n+\n+from garage.core import Serializable\n+from garage.misc import ext\n+from garage.misc.overrides import overrides\n+from garage.tf.core.networks import mlp, parameter\n+from garage.tf.models import Model\n+\n+\n+class GaussianMLPModel(Model, Serializable):\n+    \"\"\"Gaussian MLP Model.\"\"\"\n+\n+    def __init__(\n+            self,\n+            input_dim,\n+            output_dim,\n+            name=\"GaussianMLPModel\",\n+            hidden_sizes=(32, 32),\n+            learn_std=True,\n+            init_std=1.0,\n+            adaptive_std=False,\n+            std_share_network=False,\n+            std_hidden_sizes=(32, 32),\n+            min_std=1e-6,\n+            max_std=None,\n+            std_hidden_nonlinearity=tf.nn.tanh,\n+            hidden_nonlinearity=tf.nn.tanh,\n+            output_nonlinearity=None,\n+            std_parameterization='exp',\n+    ):\n+        \"\"\"\n+        Initialize a gaussian mlp model and build the graph.\n+\n+        :param input_dim: input dimension\n+        :param output_dim: output dimension\n+        :param name: name of the model\n+        :param hidden_sizes: list of sizes for the fully-connected hidden\n+          layers\n+        :param learn_std: Is std trainable\n+        :param init_std: Initial std\n+        :param adaptive_std:\n+        :param std_share_network:\n+        :param std_hidden_sizes: list of sizes for the fully-connected layers\n+          for std\n+        :param min_std: whether to make sure that the std is at least some\n+          threshold value, to avoid numerical issues\n+        :param std_hidden_nonlinearity:\n+        :param hidden_nonlinearity: nonlinearity used for each hidden layer\n+        :param output_nonlinearity: nonlinearity for the output layer\n+        :param mean_network: custom network for the output mean\n+        :param std_network: custom network for the output log std\n+        :param std_parametrization: how the std should be parametrized. There\n+          are a few options:\n+            - exp: the logarithm of the std will be stored, and applied a\n+                exponential transformation\n+            - softplus: the std will be computed as log(1+exp(x))\n+        :return:\n+        \"\"\"\n+        Serializable.quick_init(self, locals())\n+        super(GaussianMLPModel, self).__init__()\n+\n+        self.name = name\n+        self._variable_scope = tf.variable_scope(\n+            self.name, reuse=tf.AUTO_REUSE)\n+        self._name_scope = tf.name_scope(self.name)\n+\n+        # Network parameters\n+        self._input_dim = input_dim\n+        self._output_dim = output_dim\n+        self._hidden_sizes = hidden_sizes\n+        self._learn_std = learn_std\n+        self._init_std = init_std\n+        self._adaptive_std = adaptive_std\n+        self._std_share_network = std_share_network\n+        self._std_hidden_sizes = std_hidden_sizes\n+        self._min_std = min_std\n+        self._max_std = max_std\n+        self._std_hidden_nonlinearity = std_hidden_nonlinearity\n+        self._hidden_nonlinearity = hidden_nonlinearity\n+        self._output_nonlinearity = output_nonlinearity\n+        self._std_parameterization = std_parameterization\n+\n+        # Tranform std arguments to parameterized space\n+        self._init_std_param = None\n+        self._min_std_param = None\n+        self._max_std_param = None\n+        if self._std_parameterization == 'exp':\n+            self._init_std_param = np.log(init_std)\n+            if min_std:\n+                self._min_std_param = np.log(min_std)\n+            if max_std:\n+                self._max_std_param = np.log(max_std)\n+        elif self._std_parameterization == 'softplus':\n+            self._init_std_param = np.log(np.exp(init_std) - 1)\n+            if min_std:\n+                self._min_std_param = np.log(np.exp(min_std) - 1)\n+            if max_std:\n+                self._max_std_param = np.log(np.exp(max_std) - 1)\n+        else:\n+            raise NotImplementedError\n+\n+        inputs, outputs, model_info = self.build_model()\n+        self._inputs = inputs[\"input_var\"]\n+\n+        self._mean = outputs[\"mean\"]\n+        self._std = outputs[\"std\"]\n+        self._std_param = outputs[\"std_param\"]\n+        self._sample = outputs[\"sample\"]\n+        self._dist = model_info[\"dist\"]\n+\n+        self._outputs = outputs\n+\n+    @overrides\n+    def build_model(self):\n+        \"\"\"\n+        Build the graph.\n+\n+        return:\n+            inputs: a dict that contains input tensor\n+            outputs: a dict that contains mean,\n+                std, parameterized std and sample tensors\n+            model_info: a dict that contains the distribution tensor\n+        \"\"\"\n+        input_var = tf.placeholder(\n+            shape=[None, self._input_dim],\n+            dtype=tf.float32,\n+        )\n+\n+        with self._variable_scope:\n+            if self._std_share_network:\n+                # mean and std networks share an MLP\n+                b = np.concatenate(\n+                    [\n+                        np.zeros(self._output_dim),\n+                        np.full(self._output_dim, self._init_std_param)\n+                    ],\n+                    axis=0)\n+                b = tf.constant_initializer(b)\n+                mean_std_network = mlp(\n+                    input_var=input_var,\n+                    output_dim=self._output_dim * 2,\n+                    hidden_sizes=self._hidden_sizes,\n+                    hidden_nonlinearity=self._hidden_nonlinearity,\n+                    output_nonlinearity=self._output_nonlinearity,\n+                    output_b_init=b,\n+                    name=\"mean_std_network\")\n+\n+                with tf.variable_scope(\"mean_network\"):\n+                    mean_network = mean_std_network[..., :self._output_dim]\n+                with tf.variable_scope(\"std_network\"):\n+                    std_network = mean_std_network[..., self._output_dim:]\n+            else:\n+                mean_network = mlp(\n+                    input_var=input_var,\n+                    output_dim=self._output_dim,\n+                    hidden_sizes=self._hidden_sizes,\n+                    hidden_nonlinearity=self._hidden_nonlinearity,\n+                    output_nonlinearity=self._output_nonlinearity,\n+                    name=\"mean_network\")\n+\n+                if self._adaptive_std:\n+                    b = tf.constant_initializer(self._init_std_param)\n+                    std_network = mlp(\n+                        input_var=input_var,\n+                        output_dim=self._output_dim,\n+                        hidden_sizes=self._std_hidden_sizes,\n+                        hidden_nonlinearity=self._std_hidden_nonlinearity,\n+                        output_nonlinearity=self._output_nonlinearity,\n+                        output_b_init=b,\n+                        name=\"std_network\")\n+\n+                else:\n+                    p = tf.constant_initializer(self._init_std_param)\n+                    std_network = parameter(\n+                        input_var=input_var,\n+                        length=self._output_dim,\n+                        initializer=p,\n+                        trainable=self._learn_std,\n+                        name=\"std_network\")\n+\n+            mean_var = mean_network\n+            std_param_var = std_network\n+\n+            with tf.variable_scope(\"std_limits\"):\n+                if self._min_std_param:\n+                    std_param_var = tf.maximum(std_param_var,\n+                                               self._min_std_param)\n+                if self._max_std_param:\n+                    std_param_var = tf.minimum(std_param_var,\n+                                               self._max_std_param)\n+\n+        with tf.variable_scope(\"std_parameterization\"):\n+            # build std_var with std parameterization\n+            if self._std_parameterization == \"exp\":\n+                std_var = tf.exp(std_param_var)\n+            elif self._std_parameterization == \"softplus\":\n+                std_var = tf.log(1. + tf.exp(std_param_var))\n+            else:\n+                raise NotImplementedError\n+\n+        dist = tf.contrib.distributions.MultivariateNormalDiag(\n+            mean_var, std_var)\n+        sample_var = dist.sample(seed=ext.get_seed())\n+\n+        inputs = {\n+            \"input_var\": input_var,\n+        }\n+        outputs = {\n+            \"mean\": mean_var,\n+            \"std\": std_var,\n+            \"std_param\": std_param_var,\n+            \"sample\": sample_var,\n+        }\n+        model_info = {\n+            \"dist\": dist,","path":"garage/tf/models/gaussian_mlp_model.py","position":218,"original_position":217,"commit_id":"933d8d2f403e6d10ac69c85dff190944ca568b48","original_commit_id":"df17b50291430c5ed5d089df0f62675119956a16","user":{"login":"zhanpenghe","id":31218416,"node_id":"MDQ6VXNlcjMxMjE4NDE2","avatar_url":"https://avatars1.githubusercontent.com/u/31218416?v=4","gravatar_id":"","url":"https://api.github.com/users/zhanpenghe","html_url":"https://github.com/zhanpenghe","followers_url":"https://api.github.com/users/zhanpenghe/followers","following_url":"https://api.github.com/users/zhanpenghe/following{/other_user}","gists_url":"https://api.github.com/users/zhanpenghe/gists{/gist_id}","starred_url":"https://api.github.com/users/zhanpenghe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zhanpenghe/subscriptions","organizations_url":"https://api.github.com/users/zhanpenghe/orgs","repos_url":"https://api.github.com/users/zhanpenghe/repos","events_url":"https://api.github.com/users/zhanpenghe/events{/privacy}","received_events_url":"https://api.github.com/users/zhanpenghe/received_events","type":"User","site_admin":false},"body":"The reason why dist is not an output is that we cannot do `session.run(dist, feed_dict=fd)`.","created_at":"2018-12-20T03:51:32Z","updated_at":"2018-12-20T03:51:32Z","html_url":"https://github.com/rlworkgroup/garage/pull/385#discussion_r243149700","pull_request_url":"https://api.github.com/repos/rlworkgroup/garage/pulls/385","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/rlworkgroup/garage/pulls/comments/243149700"},"html":{"href":"https://github.com/rlworkgroup/garage/pull/385#discussion_r243149700"},"pull_request":{"href":"https://api.github.com/repos/rlworkgroup/garage/pulls/385"}},"in_reply_to_id":231145851},"pull_request":{"url":"https://api.github.com/repos/rlworkgroup/garage/pulls/385","id":228110527,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI4MTEwNTI3","html_url":"https://github.com/rlworkgroup/garage/pull/385","diff_url":"https://github.com/rlworkgroup/garage/pull/385.diff","patch_url":"https://github.com/rlworkgroup/garage/pull/385.patch","issue_url":"https://api.github.com/repos/rlworkgroup/garage/issues/385","number":385,"state":"open","locked":false,"title":"Add GaussianMLPModel and abstract class Model","user":{"login":"zhanpenghe","id":31218416,"node_id":"MDQ6VXNlcjMxMjE4NDE2","avatar_url":"https://avatars1.githubusercontent.com/u/31218416?v=4","gravatar_id":"","url":"https://api.github.com/users/zhanpenghe","html_url":"https://github.com/zhanpenghe","followers_url":"https://api.github.com/users/zhanpenghe/followers","following_url":"https://api.github.com/users/zhanpenghe/following{/other_user}","gists_url":"https://api.github.com/users/zhanpenghe/gists{/gist_id}","starred_url":"https://api.github.com/users/zhanpenghe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zhanpenghe/subscriptions","organizations_url":"https://api.github.com/users/zhanpenghe/orgs","repos_url":"https://api.github.com/users/zhanpenghe/repos","events_url":"https://api.github.com/users/zhanpenghe/events{/privacy}","received_events_url":"https://api.github.com/users/zhanpenghe/received_events","type":"User","site_admin":false},"body":"Implemented GaussianMLPModel. A import feature/contract of this abstraction is assuming that all tensors should be created in `build_model`. This allows users to make a copy of the graph with the same parameters. This is used in some cases e.g. MAML(#374).\r\n\r\nAlso, the model is not written with garage layers library. ref: #42 \r\nCurrently the model is using parameterized and serializable for pickling. ","created_at":"2018-11-03T10:07:25Z","updated_at":"2018-12-20T03:51:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b3c5868635f38680452255355d6bc4a8d748fea5","assignee":null,"assignees":[],"requested_reviewers":[{"login":"ahtsan","id":10270515,"node_id":"MDQ6VXNlcjEwMjcwNTE1","avatar_url":"https://avatars1.githubusercontent.com/u/10270515?v=4","gravatar_id":"","url":"https://api.github.com/users/ahtsan","html_url":"https://github.com/ahtsan","followers_url":"https://api.github.com/users/ahtsan/followers","following_url":"https://api.github.com/users/ahtsan/following{/other_user}","gists_url":"https://api.github.com/users/ahtsan/gists{/gist_id}","starred_url":"https://api.github.com/users/ahtsan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahtsan/subscriptions","organizations_url":"https://api.github.com/users/ahtsan/orgs","repos_url":"https://api.github.com/users/ahtsan/repos","events_url":"https://api.github.com/users/ahtsan/events{/privacy}","received_events_url":"https://api.github.com/users/ahtsan/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/rlworkgroup/garage/pulls/385/commits","review_comments_url":"https://api.github.com/repos/rlworkgroup/garage/pulls/385/comments","review_comment_url":"https://api.github.com/repos/rlworkgroup/garage/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rlworkgroup/garage/issues/385/comments","statuses_url":"https://api.github.com/repos/rlworkgroup/garage/statuses/933d8d2f403e6d10ac69c85dff190944ca568b48","head":{"label":"rlworkgroup:models","ref":"models","sha":"933d8d2f403e6d10ac69c85dff190944ca568b48","user":{"login":"rlworkgroup","id":39808070,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5ODA4MDcw","avatar_url":"https://avatars0.githubusercontent.com/u/39808070?v=4","gravatar_id":"","url":"https://api.github.com/users/rlworkgroup","html_url":"https://github.com/rlworkgroup","followers_url":"https://api.github.com/users/rlworkgroup/followers","following_url":"https://api.github.com/users/rlworkgroup/following{/other_user}","gists_url":"https://api.github.com/users/rlworkgroup/gists{/gist_id}","starred_url":"https://api.github.com/users/rlworkgroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rlworkgroup/subscriptions","organizations_url":"https://api.github.com/users/rlworkgroup/orgs","repos_url":"https://api.github.com/users/rlworkgroup/repos","events_url":"https://api.github.com/users/rlworkgroup/events{/privacy}","received_events_url":"https://api.github.com/users/rlworkgroup/received_events","type":"Organization","site_admin":false},"repo":{"id":136846372,"node_id":"MDEwOlJlcG9zaXRvcnkxMzY4NDYzNzI=","name":"garage","full_name":"rlworkgroup/garage","private":false,"owner":{"login":"rlworkgroup","id":39808070,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5ODA4MDcw","avatar_url":"https://avatars0.githubusercontent.com/u/39808070?v=4","gravatar_id":"","url":"https://api.github.com/users/rlworkgroup","html_url":"https://github.com/rlworkgroup","followers_url":"https://api.github.com/users/rlworkgroup/followers","following_url":"https://api.github.com/users/rlworkgroup/following{/other_user}","gists_url":"https://api.github.com/users/rlworkgroup/gists{/gist_id}","starred_url":"https://api.github.com/users/rlworkgroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rlworkgroup/subscriptions","organizations_url":"https://api.github.com/users/rlworkgroup/orgs","repos_url":"https://api.github.com/users/rlworkgroup/repos","events_url":"https://api.github.com/users/rlworkgroup/events{/privacy}","received_events_url":"https://api.github.com/users/rlworkgroup/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/rlworkgroup/garage","description":"A framework for reproducible reinforcement learning research","fork":false,"url":"https://api.github.com/repos/rlworkgroup/garage","forks_url":"https://api.github.com/repos/rlworkgroup/garage/forks","keys_url":"https://api.github.com/repos/rlworkgroup/garage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rlworkgroup/garage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rlworkgroup/garage/teams","hooks_url":"https://api.github.com/repos/rlworkgroup/garage/hooks","issue_events_url":"https://api.github.com/repos/rlworkgroup/garage/issues/events{/number}","events_url":"https://api.github.com/repos/rlworkgroup/garage/events","assignees_url":"https://api.github.com/repos/rlworkgroup/garage/assignees{/user}","branches_url":"https://api.github.com/repos/rlworkgroup/garage/branches{/branch}","tags_url":"https://api.github.com/repos/rlworkgroup/garage/tags","blobs_url":"https://api.github.com/repos/rlworkgroup/garage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rlworkgroup/garage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rlworkgroup/garage/git/refs{/sha}","trees_url":"https://api.github.com/repos/rlworkgroup/garage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rlworkgroup/garage/statuses/{sha}","languages_url":"https://api.github.com/repos/rlworkgroup/garage/languages","stargazers_url":"https://api.github.com/repos/rlworkgroup/garage/stargazers","contributors_url":"https://api.github.com/repos/rlworkgroup/garage/contributors","subscribers_url":"https://api.github.com/repos/rlworkgroup/garage/subscribers","subscription_url":"https://api.github.com/repos/rlworkgroup/garage/subscription","commits_url":"https://api.github.com/repos/rlworkgroup/garage/commits{/sha}","git_commits_url":"https://api.github.com/repos/rlworkgroup/garage/git/commits{/sha}","comments_url":"https://api.github.com/repos/rlworkgroup/garage/comments{/number}","issue_comment_url":"https://api.github.com/repos/rlworkgroup/garage/issues/comments{/number}","contents_url":"https://api.github.com/repos/rlworkgroup/garage/contents/{+path}","compare_url":"https://api.github.com/repos/rlworkgroup/garage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rlworkgroup/garage/merges","archive_url":"https://api.github.com/repos/rlworkgroup/garage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rlworkgroup/garage/downloads","issues_url":"https://api.github.com/repos/rlworkgroup/garage/issues{/number}","pulls_url":"https://api.github.com/repos/rlworkgroup/garage/pulls{/number}","milestones_url":"https://api.github.com/repos/rlworkgroup/garage/milestones{/number}","notifications_url":"https://api.github.com/repos/rlworkgroup/garage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rlworkgroup/garage/labels{/name}","releases_url":"https://api.github.com/repos/rlworkgroup/garage/releases{/id}","deployments_url":"https://api.github.com/repos/rlworkgroup/garage/deployments","created_at":"2018-06-10T21:31:23Z","updated_at":"2018-12-20T02:52:34Z","pushed_at":"2018-12-19T23:58:14Z","git_url":"git://github.com/rlworkgroup/garage.git","ssh_url":"git@github.com:rlworkgroup/garage.git","clone_url":"https://github.com/rlworkgroup/garage.git","svn_url":"https://github.com/rlworkgroup/garage","homepage":"","size":9040,"stargazers_count":150,"watchers_count":150,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":19,"mirror_url":null,"archived":false,"open_issues_count":112,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":19,"open_issues":112,"watchers":150,"default_branch":"master"}},"base":{"label":"rlworkgroup:master","ref":"master","sha":"6a26bb824b021fa09a0a36f350731ceca4ab8d56","user":{"login":"rlworkgroup","id":39808070,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5ODA4MDcw","avatar_url":"https://avatars0.githubusercontent.com/u/39808070?v=4","gravatar_id":"","url":"https://api.github.com/users/rlworkgroup","html_url":"https://github.com/rlworkgroup","followers_url":"https://api.github.com/users/rlworkgroup/followers","following_url":"https://api.github.com/users/rlworkgroup/following{/other_user}","gists_url":"https://api.github.com/users/rlworkgroup/gists{/gist_id}","starred_url":"https://api.github.com/users/rlworkgroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rlworkgroup/subscriptions","organizations_url":"https://api.github.com/users/rlworkgroup/orgs","repos_url":"https://api.github.com/users/rlworkgroup/repos","events_url":"https://api.github.com/users/rlworkgroup/events{/privacy}","received_events_url":"https://api.github.com/users/rlworkgroup/received_events","type":"Organization","site_admin":false},"repo":{"id":136846372,"node_id":"MDEwOlJlcG9zaXRvcnkxMzY4NDYzNzI=","name":"garage","full_name":"rlworkgroup/garage","private":false,"owner":{"login":"rlworkgroup","id":39808070,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM5ODA4MDcw","avatar_url":"https://avatars0.githubusercontent.com/u/39808070?v=4","gravatar_id":"","url":"https://api.github.com/users/rlworkgroup","html_url":"https://github.com/rlworkgroup","followers_url":"https://api.github.com/users/rlworkgroup/followers","following_url":"https://api.github.com/users/rlworkgroup/following{/other_user}","gists_url":"https://api.github.com/users/rlworkgroup/gists{/gist_id}","starred_url":"https://api.github.com/users/rlworkgroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rlworkgroup/subscriptions","organizations_url":"https://api.github.com/users/rlworkgroup/orgs","repos_url":"https://api.github.com/users/rlworkgroup/repos","events_url":"https://api.github.com/users/rlworkgroup/events{/privacy}","received_events_url":"https://api.github.com/users/rlworkgroup/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/rlworkgroup/garage","description":"A framework for reproducible reinforcement learning research","fork":false,"url":"https://api.github.com/repos/rlworkgroup/garage","forks_url":"https://api.github.com/repos/rlworkgroup/garage/forks","keys_url":"https://api.github.com/repos/rlworkgroup/garage/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rlworkgroup/garage/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rlworkgroup/garage/teams","hooks_url":"https://api.github.com/repos/rlworkgroup/garage/hooks","issue_events_url":"https://api.github.com/repos/rlworkgroup/garage/issues/events{/number}","events_url":"https://api.github.com/repos/rlworkgroup/garage/events","assignees_url":"https://api.github.com/repos/rlworkgroup/garage/assignees{/user}","branches_url":"https://api.github.com/repos/rlworkgroup/garage/branches{/branch}","tags_url":"https://api.github.com/repos/rlworkgroup/garage/tags","blobs_url":"https://api.github.com/repos/rlworkgroup/garage/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rlworkgroup/garage/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rlworkgroup/garage/git/refs{/sha}","trees_url":"https://api.github.com/repos/rlworkgroup/garage/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rlworkgroup/garage/statuses/{sha}","languages_url":"https://api.github.com/repos/rlworkgroup/garage/languages","stargazers_url":"https://api.github.com/repos/rlworkgroup/garage/stargazers","contributors_url":"https://api.github.com/repos/rlworkgroup/garage/contributors","subscribers_url":"https://api.github.com/repos/rlworkgroup/garage/subscribers","subscription_url":"https://api.github.com/repos/rlworkgroup/garage/subscription","commits_url":"https://api.github.com/repos/rlworkgroup/garage/commits{/sha}","git_commits_url":"https://api.github.com/repos/rlworkgroup/garage/git/commits{/sha}","comments_url":"https://api.github.com/repos/rlworkgroup/garage/comments{/number}","issue_comment_url":"https://api.github.com/repos/rlworkgroup/garage/issues/comments{/number}","contents_url":"https://api.github.com/repos/rlworkgroup/garage/contents/{+path}","compare_url":"https://api.github.com/repos/rlworkgroup/garage/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rlworkgroup/garage/merges","archive_url":"https://api.github.com/repos/rlworkgroup/garage/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rlworkgroup/garage/downloads","issues_url":"https://api.github.com/repos/rlworkgroup/garage/issues{/number}","pulls_url":"https://api.github.com/repos/rlworkgroup/garage/pulls{/number}","milestones_url":"https://api.github.com/repos/rlworkgroup/garage/milestones{/number}","notifications_url":"https://api.github.com/repos/rlworkgroup/garage/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rlworkgroup/garage/labels{/name}","releases_url":"https://api.github.com/repos/rlworkgroup/garage/releases{/id}","deployments_url":"https://api.github.com/repos/rlworkgroup/garage/deployments","created_at":"2018-06-10T21:31:23Z","updated_at":"2018-12-20T02:52:34Z","pushed_at":"2018-12-19T23:58:14Z","git_url":"git://github.com/rlworkgroup/garage.git","ssh_url":"git@github.com:rlworkgroup/garage.git","clone_url":"https://github.com/rlworkgroup/garage.git","svn_url":"https://github.com/rlworkgroup/garage","homepage":"","size":9040,"stargazers_count":150,"watchers_count":150,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":19,"mirror_url":null,"archived":false,"open_issues_count":112,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":19,"open_issues":112,"watchers":150,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rlworkgroup/garage/pulls/385"},"html":{"href":"https://github.com/rlworkgroup/garage/pull/385"},"issue":{"href":"https://api.github.com/repos/rlworkgroup/garage/issues/385"},"comments":{"href":"https://api.github.com/repos/rlworkgroup/garage/issues/385/comments"},"review_comments":{"href":"https://api.github.com/repos/rlworkgroup/garage/pulls/385/comments"},"review_comment":{"href":"https://api.github.com/repos/rlworkgroup/garage/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rlworkgroup/garage/pulls/385/commits"},"statuses":{"href":"https://api.github.com/repos/rlworkgroup/garage/statuses/933d8d2f403e6d10ac69c85dff190944ca568b48"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"zhanpenghe"}}