{"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 glob\nimport json\nimport pandas as pd\nimport numpy as np\nimport pyarrow.parquet as pq\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Flatten, LSTM, TimeDistributed\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.preprocessing.sequence import pad_sequences\nimport tensorflow as tf","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load the data\ntrain_metadata = pd.read_csv('/kaggle/input/asl-fingerspelling/train.csv')\nsupplemental_metadata = pd.read_csv('/kaggle/input/asl-fingerspelling/supplemental_metadata.csv')\n\n# Load character_to_prediction_index.json\nwith open('/kaggle/input/asl-fingerspelling/character_to_prediction_index.json', 'r') as f:\n    char_to_index = json.load(f)\n\n# Inverse the mapping to get prediction_to_character_map\nindex_to_char = {v: k for k, v in char_to_index.items()}\n\n# Pad sequences for uniform input length\nmax_sequence_len = max(\n    max([len(seq) for seq in train_metadata['phrase']]), \n    max([len(seq) for seq in supplemental_metadata['phrase']])\n)\nprint(max_sequence_len)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the model\nmodel = tf.keras.Sequential([\n    tf.keras.layers.Conv1D(1024, 32, activation='relu', input_shape=(1630, 1)),\n    tf.keras.layers.MaxPooling1D(32),\n    tf.keras.layers.LSTM(128, return_sequences=True),\n    tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(len(char_to_index), activation='softmax'))\n])\n\nmodel.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n\nmodel.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocess_and_train(model, filepath, metadata):\n    # Load landmarks\n    landmarks = pd.read_parquet(filepath)\n    \n    # Merge with metadata\n    merged = landmarks.merge(metadata, on=[\"sequence_id\"])\n    print('  Finish Merge')\n    \n    # Drop NaN\n    merged = merged.dropna()\n    print('  Finish Drop NaN')\n    \n    # Get the labels\n    y = merged['phrase']\n    x = merged.drop(columns=['phrase', 'participant_id', 'sequence_id', 'path', 'file_id'], errors='ignore')  # drop unnecessary columns\n    print('  Finish Label Getting')\n    \n    # Convert each phrase to a sequence of integers\n    y = y.apply(lambda x: [char_to_index[char] for char in list(x)])\n\n    # Pad sequences for uniform input length\n    sequence_len = 49\n    y = pad_sequences(y, maxlen=sequence_len, padding='post')\n    \n    # Split into train and validation set\n    x_train, x_val, y_train, y_val = train_test_split(x, y, test_size=0.2, random_state=42)\n    \n    # Transform DataFrames into a suitable input format for the model\n    x_train = x_train.values.reshape((-1, 1630, 1))\n    x_val = x_val.values.reshape((-1, 1630, 1))\n    \n    # Convert y to one-hot encoding\n    y_train = tf.keras.utils.to_categorical(y_train, num_classes=len(char_to_index))\n    y_val = tf.keras.utils.to_categorical(y_val, num_classes=len(char_to_index))\n    print('  Finish one-hot encoding')\n    \n#     x_train = x_train.astype('float32')\n#     y_train = y_train.astype('float32')\n#     x_val = x_val.astype('float32')\n#     y_val = y_val.astype('float32')\n    \n    # Train the model\n    for i in range(10):\n        model.fit(x_train, y_train, epochs=10, validation_data=(x_val, y_val), verbose=0)\n        loss, acc = model.evaluate(x_val, y_val, verbose=2)\n        print(f'  loss: {loss}, acc: {acc}')\n    print('  Finish Training')\n    \n    \n    # Delete landmarks and merged dataframes to save memory\n    del landmarks\n    del merged","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Loop through each file in the train and supplemental directory\nfor filepath in glob.glob('/kaggle/input/asl-fingerspelling/train_landmarks/*.parquet'):\n    print(f'Start {filepath} file')\n    preprocess_and_train(model, filepath, train_metadata)\n\nfor filepath in glob.glob('/kaggle/input/asl-fingerspelling/supplemental_landmarks/*.parquet'):\n    print(f'Start {filepath} file')\n    preprocess_and_train(model, filepath, supplemental_metadata)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create the converter\nconverter = tf.lite.TFLiteConverter.from_keras_model(model)\n\n# Set the converter to use SELECT_TF_OPS\nconverter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]\n\n# Disable experimental_lower_tensor_list_ops\nconverter._experimental_lower_tensor_list_ops = False\n\n# Convert the model\ntflite_model = converter.convert()\n\n# Save the model\nwith open('model.tflite', 'wb') as f:\n    f.write(tflite_model)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!zip submission.zip  './model.tflite'","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}