{"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":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, optimizers, constraints, regularizers\nimport numpy as np\nimport pandas as pd\nimport json\n\nprint(\"Tensorflow\", tf.__version__)\n!python --version\n\nbasedir = \"/kaggle/working/\"\nNUM_CHARACTERS = 59","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-14T08:30:51.034823Z","iopub.execute_input":"2023-06-14T08:30:51.035228Z","iopub.status.idle":"2023-06-14T08:30:51.311057Z","shell.execute_reply.started":"2023-06-14T08:30:51.035203Z","shell.execute_reply":"2023-06-14T08:30:51.309908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv('/kaggle/input/asl-fingerspelling/train.csv')\ndf_train\nSEL_FEATURES = ['x_right_hand_0','y_right_hand_0']\n\nc2p = json.load(open('/kaggle/input/asl-fingerspelling/character_to_prediction_index.json', 'r'))\np2c = {p: c for c, p in c2p.items()}","metadata":{"execution":{"iopub.status.busy":"2023-06-14T08:30:51.312993Z","iopub.execute_input":"2023-06-14T08:30:51.313318Z","iopub.status.idle":"2023-06-14T08:30:51.390411Z","shell.execute_reply.started":"2023-06-14T08:30:51.31329Z","shell.execute_reply":"2023-06-14T08:30:51.389076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Finding the best prediction\n","metadata":{}},{"cell_type":"code","source":"from Levenshtein import distance\nally = df_train['phrase'].values\ntotaly = sum([len(y) for y in ally])\n\n# Evaluate a constant prediction on the training set\ndef eval_string(s):\n    d = 0\n    for y in ally:\n        d += distance(s, y)\n    return (totaly - d) / totaly\n\n# Greedy algorithm\nbest_str = ''\nbest_score = 0\nchars = list(c2p.keys())\n\nfor i in range(20): # max length\n    inner_best = best_str\n    inner_best_score = best_score\n    \n    for position in range(len(best_str)+1): \n        for newchar in chars:              \n            new_str = best_str[:position] + str(newchar) + best_str[position:]\n            score = eval_string(new_str)\n\n            if score > inner_best_score:\n                inner_best = new_str\n                inner_best_score = score\n                print(f'New best @ {len(inner_best)}=\"{inner_best}\", score {inner_best_score:.4f}')\n\n    if best_score >= inner_best_score:\n        print('No improvement, best is', best_str)\n        break\n        \n    best_str = inner_best\n    best_score = inner_best_score\n    print(f'Best str @ {len(best_str)}=\"{best_str}\", score {best_score:.4f}')","metadata":{"execution":{"iopub.status.busy":"2023-06-14T08:30:51.391554Z","iopub.execute_input":"2023-06-14T08:30:51.391888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Turning into a TFLite model","metadata":{}},{"cell_type":"code","source":"const_pred = np.zeros((len(best_str), 59))\nfor i, c in enumerate(best_str):\n    const_pred[i, c2p[c]] = 1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the custom layer\nfrom tensorflow.keras.layers import Layer, Input\nclass ConstantLayer(Layer):\n    def __init__(self, constant_vector, name=None):\n        super(ConstantLayer, self).__init__(name=name)\n        self.constant_vector = tf.Variable(initial_value=constant_vector, trainable=False, dtype=tf.float32)\n\n    def call(self, inputs):\n        return self.constant_vector","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_layer = Input(shape=(len(SEL_FEATURES),), name='inputs')  # Let's assume we are inputting vectors of size 10\noutput_layer = ConstantLayer(const_pred, name='outputs')(input_layer)\n\nmodel = tf.keras.models.Model(inputs=input_layer, outputs=output_layer)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tflite_model = tf.lite.TFLiteConverter.from_keras_model(model).convert()\nmodel_path = 'model.tflite'\n\nwith open(model_path, 'wb') as f:\n    f.write(tflite_model)\n\n!zip submission.zip  './model.tflite' './inference_args.json'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Overall, we see 0.160 on CV, and 0.157 on LB - pretty consistent!","metadata":{}}]}