{"action":"created","comment":{"url":"https://api.github.com/repos/Theano/Theano/pulls/comments/50407276","id":50407276,"diff_hunk":"@@ -3372,52 +3372,483 @@ def transpose(x, axes=None):\n     return ret\n \n \n-def batched_dot(x, y):\n+class BatchedDot(Op):\n     \"\"\"\n-    This function computes the dot product between the two tensors, by\n-    iterating over the first dimension using scan.\n+    Computes the batched dot product of two variables:\n \n-    Parameters\n-    ----------\n-    x : tensor\n-        A Tensor with sizes e.g.: for  3D (dim1, dim3, dim2).\n-    y : tensor\n-        A Tensor with sizes e.g.: for 3D (dim1, dim2, dim4).\n+        batched_dot(a, b)[i] = dot(a[i], b[i])\n+    \"\"\"\n+    __props__ = ()\n \n-    Returns\n-    -------\n-    tensor\n-        A tensor of size e.g. if it is 3D: (dim1, dim3, dim4).\n+    def make_node(self, *inputs):\n+        inputs = list(map(as_tensor_variable, inputs))\n \n-    Notes\n-    -----\n-    This is a subset of numpy.einsum, but we do not provide it for now.\n-    But numpy einsum is slower than dot or tensordot:\n-    http://mail.scipy.org/pipermail/numpy-discussion/2012-October/064259.html\n+        if len(inputs) != 2:\n+            raise TypeError(\n+                'theano.tensor.BatchedDot: 2 arguments required, %d given ' %\n+                len(inputs))\n+        if inputs[0].ndim not in (2, 3):\n+            raise TypeError(\n+                'theano.tensor.BatchedDot: input 0 (0-indexed) must have ndim'\n+                ' of 2 or 3, %d given. Consider calling '\n+                'theano.tensor.batched_dot instead.' % inputs[0].ndim)\n+        if inputs[1].ndim not in (2, 3):\n+            raise TypeError(\n+                'theano.tensor.BatchedDot: input 1 (0-indexed) must have ndim'\n+                'of 2 or 3, %d given. Consider calling '\n+                'theano.tensor.batched_dot instead.' % inputs[1].ndim)\n+\n+        dtype = scal.upcast(*[input.type.dtype for input in inputs])\n+        # upcast inputs to common dtype if needed\n+        upcasted_inputs = [cast(input, dtype) for input in inputs]\n+        broadcastable = ((inputs[0].type.broadcastable[0] or\n+                          inputs[1].type.broadcastable[0],) +\n+                         inputs[0].type.broadcastable[1:-1] +\n+                         inputs[1].type.broadcastable[2:])\n+        return Apply(self, upcasted_inputs, [tensor(dtype, broadcastable)])\n \n-    Examples\n-    --------\n-    >>> first = tensor.tensor3('first')\n-    >>> second = tensor.tensor3('second')\n-    >>> result = batched_dot(first, second)\n+    def perform(self, node, inp, out):\n+        x, y = inp\n+        z, = out\n+\n+        if x.shape[0] != y.shape[0]:\n+            raise TypeError(\n+                'theano.tensor.BatchedDot: inputs [%s] must have the same size'\n+                'in axis 0, but have sizes [%s].'\n+                % (\", \".join(map(str, inp)),\n+                   \", \".join([str(i.shape[0]) for i in inp])))\n+\n+        shape = self.infer_shape(node, [i.shape for i in inp])[0]\n+        dtype = node.outputs[0].dtype\n+        z[0] = numpy.empty(shape, dtype=dtype)\n+        for i in xrange(z[0].shape[0]):\n+            z[0][i] = numpy.dot(x[i], y[i])\n+\n+    def c_support_code(self):\n+        from theano.tensor.blas_headers import blas_header_text\n+        batch_gemm_defn = \"\"\"\n+        template<typename dtype, typename function>\n+        bool batch_gemm(function gemm, int type_size,\n+                        PyArrayObject* xs, PyArrayObject* ys, PyArrayObject* zs) {\n+            npy_intp *Nx = PyArray_DIMS(xs), *Sx = PyArray_STRIDES(xs);\n+            npy_intp *Ny = PyArray_DIMS(ys), *Sy = PyArray_STRIDES(ys);\n+            npy_intp *Nz = PyArray_DIMS(zs), *Sz = PyArray_STRIDES(zs);\n+\n+            if (Nx[0] != Ny[0]) {\n+                PyErr_Format(PyExc_ValueError,\n+                             \"Shape mismatch: batch sizes unequal.\"\n+                             \" x.shape is (%d, %d, %d),\"\n+                             \" y.shape is (%d, %d, %d).\",\n+                             Nx[0], Nx[1], Nx[2],\n+                             Ny[0], Ny[1], Ny[2]);\n+                return 1;\n+            }\n+\n+            if (Nx[2] != Ny[1]) {\n+                PyErr_Format(PyExc_ValueError,\n+                             \"Shape mismatch: summation axis sizes unequal.\"\n+                             \" x.shape is (%d, %d, %d),\"\n+                             \" y.shape is (%d, %d, %d).\",\n+                             Nx[0], Nx[1], Nx[2],\n+                             Ny[0], Ny[1], Ny[2]);\n+                return 1;\n+            }\n+\n+            /* encode the stride structure of _x,_y,_z into a single integer. */\n+            int unit = 0;\n+            unit |= ((Sx[2] == type_size || Nx[2] == 1) ? 0x0 : (Sx[1] == type_size || Nx[1]==1) ? 0x1 : 0x2) << 8;\n+            unit |= ((Sy[2] == type_size || Ny[2] == 1) ? 0x0 : (Sy[1] == type_size || Ny[1]==1) ? 0x1 : 0x2) << 4;\n+            unit |= ((Sz[2] == type_size || Nz[2] == 1) ? 0x0 : (Sz[1] == type_size || Nz[1]==1) ? 0x1 : 0x2) << 0;\n+\n+            /* create appropriate strides for malformed matrices that are row or column\n+             * vectors, or empty matrices.\n+             * In that case, the value of the stride does not really matter, but\n+             * some versions of BLAS insist that:\n+             *  - they are not smaller than the number of elements in the array,\n+             *  - they are not 0.\n+             */\n+            int sx_1 = (Nx[1] > 1) ? Sx[1]/type_size : (Nx[2] + 1);\n+            int sx_2 = (Nx[2] > 1) ? Sx[2]/type_size : (Nx[1] + 1);\n+            int sy_1 = (Ny[1] > 1) ? Sy[1]/type_size : (Ny[2] + 1);\n+            int sy_2 = (Ny[2] > 1) ? Sy[2]/type_size : (Ny[1] + 1);\n+            int sz_1 = (Nz[1] > 1) ? Sz[1]/type_size : (Nz[2] + 1);\n+            int sz_2 = (Nz[2] > 1) ? Sz[2]/type_size : (Nz[1] + 1);\n+\n+            dtype* x = (dtype*)PyArray_DATA(xs);\n+            dtype* y = (dtype*)PyArray_DATA(ys);\n+            dtype* z = (dtype*)PyArray_DATA(zs);\n+\n+            dtype a = 1.0;\n+            dtype b = 0.0;\n+            char N = 'N';\n+            char T = 'T';\n+            int Nz1 = Nz[1], Nz2 = Nz[2], Nx2 = Nx[2];\n+\n+            // loop over batch axis\n+            for (int i = 0; i < Nz[0]; i++) {\n+                switch(unit)\n+                {\n+                    case 0x000: gemm(&N, &N, &Nz2, &Nz1, &Nx2, &a, y, &sy_1, x, &sx_1, &b, z, &sz_1); break;\n+                    case 0x100: gemm(&N, &T, &Nz2, &Nz1, &Nx2, &a, y, &sy_1, x, &sx_2, &b, z, &sz_1); break;\n+                    case 0x010: gemm(&T, &N, &Nz2, &Nz1, &Nx2, &a, y, &sy_2, x, &sx_1, &b, z, &sz_1); break;\n+                    case 0x110: gemm(&T, &T, &Nz2, &Nz1, &Nx2, &a, y, &sy_2, x, &sx_2, &b, z, &sz_1); break;\n+                    case 0x001: gemm(&T, &T, &Nz1, &Nz2, &Nx2, &a, x, &sx_1, y, &sy_1, &b, z, &sz_2); break;\n+                    case 0x101: gemm(&N, &T, &Nz1, &Nz2, &Nx2, &a, x, &sx_2, y, &sy_1, &b, z, &sz_2); break;\n+                    case 0x011: gemm(&T, &N, &Nz1, &Nz2, &Nx2, &a, x, &sx_1, y, &sy_2, &b, z, &sz_2); break;\n+                    case 0x111: gemm(&N, &N, &Nz1, &Nz2, &Nx2, &a, x, &sx_2, y, &sy_2, &b, z, &sz_2); break;\n+                    default: PyErr_SetString(PyExc_ValueError, \"some matrix has no unit stride\"); return 1;\n+                };\n+                x += Sx[0] / type_size;\n+                y += Sy[0] / type_size;\n+                z += Sz[0] / type_size;\n+            }\n+\n+            return 0;\n+        }\n+        \"\"\"\n+        return blas_header_text() + batch_gemm_defn\n+\n+    def c_libraries(self):\n+        from theano.tensor.blas import ldflags\n+        return ldflags()\n+\n+    def c_compile_args(self):\n+        from theano.tensor.blas import ldflags\n+        return ldflags(libs=False, flags=True)\n+\n+    def c_lib_dirs(self):\n+        from theano.tensor.blas import ldflags\n+        return ldflags(libs=False, libs_dir=True)\n+\n+    def c_header_dirs(self):\n+        from theano.tensor.blas import ldflags\n+        return ldflags(libs=False, include_dir=True)\n+\n+    def c_code_cleanup(self, node, name, inputs, outputs, sub):\n+        return \"\"\"\n+        // clean up views\n+        Py_XDECREF(xs); xs = 0;\n+        Py_XDECREF(ys); ys = 0;\n+        Py_XDECREF(zs); zs = 0;\n+        \"\"\"\n+\n+    def c_code(self, node, name, inp, out, sub):\n+        _x, _y = inp\n+        _z, = out\n+        fail = sub[\"fail\"]\n+\n+        x_ndim, y_ndim, z_ndim = node.inputs[0].ndim, node.inputs[1].ndim, node.outputs[0].ndim\n+\n+        # generate code to allocate output based on runtime input shapes\n+        z_dims = [\"PyArray_DIMS(%s)[0]\" % _x]\n+        if x_ndim == 3: z_dims.append(\"PyArray_DIMS(%s)[1]\" % _x)\n+        if y_ndim == 3: z_dims.append(\"PyArray_DIMS(%s)[2]\" % _y)\n+        assert len(z_dims) == z_ndim\n+\n+        z_shape_correct = \" && \".join(\"PyArray_DIMS(%s)[%i] == %s\"\n+                                      % (_z, i, dim) for i, dim in enumerate(z_dims))\n+        z_shape = \", \".join(z_dims)\n+        allocate = \"\"\"\n+            if ((NULL == %(_z)s) || !(%(z_shape_correct)s))\n+            {\n+                npy_intp dims[%(z_ndim)s] = {%(z_shape)s};\n+                Py_XDECREF(%(_z)s);\n+                %(_z)s = (PyArrayObject*)PyArray_SimpleNew(\n+                    %(z_ndim)s, dims, PyArray_TYPE(%(_x)s));\n+                if(!%(_z)s) {\n+                    PyErr_SetString(PyExc_MemoryError,\n+                                    \"failed to alloc BatchedDot output\");\n+                    %(fail)s\n+                }\n+            }\n+        \"\"\" % locals()\n+\n+        # generate code to reallocate inputs/output contiguously if necessary\n+        contiguate = []\n+        for var, ndim in [(_x, x_ndim), (_y, y_ndim), (_z, z_ndim)]:\n+            strides = \"PyArray_STRIDES(%s)\" % var\n+            not_contiguous = \" || \".join([\n+                \" || \".join(\"{strides}[{i}] < 1 || {strides}[{i}] % type_size\"\n+                            .format(strides=strides, i=i) for i in range(ndim)),\n+                \"(%s)\" % \" && \".join(\"{strides}[{i}] != type_size\"","path":"theano/tensor/basic.py","position":225,"original_position":225,"commit_id":"8f65b441f555f0983df10f7555da78be561edfd1","original_commit_id":"8f65b441f555f0983df10f7555da78be561edfd1","user":{"login":"nouiz","id":180987,"avatar_url":"https://avatars.githubusercontent.com/u/180987?v=3","gravatar_id":"","url":"https://api.github.com/users/nouiz","html_url":"https://github.com/nouiz","followers_url":"https://api.github.com/users/nouiz/followers","following_url":"https://api.github.com/users/nouiz/following{/other_user}","gists_url":"https://api.github.com/users/nouiz/gists{/gist_id}","starred_url":"https://api.github.com/users/nouiz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nouiz/subscriptions","organizations_url":"https://api.github.com/users/nouiz/orgs","repos_url":"https://api.github.com/users/nouiz/repos","events_url":"https://api.github.com/users/nouiz/events{/privacy}","received_events_url":"https://api.github.com/users/nouiz/received_events","type":"User","site_admin":false},"body":"why this part of the condition is needed (line 3573 and 3574)? Above, there is already  {strides}[{i}] % type_size above.\r\n","created_at":"2016-01-21T14:36:51Z","updated_at":"2016-01-21T14:36:51Z","html_url":"https://github.com/Theano/Theano/pull/3508#discussion_r50407276","pull_request_url":"https://api.github.com/repos/Theano/Theano/pulls/3508","_links":{"self":{"href":"https://api.github.com/repos/Theano/Theano/pulls/comments/50407276"},"html":{"href":"https://github.com/Theano/Theano/pull/3508#discussion_r50407276"},"pull_request":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3508"}}},"pull_request":{"url":"https://api.github.com/repos/Theano/Theano/pulls/3508","id":47312672,"html_url":"https://github.com/Theano/Theano/pull/3508","diff_url":"https://github.com/Theano/Theano/pull/3508.diff","patch_url":"https://github.com/Theano/Theano/pull/3508.patch","issue_url":"https://api.github.com/repos/Theano/Theano/issues/3508","number":3508,"state":"open","locked":false,"title":"WIP: BatchedDotOp","user":{"login":"cooijmanstim","id":206920,"avatar_url":"https://avatars.githubusercontent.com/u/206920?v=3","gravatar_id":"","url":"https://api.github.com/users/cooijmanstim","html_url":"https://github.com/cooijmanstim","followers_url":"https://api.github.com/users/cooijmanstim/followers","following_url":"https://api.github.com/users/cooijmanstim/following{/other_user}","gists_url":"https://api.github.com/users/cooijmanstim/gists{/gist_id}","starred_url":"https://api.github.com/users/cooijmanstim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cooijmanstim/subscriptions","organizations_url":"https://api.github.com/users/cooijmanstim/orgs","repos_url":"https://api.github.com/users/cooijmanstim/repos","events_url":"https://api.github.com/users/cooijmanstim/events{/privacy}","received_events_url":"https://api.github.com/users/cooijmanstim/received_events","type":"User","site_admin":false},"body":"Work in progress on #2968","created_at":"2015-10-09T19:50:32Z","updated_at":"2016-01-21T14:36:51Z","closed_at":null,"merged_at":null,"merge_commit_sha":"91f8a62159c229854bba6bfc3d0020008b9e470b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Theano/Theano/pulls/3508/commits","review_comments_url":"https://api.github.com/repos/Theano/Theano/pulls/3508/comments","review_comment_url":"https://api.github.com/repos/Theano/Theano/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Theano/Theano/issues/3508/comments","statuses_url":"https://api.github.com/repos/Theano/Theano/statuses/8f65b441f555f0983df10f7555da78be561edfd1","head":{"label":"cooijmanstim:batched_gemm","ref":"batched_gemm","sha":"8f65b441f555f0983df10f7555da78be561edfd1","user":{"login":"cooijmanstim","id":206920,"avatar_url":"https://avatars.githubusercontent.com/u/206920?v=3","gravatar_id":"","url":"https://api.github.com/users/cooijmanstim","html_url":"https://github.com/cooijmanstim","followers_url":"https://api.github.com/users/cooijmanstim/followers","following_url":"https://api.github.com/users/cooijmanstim/following{/other_user}","gists_url":"https://api.github.com/users/cooijmanstim/gists{/gist_id}","starred_url":"https://api.github.com/users/cooijmanstim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cooijmanstim/subscriptions","organizations_url":"https://api.github.com/users/cooijmanstim/orgs","repos_url":"https://api.github.com/users/cooijmanstim/repos","events_url":"https://api.github.com/users/cooijmanstim/events{/privacy}","received_events_url":"https://api.github.com/users/cooijmanstim/received_events","type":"User","site_admin":false},"repo":{"id":39957980,"name":"Theano","full_name":"cooijmanstim/Theano","owner":{"login":"cooijmanstim","id":206920,"avatar_url":"https://avatars.githubusercontent.com/u/206920?v=3","gravatar_id":"","url":"https://api.github.com/users/cooijmanstim","html_url":"https://github.com/cooijmanstim","followers_url":"https://api.github.com/users/cooijmanstim/followers","following_url":"https://api.github.com/users/cooijmanstim/following{/other_user}","gists_url":"https://api.github.com/users/cooijmanstim/gists{/gist_id}","starred_url":"https://api.github.com/users/cooijmanstim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cooijmanstim/subscriptions","organizations_url":"https://api.github.com/users/cooijmanstim/orgs","repos_url":"https://api.github.com/users/cooijmanstim/repos","events_url":"https://api.github.com/users/cooijmanstim/events{/privacy}","received_events_url":"https://api.github.com/users/cooijmanstim/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cooijmanstim/Theano","description":"Theano is a Python library that allows you to define, optimize, and evaluate mathematical expressions involving multi-dimensional arrays efficiently. It can use GPUs and perform efficient symbolic differentiation.","fork":true,"url":"https://api.github.com/repos/cooijmanstim/Theano","forks_url":"https://api.github.com/repos/cooijmanstim/Theano/forks","keys_url":"https://api.github.com/repos/cooijmanstim/Theano/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cooijmanstim/Theano/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cooijmanstim/Theano/teams","hooks_url":"https://api.github.com/repos/cooijmanstim/Theano/hooks","issue_events_url":"https://api.github.com/repos/cooijmanstim/Theano/issues/events{/number}","events_url":"https://api.github.com/repos/cooijmanstim/Theano/events","assignees_url":"https://api.github.com/repos/cooijmanstim/Theano/assignees{/user}","branches_url":"https://api.github.com/repos/cooijmanstim/Theano/branches{/branch}","tags_url":"https://api.github.com/repos/cooijmanstim/Theano/tags","blobs_url":"https://api.github.com/repos/cooijmanstim/Theano/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cooijmanstim/Theano/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cooijmanstim/Theano/git/refs{/sha}","trees_url":"https://api.github.com/repos/cooijmanstim/Theano/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cooijmanstim/Theano/statuses/{sha}","languages_url":"https://api.github.com/repos/cooijmanstim/Theano/languages","stargazers_url":"https://api.github.com/repos/cooijmanstim/Theano/stargazers","contributors_url":"https://api.github.com/repos/cooijmanstim/Theano/contributors","subscribers_url":"https://api.github.com/repos/cooijmanstim/Theano/subscribers","subscription_url":"https://api.github.com/repos/cooijmanstim/Theano/subscription","commits_url":"https://api.github.com/repos/cooijmanstim/Theano/commits{/sha}","git_commits_url":"https://api.github.com/repos/cooijmanstim/Theano/git/commits{/sha}","comments_url":"https://api.github.com/repos/cooijmanstim/Theano/comments{/number}","issue_comment_url":"https://api.github.com/repos/cooijmanstim/Theano/issues/comments{/number}","contents_url":"https://api.github.com/repos/cooijmanstim/Theano/contents/{+path}","compare_url":"https://api.github.com/repos/cooijmanstim/Theano/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cooijmanstim/Theano/merges","archive_url":"https://api.github.com/repos/cooijmanstim/Theano/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cooijmanstim/Theano/downloads","issues_url":"https://api.github.com/repos/cooijmanstim/Theano/issues{/number}","pulls_url":"https://api.github.com/repos/cooijmanstim/Theano/pulls{/number}","milestones_url":"https://api.github.com/repos/cooijmanstim/Theano/milestones{/number}","notifications_url":"https://api.github.com/repos/cooijmanstim/Theano/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cooijmanstim/Theano/labels{/name}","releases_url":"https://api.github.com/repos/cooijmanstim/Theano/releases{/id}","created_at":"2015-07-30T15:31:51Z","updated_at":"2015-07-30T15:31:54Z","pushed_at":"2016-01-12T23:21:53Z","git_url":"git://github.com/cooijmanstim/Theano.git","ssh_url":"git@github.com:cooijmanstim/Theano.git","clone_url":"https://github.com/cooijmanstim/Theano.git","svn_url":"https://github.com/cooijmanstim/Theano","homepage":"http://www.deeplearning.net/software/theano","size":47073,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Theano:master","ref":"master","sha":"4ad36ddc1160f38cfb985302bb6ee3503b0db34b","user":{"login":"Theano","id":970517,"avatar_url":"https://avatars.githubusercontent.com/u/970517?v=3","gravatar_id":"","url":"https://api.github.com/users/Theano","html_url":"https://github.com/Theano","followers_url":"https://api.github.com/users/Theano/followers","following_url":"https://api.github.com/users/Theano/following{/other_user}","gists_url":"https://api.github.com/users/Theano/gists{/gist_id}","starred_url":"https://api.github.com/users/Theano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Theano/subscriptions","organizations_url":"https://api.github.com/users/Theano/orgs","repos_url":"https://api.github.com/users/Theano/repos","events_url":"https://api.github.com/users/Theano/events{/privacy}","received_events_url":"https://api.github.com/users/Theano/received_events","type":"Organization","site_admin":false},"repo":{"id":2183193,"name":"Theano","full_name":"Theano/Theano","owner":{"login":"Theano","id":970517,"avatar_url":"https://avatars.githubusercontent.com/u/970517?v=3","gravatar_id":"","url":"https://api.github.com/users/Theano","html_url":"https://github.com/Theano","followers_url":"https://api.github.com/users/Theano/followers","following_url":"https://api.github.com/users/Theano/following{/other_user}","gists_url":"https://api.github.com/users/Theano/gists{/gist_id}","starred_url":"https://api.github.com/users/Theano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Theano/subscriptions","organizations_url":"https://api.github.com/users/Theano/orgs","repos_url":"https://api.github.com/users/Theano/repos","events_url":"https://api.github.com/users/Theano/events{/privacy}","received_events_url":"https://api.github.com/users/Theano/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Theano/Theano","description":"Theano is a Python library that allows you to define, optimize, and evaluate mathematical expressions involving multi-dimensional arrays efficiently. It can use GPUs and perform efficient symbolic differentiation.","fork":false,"url":"https://api.github.com/repos/Theano/Theano","forks_url":"https://api.github.com/repos/Theano/Theano/forks","keys_url":"https://api.github.com/repos/Theano/Theano/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Theano/Theano/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Theano/Theano/teams","hooks_url":"https://api.github.com/repos/Theano/Theano/hooks","issue_events_url":"https://api.github.com/repos/Theano/Theano/issues/events{/number}","events_url":"https://api.github.com/repos/Theano/Theano/events","assignees_url":"https://api.github.com/repos/Theano/Theano/assignees{/user}","branches_url":"https://api.github.com/repos/Theano/Theano/branches{/branch}","tags_url":"https://api.github.com/repos/Theano/Theano/tags","blobs_url":"https://api.github.com/repos/Theano/Theano/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Theano/Theano/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Theano/Theano/git/refs{/sha}","trees_url":"https://api.github.com/repos/Theano/Theano/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Theano/Theano/statuses/{sha}","languages_url":"https://api.github.com/repos/Theano/Theano/languages","stargazers_url":"https://api.github.com/repos/Theano/Theano/stargazers","contributors_url":"https://api.github.com/repos/Theano/Theano/contributors","subscribers_url":"https://api.github.com/repos/Theano/Theano/subscribers","subscription_url":"https://api.github.com/repos/Theano/Theano/subscription","commits_url":"https://api.github.com/repos/Theano/Theano/commits{/sha}","git_commits_url":"https://api.github.com/repos/Theano/Theano/git/commits{/sha}","comments_url":"https://api.github.com/repos/Theano/Theano/comments{/number}","issue_comment_url":"https://api.github.com/repos/Theano/Theano/issues/comments{/number}","contents_url":"https://api.github.com/repos/Theano/Theano/contents/{+path}","compare_url":"https://api.github.com/repos/Theano/Theano/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Theano/Theano/merges","archive_url":"https://api.github.com/repos/Theano/Theano/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Theano/Theano/downloads","issues_url":"https://api.github.com/repos/Theano/Theano/issues{/number}","pulls_url":"https://api.github.com/repos/Theano/Theano/pulls{/number}","milestones_url":"https://api.github.com/repos/Theano/Theano/milestones{/number}","notifications_url":"https://api.github.com/repos/Theano/Theano/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Theano/Theano/labels{/name}","releases_url":"https://api.github.com/repos/Theano/Theano/releases{/id}","created_at":"2011-08-10T03:48:06Z","updated_at":"2016-01-21T10:43:45Z","pushed_at":"2016-01-21T14:11:24Z","git_url":"git://github.com/Theano/Theano.git","ssh_url":"git@github.com:Theano/Theano.git","clone_url":"https://github.com/Theano/Theano.git","svn_url":"https://github.com/Theano/Theano","homepage":"http://www.deeplearning.net/software/theano","size":55672,"stargazers_count":2822,"watchers_count":2822,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1020,"mirror_url":null,"open_issues_count":572,"forks":1020,"open_issues":572,"watchers":2822,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3508"},"html":{"href":"https://github.com/Theano/Theano/pull/3508"},"issue":{"href":"https://api.github.com/repos/Theano/Theano/issues/3508"},"comments":{"href":"https://api.github.com/repos/Theano/Theano/issues/3508/comments"},"review_comments":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3508/comments"},"review_comment":{"href":"https://api.github.com/repos/Theano/Theano/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3508/commits"},"statuses":{"href":"https://api.github.com/repos/Theano/Theano/statuses/8f65b441f555f0983df10f7555da78be561edfd1"}}}}