{"id":14970769,"url":"https://github.com/tesserai/tfi","last_synced_at":"2025-09-02T17:37:51.554Z","repository":{"id":57474875,"uuid":"103329709","full_name":"tesserai/tfi","owner":"tesserai","description":"Use any TensorFlow model in a single line of code","archived":false,"fork":false,"pushed_at":"2018-12-22T05:45:46.000Z","size":15328,"stargazers_count":152,"open_issues_count":3,"forks_count":12,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-05T21:37:42.055Z","etag":null,"topics":["machine-learning","python","tensorflow"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tesserai.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-12T23:17:35.000Z","updated_at":"2024-02-06T09:59:35.000Z","dependencies_parsed_at":"2022-09-10T02:22:24.945Z","dependency_job_id":null,"html_url":"https://github.com/tesserai/tfi","commit_stats":null,"previous_names":["ajbouh/tfi"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tesserai%2Ftfi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tesserai%2Ftfi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tesserai%2Ftfi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tesserai%2Ftfi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tesserai","download_url":"https://codeload.github.com/tesserai/tfi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219862886,"owners_count":16555951,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["machine-learning","python","tensorflow"],"created_at":"2024-09-24T13:44:07.039Z","updated_at":"2024-10-11T04:41:54.820Z","avatar_url":"https://github.com/tesserai.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"======================================================\nTFI: Use any TensorFlow model in a single line of code\n======================================================\n\n.. teaser-begin\n\nTFI provides a simple Python interface to any TensorFlow model. It does this by automatically generating a Python class on the fly.\n\n.. -spiel-end-\n\nHere's an example of using TFI with a SavedModel based on `Inception v1 \u003chttps://github.com/tensorflow/models/blob/master/slim/nets/inception_v1.py\u003e`_. This particular SavedModel has a single ``predict`` method and a `SignatureDef \u003chttps://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/protobuf/meta_graph.proto\u003e`_ that looks something like: ``predict(images float \u003c?,224,224,3\u003e) -\u003e (categories string \u003c1001\u003e, scores float \u003c?,1001\u003e)``\n\nTFI in Action\n=============\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import tfi\n   \u003e\u003e\u003e InceptionV1 = tfi.saved_model.as_class(\"./inception_v1.saved_model\")\n\nPassing in data\n===============\n\nTFI can automatically adapt any data you provide to the shape expected by the graph. Let's take a random photo of a dog I found on the internet...\n\n.. image:: https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/dog-medium-landing-hero.ashx\n   :alt: dog\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e model = InceptionV1()\n   \u003e\u003e\u003e image = tfi.data.file(\"./dog-medium-landing-hero.jpg\")\n   \u003e\u003e\u003e result = model.predict(images=[image])\n   \u003e\u003e\u003e categories, scores = result.categories, result.scores[0]\n\nIf we print the top 5 probabilities, we see:\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e [(scores[i], categories[i].decode()) for i in scores.argsort()[:-5:-1]]\n   [(0.80796158, 'beagle'),\n    (0.10305813, 'Walker hound, Walker foxhound'),\n    (0.064740285, 'English foxhound'),\n    (0.009166114, 'basset, basset hound')]\n\nNot bad!\n\nCreating SavedModel files\n=========================\n\nTFI uses the information in a SavedModel's SignatureDefs to automatically generate the proper methods on the resulting class. Method names, keyword argument names, and expected data types are all pulled from the SignatureDef.\n\nIn our example above, we start with a .saved_model we already have on disk. In practice .saved_model files are rare beasts that aren't commonly distributed online.\n\nLuckily, TFI makes it easy to generate a SavedModel on disk. Let's start with a simple example and then graduate to the SavedModel used in the original example.\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import tfi.saved_model, tensorflow as tf\n   \u003e\u003e\u003e class Math(tfi.saved_model.Base):\n   \u003e\u003e\u003e     def __init__(self):\n   \u003e\u003e\u003e         self._x = tf.placeholder(tf.float32)\n   \u003e\u003e\u003e         self._y = tf.placeholder(tf.float32)\n   \u003e\u003e\u003e         self._w = self._x + self._y\n   \u003e\u003e\u003e         self._z = self._x * self._y\n   \u003e\u003e\u003e     def add(self, *, x: self._x, y: self._y) -\u003e {'sum': self._w}:\n   \u003e\u003e\u003e         pass\n   \u003e\u003e\u003e     def mult(self, *, x: self._x, y: self._y) -\u003e {'prod': self._z}:\n   \u003e\u003e\u003e         pass\n   \u003e\u003e\u003e\n   \u003e\u003e\u003e tfi.saved_model.export(\"./math.saved_model\", Math)\n\nTo export a SavedModel in TFI:\n1. Define a class that inherits from ``tfi.saved_model.Base``.\n2. Within ``__init__``, build a graph using placeholders as input. Save inputs and outputs as attributes on self.\n3. Define each method you'd like to be present in the SavedModel as a public instance method.\n4. Call ``tfi.saved_model.export`` with the output path and your class\n\nUsing the resulting model with TFI is straightforward, even on another machine.\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import tfi.saved_model\n   \u003e\u003e\u003e math = tfi.saved_model.as_class(\"./math.saved_model\")()\n   \u003e\u003e\u003e math.add(x=1.0, y=3.0).sum\n   4\n   \u003e\u003e\u003e math.mult(x=1.0, y=3.0).prod\n   3\n\nIf you have trouble with the above, please `file an issue \u003chttps://github.com/ajbouh/tfi/issues/new\u003e`_ and ask for clarification.\n\nNow let's see how this works for a larger model that's also been pre-trained, like Google's slim implementation of Inception v1.\n\nThe code below is spiritually equivalent to the ``Math`` example above: define a class that inherits from ``tfi.saved_model.Base``, build the graph and load a checkpoint in ``__init__``, add any instance methods you want, and export.\n\nHere's a `gist of the code below \u003chttps://gist.github.com/ajbouh/2b1d076f4af569edeeab819a39184abf\u003e`_, if that's easier to read.\n\nFirst, let's get the Python code for Inception v1 and put it on ``PYTHONPATH``.\n\n.. code-block:: bash\n\n   $ git clone https://github.com/tensorflow/models\n   $ export PYTHONPATH=$PWD/models/research/slim\n\n\n.. code-block:: python\n\n   from datasets import dataset_factory\n   from nets import nets_factory\n   import os.path\n   import tensorflow as tf\n   import tfi\n   from urllib.request import urlretrieve\n\n   CHECKPOINT_URL = \"http://download.tensorflow.org/models/inception_v1_2016_08_28.tar.gz\"\n   CHECKPOINT_FILE = \"inception_v1.ckpt\"\n   CHECKPOINT_SHA256 = \"7a620c430fcaba8f8f716241f5148c4c47c035cce4e49ef02cfbe6cd1adf96a6\"\n\n   class InceptionV1(tfi.saved_model.Base):\n       def __init__(self):\n         dataset = dataset_factory.get_dataset('imagenet', 'train', '')\n         category_items = list(dataset.labels_to_names.items())\n         category_items.sort() # sort by index\n         categories = [label for _, label in category_items]\n         self._labels = tf.constant(categories)\n\n         network_fn = nets_factory.get_network_fn(\n             'inception_v1',\n             num_classes=len(categories),\n             is_training=False)\n\n         image_size = network_fn.default_image_size\n         self._placeholder = tf.placeholder(\n                 name='input',\n                 dtype=tf.float32,\n                 shape=[None, image_size, image_size, 3])\n\n         logits, _ = network_fn(self._placeholder)\n         self._scores = tf.nn.softmax(logits)\n         tfi.checkpoint.restore(CHECKPOINT_FILE)\n\n       def predict(self, *, images: self._placeholder) -\u003e {\n             'scores': self._scores,\n             'categories': self._labels,\n          }:\n          pass\n\n   # Lazily download checkpoint file and verify its digest.\n   if not os.path.exists(CHECKPOINT_FILE):\n     import hashlib\n     import tarfile\n\n     downloaded = urlretrieve(CHECKPOINT_URL)[0]\n     def sha256(filename, blocksize=65536):\n         hash = hashlib.sha256()\n         with open(filename, \"rb\") as f:\n             for block in iter(lambda: f.read(blocksize), b\"\"):\n                 hash.update(block)\n         return hash.hexdigest()\n     s = sha256(downloaded)\n     if s != CHECKPOINT_SHA256:\n       print(\"invalid fetch of\", CHECKPOINT_URL, s, \"!=\", CHECKPOINT_SHA256)\n       exit(1)\n     with tarfile.open(downloaded, 'r|gz') as tar:\n       tar.extractall()\n\n   # Do the actual export!\n   tfi.saved_model.export(\"./inception_v1.saved_model\", InceptionV1)\n\n\nImage data\n==========\nThe ``tf.data.file`` function uses `mimetypes \u003chttps://docs.python.org/3.6/library/mimetypes.html\u003e`_ to discover the right data decoder to use. If an input to a graph is an ``\"image/*\"``, TFI will automatically decode and resize the image to the proper size. In the example above, the JPEG image of a dog is automatically decoded and resized to 224x224.\n\nBatches\n=======\nIf you look closely at the example code above, you'll see that the images argument is actually an array. The class generated by TFI is smart enough to convert an array of images to an appropriately sized batch of Tensors.\n\nGraphs with variables\n=====================\nEach instance of the class has separate variables from other instances. If a graph's variables are mutated during a session in a useful way, you can continue to use those mutations by calling methods again on that same instance.\n\nIf you'd like to have multiple instances that do not interfere with one another, you can create a second instance and call methods on each of them separately.\n\nGetting Started\n===============\n`TFI is on PyPI \u003chttps://pypi.python.org/pypi/tfi\u003e`_, install it with ``pip install tfi``.\n\nFuture work\n===========\n\nAdapting ``tfi.data`` functions to handle queues and datasets wouldn't require much effort. If this is something you'd like me to do, please `file an issue \u003chttps://github.com/ajbouh/tfi/issues/new\u003e`_ with your specific use case!\n\nExtending `tfi.data` to support more formats is also quite straightforward. `File an issue \u003chttps://github.com/ajbouh/tfi/issues/new\u003e`_ with a specific format you'd like to see. For bonus points, include the expected tensor dtype and shape. For double bonus points, include a way for me to test it in a real model.\n\nAcknowledgements\n================\nIf you're curious, the photo used above was from `a random Google image search \u003chttps://goo.gl/images/UNNf2W\u003e`_.\n\nPyPI packaging was way easier because of `this fantastic guide \u003chttps://hynek.me/articles/sharing-your-labor-of-love-pypi-quick-and-dirty/\u003e`_.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftesserai%2Ftfi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftesserai%2Ftfi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftesserai%2Ftfi/lists"}