{ "info": { "author": "Reuben John", "author_email": "reubenvjohn@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "![SandB|ox](https://image.ibb.co/bRbfGc/SandBlox.png)\n===\n***Disclaimer**: Sandblox is a work in progress, and so, we describe not only what SandBlox is currently capable of, but also some of it's eventual objectives.*\n\n**What** is it?\n--- \nA software technology framework, library, platform and movement for Machine Learning. \nFundamentally, it introduces a representation for marrying static and dynamic graph based computing with procedural and object oriented programming(yup a lil ambitions), design patterns and standards open a world of possibilities for a vibrant community. \nIt borrows ideas from some of the best frameworks, libraries, and communities that exist today, while contributing novelty of it's own. \n\n**Why** create it?\n---\n1. Modular & Composable\n2. Expressive & Concise\n3. Open Source\n - Package management\n - Sandblox Beach\n - Reusable & Extensible\n - Flexible\n4. Scalable\n5. Standardization\n6. Reproducible\n - Benchmarking\n - Dataset audit\n7. Continuous Integration\n8. Rapid Prototyping\n9. Interoperable: Marries static & dynamic graph based computing\n10. Object Oriented => Modular Inheritance\n11. Multiple Backends\n - Tensorflow\n - PyTorch (work in progress)\n12. Out-of-the-box\n - Logging\n - Saving models\n - Hierarchical graph building inferred from code\n - Tensorboard support\n - Advanced model slicing and dicing, eg: reusing initial layers of another network, transfer-learning, etc\n13. More sweg...\n\nSo you can focus on the core logic, and not about the boiler-plate\n\n**When** will it complete?\n---\nWell, as soon as possible, we're looking for all the help we can get. Besides, it's for the community and so it should be by the community!\n\n**Who**'s it for?\n---\nIn no particular order:\n\nCommunity | Justification\n---|---\nResearch | General Purpose, Expressive, Rapid, Reproducibility, Benchmarking, Backend Invariant\nNewbies | Abstract, Reusability, Package Management\nDevelopers | Package Management, Reusability, Object oriented, Open Source\nCommercial | Scalable, CI, Maintainable, Standardised, Package Management\n\n**How** does it work?\n---\nIt introduces the concept of a block. \nA block is a modular unit of logic that has well defined inputs and well defined outputs. \nA block undergoes a well defined life cycle:\n - Instantiation & configuration\n - Static graph building\n - Dynamic computation\n\nTake for instance the creation of a weird block where we concatenate two arrays, add a bias and then pass it through a fully connected layer:\n\n```python\n@sx.tf_function\ndef foo_block(x, y, bias=tf.constant(.1)):\n concat = tf.concat([x, y], axis=0)\n biased = concat + bias\n return sx.Out.logits(tf.layers.dense(biased, 2)).bias(biased)\n```\n\nBy adding the `@sx.tf_function` decorator, the function is automagically turned into a block.\nThis means that calling this function with parameters will create a new instance of the block.\n\n```python\nblock = foo_block(tf.Variable([[.4, .5]]), tf.placeholder(tf.float32, [None, 2]))\n```\n\nAnd this is where things get interesting. \nSandblox infers what arguments are required to be bound before evaluation.\nIn this case, the second placeholder argument obviously needs to be provided a value for execution to occur. \nProviding this value is as easy as passing it as an argument when running the block as shown below: \n\n```python\nwith tf.Session() as sess:\n sess.run(tf.global_variables_initializer())\n print(block.run([[.3, .3]])) # 2D logits array, and 2D biases array\n```\n\nThe order of the arguments of the run function matches the order of dynamic binding arguments (in this case only 1 such argument).\n\nFurther, the block provides convenient references to it's inputs and outputs. For instance you can evaluate just the outputs like:\n\n```python\nprint(sess.run(block.o.my_logits, feed_dict={block.i.y: [[.3, .3]]}) # 2D logits array\n```\n\nThis means you can safely abstract away logic for creating tensors inside blocks and not loose references to them:\n\n```python\ndef foo_block(x=tf.Variable([[.4, .5]]), input2=tf.placeholder(tf.float32, [None, 2]), bias=tf.constant(.1))\n ...\n```\n\nYou can even create blocks in their own name spaces:\n\n```python\nblock(tf.Variable([[.4, .5]]), ..., props=sx.Props(scope_name='block2'))\n```\n\nIn case of tensorflow, this allows for better organization of your graph, avoiding collision of tensor names and better visualization in tensorboard.\nIn case of tensorflow blocks, you can also explicitly specify props for overriding the session (`session=...`) or graph (`graph=...`) in which to perform the operations, or if you want to make the name scope unique by appending an increment (`make_scope_unique=True`).\n\nIn cases where you want to separate the instantiation stage from the static graph building stage or if you want to access the props during the static evaluation, you can use class inheritance instead of the decorator:\n\n```python\nclass FooBlock(sx.TFFunction):\n def build(self, x, y, bias):\n concat = tf.concat([x, y], axis=0)\n biased = concat + bias\n x = biased\n for _ in range(self.props.num_layers)\n x = tf.layers.dense(x, 2)\n return sx.Out.logits(x).bias(biased)\nblock = FooBlock(num_layers=4)\n...\nblock(tf.Variable([[.4, .5]]), tf.placeholder(tf.float32, [None, 2]))\n...\n```\n\nThis is especially useful if you want to perform some kind of custom initialization:\n\n```python\nclass FooBlock(sx.TFFunction):\n def __init__(self, **props):\n ...\n def build(self, ...):\n ...\n```\n\nClasses also allow you to provide custom dynamic evaluation, allowing you to utilize dynamic compute based libraries such as PyTorch:\n\n```python\nclass FooBlock(sx.TFFunction):\n ...\n def eval(*args, **kwargs):\n result = super(FooBlock, self).eval(*args, **kwargs)\n return result * 2 if result < .5 else resultl\n```\n\nThus by following this well defined design, a lot of things can be provided out-of-the-box, so that you can focus on what's inside the block instead of what's outside block.\n\nSince a block has both a static and dynamic stage, it supports both static and dynamic back-ends. \n**Chaining**: The outputs of one block could be provided as inputs to another. \n**Hierarchies**: One block could be used within another block, i.e. the output block provides it inputs and uses it's outputs. \nImagine blocks that use hierarchies and chaining together!\nFor example, a layer that sequentially applies blocks:\n\n```python\nresult = MySequentialBlock(\n tf.placeholder(...),\n ConvBlock(kernel_size=3),\n DenseBlock(size=5)\n)\nresult.run(...)\n```\n\nImagine building your entire model in an extremely concise, modular and composable fashion:\n\n```\nmodel = Foo(\n Octo(\n Cat( ^---^\n With(...), <{||=- @ @ -=||}>\n Dragon(...), ).-.(\n Wings(...), '/|||\\`\n ), '|` \n LOL(...),\n ),\n Octo(\n Cat(\n Without(...),\n Dragon(...),\n Wings(...)\n )\n ),\n ...\n)\n```\n\n\n**Where** does it apply?\n---\n - Quick and dirty prototype\n - Reusable module to share with community\n - Large models and lots of data scaling across multiple machines and GPU clusters\n - Benchmarking your code against a standard dataset\n - Streamlined project lifecycle from model prototyping and deployment\n - Opensource version-controlled projects\n - R&D and publishing reproducible results\n\nInspiration\n---\n - React\n - Caffe Zoo\n - npm community\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/SandBlox/sandblox", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "sandblox", "package_url": "https://pypi.org/project/sandblox/", "platform": "", "project_url": "https://pypi.org/project/sandblox/", "project_urls": { "Homepage": "https://github.com/SandBlox/sandblox" }, "release_url": "https://pypi.org/project/sandblox/0.1.1/", "requires_dist": [ "tensorflow (<1.11,>=1.8)", "typing (==3.6.6)" ], "requires_python": "", "summary": "Declarative programming framework for graph computing libraries", "version": "0.1.1" }, "last_serial": 4280729, "releases": { "0.1.1": [ { "comment_text": "", "digests": { "md5": "b63cdfb8f0d9692f0eeeb8014f7bdf48", "sha256": "c0e5049e749150b23e291b459c81966e985e6c3a461db9c6bc8aebfe3d72cce3" }, "downloads": -1, "filename": "sandblox-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "b63cdfb8f0d9692f0eeeb8014f7bdf48", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21489, "upload_time": "2018-09-17T20:05:51", "url": "https://files.pythonhosted.org/packages/6f/7a/e42c71926e80c6f5cf21d513d3d24dd56e930335f15487079447d911e8b8/sandblox-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2b8e0e476924b563efe4ee6395636943", "sha256": "2b933a8d9423b255f607792d166add97044dd0f919ba21e501e951f8f2784759" }, "downloads": -1, "filename": "sandblox-0.1.1.tar.gz", "has_sig": false, "md5_digest": "2b8e0e476924b563efe4ee6395636943", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25688, "upload_time": "2018-09-17T20:05:53", "url": "https://files.pythonhosted.org/packages/60/a2/291c2b08f89141534beff96ee2e3e07cd768da74b6739527e45bafef10e0/sandblox-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b63cdfb8f0d9692f0eeeb8014f7bdf48", "sha256": "c0e5049e749150b23e291b459c81966e985e6c3a461db9c6bc8aebfe3d72cce3" }, "downloads": -1, "filename": "sandblox-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "b63cdfb8f0d9692f0eeeb8014f7bdf48", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21489, "upload_time": "2018-09-17T20:05:51", "url": "https://files.pythonhosted.org/packages/6f/7a/e42c71926e80c6f5cf21d513d3d24dd56e930335f15487079447d911e8b8/sandblox-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2b8e0e476924b563efe4ee6395636943", "sha256": "2b933a8d9423b255f607792d166add97044dd0f919ba21e501e951f8f2784759" }, "downloads": -1, "filename": "sandblox-0.1.1.tar.gz", "has_sig": false, "md5_digest": "2b8e0e476924b563efe4ee6395636943", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25688, "upload_time": "2018-09-17T20:05:53", "url": "https://files.pythonhosted.org/packages/60/a2/291c2b08f89141534beff96ee2e3e07cd768da74b6739527e45bafef10e0/sandblox-0.1.1.tar.gz" } ] }