{"id":14959141,"url":"https://github.com/lizhaoliu/tensorflow_snippets","last_synced_at":"2025-05-02T12:31:46.047Z","repository":{"id":89222484,"uuid":"106587134","full_name":"lizhaoliu/tensorflow_snippets","owner":"lizhaoliu","description":null,"archived":false,"fork":false,"pushed_at":"2019-10-17T15:14:26.000Z","size":57,"stargazers_count":97,"open_issues_count":0,"forks_count":22,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-07T02:05:57.307Z","etag":null,"topics":["python","tensorflow","tensorflow-tutorial"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lizhaoliu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-11T17:32:55.000Z","updated_at":"2024-09-05T11:34:16.000Z","dependencies_parsed_at":"2023-06-14T12:00:14.055Z","dependency_job_id":null,"html_url":"https://github.com/lizhaoliu/tensorflow_snippets","commit_stats":{"total_commits":25,"total_committers":1,"mean_commits":25.0,"dds":0.0,"last_synced_commit":"6a1992717ea4a66ead68f4be20701d2d03809330"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lizhaoliu%2Ftensorflow_snippets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lizhaoliu%2Ftensorflow_snippets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lizhaoliu%2Ftensorflow_snippets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lizhaoliu%2Ftensorflow_snippets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lizhaoliu","download_url":"https://codeload.github.com/lizhaoliu/tensorflow_snippets/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252038196,"owners_count":21684646,"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":["python","tensorflow","tensorflow-tutorial"],"created_at":"2024-09-24T13:18:54.948Z","updated_at":"2025-05-02T12:31:44.533Z","avatar_url":"https://github.com/lizhaoliu.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tensorflow Snippets From the Field.\n\n## Table of Contents\n- [System Setup](#system-setup)\n- [On Convolutions](#on-convolutions)\n- [Indexing](#indexing)\n- [Numerical Stability](#numerical-stability)\n- [Shapes](#shapes)\n- [Tensor Contraction (More Generalized Matrix Multiplication)](#tensor-contraction-more-generalized-matrix-multiplication)\n- [```tf.estimator``` API](#tfestimator-api)\n- [Load A saved_model and Run Inference (in Python)](#load-a-saved_model-and-run-inference-in-python)\n- [Input Features! ```tf.train.Example``` and ```tf.train.SequenceExample```](#input-features-tftrainexample-and-tftrainsequenceexample)\n- [Misc](#misc)\n\n#### System Setup\n- Install CUDA 10.0 on Ubuntu 18.04 LTS GPU server:\n```sh\n# 1. Install NVIDIA driver either through \"Additional Drivers\", or:\n$ sudo apt install --no-install-recommends nvidia-driver-430\n# Reboot and then check that GPUs are visible using the command: nvidia-smi.\n\n# 2. Add NVIDIA package repositories\n$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-repo-ubuntu1804_10.0.130-1_amd64.deb\n$ sudo dpkg -i cuda-repo-ubuntu1804_10.0.130-1_amd64.deb\n$ sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub\n$ sudo apt update\n$ wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb\n$ sudo apt install ./nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb\n$ sudo apt update\n\n# 3. Install development and runtime libraries.\n$ sudo apt install --no-install-recommends \\\n    cuda-10-0 \\\n    libcudnn7=7.6.2.24-1+cuda10.0  \\\n    libcudnn7-dev=7.6.2.24-1+cuda10.0\n\n# 4. Install TensorRT. Requires that libcudnn7 is installed above.\n$ sudo apt install -y --no-install-recommends libnvinfer5=5.1.5-1+cuda10.0 \\\n    libnvinfer-dev=5.1.5-1+cuda10.0\n```\n- Install Tensorflow 2.0 GPU version:\n```sh\n$ python3 -m pip install --upgrade pip\n$ python3 -m pip install --user tensorflow-gpu\n```\n\n- Setup SSH server on GPU server:\n  * Install OpenSSH server: `$ sudo apt install openssh-server`.\n  * Add port forwarding rule for port 22.\n  \n- Setup SSH client on our ultra book:\n  * Create SSH key: `$ ssh-keygen -t rsa -b 4096`.\n  * Install SSH key on the GPU server as an authorized key: `$ ssh-id-copy \u003cuser\u003e@\u003cserver-ip\u003e`.\n  * Now we can connect to the GPU server by: `$ ssh -i \u003cssh-key\u003e \u003cuser\u003e@\u003cserver-ip\u003e`.\n  \n- Add [PyCharm remote Python interpreter](https://www.jetbrains.com/help/pycharm/configuring-remote-interpreters-via-ssh.html) on GPU server via SSH.\n\n- Happy machine learning!\n\n#### On Convolutions\n- Typically there are two options for ```padding```:\n  * ```SAME```: Make sure result has *same* spatial shape as input tensor, this often requires padding 0's to input tensor.\n  * ```VALID```: No paddings please, only use *valid* points . Result can have different spatial shape.\n- Tensorflow by default performs *centered* convolution (kernel is centered around current point). With ```k```: kernel size, ```d```: dilation rate, then extended kernel size ```k' = d * (k - 1) + 1```. For each spatial dimension, convolution at index ```i``` is computed using points between indices (inclusive) ```[i - (k' - 1) // 2, i + k' // 2]```. \n- *Causal* convolution uses points between indices ```[i - d * (k - 1), i]```, a simple solution is to pad ```d * (k - 1)``` of 0's at the beginning of that dimension then perform a normal convolution with ```VALID``` padding.\n- Convolution kernel has shape ```[spatial_dim[0], ..., spatial_dim[n - 1], num_input_channels, num_output_channels]```. For each output channel ```k```, ```output[..., k] = sum_over_i {input[..., i] * kernel[..., i, k]}```, here ```*``` is convolution operator.\n\n#### Indexing\n- ```tf.gather_nd(params, indices)``` retrieves slices from ```params``` by ```indices```. The rule is simple: *only the last dimension of ```indices``` does slice ```params```, and that dimension is \"replaced\" with those slices*. It's easy to see that:\n  * ```indices.shape[-1] \u003c= rank(params)```: The last dimension of ```indices``` must be no greater than the rank of ```params```.\n  * Result tensor shape is ```indices.shape[:-1] + params.shape[indices.shape[-1]:]```, example:\n  ```python\n  # params has shape [4, 5, 6].\n  params = tf.reshape(tf.range(0, 120), [4, 5, 6])\n  # indices has shape [3, 2].\n  indices = tf.constant([[2, 3], [0, 1], [1, 2]], dtype=tf.int32)\n  # slices has shape [3, 6].\n  slices = tf.gather_nd(params, indices)\n  ```\n- ```tf.gather_nd``` and Numpy fancy indexing: ```x[indices]``` == ```tf.gather_nd(x, zip(*indices))```; ```tf.gather_nd(x, indices)``` == ```x[zip(*indices)]```. Where ```x``` is Numpy array and ```indices``` is indexing array (dim \u003e 1).\n\n#### Numerical Stability\n- ```Inf``` morphs to ```NaN``` while plugged into back-prop (chain rule).\n- Watch out! ```tf.where``` Can Spawn NaN in Gradients\nIf either branch in ```tf.where``` contains Inf/NaN then it produces NaN in gradients, e.g.:\n```python\nlog_s = tf.constant([-100., 100.], dtype=tf.float32)\n# Computes 1.0 / exp(log_s), in a numerically robust way.\ninv_s = tf.where(log_s \u003e= 0.,\n                 tf.exp(-log_s),  # Creates Inf when -log_s is large.\n                 1. / (tf.exp(log_s) + 1e-6))  # tf.exp(log_s) is Inf with large log_s.\ngrad_log_s = tf.gradients(inv_s, [log_s])\nwith tf.Session() as sess:\n    inv_s, grad_log_s = sess.run([inv_s, grad_log_s])\n    print(inv_s)  # [  1.00000000e+06   3.78350585e-44]\n    print(grad_log_s)  # [array([ nan,  nan], dtype=float32)]\n```\n\n#### Shapes\n- ```tensor.shape``` returns tensor's static shape, while the graph is being built.\n- ```tensor.shape.as_list()``` returns the static shape as a integer list.\n- ```tensor.shape[i].value``` returns the static shape's i-th dimension size as an integer.\n- ```tf.shape(t)``` returns t's run-time shape as a tensor.\n- An example:\n```python\nx = tf.placeholder(tf.float32, shape=[None, 8]) # x shape is non-deterministic while building the graph.\nprint(x.shape) # Outputs static shape (?, 8).\nshape_t = tf.shape(x)\nwith tf.Session() as sess:\n    print(sess.run(shape_t, feed_dict={x: np.random.random(size=[4, 8])})) # Outputs run-time shape (4, 8).\n```\n- [] (empty square brackets) as a shape denotes a scalar (0 dim). E.g. tf.FixedLenFeature([], ..) is a scalar feature.\n- Broadcasting on two arrays starts with the _trailing_ dimensions, and works its way _backward_ to the leading dimensions. E.g. \n```\nA      (4d array):  8 x 1 x 6 x 1\nB      (3d array):      7 x 1 x 5\nResult (4d array):  8 x 7 x 6 x 5\n```\n\n#### Tensor Contraction (More Generalized Matrix Multiplication)\n```python\n# Matrix multiplication\ntf.einsum('ij,jk-\u003eik', m0, m1)  # output[i, k] = sum_j m0[i, j] * m1[j, k]\n# Dot product\ntf.einsum('i,i-\u003e', u, v)  # output = sum_i u[i]*v[i]\n# Outer product\ntf.einsum('i,j-\u003eij', u, v)  # output[i, j] = u[i]*v[j]\n# Transpose\ntf.einsum('ij-\u003eji', m)  # output[j, i] = m[i,j]\n# Batch matrix multiplication\ntf.einsum('aij,jk-\u003eaik', s, t)  # out[a, i, k] = sum_j s[a, i, j] * t[j, k]\n# Batch tensor contraction\ntf.einsum('nhwc,nwcd-\u003enhd', s, t)  # out[n, h, d] = sum_w_c s[n, h, w, c] * t[n, w, c, d]\n```\n\n#### ```tf.estimator``` API\n- A typical input_fn (used for train/eval) for tf.estimator API:\n```python\ndef make_input_fn(mode, ...):\n    \"\"\"Return input_fn for train/eval in tf.estimator API.\n\n    Args:\n        mode: Must be tf.estimator.ModeKeys.TRAIN or tf.estimator.ModeKeys.EVAL.\n        ...\n    Returns:\n        The input_fn.\n    \"\"\"\n    def _input_fn():\n        \"\"\"The input function.\n\n        Returns:\n            features: A dict of {'feature_name': feature_tensor}.\n            labels: A tensor of labels.\n        \"\"\"\n        if mode == tf.estimator.ModeKeys.TRAIN:\n            features = ...\n            labels = ...\n        elif mode == tf.estimator.ModeKeys.EVAL:\n            features = ...\n            labels = ...\n        else:\n            raise ValueError(mode)\n        return features, labels\n\n    return _input_fn\n```\n\n- A typical model_fn for tf.estimator API:\n```python\ndef make_model_fn(...):\n    \"\"\"Return model_fn to build a tf.estimator.Estimator.\n\n    Args:\n        ...\n    Returns:\n        The model_fn.\n    \"\"\"\n    def _model_fn(features, labels, mode):\n        \"\"\"Model function.\n\n        Args:\n            features: The first item returned from the input_fn for train/eval, a dict of {'feature_name': feature_tensor}. If mode is ModeKeys.PREDICT, same as in serving_input_receiver_fn.\n            labels: The second item returned from the input_fn, a single Tensor or dict. If mode is ModeKeys.PREDICT, labels=None will be passed.\n            mode: Optional. Specifies if this training, evaluation or prediction. See ModeKeys.\n        \"\"\"\n        if mode == tf.estimator.ModeKeys.PREDICT:\n            # Calculate the predictions.\n            predictions = ...\n            # For inference/prediction outputs.\n            export_outputs = {\n                tf.saved_model.signature_constants.PREDICT_METHOD_NAME: tf.estimator.export.PredictOutput({\n                    'output_1': predict_output_1,\n                    'output_2': predict_output_2,\n                    ...\n                }),\n            }\n            ...\n        else:\n            predictions = None\n            export_outputs = None\n\n        if (mode == tf.estimator.ModeKeys.TRAIN or mode == tf.estimator.ModeKeys.EVAL):\n            loss = ...\n        else:\n            loss = None\n\n        if mode == tf.estimator.ModeKeys.TRAIN:\n            train_op = ...\n            # Can use tf.group(..) to group multiple train_op as a single train_op.\n        else:\n            train_op = None\n\n        return tf.estimator.EstimatorSpec(\n            mode=mode,\n            predictions=predictions,\n            loss=loss,\n            train_op=train_op,\n            export_outputs=export_outputs)\n\n    return _model_fn\n```\n\n- Use tf.estimator.Estimator to export a saved_model:\n```python\n# serving_features must match features in model_fn when mode == tf.estimator.ModeKeys.PREDICT.\nserving_features = {'serving_input_1': tf.placeholder(...), 'serving_input_2': tf.placeholder(...), ...}\nestimator.export_savedmodel(export_dir,\n                            tf.estimator.export.build_raw_serving_input_receiver_fn(serving_features))\n```\n\n- Use tf.contrib.learn.Experiment to export a saved_model:\n```python\n# serving_features must match features in model_fn when mode == tf.estimator.ModeKeys.PREDICT.\nserving_features = {'serving_input_1': tf.placeholder(...), 'serving_input_2': tf.placeholder(...), ...}\nexport_strategy = tf.contrib.learn.utils.make_export_strategy(tf.estimator.export.build_raw_serving_input_receiver_fn(serving_features))\nexpriment = tf.contrib.learn.Experiment(..., export_strategies=[export_strategy], ...)\n```\n\n#### Load A saved_model and Run Inference (in Python)\n```python\nwith tf.Session(...) as sess:\n    # Load saved_model MetaGraphDef from export_dir.\n    meta_graph_def = tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.SERVING], export_dir)\n\n    # Get SignatureDef for serving (here PREDICT_METHOD_NAME is used as export_outputs key in model_fn).\n    sigs = meta_graph_def.signature_def[tf.saved_model.signature_constants.PREDICT_METHOD_NAME]\n\n    # Get the graph for retrieving input/output tensors.\n    g = tf.get_default_graph()\n\n    # Retrieve serving input tensors, keys must match keys defined in serving_features (when building input receiver fn).\n    input_1 = g.get_tensor_by_name(sigs.inputs['input_1'].name)\n    input_2 = g.get_tensor_by_name(sigs.inputs['input_2'].name)\n    ...\n\n    # Retrieve serving output tensors, keys must match keys defined in ExportOutput (e.g. PredictOutput) in export_outputs.\n    output_1 = g.get_tensor_by_name(sigs.outputs['output_1'].name)\n    output_2 = g.get_tensor_by_name(sigs.outputs['output_2'].name)\n    ...\n\n    # Run inferences.\n    outputs_values = sess.run([output_1, output_2, ...], feed_dict={input_1: ..., input_2: ..., ...})\n```\n\n#### Input Features! ```tf.train.Example``` and ```tf.train.SequenceExample```\n- A [tf.train.Example](https://github.com/tensorflow/tensorflow/blob/r1.3/tensorflow/core/example/example.proto#L88) is roughly a map of *{feature_name: value_list}*.\n- A [tf.train.SequenceExample](https://github.com/tensorflow/tensorflow/blob/r1.3/tensorflow/core/example/example.proto#L292) is roughly a ```tf.train.Example``` plus a map of *{feature_name: list_of_value_lists}*.\n- Build a tf.train.Example in Python:\n```python\n# ==================== Build in one line ====================\nexample = tf.train.Example(features=tf.train.Features(feature={\n    'bytes_values': tf.train.Feature(\n        bytes_list=tf.train.BytesList(value=[bytes_feature])),\n    'float_values': tf.train.Feature(\n        float_list=tf.train.FloatList(value=[float_feature])),\n    'int64_values': tf.train.Feature(\n        int64_list=tf.train.Int64List(value=[int64_feature])),\n    ...\n}))\n# ==================== OR progressivly ====================\nexample = tf.train.Example()\nexample.features.feature['bytes_feature'].bytes_list.value.extend(bytes_values)\nexample.features.feature['float_feature'].float_list.value.extend(float_values)\nexample.features.feature['int64_feature'].int64_list.value.extend(int64_values)\n...\n```\n- Build a tf.train.SequenceExample in Python:\n```python\nsequence_example = tf.train.SequenceExample()\n\n# Populate context data.\nsequence_example.context.feature[\n    'context_bytes_values_1'].bytes_list.value.extend(bytes_values)\nsequence_example.context.feature[\n    'context_float_values_1'].float_list.value.extend(float_values)\nsequence_example.context.feature[\n    'context_int64_values_1'].int64_list.value.extend(int64_values)\n...\n\n# Populate sequence data.\nfeature_list_1 = sequence_example.feature_lists.feature_list['feature_list_1']\n# Add tf.train.Feature to feature_list_1.\nfeature_1 = feature_list_1.feature.add()\n# Populate feature_1, e.g. feature_1.float_list.value.extend(float_values)\n# Add tf.train.Feature to feature_list_1, if any.\n...\n```\n\n- To parse a SequenceExample:\n```python\ntf.parse_single_sequence_example(serialized,\n    context_features={\n        'context_feature_1': tf.FixedLenFeature([], dtype=...),\n        ...\n    },\n    sequence_features={\n        # For 'sequence_features_1' shape, [] results with [?] and [k] results with [?, k], where:\n        # ?: timesteps, i.e. number of tf.Train.Feature in 'sequence_features_1' list, can be variable.\n        # k: number of elements in each tf.Train.Feature in 'sequence_features_1'.\n        'sequence_features_1': tf.FixedLenSequenceFeature([], dtype=...),\n        ...\n    },)\n```\n\n- Write tfrecords to sharded files. Reading data from multiple input files can increase I/O throughput in TF:\n```python\nimport multiprocessing\nfrom concurrent import futures\n\ndef write_tf_records(file_path, tf_records):\n    \"\"\"Writes TFRecord (Example or SequenceExample) data to output file.\n\n    :param file_path: the full output file path, can add `@N` at the end that\n        specifies total number of shards, e.g. /data/training.tfrecords@10.\n    :param tf_records: a list or tuple of `tf.train.Example` or\n        `tf.train.SequenceExample` instances.\n    \"\"\"\n\n    def _write_data_to_file(file_path, tf_records):\n        \"\"\"Writes data into specified output file path.\n\n        :param file_path: full path of output file.\n        :param tf_records: a list of Example or SequenceExample instances.\n        \"\"\"\n        with tf.python_io.TFRecordWriter(file_path) as writer:\n            for tf_record in tf_records:\n                writer.write(tf_record.SerializeToString())\n\n    def _get_shards_paths(file_path):\n        \"\"\"Gets (shard) file paths by parsing from provided file path.\n\n        :param file_path: file path that may contain shard syntax \"@N\".\n        :return: a list of file paths.\n        \"\"\"\n        shard_char_idx = file_path.rfind('@')\n\n        # No shards specified.\n        if shard_char_idx == -1:\n            return [file_path]\n\n        num_shards = int(file_path[shard_char_idx + 1:])\n        if num_shards \u003c= 0:\n            raise ValueError('Number of shards must be a positive integer.')\n        prefix = file_path[:shard_char_idx]\n        return ['{}-{}-of-{}'.format(prefix, i, num_shards) for i\n                in range(num_shards)]\n\n    if not isinstance(tf_records, list) and not isinstance(tf_records, tuple):\n        raise TypeError('tf_records must be a list or tuple.')\n\n    tf_records = list(tf_records)\n    shards_paths = _get_shards_paths(file_path)\n\n    if len(shards_paths) \u003e len(tf_records):\n        raise ValueError('More data than file shards.')\n\n    with futures.ThreadPoolExecutor(\n            max_workers=multiprocessing.cpu_count() - 1) as executor:\n        for shard_id, file_path in enumerate(shards_paths):\n            executor.submit(_write_data_to_file, file_path,\n                            tf_records[shard_id::len(shards_paths)])\n```\n\n#### Misc\n- Don't Forget to Reset Default Graph in Jupyter Notebook\nIf you forgot to reset default Tensorflow graph (or create a new graph) in a Jupyter notebook cell, and run that cell for a few times then you may get weird results.\n- Visualize Tensorflow Graph in Jupyter Notebook\n```python\nimport numpy as np\nfrom IPython import display\n\ndef strip_consts(graph_def, max_const_size=32):\n    \"\"\"Strip large constant values from graph_def.\"\"\"\n    strip_def = tf.GraphDef()\n    for n0 in graph_def.node:\n        n = strip_def.node.add()\n        n.MergeFrom(n0)\n        if n.op == 'Const':\n            tensor = n.attr['value'].tensor\n            size = len(tensor.tensor_content)\n            if size \u003e max_const_size:\n                tensor.tensor_content = \"\u003cstripped {} bytes\u003e\".format(size)\n    return strip_def\n\n\ndef show_graph(graph_def, max_const_size=32):\n    \"\"\"Visualize TensorFlow graph.\"\"\"\n    if hasattr(graph_def, 'as_graph_def'):\n        graph_def = graph_def.as_graph_def()\n    strip_def = strip_consts(graph_def, max_const_size=max_const_size)\n    code = \"\"\"\n        \u003cscript\u003e\n          function load() {{\n            document.getElementById(\"{id}\").pbtxt = {data};\n          }}\n        \u003c/script\u003e\n        \u003clink rel=\"import\" href=\"https://tensorboard.appspot.com/tf-graph\n        -basic.build.html\" onload=load()\u003e\n        \u003cdiv style=\"height:600px\"\u003e\n          \u003ctf-graph-basic id=\"{id}\"\u003e\u003c/tf-graph-basic\u003e\n        \u003c/div\u003e\n    \"\"\".format(data=repr(str(strip_def)), id='graph' + str(np.random.rand()))\n\n    iframe = \"\"\"\n        \u003ciframe seamless style=\"width:1200px;height:620px;border:0\" srcdoc=\"{}\"\u003e\u003c/iframe\u003e\n    \"\"\".format(code.replace('\"', '\u0026quot;'))\n    display.display(display.HTML(iframe))\n```\nThen call ```show_graph(tf.get_default_graph())``` to show in your Jupyter/IPython notebook.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flizhaoliu%2Ftensorflow_snippets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flizhaoliu%2Ftensorflow_snippets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flizhaoliu%2Ftensorflow_snippets/lists"}