{"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 pandas as pd\nimport numpy as np\nimport tensorflow as tf\nimport json","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:07.578324Z","iopub.execute_input":"2023-03-01T04:55:07.578729Z","iopub.status.idle":"2023-03-01T04:55:16.269770Z","shell.execute_reply.started":"2023-03-01T04:55:07.578696Z","shell.execute_reply":"2023-03-01T04:55:16.268688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import Labels and Paths","metadata":{}},{"cell_type":"code","source":"train_labels = pd.read_csv(\"/kaggle/input/asl-signs/train.csv\")\n\n# load the JSON file into a dictionary\nwith open('/kaggle/input/asl-signs/sign_to_prediction_index_map.json') as f:\n    mapping = json.load(f)\n\n# map the strings to integers using the dictionary\ntrain_labels['sign_as_int'] = train_labels['sign'].map(mapping)\ntrain_labels","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:16.271570Z","iopub.execute_input":"2023-03-01T04:55:16.272182Z","iopub.status.idle":"2023-03-01T04:55:16.498207Z","shell.execute_reply.started":"2023-03-01T04:55:16.272132Z","shell.execute_reply":"2023-03-01T04:55:16.497251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating a tf.data.Dataset","metadata":{}},{"cell_type":"code","source":"DATA_COLUMNS    = ['x', 'y', 'z']\nROWS_PER_FRAME  = 543","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:16.499481Z","iopub.execute_input":"2023-03-01T04:55:16.500269Z","iopub.status.idle":"2023-03-01T04:55:16.505188Z","shell.execute_reply.started":"2023-03-01T04:55:16.500230Z","shell.execute_reply":"2023-03-01T04:55:16.504250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_relevant_data_subset(pq_path):\n    data = pd.read_parquet('/kaggle/input/asl-signs/'+pq_path, columns=DATA_COLUMNS)\n    n_frames = int(len(data) / ROWS_PER_FRAME)\n    data = data.values.astype(np.float32)\n    return data.reshape(n_frames, ROWS_PER_FRAME, len(DATA_COLUMNS))","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:16.507649Z","iopub.execute_input":"2023-03-01T04:55:16.508023Z","iopub.status.idle":"2023-03-01T04:55:16.518730Z","shell.execute_reply.started":"2023-03-01T04:55:16.507989Z","shell.execute_reply":"2023-03-01T04:55:16.517645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def tf_get_features(ftensor):\n    def feat_wrapper(ftensor):\n        return load_relevant_data_subset(ftensor.numpy().decode('utf-8'))\n    return tf.py_function(\n        feat_wrapper,\n        [ftensor],\n        Tout=tf.float32\n    )","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:16.520005Z","iopub.execute_input":"2023-03-01T04:55:16.520470Z","iopub.status.idle":"2023-03-01T04:55:16.534032Z","shell.execute_reply.started":"2023-03-01T04:55:16.520441Z","shell.execute_reply":"2023-03-01T04:55:16.532555Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_ds = tf.data.Dataset.from_tensor_slices(train_labels.path.values).map(tf_get_features)\ny_ds = tf.data.Dataset.from_tensor_slices(train_labels['sign_as_int'])\n\ntrain_ds = tf.data.Dataset.zip((X_ds, y_ds))","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:16.535600Z","iopub.execute_input":"2023-03-01T04:55:16.536237Z","iopub.status.idle":"2023-03-01T04:55:16.718002Z","shell.execute_reply.started":"2023-03-01T04:55:16.536195Z","shell.execute_reply":"2023-03-01T04:55:16.716924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Custom Pre-Processing Layer","metadata":{}},{"cell_type":"code","source":"max_samp_frames = 100\n\nclass ImagePreprocessingLayer(tf.keras.layers.Layer):\n    def __init__(self):\n        super(ImagePreprocessingLayer, self).__init__()\n        self.trainable = False\n        \n    def call(self, inputs):\n        # Determine the number of rows in the input image(not actually an image)\n        n_rows = tf.shape(inputs)[0]\n        \n        # If the number of rows is greater than 100, downsample to (100, 500, 3)\n        if n_rows > max_samp_frames:\n            inputs = tf.image.resize(inputs, size=(max_samp_frames, 543))\n    \n        # If the number of rows is less than 100, pad with zeros until row 100\n        elif n_rows < max_samp_frames:\n            padding = tf.zeros(shape=(max_samp_frames - n_rows, 543, 3), dtype=inputs.dtype)\n            inputs = tf.concat([inputs, padding], axis=0)\n        \n        # Lastly filling na's with 0's\n        inputs = tf.where(tf.math.is_nan(inputs), tf.zeros_like(inputs), inputs)\n\n        return inputs","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:16.719281Z","iopub.execute_input":"2023-03-01T04:55:16.719682Z","iopub.status.idle":"2023-03-01T04:55:16.727924Z","shell.execute_reply.started":"2023-03-01T04:55:16.719644Z","shell.execute_reply":"2023-03-01T04:55:16.726590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Building the Model","metadata":{}},{"cell_type":"code","source":"model = tf.keras.Sequential(\n    [\n        tf.keras.layers.Input(shape=(None, 543, 3)),\n        ImagePreprocessingLayer(),\n        tf.keras.layers.Flatten(),\n        tf.keras.layers.Dense(250, activation='relu'),\n        tf.keras.layers.Dense(250, activation='softmax'),\n    ]\n)","metadata":{"execution":{"iopub.status.busy":"2023-03-01T04:55:31.949578Z","iopub.execute_input":"2023-03-01T04:55:31.950366Z","iopub.status.idle":"2023-03-01T04:55:32.146086Z","shell.execute_reply.started":"2023-03-01T04:55:31.950319Z","shell.execute_reply":"2023-03-01T04:55:32.144886Z"},"trusted":true},"execution_count":null,"outputs":[]}]}