{"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":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n\nprint(\"TensorFlow version:\", tf.__version__)\n\ntry: # detect TPUs\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect() # TPU detection\n    strategy = tf.distribute.TPUStrategy(tpu)\nexcept ValueError: # detect GPUs\n    strategy = tf.distribute.MirroredStrategy() # for GPU or multi-GPU machines\n    #strategy = tf.distribute.get_strategy() # default strategy that works on CPU and single GPU\n    #strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy() # for clusters of multi-GPU machines\n\nprint(\"Number of accelerators: \", strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T11:49:44.116402Z","iopub.execute_input":"2023-10-23T11:49:44.116741Z","iopub.status.idle":"2023-10-23T11:50:32.669340Z","shell.execute_reply.started":"2023-10-23T11:49:44.116716Z","shell.execute_reply":"2023-10-23T11:50:32.668182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image, ImageOps\nimport os\nimport shutil\n\n# Define the image directory\nimage_dir = '/kaggle/input/skinlesionretina/my_model/train_images'\n\n# Define the target size for resizing\ntarget_size = (331, 331)\n\n# Create a directory to store resized images (if it doesn't exist)\nresized_dir = 'resized_images_final'\n\nif os.path.exists(resized_dir):\n    shutil.rmtree(resized_dir)\n    print(f\"Directory '{resized_dir}' has been deleted.\")\n\nos.makedirs(resized_dir, exist_ok=True)\n\n# Get a list of image filenames in the directory\nimage_filenames = sorted(os.listdir(image_dir))\n\n# Loop through each image and resize it\nfor image_filename in image_filenames:\n    # Open the image\n    image_path = os.path.join(image_dir, image_filename)\n    image = Image.open(image_path)\n    \n    # Resize the image to the target size with LANCZOS filter\n    resized_image = ImageOps.fit(image, target_size, Image.LANCZOS)\n    \n    # Save the resized image to the resized directory\n    resized_image.save(os.path.join(resized_dir, image_filename))\n    \nprint(f\"Resized {len(image_filenames)} images to {target_size}.\")\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T11:50:43.304520Z","iopub.execute_input":"2023-10-23T11:50:43.304943Z","iopub.status.idle":"2023-10-23T12:10:57.313217Z","shell.execute_reply.started":"2023-10-23T11:50:43.304910Z","shell.execute_reply":"2023-10-23T12:10:57.311962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\ncsv_file2 = '/kaggle/input/aptos2019-blindness-detection/train.csv'\ndf2 = pd.read_csv(csv_file2)\ndf2.iloc[:, 1] = 0\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:15:22.109657Z","iopub.execute_input":"2023-10-23T12:15:22.110081Z","iopub.status.idle":"2023-10-23T12:15:22.130383Z","shell.execute_reply.started":"2023-10-23T12:15:22.110051Z","shell.execute_reply":"2023-10-23T12:15:22.129407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport os\nimport pandas as pd\nimport numpy as np\nimport shutil\n\n# Define the directory where your images are stored\nimage_dir = '/kaggle/working/resized_images_final/'\n\n# Define the input TFRecord file\n# input_tfrecord = '/kaggle/input/aptos2019-blindness-detection/datasetFinal.tfrecord'\n\n# Define the output directory for split TFRecord files\noutput_dir = '/kaggle/working/split_tfrecords/'\n\nif os.path.exists(output_dir):\n    shutil.rmtree(output_dir)\n    print(f\"Directory '{output_dir}' has been deleted.\")\n\n# Ensure the output directory exists\nos.makedirs(output_dir, exist_ok=True)\n\n# Define the number of split TFRecord files you want to create\nnum_split_files = 6\n\n# Read the CSV file to get image labels as lists of 0s and 1s\ncsv_file = '/kaggle/input/skinlesionretina/my_model/train.csv'\ndf1 = pd.read_csv(csv_file)\n\n# Delete the first 3662 rows from df1\ndf1 = df1.iloc[3662:]\n\n# Concatenate df2 at the top\ndf = pd.concat([df2, df1])\n\n# Function to encode image and label into a TFRecord example\ndef create_tfrecord_example(image_path, label):\n    with tf.io.gfile.GFile(image_path, 'rb') as f:\n        image = f.read()\n\n    feature = {\n        'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),\n        'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),\n    }\n\n    example = tf.train.Example(features=tf.train.Features(feature=feature))\n    return example\n\n# Create a TFRecord writer for each split\nfor i in range(num_split_files):\n    # Create a TFRecord writer for the split\n    split_filename = os.path.join(output_dir, f'split_{i}.tfrecord')\n    with tf.io.TFRecordWriter(split_filename) as writer:\n        # Calculate the range of records to write to this split\n        start = i * (len(df) // num_split_files)\n        end = (i + 1) * (len(df) // num_split_files)\n\n        for index in range(start, end):\n            image_id = df['id_code'][index]\n            label = df['diagnosis'][index]\n            if image_id.startswith('ISIC'):\n                image_path = os.path.join(image_dir, f\"{image_id}.jpg\")\n            else:\n                image_path = os.path.join(image_dir, f\"{image_id}.png\")\n            tf_example = create_tfrecord_example(image_path, label)\n            writer.write(tf_example.SerializeToString())\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:15:37.076447Z","iopub.execute_input":"2023-10-23T12:15:37.076869Z","iopub.status.idle":"2023-10-23T12:15:39.448277Z","shell.execute_reply.started":"2023-10-23T12:15:37.076838Z","shell.execute_reply":"2023-10-23T12:15:39.447042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport os\nimport shutil\n# import tensorflow.experimental.numpy as tnp  # Import TensorFlow's NumPy API\nimport cv2\nimport numpy as np\n\nAUTO = tf.data.experimental.AUTOTUNE\n\n# Define the image size\nIMAGE_SIZE = [331, 331]\n\n# Define other parameters\nnum_classes = 3\nbatch_size = 16 * strategy.num_replicas_in_sync\n\n# Define the directory path for TFRecord files\ntfrecords_dir = 'split_tfrecords/'\n\n\n# Set the validation split ratio\nvalidation_split = 0.20\n\n# Get the list of TFRecord filenames\nfilenames = tf.io.gfile.glob(os.path.join(tfrecords_dir, 'split_*.tfrecord'))\n\n# Calculate the split point\nsplit = len(filenames) - int(len(filenames) * validation_split)\n\n# Split filenames into training and validation\ntrain_filenames = filenames[:split]\nvalidation_filenames = filenames[split:]\n\n# Updated TFRecord feature description\nfeature_description = {\n    'image': tf.io.FixedLenFeature([], tf.string),\n    'label': tf.io.FixedLenFeature([], tf.int64),\n}\n\n\ndef parse_tfrecord(example):\n    example = tf.io.parse_single_example(example, feature_description)\n    image = tf.io.decode_png(example['image'], channels=3)\n    \n    normalized = tf.cast(image, tf.float32) / 255.0 # convert each 0-255 value to floats in [0, 1] range\n    image_tensor = tf.reshape(normalized, [*IMAGE_SIZE, 3])\n    \n    label = example['label']\n    \n    # Convert label to one-hot encoded format\n    one_hot_label = tf.one_hot(label, num_classes)\n    \n    return image_tensor, one_hot_label\n\n\ndef load_dataset(filenames):\n    records = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTO)\n    return records.map(parse_tfrecord, num_parallel_calls=AUTO)\n\ndef data_augment(image, label):\n    modified = tf.image.random_flip_left_right(image)\n    modified = tf.image.random_saturation(modified, 0, 2)\n    return modified, label\n\ndef get_training_dataset():\n    dataset = load_dataset(train_filenames)\n    augmented = dataset.map(data_augment, num_parallel_calls=AUTO)\n    return augmented.repeat().shuffle(2048).batch(batch_size).prefetch(AUTO)\n\ndef get_validation_dataset():\n    return load_dataset(validation_filenames).batch(batch_size).prefetch(AUTO)\n\n# Create training and validation datasets\ntraining_dataset = get_training_dataset()\nvalidation_dataset = get_validation_dataset()\n\n# Print dataset information\nprint(training_dataset)\nprint(validation_dataset)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:15:51.195660Z","iopub.execute_input":"2023-10-23T12:15:51.196080Z","iopub.status.idle":"2023-10-23T12:15:52.327060Z","shell.execute_reply.started":"2023-10-23T12:15:51.196049Z","shell.execute_reply":"2023-10-23T12:15:52.325825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nimport matplotlib.pyplot as plt\n\ndef display_one_image(image, title, subplot, color):\n  plt.subplot(subplot)\n  plt.axis('off')\n  plt.imshow(image)\n  plt.title(title, fontsize=16, color=color)\n  \n# If model is provided, use it to generate predictions.\ndef display_nine_images(images, titles, title_colors=None):\n  subplot = 331\n  plt.figure(figsize=(13,13))\n  for i in range(9):\n    color = 'black' if title_colors is None else title_colors[i]\n    display_one_image(images[i], titles[i], 331+i, color)\n  plt.tight_layout()\n  plt.subplots_adjust(wspace=0.1, hspace=0.1)\n  plt.show()\n\ndef get_dataset_iterator(dataset, n_examples):\n  return dataset.unbatch().batch(n_examples).as_numpy_iterator()\n\n\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:15:56.956541Z","iopub.execute_input":"2023-10-23T12:15:56.956956Z","iopub.status.idle":"2023-10-23T12:15:58.102446Z","shell.execute_reply.started":"2023-10-23T12:15:56.956927Z","shell.execute_reply":"2023-10-23T12:15:58.101197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_viz_iterator = get_dataset_iterator(training_dataset, 9)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:16:44.401669Z","iopub.execute_input":"2023-10-23T12:16:44.402048Z","iopub.status.idle":"2023-10-23T12:16:44.921264Z","shell.execute_reply.started":"2023-10-23T12:16:44.402018Z","shell.execute_reply":"2023-10-23T12:16:44.920186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Define a dictionary to map label numbers to label names\nlabel_names = {\n    0: 'Retina',    # Melanoma (Highly cancerous)\n    1: 'Skin',     # Melanocytic nevus (Not cancerous)\n    2: 'other',    # Basal cell carcinoma (Cancerous)\n}\n\n\n# Re-run this cell to show a new batch of images\nimages, classes = next(training_viz_iterator)\nclass_idxs = tf.argmax(classes, axis=-1).numpy() # transform from one-hot array to class number\nlabels = [label_names[idx] for idx in class_idxs]\ndisplay_nine_images(images, labels)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:16:49.363408Z","iopub.execute_input":"2023-10-23T12:16:49.363766Z","iopub.status.idle":"2023-10-23T12:16:52.276526Z","shell.execute_reply.started":"2023-10-23T12:16:49.363737Z","shell.execute_reply":"2023-10-23T12:16:52.275375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Extract one-hot encoded labels for the training dataset\ntrain_labels_one_hot = []\nfor record in load_dataset(train_filenames):\n    _, one_hot_label = record\n    train_labels_one_hot.append(one_hot_label.numpy())\n\ntrain_labels_one_hot = np.array(train_labels_one_hot)\n\n# Convert one-hot encoded labels back to normal label format\ntrain_labels = np.argmax(train_labels_one_hot, axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:17:03.449067Z","iopub.execute_input":"2023-10-23T12:17:03.449469Z","iopub.status.idle":"2023-10-23T12:17:04.759353Z","shell.execute_reply.started":"2023-10-23T12:17:03.449439Z","shell.execute_reply":"2023-10-23T12:17:04.758241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_labels.shape)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:17:10.253135Z","iopub.execute_input":"2023-10-23T12:17:10.253485Z","iopub.status.idle":"2023-10-23T12:17:10.258450Z","shell.execute_reply.started":"2023-10-23T12:17:10.253458Z","shell.execute_reply":"2023-10-23T12:17:10.257600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.utils.class_weight import compute_class_weight\n\n# Calculate class weights\nclass_weights = compute_class_weight(class_weight = 'balanced', classes = np.unique(train_labels), y = train_labels)\n\n# Convert class_weights to a dictionary format expected by TensorFlow\nclass_weight_dict = dict(enumerate(class_weights))\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:17:15.767238Z","iopub.execute_input":"2023-10-23T12:17:15.768278Z","iopub.status.idle":"2023-10-23T12:17:16.083812Z","shell.execute_reply.started":"2023-10-23T12:17:15.768211Z","shell.execute_reply":"2023-10-23T12:17:16.082921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(class_weight_dict)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:17:19.964531Z","iopub.execute_input":"2023-10-23T12:17:19.965347Z","iopub.status.idle":"2023-10-23T12:17:19.970418Z","shell.execute_reply.started":"2023-10-23T12:17:19.965246Z","shell.execute_reply":"2023-10-23T12:17:19.969564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_model():\n    pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3], include_top=False)\n    pretrained_model.trainable = True\n    model = tf.keras.Sequential([\n        pretrained_model,\n        tf.keras.layers.GlobalAveragePooling2D(),\n        tf.keras.layers.Dense(3, activation='softmax')  # Assuming 9 classes for your specific task\n    ])\n    model.compile(\n        optimizer='adam',\n        loss='categorical_crossentropy',\n        metrics=['accuracy']\n    )\n    return model\n\nwith strategy.scope():\n    model = create_model()\n\nmodel.summary()\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:28:01.274058Z","iopub.execute_input":"2023-10-23T12:28:01.274431Z","iopub.status.idle":"2023-10-23T12:28:10.156329Z","shell.execute_reply.started":"2023-10-23T12:28:01.274402Z","shell.execute_reply":"2023-10-23T12:28:10.155399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 10\n\nstart_lr = 0.00001\nmin_lr = 0.00001\nmax_lr = 0.00005 * strategy.num_replicas_in_sync\nrampup_epochs = 5\nsustain_epochs = 0\nexp_decay = .8\n\ndef lrfn(epoch):\n  if epoch < rampup_epochs:\n    return (max_lr - start_lr)/rampup_epochs * epoch + start_lr\n  elif epoch < rampup_epochs + sustain_epochs:\n    return max_lr\n  else:\n    return (max_lr - min_lr) * exp_decay**(epoch-rampup_epochs-sustain_epochs) + min_lr\n    \nlr_callback = tf.keras.callbacks.LearningRateScheduler(lambda epoch: lrfn(epoch), verbose=True)\n\nrang = np.arange(EPOCHS)\ny = [lrfn(x) for x in rang]\nplt.plot(rang, y)\nprint('Learning rate per epoch:')","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:28:21.390391Z","iopub.execute_input":"2023-10-23T12:28:21.390748Z","iopub.status.idle":"2023-10-23T12:28:21.572283Z","shell.execute_reply.started":"2023-10-23T12:28:21.390719Z","shell.execute_reply":"2023-10-23T12:28:21.571290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Calculate the number of training images\nnum_training_images = sum([sum(1 for _ in tf.data.TFRecordDataset(f, num_parallel_reads=AUTO)) for f in train_filenames])\nprint(num_training_images)\n# Calculate steps_per_epoch\nsteps_per_epoch = num_training_images // batch_size\nprint(steps_per_epoch)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:28:27.752929Z","iopub.execute_input":"2023-10-23T12:28:27.753317Z","iopub.status.idle":"2023-10-23T12:28:28.451618Z","shell.execute_reply.started":"2023-10-23T12:28:27.753286Z","shell.execute_reply":"2023-10-23T12:28:28.450562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a TensorBoard callback for monitoring the training process (optional)\ntensorboard_callback = TensorBoard(log_dir='./logs', histogram_freq=1)","metadata":{"execution":{"iopub.status.busy":"2023-09-27T12:23:56.311468Z","iopub.execute_input":"2023-09-27T12:23:56.311833Z","iopub.status.idle":"2023-09-27T12:23:56.317282Z","shell.execute_reply.started":"2023-09-27T12:23:56.311804Z","shell.execute_reply":"2023-09-27T12:23:56.316049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n    training_dataset,\n    steps_per_epoch=steps_per_epoch,\n    epochs=EPOCHS,\n    validation_data=validation_dataset,\n    callbacks=[lr_callback],\n    class_weight=class_weight_dict  # Pass the class weights here\n)\n\nfinal_accuracy = history.history[\"val_accuracy\"][-5:]\nprint(\"FINAL ACCURACY MEAN-5: \", np.mean(final_accuracy))","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:28:34.997325Z","iopub.execute_input":"2023-10-23T12:28:34.997738Z","iopub.status.idle":"2023-10-23T12:31:44.440202Z","shell.execute_reply.started":"2023-10-23T12:28:34.997706Z","shell.execute_reply":"2023-10-23T12:31:44.439011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef display_training_curves(training, validation, title, subplot):\n  ax = plt.subplot(subplot)\n  ax.plot(training)\n  ax.plot(validation)\n  ax.set_title('model '+ title)\n  ax.set_ylabel(title)\n  ax.set_xlabel('epoch')\n  ax.legend(['training', 'validation'])\n\nplt.subplots(figsize=(10,10))\nplt.tight_layout()\ndisplay_training_curves(history.history['accuracy'], history.history['val_accuracy'], 'accuracy', 211)\ndisplay_training_curves(history.history['loss'], history.history['val_loss'], 'loss', 212)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:31:49.266480Z","iopub.execute_input":"2023-10-23T12:31:49.266837Z","iopub.status.idle":"2023-10-23T12:31:49.770656Z","shell.execute_reply.started":"2023-10-23T12:31:49.266809Z","shell.execute_reply":"2023-10-23T12:31:49.769650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def disease_title(label, prediction):\n  # Both prediction (probabilities) and label (one-hot) are arrays with one item per class.\n  class_idx = np.argmax(label, axis=-1)\n  prediction_idx = np.argmax(prediction, axis=-1)\n  if class_idx == prediction_idx:\n    return f'{label_names[prediction_idx]} [correct]', 'black'\n  else:\n    return f'{label_names[prediction_idx]} [incorrect, should be {label_names[class_idx]}]', 'red'\n\ndef get_titles(images, labels, model):\n  predictions = model.predict(images)\n  titles, colors = [], []\n  for label, prediction in zip(labels, predictions):\n    title, color = disease_title(label, prediction)\n    titles.append(title)\n    colors.append(color)\n  return titles, colors\nvalidation_viz_iterator = get_dataset_iterator(validation_dataset, 9)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:51:24.127298Z","iopub.execute_input":"2023-10-23T12:51:24.127779Z","iopub.status.idle":"2023-10-23T12:51:24.285757Z","shell.execute_reply.started":"2023-10-23T12:51:24.127744Z","shell.execute_reply":"2023-10-23T12:51:24.284562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Re-run this cell to show a new batch of images\nimages, classes = next(validation_viz_iterator)\ntitles, colors = get_titles(images, classes, model)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:51:29.894821Z","iopub.execute_input":"2023-10-23T12:51:29.895168Z","iopub.status.idle":"2023-10-23T12:51:30.533601Z","shell.execute_reply.started":"2023-10-23T12:51:29.895141Z","shell.execute_reply":"2023-10-23T12:51:30.532309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_nine_images(images, titles, colors)","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:51:35.135843Z","iopub.execute_input":"2023-10-23T12:51:35.136255Z","iopub.status.idle":"2023-10-23T12:51:36.630493Z","shell.execute_reply.started":"2023-10-23T12:51:35.136223Z","shell.execute_reply":"2023-10-23T12:51:36.629068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('best_model.h5')","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:51:56.902665Z","iopub.execute_input":"2023-10-23T12:51:56.903064Z","iopub.status.idle":"2023-10-23T12:51:58.471150Z","shell.execute_reply.started":"2023-10-23T12:51:56.903034Z","shell.execute_reply":"2023-10-23T12:51:58.470100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile\n\nwith zipfile.ZipFile('out.zip', 'w') as zipf:\n    zipf.write('/kaggle/working/best_model.h5', 'best_model.h5')","metadata":{"execution":{"iopub.status.busy":"2023-10-23T12:52:08.076132Z","iopub.execute_input":"2023-10-23T12:52:08.076548Z","iopub.status.idle":"2023-10-23T12:52:08.679746Z","shell.execute_reply.started":"2023-10-23T12:52:08.076514Z","shell.execute_reply":"2023-10-23T12:52:08.678721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}