{"action":"created","comment":{"url":"https://api.github.com/repos/apache/incubator-singa/pulls/comments/187803110","pull_request_review_id":119656629,"id":187803110,"diff_hunk":"@@ -1,6 +1,531 @@\n+\n+from __future__ import division\n+\n+from functools import reduce\n from collections import Counter, deque\n-from .tensor import Tensor, Dummy\n+from .tensor import Tensor, Dummy, Operation\n+\n+from singa import layer\n+from singa.proto import model_pb2\n+from . import singa_wrap as singa\n+\n+import numpy as np\n+\n+CTensor = singa.Tensor\n+\n+\n+class ReLU(Operation):\n+\n+    def forward(self, x):\n+        '''\n+        Args:\n+            x(CTensor): input tensor\n+\n+        Returns:\n+            a new CTensor whose element y = x if x >= 0; otherwise 0;\n+        '''\n+        self.input = x\n+        return singa.ReLU(x)\n+\n+    def backward(self, dy):\n+        '''\n+        Args:\n+            dy(CTensor): dL / dy\n+\n+        Returns:\n+            dx(CTensor): dL / dx = dy if x >= 0; otherwise 0;\n+        '''\n+        dx = singa.GTFloat(self.input, 0.0)\n+        return singa.__mul__(dy, dx)\n+\n+\n+def relu(x):\n+    return ReLU()(x)[0]\n+\n+\n+class Matmul(Operation):\n+    '''For matrix multiplication'''\n+\n+    def forward(self, x, w):\n+        '''Do forward propgation.\n+\n+        Store the x(or w) if w(or x) requires gradient.\n+\n+        Args:\n+            x (CTensor): matrix\n+            w (CTensor): matrix\n+\n+        Returns:\n+            a CTensor for the result\n+        '''\n+        self.input = (x, w)\n+        return singa.Mult(x, w)\n+\n+    def backward(self, dy):\n+        '''\n+        Args:\n+            dy (CTensor): data for the dL / dy, L is the loss\n+\n+        Returns:\n+            a tuple for (dx, dw)\n+        '''\n+        return singa.Mult(dy, self.input[1].T()), \\\n+            singa.Mult(self.input[0].T(), dy)\n+\n+\n+def matmul(x, w):\n+    return Matmul()(x, w)[0]\n+\n+\n+class AddBias(Operation):\n+    '''\n+    Add Bias to each row / column of the Tensor, depending on the parameter axis.\n+    '''\n+\n+    def __init__(self, axis=0):\n+        '''\n+        To indicate the calculation axis, 0 for row, 1 for column.\n+\n+        Args:\n+            axis: 0 or 1, default is 0.\n+        '''\n+        self.axis = axis\n+\n+    def forward(self, x, b):\n+        '''\n+        Args:\n+            x: matrix.\n+            b: bias to be added.\n+\n+        Return:\n+            the result Tensor\n+        '''\n+        if self.axis == 0:\n+            singa.AddRow(b, x)\n+        elif self.axis == 1:\n+            singa.AddColumn(b, x)\n+        return x\n+\n+    def backward(self, dy):\n+        '''\n+        Args:\n+            dy (CTensor): data for the dL / dy, L is the loss.\n+\n+        Return:\n+            a tuple for (db, dx), db is data for dL / db, dx is data\n+            for dL / dx.\n+        '''\n+        if self.axis == 0:\n+            return dy, singa.Sum(dy, 0)\n+        elif self.axis == 1:\n+            return dy, singa.Sum(dy, 0)\n+\n+\n+def add_bias(x, b, axis=0):\n+    return AddBias(axis)(x, b)[0]\n+\n+\n+class SoftMax(Operation):\n+    '''\n+    Apply SoftMax for each row of the Tensor or each column of the Tensor\n+    according to the parameter axis.\n+    '''\n+\n+    def __init__(self, axis=0):\n+        self.axis = axis\n+\n+    def forward(self, x):\n+        '''\n+        Args:\n+            x(data): the input 1d or 2d tensor\n+\n+        Returns:\n+            the result Tensor\n+        '''\n+        if self.axis == 1:\n+            x = x.T()\n+        self.output = singa.SoftMax(x)\n+        if self.axis == 0:\n+            return self.output\n+        elif self.axis == 1:\n+            return self.output.T()\n+\n+    def backward(self, dy):\n+        '''\n+        Args:\n+            dy (CTensor): data for the dL / dy, L is the loss\n+\n+        Returns:\n+            dx (Ctensor): data for the dL / dx, L is the loss,\n+            x is the input of current Opertion\n+        '''\n+        # calculations are made on numpy array\n+        if self.axis == 1:\n+            dy = dy.T()\n+        grad = ctensor2numpy(dy)\n+        output = ctensor2numpy(self.output)\n+        out_1 = np.einsum('ki,ki->ki', grad, output)\n+        medium_out = np.einsum('ki,kj->kij', output, output)\n+        out_2 = np.einsum('kij,kj->ki', medium_out, grad)\n+        out = out_1 - out_2\n+        dx = CTensor(out_1.shape)\n+        dx.CopyFloatDataFromHostPtr(out.flatten())\n+        if self.axis == 0:\n+            return dx\n+        elif self.axis == 1:\n+            return dx.T()\n+\n+\n+def soft_max(x, axis=0):\n+    return SoftMax(axis)(x)[0]\n+\n+\n+class CrossEntropy(Operation):\n+    '''\n+    Calculte CrossEntropy loss for a batch of training data.\n+\n+    '''\n+\n+    def forward(self, x, t):\n+        '''\n+        Args:\n+            x (CTensor): 1d or 2d tensor, the prediction data(output) of current network.\n+            t (CTensor): 1d or 2d tensor, the target data for training.\n+\n+        Returns:\n+            loss (CTensor): scalar.\n+        '''\n+        loss = CTensor((1,))\n+        loss_data = -singa.SumAsFloat(singa.__mul__(t, singa.Log(x)))\n+        loss.SetFloatValue(loss_data / x.shape()[0])\n+        self.x = x\n+        self.t = t\n+        self.input = (x, t)\n+        return loss\n+\n+    def backward(self, dy=1.0):\n+        '''\n+        Args:\n+            dy (float or CTensor): scalar, accumulate gradient from outside of current network, usually\n+            equal to 1.0\n+\n+        Returns:\n+            dx (CTensor): data for the dL /dx, L is the loss, x is the output of current network.\n+            note that this is true for dy = 1.0\n+        '''\n+        dx = singa.__div__(self.t, self.x)\n+        dx *= float(-1 / self.x.shape()[0])\n+        if isinstance(dy, float):\n+            # dtype of dy: float\n+            dx *= dy\n+            return dx, None\n+        elif isinstance(dy, CTensor):\n+            pass  # TODO, broadcast elementwise multiply seems not support\n+\n+\n+def cross_entropy(y, t):\n+    return CrossEntropy()(y, t)[0]\n+\n+\n+def ctensor2numpy(x):\n+    '''\n+    To be used in SoftMax Operation.\n+    Convert a singa_tensor to numpy_tensor.\n+    '''\n+    np_array = x.GetFloatValue(int(x.Size()))\n+    return np_array.reshape(x.shape())\n+\n+class Conv2d(Operation):\n+    def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, padding=0, dilation=1, groups=1, bias=True, **kwargs):\n+\n+        name = 'Conv2d'\n+        border_mode = 'same'\n+        cudnn_prefer = 'fastest'\n+        workspace_byte_limit = 1024\n+        data_format = 'NCHW'\n+        W_specs ={'init': 'gaussian',\n+                  'mean':0.0,\n+                  'std':0.1}\n+        b_specs = {'init': 'constant'}\n+        input_sample_shape = None\n+\n+        inner_params = {'name':name,\n+                          'border_mode':border_mode,\n+                          'cudnn_prefer':cudnn_prefer,\n+                          'workspace_byte_limit':workspace_byte_limit,\n+                          'data_format':data_format,\n+                          'W_specs':W_specs,\n+                          'b_specs':b_specs,\n+                          'input_sample_shape':input_sample_shape\n+                          }\n+        # TODO valid value of inner_params check\n+\n+        for kwarg in kwargs:\n+            if kwarg not in inner_params:\n+                raise TypeError('Keyword argument not understood:', kwarg)\n+            else:\n+                inner_params[kwarg] = kwargs[kwarg]\n+                \n+\n+        self.W_specs=inner_params['W_specs']\n+        self.b_specs=inner_params['b_specs']\n+\n+        if padding == 0:\n+            pad = None\n+        else:\n+            pad = padding\n+\n+        if dilation != 1 or groups != 1:\n+            raise ValueError('Not implemented yet')\n+\n+        self.PyLayer = layer.Conv2D(inner_params['name'], nb_kernels=out_channels, kernel=kernel_size, stride=stride,\n+                                    border_mode=inner_params['border_mode'],\n+                 cudnn_prefer=inner_params['cudnn_prefer'], workspace_byte_limit=inner_params['workspace_byte_limit'],\n+                 data_format=inner_params['data_format'], use_bias=bias, W_specs=self.W_specs, b_specs=self.b_specs,\n+                 pad=pad, input_sample_shape=inner_params['input_sample_shape'])\n+\n+    def __call__(self, x, flag=True):\n+        assert type(flag) is bool, 'flag can only be bool.'\n+        if flag:\n+            self.flag = model_pb2.kTrain\n+        else:\n+            self.flag = model_pb2.kEval\n+\n+        if not self.PyLayer.has_setup:\n+            self.PyLayer.setup(x.shape[1:])\n+\n+        param_data = self.PyLayer.layer.param_values()\n+        if not hasattr(self, 'w'):\n+            self.w = Tensor(data=param_data[0], requires_grad=True, stores_grad=True)\n+            if self.W_specs['init'] == 'gaussian':\n+                if 'std' not in self.W_specs or 'mean' not in self.W_specs:\n+                    self.w.gaussian(0.0, 0.1)\n+                else:\n+                    self.w.gaussian(self.W_specs['mean'],self.W_specs['std'])\n+            elif self.W_specs['init'] == 'uniform':\n+                if 'low' not in self.W_specs or 'high' not in self.W_specs:\n+                    self.w.uniform(0.0, 1.0)\n+                else:\n+                    self.w.uniform(self.W_specs['low'],self.W_specs['high'])\n+            elif self.W_specs['init'] == 'xavier':\n+                pass  # TODO\n+\n+        xs = [x, self.w]\n+\n+        if len(param_data) == 2:\n+            if not hasattr(self, 'b'):\n+                self.b = Tensor(data=param_data[1], requires_grad=True, stores_grad=True)\n+                if self.b_specs['init'] == 'gaussian':\n+                    if 'std' not in self.b_specs or 'mean' not in self.b_specs:\n+                        self.b.gaussian(0.0, 0.1)\n+                    else:\n+                        self.b.gaussian(self.b_specs['mean'], self.b_specs['std'])\n+                elif self.b_specs['init'] == 'uniform':\n+                    if 'low' not in self.b_specs or 'high' not in self.b_specs:\n+                        self.b.uniform(0.0, 1.0)\n+                    else:\n+                        self.b.uniform(self.b_specs['low'], self.b_specs['high'])\n+                elif self.b_specs['init'] == 'xavier':\n+                    pass  # TODO\n+                elif self.b_specs['init'] == 'constant':\n+                    self.b.set_value(0.0)\n+\n+            xs.append(self.b)\n+\n+        xs = tuple(xs)\n+        return self._do_forward(*xs)\n+\n+    def forward(self, *xs):\n+        return self.PyLayer.layer.Forward(self.flag, xs[0])","path":"python/singa/autograd.py","position":552,"original_position":340,"commit_id":"9b1cdd27c90789c8d83e2d1f4e4ecba28cdeb38d","original_commit_id":"cc102905a7302c00bb6ea4d4a62eb9b55044c99c","user":{"login":"nudles","id":3797447,"avatar_url":"https://avatars0.githubusercontent.com/u/3797447?v=4","gravatar_id":"","url":"https://api.github.com/users/nudles","html_url":"https://github.com/nudles","followers_url":"https://api.github.com/users/nudles/followers","following_url":"https://api.github.com/users/nudles/following{/other_user}","gists_url":"https://api.github.com/users/nudles/gists{/gist_id}","starred_url":"https://api.github.com/users/nudles/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nudles/subscriptions","organizations_url":"https://api.github.com/users/nudles/orgs","repos_url":"https://api.github.com/users/nudles/repos","events_url":"https://api.github.com/users/nudles/events{/privacy}","received_events_url":"https://api.github.com/users/nudles/received_events","type":"User","site_admin":false},"body":"CTensor is just Tensor.data","created_at":"2018-05-13T14:38:03Z","updated_at":"2018-05-13T14:41:19Z","html_url":"https://github.com/apache/incubator-singa/pull/357#discussion_r187803110","pull_request_url":"https://api.github.com/repos/apache/incubator-singa/pulls/357","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/apache/incubator-singa/pulls/comments/187803110"},"html":{"href":"https://github.com/apache/incubator-singa/pull/357#discussion_r187803110"},"pull_request":{"href":"https://api.github.com/repos/apache/incubator-singa/pulls/357"}},"in_reply_to_id":186928886},"pull_request":{"url":"https://api.github.com/repos/apache/incubator-singa/pulls/357","id":182819623,"html_url":"https://github.com/apache/incubator-singa/pull/357","diff_url":"https://github.com/apache/incubator-singa/pull/357.diff","patch_url":"https://github.com/apache/incubator-singa/pull/357.patch","issue_url":"https://api.github.com/repos/apache/incubator-singa/issues/357","number":357,"state":"open","locked":false,"title":"SINGA-349 Create layer operations for autograd","user":{"login":"xuewanqi","id":36396136,"avatar_url":"https://avatars2.githubusercontent.com/u/36396136?v=4","gravatar_id":"","url":"https://api.github.com/users/xuewanqi","html_url":"https://github.com/xuewanqi","followers_url":"https://api.github.com/users/xuewanqi/followers","following_url":"https://api.github.com/users/xuewanqi/following{/other_user}","gists_url":"https://api.github.com/users/xuewanqi/gists{/gist_id}","starred_url":"https://api.github.com/users/xuewanqi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuewanqi/subscriptions","organizations_url":"https://api.github.com/users/xuewanqi/orgs","repos_url":"https://api.github.com/users/xuewanqi/repos","events_url":"https://api.github.com/users/xuewanqi/events{/privacy}","received_events_url":"https://api.github.com/users/xuewanqi/received_events","type":"User","site_admin":false},"body":"Add more layer operations such as convolution(), pooling() to support autograd.\r\n","created_at":"2018-04-19T15:45:35Z","updated_at":"2018-05-13T14:41:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a0ad476f1ac1bca11e6f6d54c2e0a7f7545639c4","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/apache/incubator-singa/pulls/357/commits","review_comments_url":"https://api.github.com/repos/apache/incubator-singa/pulls/357/comments","review_comment_url":"https://api.github.com/repos/apache/incubator-singa/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/incubator-singa/issues/357/comments","statuses_url":"https://api.github.com/repos/apache/incubator-singa/statuses/9b1cdd27c90789c8d83e2d1f4e4ecba28cdeb38d","head":{"label":"xuewanqi:autograd-v1.1","ref":"autograd-v1.1","sha":"9b1cdd27c90789c8d83e2d1f4e4ecba28cdeb38d","user":{"login":"xuewanqi","id":36396136,"avatar_url":"https://avatars2.githubusercontent.com/u/36396136?v=4","gravatar_id":"","url":"https://api.github.com/users/xuewanqi","html_url":"https://github.com/xuewanqi","followers_url":"https://api.github.com/users/xuewanqi/followers","following_url":"https://api.github.com/users/xuewanqi/following{/other_user}","gists_url":"https://api.github.com/users/xuewanqi/gists{/gist_id}","starred_url":"https://api.github.com/users/xuewanqi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuewanqi/subscriptions","organizations_url":"https://api.github.com/users/xuewanqi/orgs","repos_url":"https://api.github.com/users/xuewanqi/repos","events_url":"https://api.github.com/users/xuewanqi/events{/privacy}","received_events_url":"https://api.github.com/users/xuewanqi/received_events","type":"User","site_admin":false},"repo":{"id":121206718,"name":"incubator-singa","full_name":"xuewanqi/incubator-singa","owner":{"login":"xuewanqi","id":36396136,"avatar_url":"https://avatars2.githubusercontent.com/u/36396136?v=4","gravatar_id":"","url":"https://api.github.com/users/xuewanqi","html_url":"https://github.com/xuewanqi","followers_url":"https://api.github.com/users/xuewanqi/followers","following_url":"https://api.github.com/users/xuewanqi/following{/other_user}","gists_url":"https://api.github.com/users/xuewanqi/gists{/gist_id}","starred_url":"https://api.github.com/users/xuewanqi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xuewanqi/subscriptions","organizations_url":"https://api.github.com/users/xuewanqi/orgs","repos_url":"https://api.github.com/users/xuewanqi/repos","events_url":"https://api.github.com/users/xuewanqi/events{/privacy}","received_events_url":"https://api.github.com/users/xuewanqi/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/xuewanqi/incubator-singa","description":"Mirror of Apache Singa (Incubating)","fork":true,"url":"https://api.github.com/repos/xuewanqi/incubator-singa","forks_url":"https://api.github.com/repos/xuewanqi/incubator-singa/forks","keys_url":"https://api.github.com/repos/xuewanqi/incubator-singa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xuewanqi/incubator-singa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xuewanqi/incubator-singa/teams","hooks_url":"https://api.github.com/repos/xuewanqi/incubator-singa/hooks","issue_events_url":"https://api.github.com/repos/xuewanqi/incubator-singa/issues/events{/number}","events_url":"https://api.github.com/repos/xuewanqi/incubator-singa/events","assignees_url":"https://api.github.com/repos/xuewanqi/incubator-singa/assignees{/user}","branches_url":"https://api.github.com/repos/xuewanqi/incubator-singa/branches{/branch}","tags_url":"https://api.github.com/repos/xuewanqi/incubator-singa/tags","blobs_url":"https://api.github.com/repos/xuewanqi/incubator-singa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xuewanqi/incubator-singa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xuewanqi/incubator-singa/git/refs{/sha}","trees_url":"https://api.github.com/repos/xuewanqi/incubator-singa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xuewanqi/incubator-singa/statuses/{sha}","languages_url":"https://api.github.com/repos/xuewanqi/incubator-singa/languages","stargazers_url":"https://api.github.com/repos/xuewanqi/incubator-singa/stargazers","contributors_url":"https://api.github.com/repos/xuewanqi/incubator-singa/contributors","subscribers_url":"https://api.github.com/repos/xuewanqi/incubator-singa/subscribers","subscription_url":"https://api.github.com/repos/xuewanqi/incubator-singa/subscription","commits_url":"https://api.github.com/repos/xuewanqi/incubator-singa/commits{/sha}","git_commits_url":"https://api.github.com/repos/xuewanqi/incubator-singa/git/commits{/sha}","comments_url":"https://api.github.com/repos/xuewanqi/incubator-singa/comments{/number}","issue_comment_url":"https://api.github.com/repos/xuewanqi/incubator-singa/issues/comments{/number}","contents_url":"https://api.github.com/repos/xuewanqi/incubator-singa/contents/{+path}","compare_url":"https://api.github.com/repos/xuewanqi/incubator-singa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xuewanqi/incubator-singa/merges","archive_url":"https://api.github.com/repos/xuewanqi/incubator-singa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xuewanqi/incubator-singa/downloads","issues_url":"https://api.github.com/repos/xuewanqi/incubator-singa/issues{/number}","pulls_url":"https://api.github.com/repos/xuewanqi/incubator-singa/pulls{/number}","milestones_url":"https://api.github.com/repos/xuewanqi/incubator-singa/milestones{/number}","notifications_url":"https://api.github.com/repos/xuewanqi/incubator-singa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xuewanqi/incubator-singa/labels{/name}","releases_url":"https://api.github.com/repos/xuewanqi/incubator-singa/releases{/id}","deployments_url":"https://api.github.com/repos/xuewanqi/incubator-singa/deployments","created_at":"2018-02-12T06:01:26Z","updated_at":"2018-05-04T09:28:45Z","pushed_at":"2018-05-11T07:09:56Z","git_url":"git://github.com/xuewanqi/incubator-singa.git","ssh_url":"git@github.com:xuewanqi/incubator-singa.git","clone_url":"https://github.com/xuewanqi/incubator-singa.git","svn_url":"https://github.com/xuewanqi/incubator-singa","homepage":null,"size":14209,"stargazers_count":1,"watchers_count":1,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"c92ddb77720832adb42ac3572fc8aa2e3fe1806b","user":{"login":"apache","id":47359,"avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":33294317,"name":"incubator-singa","full_name":"apache/incubator-singa","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/incubator-singa","description":"Mirror of Apache Singa (Incubating)","fork":false,"url":"https://api.github.com/repos/apache/incubator-singa","forks_url":"https://api.github.com/repos/apache/incubator-singa/forks","keys_url":"https://api.github.com/repos/apache/incubator-singa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/incubator-singa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/incubator-singa/teams","hooks_url":"https://api.github.com/repos/apache/incubator-singa/hooks","issue_events_url":"https://api.github.com/repos/apache/incubator-singa/issues/events{/number}","events_url":"https://api.github.com/repos/apache/incubator-singa/events","assignees_url":"https://api.github.com/repos/apache/incubator-singa/assignees{/user}","branches_url":"https://api.github.com/repos/apache/incubator-singa/branches{/branch}","tags_url":"https://api.github.com/repos/apache/incubator-singa/tags","blobs_url":"https://api.github.com/repos/apache/incubator-singa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/incubator-singa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/incubator-singa/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/incubator-singa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/incubator-singa/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/incubator-singa/languages","stargazers_url":"https://api.github.com/repos/apache/incubator-singa/stargazers","contributors_url":"https://api.github.com/repos/apache/incubator-singa/contributors","subscribers_url":"https://api.github.com/repos/apache/incubator-singa/subscribers","subscription_url":"https://api.github.com/repos/apache/incubator-singa/subscription","commits_url":"https://api.github.com/repos/apache/incubator-singa/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/incubator-singa/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/incubator-singa/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/incubator-singa/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/incubator-singa/contents/{+path}","compare_url":"https://api.github.com/repos/apache/incubator-singa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/incubator-singa/merges","archive_url":"https://api.github.com/repos/apache/incubator-singa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/incubator-singa/downloads","issues_url":"https://api.github.com/repos/apache/incubator-singa/issues{/number}","pulls_url":"https://api.github.com/repos/apache/incubator-singa/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/incubator-singa/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/incubator-singa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/incubator-singa/labels{/name}","releases_url":"https://api.github.com/repos/apache/incubator-singa/releases{/id}","deployments_url":"https://api.github.com/repos/apache/incubator-singa/deployments","created_at":"2015-04-02T07:00:05Z","updated_at":"2018-05-12T14:38:40Z","pushed_at":"2018-05-13T13:01:41Z","git_url":"git://github.com/apache/incubator-singa.git","ssh_url":"git@github.com:apache/incubator-singa.git","clone_url":"https://github.com/apache/incubator-singa.git","svn_url":"https://github.com/apache/incubator-singa","homepage":null,"size":14280,"stargazers_count":1425,"watchers_count":1425,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":313,"mirror_url":null,"archived":false,"open_issues_count":24,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":313,"open_issues":24,"watchers":1425,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/incubator-singa/pulls/357"},"html":{"href":"https://github.com/apache/incubator-singa/pull/357"},"issue":{"href":"https://api.github.com/repos/apache/incubator-singa/issues/357"},"comments":{"href":"https://api.github.com/repos/apache/incubator-singa/issues/357/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/incubator-singa/pulls/357/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/incubator-singa/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/incubator-singa/pulls/357/commits"},"statuses":{"href":"https://api.github.com/repos/apache/incubator-singa/statuses/9b1cdd27c90789c8d83e2d1f4e4ecba28cdeb38d"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"nudles"}}