{"action":"created","comment":{"url":"https://api.github.com/repos/blue-oil/blueoil/pulls/comments/242407177","pull_request_review_id":185907421,"id":242407177,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0MjQwNzE3Nw==","diff_hunk":"@@ -14,632 +14,381 @@\n # limitations under the License.\n # =============================================================================\n \"\"\"Module of optimization passes.\"\"\"\n+import math\n import numpy as np\n-from core.data_types import DataType, Float32, Float64, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64, \\\n-    Bool, String, QUANTIZED_NOT_PACKED\n-from core.graph import Graph, GraphRunner\n-from core.operators import Add, AveragePool, BatchNormalization, Constant, Conv, Identity, Input, \\\n-    MaxPool, Operator, Output, Transpose, Quantizer, QTZ_binary_mean_scaling, QTZ_linear_mid_tread_half, \\\n-    Reshape, Softmax, Relu, Flatten, Dropout, Gemm, SpaceToDepth, QTZ_binary_channel_wise_mean_scaling, ConcatOnDepth,\\\n-    Maximum, DepthToSpace, Split\n-\n-from typing import Any, Dict, List, Optional, Set, cast\n-from functools import reduce\n-from enum import Enum\n \n+from core.graph import Graph\n+from core.graph_pattern_matching import find_pattern, Pattern, get_nodes_in_branch\n+from core.operators import Constant, Operator\n+from core.data_types import Uint32, QUANTIZED_NOT_PACKED\n+from typing import cast\n+from collections import defaultdict\n from modules.packer import Packer\n \n-NodeGroup = List[Operator]\n \n+def pass_dot_graph(graph: Graph, filename) -> None:\n \n-def node_is_add(node: Operator) -> bool:\n-    return node.op_type == 'Add'\n+    dot_script = 'digraph {'\n \n+    code = {}\n+    counter = 0\n+    for node in graph.operators:\n+        code[node.name] = counter\n+        counter += 1\n \n-def node_is_conv(node: Operator) -> bool:\n-    return node.op_type == 'Conv'\n+    for node in graph.operators:\n \n+        shape = '-'\n+        if node.shape:\n+            shape = 'x'.join(str(x) for x in node.shape)\n+        shape += '(' + node.dimension + ')'\n \n-def node_is_concat(node: Operator) -> bool:\n-    return node.op_type == 'ConcatV2'\n+        dot_script += node.name + '[label=\"<f0> ' + format(code[node.name], '04X') + '| <f1> ' + \\\n+            node.op_type + '| <f2> ' + shape + '| <f3> ' + node.dtype.cpptype() + '\" shape = \"record\"];'\n+        for i in node.input_nodes:\n+            dot_script += i.name + ' -> ' + node.name + ';'\n \n+    dot_script += '}'\n \n-def node_is_const(node: Operator) -> bool:\n-    return node.op_type == 'Constant'\n+    with open(filename, 'w') as f:\n+        f.write(dot_script)\n \n \n-def node_is_qconv(node: Operator) -> bool:\n-    return node.op_type == 'Conv' and cast(Conv, node).is_quantized\n+def pass_remove_identities(graph: Graph) -> None:\n+    p = Pattern(\"Identity\")\n+    matches = find_pattern(graph, p)\n+    to_be_removed = list()\n \n+    for m in matches:\n+        \"\"\"skip all identity.\"\"\"\n+        in_op = m.node.input_ops['input']\n+        out_ops = m.node.output_ops['output']\n+        for out_op in out_ops:\n+            for k, v in out_op.input_ops.items():\n+                if v == m.node:\n+                    # change the output's input to this identity's input\n+                    out_op.add_input(k, in_op)\n+                    # change the input's output to this identity's output\n+                    for k2, v2 in in_op.output_ops.items():\n+                        if m.node in v2:\n+                            v2.remove(m.node)\n+                            v2.append(out_op)\n+                            break\n+                    break\n \n-def node_is_input(node: Operator) -> bool:\n-    return node.op_type == 'Input'\n-\n-\n-def node_is_weight_quantizer(node: Operator) -> bool:\n-    return (node.op_type == 'QTZ_binary_mean_scaling'\n-            or node.op_type == 'QTZ_binary_channel_wise_mean_scaling')\n-\n-\n-def node_is_activation_quantizer(node: Operator) -> bool:\n-    return node.op_type == 'QTZ_linear_mid_tread_half'\n-\n-\n-class NHWC_Transposer(GraphRunner):\n-    \"\"\"Transposer of all nodes to NHWC.\"\"\"\n-\n-    def _get_permutation(self, dim: str) -> List[int]:\n-        \"\"\"Create a permutation from the source dimension.\"\"\"\n-        assert len(dim) == 4 and set(dim).issubset({'N', 'H', 'W', 'C', 'I', 'O'}), \\\n-            f'illegal dimension found: {dim}'\n-\n-        if set(dim) == set('HWIO'):\n-            dim = dim.replace('I', 'C')\n-            dim = dim.replace('O', 'N')\n-\n-        return list(map(lambda s: dim.index(s), 'NHWC'))\n-\n-    def _check_and_transpose(self, node: Operator) -> None:\n-        perm = self._get_permutation(node.dimension)\n-        node.transpose(perm)\n-\n-    def run_backward_input(self, node: Input, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_constant(self, node: Constant, **kwargs: Any) -> None:\n-        if node.ndims == 4 and set(node.dimension).issubset({'N', 'H', 'W', 'C', 'I', 'O'}):\n-            self._check_and_transpose(node)\n-\n-    def run_backward_identity(self, node: Identity, **kwargs: Any) -> None:\n-        if node.ndims == 4 and set(node.dimension).issubset({'N', 'H', 'W', 'C', 'I', 'O'}):\n-            self._check_and_transpose(node)\n-\n-    def run_backward_QTZ_binary_mean_scaling(self, node: QTZ_binary_mean_scaling, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_transpose(self, node: Transpose, **kwargs: Any) -> None:\n-        raise NotImplementedError('Transposing Transpose operator is not supported yet.')\n-\n-    def run_backward_conv(self, node: Conv, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_batch_normalization(self, node: BatchNormalization, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_QTZ_linear_mid_tread_half(self, node: QTZ_linear_mid_tread_half, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_max_pool(self, node: MaxPool, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_average_pool(self, node: AveragePool, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_SpaceToDepth(self, node: SpaceToDepth, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_QTZ_binary_channel_wise_mean_scaling(\n-            self,\n-            node: QTZ_binary_channel_wise_mean_scaling,\n-            **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_ConcatOnDepth(self, node: ConcatOnDepth, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_Maximum(self, node: Maximum, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-    def run_backward_DepthToSpace(self, node: DepthToSpace, **kwargs: Any) -> None:\n-        self._check_and_transpose(node)\n-\n-\n-class PreComputeRunner(GraphRunner):\n-    \"\"\"Optimization class that does precomputation and pruning on the graph.\n-\n-    Fron a constant node, this object precomputes as far as possible, and\n-    replaces all precomputed nodes with a newly defined constant node.\n-\n-    Additionally, in the hard-quantized mode, this object replaces a\n-    weight-quantizer node and succesive Conv node with a QConv node, and\n-    packs the weight.\n-    \"\"\"\n-\n-    _quantized_bitwidth = 1\n-    _wordsize = 32\n-\n-    def __init__(self, graph: Graph, hard_quantized: bool = False) -> None:\n-        \"\"\"Set up internal varibles.\"\"\"\n-        self._precomp_dic: Dict[str, bool] = {}\n-        self._nodes_removed: Set[Operator] = set()\n-        self._hard_quantized = hard_quantized\n-        self._quantizers: Dict[str, Quantizer] = {}  # the operator name and its quantizer\n-        self._connected_convs: Dict[Operator, List[Conv]] = {}  # node name and its connected convolver\n-\n-        super().__init__(graph)\n-\n-    def initialize(self, **kwargs: Any) -> None:\n-        qconvs: List[Conv] = kwargs['qconv']\n-        self._connected_convs = {q: [q] for q in qconvs}\n+        to_be_removed.append(m.node)\n \n-    def finalize(self, **kwargs: Any) -> None:\n-        \"\"\"Remove all unused nodes from the graph.\"\"\"\n-        for n in self._nodes_removed:\n-            self._graph.remove_op(n)\n+    for op in to_be_removed:\n+        graph.remove_op(op)\n \n-    # 1st phase: check which conv the node connects\n \n-    def run_backward_by_default(self, node: Operator, **kwargs: Any) -> None:\n-        outputs = node.output_op_list\n+def pass_transpose(graph: Graph) -> None:\n+    p = Pattern(\"*\")\n+    matches = find_pattern(graph, p)\n \n-        convs: List[Conv] = sum([self._connected_convs[out] for out in outputs if self._connected_convs.get(out)], [])\n-        self._connected_convs[node] = convs\n+    for m in matches:\n+        dim = m.node.dimension\n+        shape = m.node.shape\n+        if len(shape) != 4 or len(dim) != 4 or not set(dim).issubset({'N', 'H', 'W', 'C', 'I', 'O'}):\n+            continue\n \n-    def run_backward_conv(self, node: Conv, **kwargs: Any) -> None:\n-        pass  # do nothing, as all (quantized) conv node is already registered to self._connected_convs\n+        dim = dim.replace('I', 'C')\n+        dim = dim.replace('O', 'N')\n \n-    # 2nd phase: precompute and prune\n+        permutation = list(map(lambda s: dim.index(s), 'NHWC'))\n+        m.node.transpose(permutation)\n \n-    def _has_precompute_value(self, op: Operator) -> bool:\n-        \"\"\"Return True if the operator has precompute value.\"\"\"\n-        return self._precomp_dic[op.name]\n \n-    def _is_prunable(self, op: Operator) -> bool:\n-        \"\"\"Return True if op can be prunable.\"\"\"\n-        return self._has_precompute_value(op) and op.op_type != 'Constant'\n+def pass_precompute(graph: Graph, processed_nodes) -> bool:","path":"dlk/python/dlk/core/optimizer.py","position":238,"original_position":238,"commit_id":"2bbfa9cf6b7591ca104f259462a0a119a54faf90","original_commit_id":"2bbfa9cf6b7591ca104f259462a0a119a54faf90","user":{"login":"ruimashita","id":138891,"node_id":"MDQ6VXNlcjEzODg5MQ==","avatar_url":"https://avatars2.githubusercontent.com/u/138891?v=4","gravatar_id":"","url":"https://api.github.com/users/ruimashita","html_url":"https://github.com/ruimashita","followers_url":"https://api.github.com/users/ruimashita/followers","following_url":"https://api.github.com/users/ruimashita/following{/other_user}","gists_url":"https://api.github.com/users/ruimashita/gists{/gist_id}","starred_url":"https://api.github.com/users/ruimashita/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ruimashita/subscriptions","organizations_url":"https://api.github.com/users/ruimashita/orgs","repos_url":"https://api.github.com/users/ruimashita/repos","events_url":"https://api.github.com/users/ruimashita/events{/privacy}","received_events_url":"https://api.github.com/users/ruimashita/received_events","type":"User","site_admin":false},"body":"Please write docstring all of pass","created_at":"2018-12-18T05:00:54Z","updated_at":"2018-12-18T05:00:54Z","html_url":"https://github.com/blue-oil/blueoil/pull/53#discussion_r242407177","pull_request_url":"https://api.github.com/repos/blue-oil/blueoil/pulls/53","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/blue-oil/blueoil/pulls/comments/242407177"},"html":{"href":"https://github.com/blue-oil/blueoil/pull/53#discussion_r242407177"},"pull_request":{"href":"https://api.github.com/repos/blue-oil/blueoil/pulls/53"}}},"pull_request":{"url":"https://api.github.com/repos/blue-oil/blueoil/pulls/53","id":234493393,"node_id":"MDExOlB1bGxSZXF1ZXN0MjM0NDkzMzkz","html_url":"https://github.com/blue-oil/blueoil/pull/53","diff_url":"https://github.com/blue-oil/blueoil/pull/53.diff","patch_url":"https://github.com/blue-oil/blueoil/pull/53.patch","issue_url":"https://api.github.com/repos/blue-oil/blueoil/issues/53","number":53,"state":"open","locked":false,"title":"Added pattern matching and new optimization passes","user":{"login":"antonionevado","id":21376077,"node_id":"MDQ6VXNlcjIxMzc2MDc3","avatar_url":"https://avatars2.githubusercontent.com/u/21376077?v=4","gravatar_id":"","url":"https://api.github.com/users/antonionevado","html_url":"https://github.com/antonionevado","followers_url":"https://api.github.com/users/antonionevado/followers","following_url":"https://api.github.com/users/antonionevado/following{/other_user}","gists_url":"https://api.github.com/users/antonionevado/gists{/gist_id}","starred_url":"https://api.github.com/users/antonionevado/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antonionevado/subscriptions","organizations_url":"https://api.github.com/users/antonionevado/orgs","repos_url":"https://api.github.com/users/antonionevado/repos","events_url":"https://api.github.com/users/antonionevado/events{/privacy}","received_events_url":"https://api.github.com/users/antonionevado/received_events","type":"User","site_admin":false},"body":"This PR simplify the current optimization mechanism.\r\nThe idea is to only have a collection of simple passes that perform some actions over every sub-graph that match some given pattern.\r\n\r\nThe benefits of this PR are:\r\n\r\n- Improve speed: previous implementation compilation time was around 80 seconds. The new implementation takes around 1~2 seconds. Thanks to Joel-san and Neil-san for finding a way of computing thresholds in constant time!\r\n- The code is very simple and easy to understand: several functions each one applying a different pass.\r\n- The code is also very short compared to the previous implementation.\r\n","created_at":"2018-11-29T03:01:24Z","updated_at":"2018-12-18T05:00:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"abd972008e825fb0041fecdbd5ce410a7e463ec2","assignee":{"login":"antonionevado","id":21376077,"node_id":"MDQ6VXNlcjIxMzc2MDc3","avatar_url":"https://avatars2.githubusercontent.com/u/21376077?v=4","gravatar_id":"","url":"https://api.github.com/users/antonionevado","html_url":"https://github.com/antonionevado","followers_url":"https://api.github.com/users/antonionevado/followers","following_url":"https://api.github.com/users/antonionevado/following{/other_user}","gists_url":"https://api.github.com/users/antonionevado/gists{/gist_id}","starred_url":"https://api.github.com/users/antonionevado/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antonionevado/subscriptions","organizations_url":"https://api.github.com/users/antonionevado/orgs","repos_url":"https://api.github.com/users/antonionevado/repos","events_url":"https://api.github.com/users/antonionevado/events{/privacy}","received_events_url":"https://api.github.com/users/antonionevado/received_events","type":"User","site_admin":false},"assignees":[{"login":"antonionevado","id":21376077,"node_id":"MDQ6VXNlcjIxMzc2MDc3","avatar_url":"https://avatars2.githubusercontent.com/u/21376077?v=4","gravatar_id":"","url":"https://api.github.com/users/antonionevado","html_url":"https://github.com/antonionevado","followers_url":"https://api.github.com/users/antonionevado/followers","following_url":"https://api.github.com/users/antonionevado/following{/other_user}","gists_url":"https://api.github.com/users/antonionevado/gists{/gist_id}","starred_url":"https://api.github.com/users/antonionevado/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antonionevado/subscriptions","organizations_url":"https://api.github.com/users/antonionevado/orgs","repos_url":"https://api.github.com/users/antonionevado/repos","events_url":"https://api.github.com/users/antonionevado/events{/privacy}","received_events_url":"https://api.github.com/users/antonionevado/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"nlpng","id":34891526,"node_id":"MDQ6VXNlcjM0ODkxNTI2","avatar_url":"https://avatars3.githubusercontent.com/u/34891526?v=4","gravatar_id":"","url":"https://api.github.com/users/nlpng","html_url":"https://github.com/nlpng","followers_url":"https://api.github.com/users/nlpng/followers","following_url":"https://api.github.com/users/nlpng/following{/other_user}","gists_url":"https://api.github.com/users/nlpng/gists{/gist_id}","starred_url":"https://api.github.com/users/nlpng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nlpng/subscriptions","organizations_url":"https://api.github.com/users/nlpng/orgs","repos_url":"https://api.github.com/users/nlpng/repos","events_url":"https://api.github.com/users/nlpng/events{/privacy}","received_events_url":"https://api.github.com/users/nlpng/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":1095590113,"node_id":"MDU6TGFiZWwxMDk1NTkwMTEz","url":"https://api.github.com/repos/blue-oil/blueoil/labels/enhancement","name":"enhancement","color":"a2eeef","default":true}],"milestone":null,"commits_url":"https://api.github.com/repos/blue-oil/blueoil/pulls/53/commits","review_comments_url":"https://api.github.com/repos/blue-oil/blueoil/pulls/53/comments","review_comment_url":"https://api.github.com/repos/blue-oil/blueoil/pulls/comments{/number}","comments_url":"https://api.github.com/repos/blue-oil/blueoil/issues/53/comments","statuses_url":"https://api.github.com/repos/blue-oil/blueoil/statuses/2bbfa9cf6b7591ca104f259462a0a119a54faf90","head":{"label":"antonionevado:simplify_optimizer","ref":"simplify_optimizer","sha":"2bbfa9cf6b7591ca104f259462a0a119a54faf90","user":{"login":"antonionevado","id":21376077,"node_id":"MDQ6VXNlcjIxMzc2MDc3","avatar_url":"https://avatars2.githubusercontent.com/u/21376077?v=4","gravatar_id":"","url":"https://api.github.com/users/antonionevado","html_url":"https://github.com/antonionevado","followers_url":"https://api.github.com/users/antonionevado/followers","following_url":"https://api.github.com/users/antonionevado/following{/other_user}","gists_url":"https://api.github.com/users/antonionevado/gists{/gist_id}","starred_url":"https://api.github.com/users/antonionevado/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antonionevado/subscriptions","organizations_url":"https://api.github.com/users/antonionevado/orgs","repos_url":"https://api.github.com/users/antonionevado/repos","events_url":"https://api.github.com/users/antonionevado/events{/privacy}","received_events_url":"https://api.github.com/users/antonionevado/received_events","type":"User","site_admin":false},"repo":{"id":159596859,"node_id":"MDEwOlJlcG9zaXRvcnkxNTk1OTY4NTk=","name":"blueoil","full_name":"antonionevado/blueoil","private":false,"owner":{"login":"antonionevado","id":21376077,"node_id":"MDQ6VXNlcjIxMzc2MDc3","avatar_url":"https://avatars2.githubusercontent.com/u/21376077?v=4","gravatar_id":"","url":"https://api.github.com/users/antonionevado","html_url":"https://github.com/antonionevado","followers_url":"https://api.github.com/users/antonionevado/followers","following_url":"https://api.github.com/users/antonionevado/following{/other_user}","gists_url":"https://api.github.com/users/antonionevado/gists{/gist_id}","starred_url":"https://api.github.com/users/antonionevado/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antonionevado/subscriptions","organizations_url":"https://api.github.com/users/antonionevado/orgs","repos_url":"https://api.github.com/users/antonionevado/repos","events_url":"https://api.github.com/users/antonionevado/events{/privacy}","received_events_url":"https://api.github.com/users/antonionevado/received_events","type":"User","site_admin":false},"html_url":"https://github.com/antonionevado/blueoil","description":"Bring Deep Learning to small devices","fork":true,"url":"https://api.github.com/repos/antonionevado/blueoil","forks_url":"https://api.github.com/repos/antonionevado/blueoil/forks","keys_url":"https://api.github.com/repos/antonionevado/blueoil/keys{/key_id}","collaborators_url":"https://api.github.com/repos/antonionevado/blueoil/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/antonionevado/blueoil/teams","hooks_url":"https://api.github.com/repos/antonionevado/blueoil/hooks","issue_events_url":"https://api.github.com/repos/antonionevado/blueoil/issues/events{/number}","events_url":"https://api.github.com/repos/antonionevado/blueoil/events","assignees_url":"https://api.github.com/repos/antonionevado/blueoil/assignees{/user}","branches_url":"https://api.github.com/repos/antonionevado/blueoil/branches{/branch}","tags_url":"https://api.github.com/repos/antonionevado/blueoil/tags","blobs_url":"https://api.github.com/repos/antonionevado/blueoil/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/antonionevado/blueoil/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/antonionevado/blueoil/git/refs{/sha}","trees_url":"https://api.github.com/repos/antonionevado/blueoil/git/trees{/sha}","statuses_url":"https://api.github.com/repos/antonionevado/blueoil/statuses/{sha}","languages_url":"https://api.github.com/repos/antonionevado/blueoil/languages","stargazers_url":"https://api.github.com/repos/antonionevado/blueoil/stargazers","contributors_url":"https://api.github.com/repos/antonionevado/blueoil/contributors","subscribers_url":"https://api.github.com/repos/antonionevado/blueoil/subscribers","subscription_url":"https://api.github.com/repos/antonionevado/blueoil/subscription","commits_url":"https://api.github.com/repos/antonionevado/blueoil/commits{/sha}","git_commits_url":"https://api.github.com/repos/antonionevado/blueoil/git/commits{/sha}","comments_url":"https://api.github.com/repos/antonionevado/blueoil/comments{/number}","issue_comment_url":"https://api.github.com/repos/antonionevado/blueoil/issues/comments{/number}","contents_url":"https://api.github.com/repos/antonionevado/blueoil/contents/{+path}","compare_url":"https://api.github.com/repos/antonionevado/blueoil/compare/{base}...{head}","merges_url":"https://api.github.com/repos/antonionevado/blueoil/merges","archive_url":"https://api.github.com/repos/antonionevado/blueoil/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/antonionevado/blueoil/downloads","issues_url":"https://api.github.com/repos/antonionevado/blueoil/issues{/number}","pulls_url":"https://api.github.com/repos/antonionevado/blueoil/pulls{/number}","milestones_url":"https://api.github.com/repos/antonionevado/blueoil/milestones{/number}","notifications_url":"https://api.github.com/repos/antonionevado/blueoil/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/antonionevado/blueoil/labels{/name}","releases_url":"https://api.github.com/repos/antonionevado/blueoil/releases{/id}","deployments_url":"https://api.github.com/repos/antonionevado/blueoil/deployments","created_at":"2018-11-29T02:40:21Z","updated_at":"2018-11-29T02:40:26Z","pushed_at":"2018-12-14T01:35:32Z","git_url":"git://github.com/antonionevado/blueoil.git","ssh_url":"git@github.com:antonionevado/blueoil.git","clone_url":"https://github.com/antonionevado/blueoil.git","svn_url":"https://github.com/antonionevado/blueoil","homepage":"https://blue-oil.org","size":186536,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"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","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"blue-oil:master","ref":"master","sha":"f9d6e71067202db062739c96f50e6c30a47cdf42","user":{"login":"blue-oil","id":43470236,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQzNDcwMjM2","avatar_url":"https://avatars2.githubusercontent.com/u/43470236?v=4","gravatar_id":"","url":"https://api.github.com/users/blue-oil","html_url":"https://github.com/blue-oil","followers_url":"https://api.github.com/users/blue-oil/followers","following_url":"https://api.github.com/users/blue-oil/following{/other_user}","gists_url":"https://api.github.com/users/blue-oil/gists{/gist_id}","starred_url":"https://api.github.com/users/blue-oil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blue-oil/subscriptions","organizations_url":"https://api.github.com/users/blue-oil/orgs","repos_url":"https://api.github.com/users/blue-oil/repos","events_url":"https://api.github.com/users/blue-oil/events{/privacy}","received_events_url":"https://api.github.com/users/blue-oil/received_events","type":"Organization","site_admin":false},"repo":{"id":153597157,"node_id":"MDEwOlJlcG9zaXRvcnkxNTM1OTcxNTc=","name":"blueoil","full_name":"blue-oil/blueoil","private":false,"owner":{"login":"blue-oil","id":43470236,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQzNDcwMjM2","avatar_url":"https://avatars2.githubusercontent.com/u/43470236?v=4","gravatar_id":"","url":"https://api.github.com/users/blue-oil","html_url":"https://github.com/blue-oil","followers_url":"https://api.github.com/users/blue-oil/followers","following_url":"https://api.github.com/users/blue-oil/following{/other_user}","gists_url":"https://api.github.com/users/blue-oil/gists{/gist_id}","starred_url":"https://api.github.com/users/blue-oil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blue-oil/subscriptions","organizations_url":"https://api.github.com/users/blue-oil/orgs","repos_url":"https://api.github.com/users/blue-oil/repos","events_url":"https://api.github.com/users/blue-oil/events{/privacy}","received_events_url":"https://api.github.com/users/blue-oil/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/blue-oil/blueoil","description":"Bring Deep Learning to small devices","fork":false,"url":"https://api.github.com/repos/blue-oil/blueoil","forks_url":"https://api.github.com/repos/blue-oil/blueoil/forks","keys_url":"https://api.github.com/repos/blue-oil/blueoil/keys{/key_id}","collaborators_url":"https://api.github.com/repos/blue-oil/blueoil/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/blue-oil/blueoil/teams","hooks_url":"https://api.github.com/repos/blue-oil/blueoil/hooks","issue_events_url":"https://api.github.com/repos/blue-oil/blueoil/issues/events{/number}","events_url":"https://api.github.com/repos/blue-oil/blueoil/events","assignees_url":"https://api.github.com/repos/blue-oil/blueoil/assignees{/user}","branches_url":"https://api.github.com/repos/blue-oil/blueoil/branches{/branch}","tags_url":"https://api.github.com/repos/blue-oil/blueoil/tags","blobs_url":"https://api.github.com/repos/blue-oil/blueoil/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/blue-oil/blueoil/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/blue-oil/blueoil/git/refs{/sha}","trees_url":"https://api.github.com/repos/blue-oil/blueoil/git/trees{/sha}","statuses_url":"https://api.github.com/repos/blue-oil/blueoil/statuses/{sha}","languages_url":"https://api.github.com/repos/blue-oil/blueoil/languages","stargazers_url":"https://api.github.com/repos/blue-oil/blueoil/stargazers","contributors_url":"https://api.github.com/repos/blue-oil/blueoil/contributors","subscribers_url":"https://api.github.com/repos/blue-oil/blueoil/subscribers","subscription_url":"https://api.github.com/repos/blue-oil/blueoil/subscription","commits_url":"https://api.github.com/repos/blue-oil/blueoil/commits{/sha}","git_commits_url":"https://api.github.com/repos/blue-oil/blueoil/git/commits{/sha}","comments_url":"https://api.github.com/repos/blue-oil/blueoil/comments{/number}","issue_comment_url":"https://api.github.com/repos/blue-oil/blueoil/issues/comments{/number}","contents_url":"https://api.github.com/repos/blue-oil/blueoil/contents/{+path}","compare_url":"https://api.github.com/repos/blue-oil/blueoil/compare/{base}...{head}","merges_url":"https://api.github.com/repos/blue-oil/blueoil/merges","archive_url":"https://api.github.com/repos/blue-oil/blueoil/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/blue-oil/blueoil/downloads","issues_url":"https://api.github.com/repos/blue-oil/blueoil/issues{/number}","pulls_url":"https://api.github.com/repos/blue-oil/blueoil/pulls{/number}","milestones_url":"https://api.github.com/repos/blue-oil/blueoil/milestones{/number}","notifications_url":"https://api.github.com/repos/blue-oil/blueoil/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/blue-oil/blueoil/labels{/name}","releases_url":"https://api.github.com/repos/blue-oil/blueoil/releases{/id}","deployments_url":"https://api.github.com/repos/blue-oil/blueoil/deployments","created_at":"2018-10-18T09:19:36Z","updated_at":"2018-12-18T03:16:02Z","pushed_at":"2018-12-18T01:52:33Z","git_url":"git://github.com/blue-oil/blueoil.git","ssh_url":"git@github.com:blue-oil/blueoil.git","clone_url":"https://github.com/blue-oil/blueoil.git","svn_url":"https://github.com/blue-oil/blueoil","homepage":"https://blue-oil.org","size":186565,"stargazers_count":141,"watchers_count":141,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":31,"mirror_url":null,"archived":false,"open_issues_count":42,"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":31,"open_issues":42,"watchers":141,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/blue-oil/blueoil/pulls/53"},"html":{"href":"https://github.com/blue-oil/blueoil/pull/53"},"issue":{"href":"https://api.github.com/repos/blue-oil/blueoil/issues/53"},"comments":{"href":"https://api.github.com/repos/blue-oil/blueoil/issues/53/comments"},"review_comments":{"href":"https://api.github.com/repos/blue-oil/blueoil/pulls/53/comments"},"review_comment":{"href":"https://api.github.com/repos/blue-oil/blueoil/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/blue-oil/blueoil/pulls/53/commits"},"statuses":{"href":"https://api.github.com/repos/blue-oil/blueoil/statuses/2bbfa9cf6b7591ca104f259462a0a119a54faf90"}},"author_association":"NONE"}}
{"actor":{"display_login":"ruimashita"}}