{"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":"## Isolated Sign Language Recognition: Create TFRecord\n\nIn this notebook, I will create time-series TFRecord for [Google - Isolated Sign Language Recognition Competition](https://www.kaggle.com/competitions/asl-signs). I will choose 12 as sequence_length. The dataset has dynamic sequence length, I will convert to static sequence length by simply using `tf.image.resize` API. [Here](https://www.kaggle.com/code/lonnieqin/isolated-sign-language-recognition-with-convlstm1d/notebook?scriptVersionId=120834686) is a baseline to train with this dataset. ","metadata":{}},{"cell_type":"markdown","source":"## Configuration","metadata":{}},{"cell_type":"code","source":"class CFG:\n    data_path = \"../input/asl-signs/\"\n    sequence_length = 12\n    rows_per_frame = 543 ","metadata":{"execution":{"iopub.status.busy":"2023-03-01T05:14:57.963032Z","iopub.execute_input":"2023-03-01T05:14:57.963386Z","iopub.status.idle":"2023-03-01T05:14:57.969809Z","shell.execute_reply.started":"2023-03-01T05:14:57.963332Z","shell.execute_reply":"2023-03-01T05:14:57.968706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Import Libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom tqdm import tqdm\nimport json\nimport os","metadata":{"execution":{"iopub.status.busy":"2023-03-01T05:15:00.280119Z","iopub.execute_input":"2023-03-01T05:15:00.280478Z","iopub.status.idle":"2023-03-01T05:15:08.733702Z","shell.execute_reply.started":"2023-03-01T05:15:00.280448Z","shell.execute_reply":"2023-03-01T05:15:08.732800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Utilities","metadata":{}},{"cell_type":"code","source":"ROWS_PER_FRAME = 543  # number of landmarks per frame\n\ndef load_relevant_data_subset_with_imputation(pq_path):\n    data_columns = ['x', 'y', 'z']\n    data = pd.read_parquet(pq_path, columns=data_columns)\n    data.replace(np.nan, 0, inplace=True)\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\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\ndef read_dict(file_path):\n    path = os.path.expanduser(file_path)\n    with open(path, \"r\") as f:\n        dic = json.load(f)\n    return dic","metadata":{"execution":{"iopub.status.busy":"2023-03-01T05:17:19.333065Z","iopub.execute_input":"2023-03-01T05:17:19.333447Z","iopub.status.idle":"2023-03-01T05:17:19.341552Z","shell.execute_reply.started":"2023-03-01T05:17:19.333416Z","shell.execute_reply":"2023-03-01T05:17:19.340517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load data","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(f\"{CFG.data_path}train.csv\")\nlabel_index = read_dict(f\"{CFG.data_path}sign_to_prediction_index_map.json\")\nindex_label = dict([(label_index[key], key) for key in label_index])\nprint(label_index)\ntrain[\"label\"] = train[\"sign\"].map(lambda sign: label_index[sign])\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-01T05:15:17.963439Z","iopub.execute_input":"2023-03-01T05:15:17.963829Z","iopub.status.idle":"2023-03-01T05:15:18.168873Z","shell.execute_reply.started":"2023-03-01T05:15:17.963783Z","shell.execute_reply":"2023-03-01T05:15:18.167771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create TF-Record","metadata":{}},{"cell_type":"code","source":"def create_record(feature, label):\n    dic = {}\n    dic[\"feature\"] = tf.train.Feature(float_list=tf.train.FloatList(value=feature))\n    dic[\"label\"] = tf.train.Feature(int64_list=tf.train.Int64List(value=[label]))\n    record_bytes = tf.train.Example(features=tf.train.Features(feature=dic)).SerializeToString()\n    return record_bytes\n    \ndef decode_function(record_bytes):\n  return tf.io.parse_single_example(\n      # Data\n      record_bytes,\n      # Schema\n      {\n          \"feature\": tf.io.FixedLenFeature([CFG.sequence_length * CFG.rows_per_frame * 3], dtype=tf.float32),\n          \"label\": tf.io.FixedLenFeature([], dtype=tf.int64)\n      }\n  )","metadata":{"execution":{"iopub.status.busy":"2023-03-01T05:27:31.358467Z","iopub.execute_input":"2023-03-01T05:27:31.358802Z","iopub.status.idle":"2023-03-01T05:27:31.366712Z","shell.execute_reply.started":"2023-03-01T05:27:31.358771Z","shell.execute_reply":"2023-03-01T05:27:31.365282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for participant_id in train.participant_id.unique():\n    df = train[train.participant_id == participant_id]\n    save_path = f\"{participant_id}.tfrecords\"\n    with tf.io.TFRecordWriter(save_path) as file_writer:\n        for i in tqdm(range(len(df))):\n            path = f\"{CFG.data_path}{df.iloc[i].path}\"\n            feature = load_relevant_data_subset_with_imputation(path)\n            feature = tf.image.resize(tf.constant(feature), (CFG.sequence_length, 543)).numpy().reshape(-1)\n            label = int(df.iloc[i].label)\n            file_writer.write(create_record(feature, label))","metadata":{"execution":{"iopub.status.busy":"2023-03-01T05:30:42.407048Z","iopub.execute_input":"2023-03-01T05:30:42.407415Z"},"trusted":true},"execution_count":null,"outputs":[]}]}