{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<br>\n\n\n<br>\n\n<div style=\"background-color: #0F092D; padding: 20px 0;\">\n    <h2 style=\"text-align: center; font-family: Verdana; font-size: 32px; font-style: normal; font-weight: bold; text-transform: none; letter-spacing: 2px; color: #FC796D; background-color: #0F092D; font-variant: small-caps;\">\n      <center><img style=\"padding: 20px 0 0 0;\" src=\"https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png\" alt=\"Google Logo\"></center><br>Isolated Sign Language Recognition<br><br><span style = \"font-size: 20px; color: white;\">HOW TO SUBMIT!</span></h2>\n    \n  <center><img src=\"https://cdn-cbkob.nitrocdn.com/TiGMibPGMREAJjbFYNLfxxdkUjUGroSw/assets/images/optimized/rev-22fc791/wp-content/uploads/2022/12/sign-language.jpg\" width=100% alt=\"asl banner\"></center>\n<h5 style=\"text-align: center; font-family: Verdana; font-size: 12px; font-style: normal; font-weight: bold; text-decoration: None; text-transform: none; letter-spacing: 1px; color: white;\">CREATED BY:  DARIEN SCHETTLER</h5><br>\n\n</div>\n\n<br><br>\n\n\n\n<br>\n\n---\n\n<br>\n\n<center><div class=\"alert alert-block alert-danger\" style=\"margin: 2em; line-height: 1.7em; font-family: Verdana;\">\n    <b style=\"font-size: 18px;\">🛑 &nbsp; WARNING:</b><br><br><b>THIS IS A WORK IN PROGRESS</b><br>\n</div></center>\n\n\n<center><div class=\"alert alert-block alert-warning\" style=\"margin: 2em; line-height: 1.7em; font-family: Verdana;\">\n    <b style=\"font-size: 18px;\">👏 &nbsp; IF YOU FORK THIS OR FIND THIS HELPFUL &nbsp; 👏</b><br><br><b style=\"font-size: 22px; color: darkorange\">PLEASE UPVOTE!</b><br><br>This was a lot of work for me and while it may seem silly, it makes me feel appreciated when others like my work. 😅\n</div></center>","metadata":{}},{"cell_type":"markdown","source":"<br>\n\n<b>In this notebook we will make a simple – <u>untrained</u> – <code>tf.keras</code> model that we will convert into tflite to show how to make a submission.</b>\n\n<br>\n\nThe following is some details about Tensorflow Lite and the conversion process:\n\n<br>\n\n---\n\n<a id=\"tensorflow\"></a><br><b style=\"text-decoration: underline; font-family: Verdana; font-size: 120%; text-transform: uppercase;\">TensorFlow Lite</b>\n\n<a id=\"tensorflow_definition\"></a><br>\n\n<b>Textbook Definition (Key Points) <a href=\"https://www.tensorflow.org/lite/guide\">[REF]</a></b>\n\n\n<ul><li>TensorFlow Lite is a lightweight, open-source machine learning framework developed by Google for mobile and embedded devices.</li>\n<li>It is designed to run models on mobile devices with low-latency, using a variety of hardware accelerators.</li>\n<li>TensorFlow Lite supports a variety of model formats, including TensorFlow, Keras, and other popular machine learning frameworks.</li>\n<li>TensorFlow Lite provides optimized on-device machine learning by addressing key constraints such as latency, privacy, size, and power consumption, and supports multiple platforms and diverse languages.</li>\n<li>TensorFlow Lite Key Features<ul>\n    <li>Optimized for on-device machine learning, by addressing 5 key constraints: latency (there's no round-trip to a server), privacy (no personal data leaves the device), connectivity (internet connectivity is not required), size (reduced model and binary size) and power consumption (efficient inference and a lack of network connections).</li>\n    <li>Multiple platform support, covering Android and iOS devices, embedded Linux, and microcontrollers.</li>\n    <li>Diverse language support, which includes Java, Swift, Objective-C, C++, and Python.\n        High performance, with hardware acceleration and model optimization.</li>\n    <li>End-to-end examples, for common machine learning tasks such as image classification, object detection, pose estimation, question answering, text classification, etc. on multiple platforms.</li>\n</ul></li>\n<li>Most of our training in this competition will likely not be done in TFLite. Instead, we will likely create and train our models in TensorFlow's core frameworks and convert it to TFLite. TensorFlow has a conversion system that shows how to convert any TensorFlow model to TFLite. See this <a href=\"https://www.kaggle.com/competitions/asl-signs/discussion/390182\"><b>Kaggle discussion post</b></a> for more information.<b><a href=\"https://www.tensorflow.org/lite/models/convert/\"> [TF REF]</a></b></li>\n\n</ul>\n\n\n<a id=\"tensorflow_eli5\"></a><br>\n\n<b>ELI5 Competition Definition</b>\n\nTensorFlow Lite is a specialized version of TensorFlow, a powerful machine learning framework that has been optimized for running on mobile and embedded devices. It allows us to run our models on a variety of devices, including smartphones and tablets, and provides fast, low-latency performance.\n\n<br><a id=\"tensorflow_visual\"></a><b>Explain With Pictures</b>\n\n<b><sub>TF Model Conversion Workflow</sub></b>\n\n<img src=\"https://www.tensorflow.org/lite/images/convert/convert.png\" width=67%>\n\n<br>\n\n---","metadata":{}},{"cell_type":"code","source":"###############################################\n########        Step 0 – Imports        #######\n###############################################\nimport tensorflow as tf\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport json\nimport os\n\n\n###############################################\n########         Step 1 – Setup         #######\n###############################################\ndef read_json_file(file_path):\n    with open(file_path, 'r') as file:\n        return json.load(file)\n    \nDATA_DIR = \"/kaggle/input/asl-signs\"\ntrain_df = pd.read_csv(os.path.join(DATA_DIR, \"train.csv\"))\ns2p_map  = {k.lower():v for k,v in read_json_file(os.path.join(DATA_DIR, \"sign_to_prediction_index_map.json\")).items()}\np2s_map  = {v:k for k,v in read_json_file(os.path.join(DATA_DIR, \"sign_to_prediction_index_map.json\")).items()}\nencoder  = lambda x: s2p_map.get(x.lower())\ndecoder  = lambda x: p2s_map.get(x)\n\ntrain_df[\"path\"] = DATA_DIR+\"/\"+train_df[\"path\"]\ndisplay(train_df)\n\nROWS_PER_FRAME = 543  # number of landmarks per frame\nINPUT_SHAPE = (543,3) # ...reshape(n_frames, ROWS_PER_FRAME, len(data_columns))\nN_LABELS = 250        # train_df.sign.nunique()\n\n\n###############################################\n###      Step 2 – Host Provided Load Fn     ###\n###############################################\n\ndef load_relevant_data_subset(pq_path):\n    data_columns = ['x', 'y', 'z']\n    data = pd.read_parquet(pq_path, columns=data_columns)\n    n_frames = int(len(data) / ROWS_PER_FRAME)\n    data = data.values.reshape(n_frames, ROWS_PER_FRAME, len(data_columns))\n    return data.astype(np.float32)\n\n\n###############################################\n###        Step 3 – Model Creation Fn       ###\n###############################################\n\ndef get_tf_keras_model(optimizer=\"adam\", loss=\"sparse_categorical_crossentropy\"):\n    \"\"\" Basic model creation fn with NaN handling \"\"\"\n    \n    # (batch_size, n_landmarks, n_coords)\n    _inputs = tf.keras.layers.Input(shape=INPUT_SHAPE, name=\"inputs\") \n    \n    # Replace all nan with 0\n    x = tf.keras.layers.Lambda(\n        lambda _x: tf.where(tf.math.is_nan(_x), tf.zeros_like(_x), _x), name=\"nan_to_zero\",\n    )(_inputs)\n    \n    # Flatten all data points and reduce 'batch_dim' (which is actually frame_dim)\n    # to 1 via averaging --> yields (1, n_landmarks*n_coords)\n    x = tf.keras.layers.Lambda(\n       lambda _x:  tf.reshape(tf.reduce_mean(_x, axis=0), \n                              (1, INPUT_SHAPE[0]*INPUT_SHAPE[1])), \n        name=\"flatten_all\",\n    )(x)\n    \n    # (1, n_labels)\n    _outputs = tf.keras.layers.Dense(N_LABELS, activation=\"softmax\", name=\"outputs\")(x)\n\n    # Make model with optimizer and loss (probably not necessary)\n    _model = tf.keras.Model(inputs=_inputs, outputs=_outputs)\n    _model.compile(optimizer, loss)\n    return _model\n\n\n##################################################\n###  Step 4 – Create & Save Model [BRANCHING]  ###\n##################################################\n\n# BRANCH A --> tf.lite.TFLiteConverter.from_saved_model() \nmodel = get_tf_keras_model()\nprint(model.summary())\nmodel.save(\"./model\")\n\n# BRANCH B --> tf.lite.TFLiteConverter.from_keras_model() \n### NOTHING REQUIRED AT THIS STEP ###\n\n\n####################################################\n### Step 5 – Convert Model to TFLite [BRANCHING] ###\n####################################################\n\n# BRANCH A --> tf.lite.TFLiteConverter.from_saved_model() \nsaved_model_converter = tf.lite.TFLiteConverter.from_saved_model(\"./model\")\ntflite_model = saved_model_converter.convert()\n\n### BRANCH B --> tf.lite.TFLiteConverter.from_keras_model() \n# keras_converter = tf.lite.TFLiteConverter.from_keras_model(model)\n# tflite_model = keras_model_converter.convert()\n\n\n####################################################\n###   Step 6 – Save Newly Created TFLite Model   ###\n####################################################\n\n# Save the model.\nwith open('model.tflite', 'wb') as f:\n    f.write(tflite_model)\n    \n####################################################\n###    Step 7 – ZIP Saved File For Submission    ###\n####################################################\n!zip submission.zip ./model.tflite\n\n# Check our pwd\n!ls ./    ","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-02-27T17:26:14.153791Z","iopub.execute_input":"2023-02-27T17:26:14.154341Z","iopub.status.idle":"2023-02-27T17:26:20.832177Z","shell.execute_reply.started":"2023-02-27T17:26:14.154292Z","shell.execute_reply":"2023-02-27T17:26:20.830120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<br>\n\n<b>Test Our Model</b>","metadata":{}},{"cell_type":"code","source":"!pip install tflite-runtime\nimport tflite_runtime.interpreter as tflite\n\ninterpreter = tflite.Interpreter(\"./model.tflite\")\nfound_signatures = list(interpreter.get_signature_list().keys())\n# if REQUIRED_SIGNATURE not in found_signatures:\n#     raise KernelEvalException('Required input signature not found.')\nprediction_fn = interpreter.get_signature_runner(\"serving_default\")\n\noutput = prediction_fn(inputs=load_relevant_data_subset(train_df.path[0]))\nsign = np.argmax(output[\"outputs\"])\n\nprint(\"PRED : \", decoder(sign))\nprint(\"GT   : \", train_df.sign[0])","metadata":{"execution":{"iopub.status.busy":"2023-02-27T17:26:53.857454Z","iopub.execute_input":"2023-02-27T17:26:53.859662Z","iopub.status.idle":"2023-02-27T17:26:53.877951Z","shell.execute_reply.started":"2023-02-27T17:26:53.859336Z","shell.execute_reply":"2023-02-27T17:26:53.876585Z"},"trusted":true},"execution_count":null,"outputs":[]}]}