{"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":"# to process and visualize type data\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n# utilities\nimport os\nimport shutil\nimport random\nimport string\n\n# fixed figure size\nplt.rcParams[\"figure.figsize\"] = (21, 12)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-11-18T10:10:34.409786Z","iopub.execute_input":"2022-11-18T10:10:34.410419Z","iopub.status.idle":"2022-11-18T10:10:34.417246Z","shell.execute_reply.started":"2022-11-18T10:10:34.410372Z","shell.execute_reply":"2022-11-18T10:10:34.415704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n\nfrom tensorflow.keras.applications.resnet import ResNet101\n\n# image preprocessing\nfrom tensorflow.keras.preprocessing.image import img_to_array, ImageDataGenerator, load_img\n\n# to build model\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, Dense, MaxPooling2D, Dropout, Flatten, BatchNormalization\nfrom tensorflow.keras.activations import softmax\n\n# cost function / optimizer\nfrom tensorflow.keras.optimizers import Adam","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:10:35.562623Z","iopub.execute_input":"2022-11-18T10:10:35.563045Z","iopub.status.idle":"2022-11-18T10:10:41.700793Z","shell.execute_reply.started":"2022-11-18T10:10:35.563003Z","shell.execute_reply":"2022-11-18T10:10:41.699643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare Data","metadata":{}},{"cell_type":"code","source":"TRAIN_VAL_PATH = \"../input/sartorius-cell-instance-segmentation/LIVECell_dataset_2021/images/livecell_train_val_images\"\nTEST_PATH = \"../input/sartorius-cell-instance-segmentation/LIVECell_dataset_2021/images/livecell_test_images\"","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:10:41.702884Z","iopub.execute_input":"2022-11-18T10:10:41.703379Z","iopub.status.idle":"2022-11-18T10:10:41.714794Z","shell.execute_reply.started":"2022-11-18T10:10:41.703351Z","shell.execute_reply":"2022-11-18T10:10:41.713131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PARAMETERS\n\nHEIGHT, WIDTH = (520, 704)\nNUM_CLASSES = 9\nCELL_TYPES = list(set(os.listdir(TRAIN_VAL_PATH)))","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:10:41.716692Z","iopub.execute_input":"2022-11-18T10:10:41.717035Z","iopub.status.idle":"2022-11-18T10:10:41.744787Z","shell.execute_reply.started":"2022-11-18T10:10:41.716994Z","shell.execute_reply":"2022-11-18T10:10:41.743987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CELL_TYPES","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:10:41.748003Z","iopub.execute_input":"2022-11-18T10:10:41.748258Z","iopub.status.idle":"2022-11-18T10:10:41.757917Z","shell.execute_reply.started":"2022-11-18T10:10:41.748235Z","shell.execute_reply":"2022-11-18T10:10:41.754987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_frequency_of_cell_types(PATH : list, countplot=True):\n    \"\"\"Return a list frequency of train cell types and a list frequency of total cell types\"\"\"\n    if len(PATH) != 2:\n        raise TypeError(\"The passed value must be a list and length of 2.\")\n    cell_types = {}\n    all_cell_types = {}\n    for path in PATH:\n        tmp_cell_types = {}\n        for cell_type in os.listdir(path):\n            look = os.path.join(path, cell_type)\n            n_look = len(os.listdir(look))\n            if cell_type in tmp_cell_types.keys():\n                tmp_cell_types[cell_type] += n_look\n            else:\n                tmp_cell_types[cell_type] = n_look\n        cell_types[path] = tmp_cell_types\n        for k, v in tmp_cell_types.items():\n            if k in all_cell_types.keys():\n                all_cell_types[k] += v\n            else:\n                all_cell_types[k] = v\n    if countplot:\n        i=1\n        plt.figure(figsize=(16, 6))\n        for k in cell_types.keys():\n            plt.subplot(1, len(cell_types), i)\n            d = cell_types[k]\n            plt.title(f\"From LIVECell 2021: {k.split('/')[-1]}\")\n            sns.barplot(list(d.keys()), list(d.values()))\n            i+=1\n\n    return cell_types, all_cell_types","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:10:48.152632Z","iopub.execute_input":"2022-11-18T10:10:48.153015Z","iopub.status.idle":"2022-11-18T10:10:48.164966Z","shell.execute_reply.started":"2022-11-18T10:10:48.152983Z","shell.execute_reply":"2022-11-18T10:10:48.163811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cell_types, all_cell_types = get_frequency_of_cell_types([TRAIN_VAL_PATH, TEST_PATH])","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:10:49.343249Z","iopub.execute_input":"2022-11-18T10:10:49.343610Z","iopub.status.idle":"2022-11-18T10:10:52.157534Z","shell.execute_reply.started":"2022-11-18T10:10:49.343579Z","shell.execute_reply":"2022-11-18T10:10:52.156488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## * data distribution is different!!!","metadata":{}},{"cell_type":"code","source":"TRAIN_VAL_PATH = \"../input/sartorius-cell-instance-segmentation/LIVECell_dataset_2021/images/livecell_train_val_images\"","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:13:47.483480Z","iopub.execute_input":"2022-11-18T10:13:47.483853Z","iopub.status.idle":"2022-11-18T10:13:47.489669Z","shell.execute_reply.started":"2022-11-18T10:13:47.483820Z","shell.execute_reply":"2022-11-18T10:13:47.488467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_DIR = \"./classification\"\n\nif os.path.exists(BASE_DIR):\n    shutil.rmtree(BASE_DIR)\n\nos.makedirs(BASE_DIR)\nos.makedirs(os.path.join(BASE_DIR, \"training_classification\"))\nos.makedirs(os.path.join(BASE_DIR, \"validation_classification\"))","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:13:47.737647Z","iopub.execute_input":"2022-11-18T10:13:47.738245Z","iopub.status.idle":"2022-11-18T10:13:47.745717Z","shell.execute_reply.started":"2022-11-18T10:13:47.738207Z","shell.execute_reply":"2022-11-18T10:13:47.744705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_CL_PATH = os.path.join(BASE_DIR, \"training_classification\")\nVAL_CL_PATH = os.path.join(BASE_DIR, \"validation_classification\")","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:13:48.498195Z","iopub.execute_input":"2022-11-18T10:13:48.499309Z","iopub.status.idle":"2022-11-18T10:13:48.504693Z","shell.execute_reply.started":"2022-11-18T10:13:48.499262Z","shell.execute_reply":"2022-11-18T10:13:48.503331Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for cell_type in CELL_TYPES:\n    os.makedirs(os.path.join(os.path.join(BASE_DIR, \"training_classification\"), cell_type))\n    os.makedirs(os.path.join(os.path.join(BASE_DIR, \"validation_classification\"), cell_type))","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:13:49.290967Z","iopub.execute_input":"2022-11-18T10:13:49.291306Z","iopub.status.idle":"2022-11-18T10:13:49.297823Z","shell.execute_reply.started":"2022-11-18T10:13:49.291275Z","shell.execute_reply":"2022-11-18T10:13:49.296819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_val_generators(train_dir, val_dir):\n    \"\"\" Returns train and validation image data generators \"\"\"\n    train_gen = ImageDataGenerator(rescale=1/255.,\n                                  )\n    val_gen = ImageDataGenerator(rescale=1/255.,\n                                )\n    train_generator = train_gen.flow_from_directory(directory=train_dir,\n                                                    batch_size=16,\n                                                    class_mode=\"categorical\",\n                                                    target_size=(HEIGHT, WIDTH),\n                                                    shuffle=True)\n    val_generator = val_gen.flow_from_directory(directory=val_dir,\n                                               batch_size=16,\n                                               class_mode=\"categorical\",\n                                               target_size=(HEIGHT, WIDTH),\n                                               shuffle=True)\n    return train_generator, val_generator","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:13:49.980877Z","iopub.execute_input":"2022-11-18T10:13:49.981245Z","iopub.status.idle":"2022-11-18T10:13:49.988272Z","shell.execute_reply.started":"2022-11-18T10:13:49.981213Z","shell.execute_reply":"2022-11-18T10:13:49.987098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def split_data(source, train_path, val_path, split_size=0.8):\n    \"\"\" Returns None. Shuffles and splits data as given split_size.\n        Then, copies data to the created directories, so that the power of data generators usage will be enabled.\n    \"\"\"\n    all_files = []\n    for cell_type in CELL_TYPES:\n        cell_path = os.path.join(source, cell_type)\n        cell_image_paths = os.listdir(cell_path)\n        for cell_image_path in cell_image_paths:\n            last_path = os.path.join(cell_path, cell_image_path) \n            if os.path.getsize(last_path):\n                all_files.append(last_path)\n            else:\n                print(f\"{last_path} has zero size, so skipping.\")\n    n_files = len(all_files)\n    split_point = int(split_size * n_files)\n    shuffled_files = random.sample(all_files, n_files)\n\n    train_image = shuffled_files[:split_point]\n    val_image = shuffled_files[split_point:]\n\n    for train_cell in train_image:\n        cell_type = train_cell.split(\"/\")[-2]\n        #print(train_cell)\n        to_where = os.path.join(train_path, cell_type)\n        shutil.copy(train_cell, to_where)\n\n    for val_cell in val_image:\n        cell_type = val_cell.split(\"/\")[-2]\n        to_where = os.path.join(val_path, cell_type)\n        shutil.copy(val_cell, to_where)","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:13:50.603926Z","iopub.execute_input":"2022-11-18T10:13:50.604657Z","iopub.status.idle":"2022-11-18T10:13:50.613878Z","shell.execute_reply.started":"2022-11-18T10:13:50.604618Z","shell.execute_reply":"2022-11-18T10:13:50.612720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"split_data(TRAIN_VAL_PATH, TRAIN_CL_PATH, VAL_CL_PATH, split_size=0.8)","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:13:51.166898Z","iopub.execute_input":"2022-11-18T10:13:51.167285Z","iopub.status.idle":"2022-11-18T10:14:30.586425Z","shell.execute_reply.started":"2022-11-18T10:13:51.167252Z","shell.execute_reply":"2022-11-18T10:14:30.585430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_gen, val_gen = train_val_generators(TRAIN_CL_PATH, VAL_CL_PATH)","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:14:30.588595Z","iopub.execute_input":"2022-11-18T10:14:30.589004Z","iopub.status.idle":"2022-11-18T10:14:30.906645Z","shell.execute_reply.started":"2022-11-18T10:14:30.588962Z","shell.execute_reply":"2022-11-18T10:14:30.905587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.utils import class_weight\n\nclass_weights = class_weight.compute_class_weight(\n                class_weight ='balanced',\n                classes = np.unique(train_gen.classes), \n                y=train_gen.classes)\n\nclass_weights = dict(zip(np.unique(train_gen.classes), class_weights))\nprint(f\"Train Gen:\\n{class_weights}\")\n\nclass_weights2 = class_weight.compute_class_weight(\n                class_weight ='balanced',\n                classes = np.unique(val_gen.classes), \n                y=val_gen.classes)\n\nclass_weights2 = dict(zip(np.unique(val_gen.classes), class_weights2))\nprint(f\"Val Gen:\\n{class_weights2}\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#import cv2\n#gray = cv2.cvtColor(cv2.imread(\"../input/sartorius-cell-instance-segmentation/LIVECell_dataset_2021/images/livecell_train_val_images/A172/A172_Phase_A7_1_00d00h00m_1.tif\"), cv2.COLOR_BGR2GRAY)\n#clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))\n#equalized = clahe.apply(gray)\n\n#plt.imshow(equalized, cmap=\"gray\")","metadata":{"execution":{"iopub.status.busy":"2022-11-17T16:03:23.350237Z","iopub.execute_input":"2022-11-17T16:03:23.350787Z","iopub.status.idle":"2022-11-17T16:03:23.372813Z","shell.execute_reply.started":"2022-11-17T16:03:23.350747Z","shell.execute_reply":"2022-11-17T16:03:23.371868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# always visualize data :>\nplt.title(CELL_TYPES[train_gen.labels[5]])\nplt.imshow(next(iter(train_gen))[0][5])","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:16:37.279494Z","iopub.execute_input":"2022-11-18T10:16:37.280775Z","iopub.status.idle":"2022-11-18T10:16:38.054184Z","shell.execute_reply.started":"2022-11-18T10:16:37.280733Z","shell.execute_reply":"2022-11-18T10:16:38.053345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(next(next(iter(val_gen)))[0][3])","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.title(CELL_TYPES[val_gen.labels[3]])\nplt.imshow(next(iter(val_gen))[0][3])","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:16:38.572614Z","iopub.execute_input":"2022-11-18T10:16:38.572953Z","iopub.status.idle":"2022-11-18T10:16:39.319769Z","shell.execute_reply.started":"2022-11-18T10:16:38.572925Z","shell.execute_reply":"2022-11-18T10:16:39.318469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Resampling","metadata":{}},{"cell_type":"code","source":"def resampling(df, resample=\"DOWN\", label=\"cell_type\"):\n    \"\"\"Returns the df that is sampled according to resample type.\"\"\"\n    df_res = df.copy()\n    dist_df = df[\"label\"].value_counts().rename_axis(label).reset_index(name=\"counts\")\n    counts = dist_df[\"counts\"]\n    y = df[label]\n    \n    if resampling == \"DOWN\":\n        min_counts = min(counts)\n        for idx in range(NUM_CLASSES):\n            if ((counts.iloc[idx] - min_counts) / counts.iloc[idx]) > 0.01:\n                class_i = dist_df[label].iloc[idx]\n                list_idx_i = list(df_res[class_i == y].index)\n                list_idx_sample = random.sample(list_idx_i, counts[idx] - int(min_counts*1.001))\n                list_idx_sample = sorted(list(list_idx_sample))\n                df_res = df_res.drop(list_idx_sample, axis=0)\n        df_res = df_res.reset_index(drop=True)\n        \n    if resampling == \"UP\":\n        max_counts = max(counts)\n        for idx in range(NUM_CLASSES):\n            if ((max_counts - counts.iloc[idx]) / max_counts) > 0.05:\n                class_i = dist_df[label].iloc[idx]\n                list_idx_i = list(df_res[class_i == y].index)\n                list_idx_sample = random.choices(list_idx_i, k=(max_counts - counts[idx]))\n                list_idx_sample = list(list_idx_sample)\n                df_res_up = df_res.iloc[list_idx_sample]\n                df_res = df_Res.appedn(df_res_up)\n        df_res = df_res.sample(frac=1).reset_index(drop=True)\n\n\n    return df_res","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications.resnet50 import ResNet50\n\nbase_model = ResNet50(include_top=False,\n                     input_shape=(HEIGHT, WIDTH, 3),)","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:50:01.660978Z","iopub.execute_input":"2022-11-18T10:50:01.661357Z","iopub.status.idle":"2022-11-18T10:50:03.337842Z","shell.execute_reply.started":"2022-11-18T10:50:01.661325Z","shell.execute_reply":"2022-11-18T10:50:03.336844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for layer in base_model.layers[:-10]:\n    layer.trainable = False","metadata":{"execution":{"iopub.status.busy":"2022-11-18T10:50:04.717066Z","iopub.execute_input":"2022-11-18T10:50:04.717399Z","iopub.status.idle":"2022-11-18T10:50:04.728772Z","shell.execute_reply.started":"2022-11-18T10:50:04.717370Z","shell.execute_reply":"2022-11-18T10:50:04.727505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.keras.backend.clear_session()\n\nmodel_classification = Sequential([\n    base_model,\n    Dropout(0.2),\n    \n    Conv2D(32, (3,3), activation=\"relu\"),\n    Conv2D(32, (3,3), activation=\"relu\"),\n    MaxPooling2D(2,2),\n    BatchNormalization(),\n\n    Conv2D(32, (3,3), activation=\"relu\"),\n    Conv2D(32, (3,3), activation=\"relu\"),\n    MaxPooling2D(2,2),\n    BatchNormalization(),\n\n    Flatten(),\n    Dense(32, activation=\"relu\"),\n    Dense(9, activation=\"softmax\")\n])","metadata":{"execution":{"iopub.status.busy":"2022-11-18T11:53:20.198324Z","iopub.execute_input":"2022-11-18T11:53:20.199316Z","iopub.status.idle":"2022-11-18T11:53:20.668266Z","shell.execute_reply.started":"2022-11-18T11:53:20.199278Z","shell.execute_reply":"2022-11-18T11:53:20.667255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras import backend as K\nimport tensorflow as tf\n\n# Compatible with tensorflow backend\n\ndef focal_loss(gamma=2., alpha=.25):\n    def focal_loss_fixed(y_true, y_pred):\n        pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))\n        pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))\n        return -K.mean(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1+K.epsilon())) - K.mean((1 - alpha) * K.pow(pt_0, gamma) * K.log(1. - pt_0 + K.epsilon()))\n    return focal_loss_fixed","metadata":{"execution":{"iopub.status.busy":"2022-11-18T11:53:20.925875Z","iopub.execute_input":"2022-11-18T11:53:20.926473Z","iopub.status.idle":"2022-11-18T11:53:20.935024Z","shell.execute_reply.started":"2022-11-18T11:53:20.926415Z","shell.execute_reply":"2022-11-18T11:53:20.934007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=7)","metadata":{"execution":{"iopub.status.busy":"2022-11-18T11:53:21.392018Z","iopub.execute_input":"2022-11-18T11:53:21.392678Z","iopub.status.idle":"2022-11-18T11:53:21.397688Z","shell.execute_reply.started":"2022-11-18T11:53:21.392633Z","shell.execute_reply":"2022-11-18T11:53:21.396393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#optim = tf.keras.optimizers.Adam(learning_rate=0.0009)\noptim = tf.keras.optimizers.SGD()\n\nmodel_classification.compile(optimizer=optim, loss=focal_loss(), metrics=[\"accuracy\", tf.keras.metrics.AUC(name=\"AUC\")])","metadata":{"execution":{"iopub.status.busy":"2022-11-18T11:53:22.045854Z","iopub.execute_input":"2022-11-18T11:53:22.046144Z","iopub.status.idle":"2022-11-18T11:53:22.063908Z","shell.execute_reply.started":"2022-11-18T11:53:22.046117Z","shell.execute_reply":"2022-11-18T11:53:22.062678Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model_classification.fit(train_gen, validation_data=val_gen, epochs=200, callbacks=[callback])","metadata":{"execution":{"iopub.status.busy":"2022-11-18T11:53:22.664775Z","iopub.execute_input":"2022-11-18T11:53:22.665080Z","iopub.status.idle":"2022-11-18T13:02:27.749997Z","shell.execute_reply.started":"2022-11-18T11:53:22.665053Z","shell.execute_reply":"2022-11-18T13:02:27.748929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot the results\n\neps = range(len(history.history[\"loss\"]))\nplt.figure(figsize=(10, 6))\nplt.plot(eps, history.history[\"loss\"])\nplt.plot(eps, history.history[\"val_loss\"])\nplt.legend([\"loss\", \"val_loss\"])\nplt.savefig(\"cell_classification_2021_loss.png\")\n\neps = range(len(history.history[\"accuracy\"]))\nplt.figure(figsize=(10, 6))\nplt.plot(eps, history.history[\"accuracy\"])\nplt.plot(eps, history.history[\"val_accuracy\"])\nplt.legend([\"accuracy\", \"val_accuracy\"])\nplt.savefig(\"cell_classification_2021_acc.png\")","metadata":{"execution":{"iopub.status.busy":"2022-11-18T13:07:43.708171Z","iopub.execute_input":"2022-11-18T13:07:43.708806Z","iopub.status.idle":"2022-11-18T13:07:44.286936Z","shell.execute_reply.started":"2022-11-18T13:07:43.708725Z","shell.execute_reply":"2022-11-18T13:07:44.285898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_classification.save(\"cell_classification_2021.h5\")","metadata":{"execution":{"iopub.status.busy":"2022-11-18T13:06:19.196527Z","iopub.execute_input":"2022-11-18T13:06:19.196920Z","iopub.status.idle":"2022-11-18T13:06:19.613657Z","shell.execute_reply.started":"2022-11-18T13:06:19.196890Z","shell.execute_reply":"2022-11-18T13:06:19.612674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}