{"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 numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers\nfrom sklearn.model_selection import train_test_split\n\nimport os\nimport random\nimport json\nimport glob","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:04.269408Z","iopub.execute_input":"2023-03-14T13:26:04.269948Z","iopub.status.idle":"2023-03-14T13:26:04.283255Z","shell.execute_reply.started":"2023-03-14T13:26:04.269903Z","shell.execute_reply":"2023-03-14T13:26:04.281997Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Install nb_black for autoformatting\n!pip install nb_black --quiet\n%load_ext lab_black","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:04.287108Z","iopub.execute_input":"2023-03-14T13:26:04.289309Z","iopub.status.idle":"2023-03-14T13:26:15.368857Z","shell.execute_reply.started":"2023-03-14T13:26:04.289270Z","shell.execute_reply":"2023-03-14T13:26:15.367398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Constante\nROWS_PER_FRAME = 543\ndata_dir = \"/kaggle/input/asl-signs\"\nlandmark_fimes_dir = \"/kaggle/input/asl-signs/train_landmark_files\"","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.370736Z","iopub.execute_input":"2023-03-14T13:26:15.371143Z","iopub.status.idle":"2023-03-14T13:26:15.377786Z","shell.execute_reply.started":"2023-03-14T13:26:15.371091Z","shell.execute_reply":"2023-03-14T13:26:15.376566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_it_all(seed=42):\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n\n\nseed_it_all()  # Reproducible","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.381148Z","iopub.execute_input":"2023-03-14T13:26:15.381807Z","iopub.status.idle":"2023-03-14T13:26:15.391454Z","shell.execute_reply.started":"2023-03-14T13:26:15.381769Z","shell.execute_reply":"2023-03-14T13:26:15.389948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ROWS_PER_FRAME = 543  # number of landmarks per frame\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)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.393638Z","iopub.execute_input":"2023-03-14T13:26:15.394302Z","iopub.status.idle":"2023-03-14T13:26:15.404970Z","shell.execute_reply.started":"2023-03-14T13:26:15.394267Z","shell.execute_reply":"2023-03-14T13:26:15.403860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_json(path):\n    with open(path, \"r\") as file:\n        json_data = json.load(file)\n    return json_data","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.406383Z","iopub.execute_input":"2023-03-14T13:26:15.406805Z","iopub.status.idle":"2023-03-14T13:26:15.415803Z","shell.execute_reply.started":"2023-03-14T13:26:15.406759Z","shell.execute_reply":"2023-03-14T13:26:15.414776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(data_dir + \"/train.csv\")\ntrain_df[\"path\"] = data_dir + \"/\" + train_df[\"path\"]\ndisplay(train_df.head(2)), len(train_df)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.417008Z","iopub.execute_input":"2023-03-14T13:26:15.417364Z","iopub.status.idle":"2023-03-14T13:26:15.549851Z","shell.execute_reply.started":"2023-03-14T13:26:15.417329Z","shell.execute_reply":"2023-03-14T13:26:15.548722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.describe()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.551946Z","iopub.execute_input":"2023-03-14T13:26:15.552325Z","iopub.status.idle":"2023-03-14T13:26:15.576240Z","shell.execute_reply.started":"2023-03-14T13:26:15.552287Z","shell.execute_reply":"2023-03-14T13:26:15.575152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.tail()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.578017Z","iopub.execute_input":"2023-03-14T13:26:15.578416Z","iopub.status.idle":"2023-03-14T13:26:15.590635Z","shell.execute_reply.started":"2023-03-14T13:26:15.578369Z","shell.execute_reply":"2023-03-14T13:26:15.589052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.hist","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.597353Z","iopub.execute_input":"2023-03-14T13:26:15.597954Z","iopub.status.idle":"2023-03-14T13:26:15.609086Z","shell.execute_reply.started":"2023-03-14T13:26:15.597925Z","shell.execute_reply":"2023-03-14T13:26:15.607693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.info()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.611329Z","iopub.execute_input":"2023-03-14T13:26:15.611787Z","iopub.status.idle":"2023-03-14T13:26:15.633423Z","shell.execute_reply.started":"2023-03-14T13:26:15.611749Z","shell.execute_reply":"2023-03-14T13:26:15.632366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s2p_map = read_json(os.path.join(data_dir, \"sign_to_prediction_index_map.json\"))\np2s_map = {v: k for k, v in s2p_map.items()}\n\nencoder = lambda x: s2p_map.get(x)\ndecoder = lambda x: p2s_map.get(x)\n\ntrain_df[\"label\"] = train_df[\"sign\"].map(encoder)\nprint(f\"shape = {train_df.shape}\")\n\ntrain_df.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.635082Z","iopub.execute_input":"2023-03-14T13:26:15.635705Z","iopub.status.idle":"2023-03-14T13:26:15.695702Z","shell.execute_reply.started":"2023-03-14T13:26:15.635651Z","shell.execute_reply":"2023-03-14T13:26:15.694788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"participants = os.listdir(landmark_fimes_dir)\nprint(f\"Total number of participants = {len(participants)}\")\nprint(\n    f\"Average number of sequences per participant = {len(glob.glob(landmark_fimes_dir + '/*/*.parquet'))/len(participants)}\"\n)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:15.696906Z","iopub.execute_input":"2023-03-14T13:26:15.697700Z","iopub.status.idle":"2023-03-14T13:26:18.736622Z","shell.execute_reply.started":"2023-03-14T13:26:15.697649Z","shell.execute_reply":"2023-03-14T13:26:18.735452Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"int(21 * 4498.9), train_df.shape[0]  # ~ same","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.738217Z","iopub.execute_input":"2023-03-14T13:26:18.738578Z","iopub.status.idle":"2023-03-14T13:26:18.747527Z","shell.execute_reply.started":"2023-03-14T13:26:18.738540Z","shell.execute_reply":"2023-03-14T13:26:18.746404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_path = train_df.path[0]\nsample = pd.read_parquet(sample_path)\n\nprint(f\"Sample shape = {sample.shape}\")\nprint(f\"Number of Frames = {int(len(sample) / ROWS_PER_FRAME)}\")\n# ROWS_PER_FRAME = 543 i.e. one frame is represented by 543 row in our dataset, including the face, both hands and pose\n# n_frame can also be found : 20->42=>23frames i.e. sample.frame.max() -> sample.frame.min() : sample.nunique()\n\ndisplay(sample), display(sample.iloc[541:544])","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.749106Z","iopub.execute_input":"2023-03-14T13:26:18.749773Z","iopub.status.idle":"2023-03-14T13:26:18.860911Z","shell.execute_reply.started":"2023-03-14T13:26:18.749734Z","shell.execute_reply":"2023-03-14T13:26:18.859893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample.isna().sum()  # probably the hand as explain in the 'Dataset Description' section","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.862593Z","iopub.execute_input":"2023-03-14T13:26:18.863261Z","iopub.status.idle":"2023-03-14T13:26:18.875838Z","shell.execute_reply.started":"2023-03-14T13:26:18.863223Z","shell.execute_reply":"2023-03-14T13:26:18.874817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_data_np = load_relevant_data_subset(sample_path)\nprint(f\"shape = {sample_data_np.shape} = (n_frames, row_per_frame, xyz) \\n\")\nsample_data_np[:1, :4, :]","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.877450Z","iopub.execute_input":"2023-03-14T13:26:18.878137Z","iopub.status.idle":"2023-03-14T13:26:18.893271Z","shell.execute_reply.started":"2023-03-14T13:26:18.878097Z","shell.execute_reply":"2023-03-14T13:26:18.892330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_path_hand = train_df.path[5]  # 5 : empirical choice\nsample_for_hand = pd.read_parquet(sample_path_hand)\n\nprint(f\"Number of Frames = {int(len(sample_for_hand) / ROWS_PER_FRAME)}\")\nprint(f\"First frame indice is {sample_for_hand.frame.min()}\")\nprint(f\"Last frame indice is {sample_for_hand.frame.max()}\")\nprint(f\"Sample signe is : {train_df.sign[5]}\")\n\nright_hand_sample = sample_for_hand[sample_for_hand.type == \"right_hand\"]\nleft_hand_sample = sample_for_hand[sample_for_hand.type == \"left_hand\"]\nright_hand_sample.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.894775Z","iopub.execute_input":"2023-03-14T13:26:18.895367Z","iopub.status.idle":"2023-03-14T13:26:18.938820Z","shell.execute_reply.started":"2023-03-14T13:26:18.895332Z","shell.execute_reply":"2023-03-14T13:26:18.937606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\n    f\"Percentage of nulls in Right Hand data = {100*np.mean(right_hand_sample['x'].isnull()):.2f} %\"\n)\nprint(\n    f\"Percentage of nulls in Left Hand data = {100*np.mean(left_hand_sample['x'].isnull()):.02f} %\"\n)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.940211Z","iopub.execute_input":"2023-03-14T13:26:18.941100Z","iopub.status.idle":"2023-03-14T13:26:18.950622Z","shell.execute_reply.started":"2023-03-14T13:26:18.941072Z","shell.execute_reply":"2023-03-14T13:26:18.949340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"edges = [\n    (0, 1),\n    (1, 2),\n    (2, 3),\n    (3, 4),\n    (0, 5),\n    (0, 17),\n    (5, 6),\n    (6, 7),\n    (7, 8),\n    (5, 9),\n    (9, 10),\n    (10, 11),\n    (11, 12),\n    (9, 13),\n    (13, 14),\n    (14, 15),\n    (15, 16),\n    (13, 17),\n    (17, 18),\n    (18, 19),\n    (19, 20),\n]  # see above\n\n\ndef plot_frame(df, frame_id, ax):\n    df = df[df.frame == frame_id].sort_values([\"landmark_index\"])\n    x = list(df.x)\n    y = list(df.y)\n\n    ax.scatter(df.x, df.y, color=\"dodgerblue\")\n    for i in range(len(x)):\n        ax.text(x[i], y[i], str(i))\n\n    for edge in edges:\n        ax.plot([x[edge[0]], x[edge[1]]], [y[edge[0]], y[edge[1]]], color=\"salmon\")\n        ax.set_title(f\"Frame no. {frame_id}\")\n        ax.axis(False)\n\n\ndef plot_frame_seq(df, frame_id_range, n_frames):\n    frames = np.linspace(\n        frame_id_range[0], frame_id_range[1], n_frames, dtype=int, endpoint=True\n    )\n    fig, ax = plt.subplots(n_frames, 1, figsize=(5, 25))\n    for i in range(n_frames):\n        plot_frame(df, frames[i], ax[i])\n\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.951850Z","iopub.execute_input":"2023-03-14T13:26:18.952131Z","iopub.status.idle":"2023-03-14T13:26:18.976686Z","shell.execute_reply.started":"2023-03-14T13:26:18.952107Z","shell.execute_reply":"2023-03-14T13:26:18.975708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_frame_seq(right_hand_sample, (20, 40), 5)  # take 1 frame out of 4","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:18.980639Z","iopub.execute_input":"2023-03-14T13:26:18.980966Z","iopub.status.idle":"2023-03-14T13:26:19.720283Z","shell.execute_reply.started":"2023-03-14T13:26:18.980899Z","shell.execute_reply":"2023-03-14T13:26:19.718929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class FeatureGen(tf.keras.layers.Layer):\n    def __init__(self):\n        super().__init__()\n\n    def call(self, x):\n        x = tf.where(tf.math.is_nan(x), tf.zeros_like(x), x)\n        x = np.mean(x, axis=0)\n        return x\n\n\nfeature_converter = FeatureGen()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:19.721388Z","iopub.execute_input":"2023-03-14T13:26:19.722541Z","iopub.status.idle":"2023-03-14T13:26:19.743744Z","shell.execute_reply.started":"2023-03-14T13:26:19.722501Z","shell.execute_reply":"2023-03-14T13:26:19.742735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_lenght_experiment = len(train_df)\ndata_lenght_experiment","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:19.745077Z","iopub.execute_input":"2023-03-14T13:26:19.745398Z","iopub.status.idle":"2023-03-14T13:26:19.753758Z","shell.execute_reply.started":"2023-03-14T13:26:19.745364Z","shell.execute_reply":"2023-03-14T13:26:19.752594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convert_row(row):\n    x = load_relevant_data_subset(os.path.join(\"/kaggle/input/asl-signs\", row.path))\n    x = feature_converter(x)\n    return x, row.label","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:19.755295Z","iopub.execute_input":"2023-03-14T13:26:19.756450Z","iopub.status.idle":"2023-03-14T13:26:19.764468Z","shell.execute_reply.started":"2023-03-14T13:26:19.756415Z","shell.execute_reply":"2023-03-14T13:26:19.762992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convert_and_save_data():\n    np_features = np.zeros((data_lenght_experiment, ROWS_PER_FRAME, 3))\n    np_labels = np.zeros(data_lenght_experiment)\n\n    print(f\"Total data to processe : {data_lenght_experiment}\")\n    for index, row in tqdm(train_df.iterrows()):\n        if index > data_lenght_experiment - 1:\n            break\n\n        data = load_relevant_data_subset(row.path)\n        feature, label = convert_row(row)\n        np_features[index, :, :] = feature\n        np_labels[index] = label\n\n    np.save(\"features.npy\", np_features)\n    np.save(\"labels.npy\", np_labels)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:19.765892Z","iopub.execute_input":"2023-03-14T13:26:19.766350Z","iopub.status.idle":"2023-03-14T13:26:19.778962Z","shell.execute_reply.started":"2023-03-14T13:26:19.766291Z","shell.execute_reply":"2023-03-14T13:26:19.777876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    features = np.load(\"/kaggle/working/feature.npy\")\n    labels = np.load(\"/kaggle/working/label.npy\")\nexcept:\n    convert_and_save_data()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:26:19.780462Z","iopub.execute_input":"2023-03-14T13:26:19.780920Z","iopub.status.idle":"2023-03-14T13:58:50.250465Z","shell.execute_reply.started":"2023-03-14T13:26:19.780849Z","shell.execute_reply":"2023-03-14T13:58:50.248144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"features = np.load(\"features.npy\")\nlabels = np.load(\"labels.npy\")","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:58:50.261632Z","iopub.execute_input":"2023-03-14T13:58:50.262142Z","iopub.status.idle":"2023-03-14T13:58:53.307890Z","shell.execute_reply.started":"2023-03-14T13:58:50.262087Z","shell.execute_reply":"2023-03-14T13:58:53.306842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model(n_labels=250, learning_rate=0.001):\n    inputs = layers.Input(shape=(ROWS_PER_FRAME, 3))\n    x = layers.Dense(128, activation=\"relu\")(inputs)\n    x = layers.Dense(64, activation=\"relu\")(x)\n    x = layers.Dense(32, activation=\"relu\")(x)\n    x = layers.Dense(16, activation=\"relu\")(x)\n    # x = layers.Dense(8, activation=\"relu\")(x)\n    x = layers.Flatten()(x)\n    output = layers.Dense(n_labels, activation=\"softmax\")(x)\n    model = tf.keras.Model(inputs=inputs, outputs=output)\n\n    model.compile(\n        loss=\"sparse_categorical_crossentropy\",\n        optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),\n        metrics=[\"accuracy\"],\n    )\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:58:53.314365Z","iopub.execute_input":"2023-03-14T13:58:53.315402Z","iopub.status.idle":"2023-03-14T13:58:53.329349Z","shell.execute_reply.started":"2023-03-14T13:58:53.315362Z","shell.execute_reply":"2023-03-14T13:58:53.328131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"es_callback = tf.keras.callbacks.EarlyStopping(\n    monitor=\"val_loss\", patience=3, restore_best_weights=True\n)\n\ncheckpoint_callback = tf.keras.callbacks.ModelCheckpoint(\n    \"./ASL_model\",\n    save_best_only=True,\n    restore_best_weights=True,\n    monitor=\"val_accuracy\",\n    mode=\"max\",\n    verbose=False,\n)\n\ncb_list = [checkpoint_callback]\n\nX_train, X_val, y_train, y_val = train_test_split(\n    features, labels, test_size=0.2, stratify=labels, random_state=42\n)\n\nmodel = get_model()\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:58:53.330742Z","iopub.execute_input":"2023-03-14T13:58:53.331307Z","iopub.status.idle":"2023-03-14T13:58:55.781141Z","shell.execute_reply.started":"2023-03-14T13:58:53.331266Z","shell.execute_reply":"2023-03-14T13:58:55.779993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    model = tf.keras.models.load_model(\"./ASL_mode\")\nexcept:\n    history = model.fit(\n        X_train,\n        y_train,\n        validation_data=(X_val, y_val),\n        epochs=50,\n        callbacks=cb_list,\n        batch_size=64,\n    )","metadata":{"execution":{"iopub.status.busy":"2023-03-14T13:58:55.782778Z","iopub.execute_input":"2023-03-14T13:58:55.783125Z","iopub.status.idle":"2023-03-14T14:07:20.979881Z","shell.execute_reply.started":"2023-03-14T13:58:55.783086Z","shell.execute_reply":"2023-03-14T14:07:20.978785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = tf.keras.models.load_model(\"./ASL_model\")\nscore = model.evaluate(X_val, y_val)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T14:07:20.981585Z","iopub.execute_input":"2023-03-14T14:07:20.982454Z","iopub.status.idle":"2023-03-14T14:07:24.914228Z","shell.execute_reply.started":"2023-03-14T14:07:20.982405Z","shell.execute_reply":"2023-03-14T14:07:24.913134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_inference_model(model):\n    inputs = tf.keras.Input((543, 3), dtype=tf.float32, name=\"inputs\")\n    x = tf.where(tf.math.is_nan(inputs), tf.zeros_like(inputs), inputs)\n    x = tf.reduce_mean(x, axis=0, keepdims=True)\n    x = model(x)\n    output = tf.keras.layers.Activation(activation=\"linear\", name=\"outputs\")(x)\n    inference_model = tf.keras.Model(inputs=inputs, outputs=output)\n    inference_model.compile(\n        loss=tf.keras.losses.SparseCategoricalCrossentropy(), metrics=[\"accuracy\"]\n    )\n    return inference_model","metadata":{"execution":{"iopub.status.busy":"2023-03-14T14:07:24.915599Z","iopub.execute_input":"2023-03-14T14:07:24.916289Z","iopub.status.idle":"2023-03-14T14:07:24.943989Z","shell.execute_reply.started":"2023-03-14T14:07:24.916248Z","shell.execute_reply":"2023-03-14T14:07:24.943030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inference_model = get_inference_model(model)\ninference_model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T14:07:24.945598Z","iopub.execute_input":"2023-03-14T14:07:24.945984Z","iopub.status.idle":"2023-03-14T14:07:25.036504Z","shell.execute_reply.started":"2023-03-14T14:07:24.945946Z","shell.execute_reply":"2023-03-14T14:07:25.035725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"converter = tf.lite.TFLiteConverter.from_keras_model(inference_model)\ntflite_model = converter.convert()\nmodel_path = \"model.tflite\"\n# Save the model.\nwith open(model_path, \"wb\") as f:\n    f.write(tflite_model)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T14:07:25.037538Z","iopub.execute_input":"2023-03-14T14:07:25.037948Z","iopub.status.idle":"2023-03-14T14:07:27.539797Z","shell.execute_reply.started":"2023-03-14T14:07:25.037896Z","shell.execute_reply":"2023-03-14T14:07:27.538627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!zip submission.zip $model_path","metadata":{"execution":{"iopub.status.busy":"2023-03-14T14:07:27.541473Z","iopub.execute_input":"2023-03-14T14:07:27.541844Z","iopub.status.idle":"2023-03-14T14:07:29.039006Z","shell.execute_reply.started":"2023-03-14T14:07:27.541806Z","shell.execute_reply":"2023-03-14T14:07:29.036647Z"},"trusted":true},"execution_count":null,"outputs":[]}]}