{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":45867,"databundleVersionId":6924515,"sourceType":"competition"},{"sourceId":6661702,"sourceType":"datasetVersion","datasetId":3844162}],"dockerImageVersionId":30558,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\n\nimport numpy as np\nimport pandas as pd\nimport shutil\n\nfrom matplotlib import pyplot as plt\nimport PIL\nfrom PIL import Image\nfrom tqdm import tqdm\n\nfrom sklearn.metrics import confusion_matrix, balanced_accuracy_score, ConfusionMatrixDisplay\nfrom sklearn.model_selection import train_test_split\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.models import Sequential, load_model\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.applications import EfficientNetV2S\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\n\nPIL.Image.MAX_IMAGE_PIXELS = 9331200000000","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-13T05:35:02.688792Z","iopub.execute_input":"2023-12-13T05:35:02.689785Z","iopub.status.idle":"2023-12-13T05:35:13.398283Z","shell.execute_reply.started":"2023-12-13T05:35:02.689751Z","shell.execute_reply":"2023-12-13T05:35:13.397268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!kaggle competitions download -c UBC-OCEAN -f train_images/2906.png","metadata":{"execution":{"iopub.status.busy":"2023-12-13T05:50:24.711574Z","iopub.execute_input":"2023-12-13T05:50:24.711959Z","iopub.status.idle":"2023-12-13T05:50:26.055808Z","shell.execute_reply.started":"2023-12-13T05:50:24.711929Z","shell.execute_reply":"2023-12-13T05:50:26.054655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.__version__","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.658941Z","iopub.execute_input":"2023-12-09T15:18:17.65964Z","iopub.status.idle":"2023-12-09T15:18:17.669033Z","shell.execute_reply.started":"2023-12-09T15:18:17.659602Z","shell.execute_reply":"2023-12-09T15:18:17.667604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()\n    print(\"Device:\", tpu.master())\n    strategy = tf.distribute.TPUStrategy(tpu)\nexcept ValueError:\n    print(\"Not connected to a TPU runtime. Using CPU/GPU strategy\")\n    strategy = tf.distribute.MirroredStrategy()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.670749Z","iopub.execute_input":"2023-12-09T15:18:17.671222Z","iopub.status.idle":"2023-12-09T15:18:17.792076Z","shell.execute_reply.started":"2023-12-09T15:18:17.671178Z","shell.execute_reply":"2023-12-09T15:18:17.790851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Defining variables","metadata":{}},{"cell_type":"code","source":"# Copying train_meta data into other data folder\n\nPATH_DIR_2964_PNG = '/kaggle/input/ubc-reduced-png-2964x2964'\nPATH_DIR = '/kaggle/input/UBC-OCEAN'\n\nIMG_SIZE = 600\nNUM_CLASSES = 5\n\nbatch_size = 8","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.795409Z","iopub.execute_input":"2023-12-09T15:18:17.79577Z","iopub.status.idle":"2023-12-09T15:18:17.802457Z","shell.execute_reply.started":"2023-12-09T15:18:17.795739Z","shell.execute_reply":"2023-12-09T15:18:17.800835Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Reading the Training Metadata","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv(os.path.join(PATH_DIR, 'train.csv'))\ntest_df = pd.read_csv(os.path.join(PATH_DIR, 'test.csv'))","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.804439Z","iopub.execute_input":"2023-12-09T15:18:17.805647Z","iopub.status.idle":"2023-12-09T15:18:17.840052Z","shell.execute_reply.started":"2023-12-09T15:18:17.805605Z","shell.execute_reply":"2023-12-09T15:18:17.838633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.shape, test_df.shape","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.841952Z","iopub.execute_input":"2023-12-09T15:18:17.842327Z","iopub.status.idle":"2023-12-09T15:18:17.850625Z","shell.execute_reply.started":"2023-12-09T15:18:17.842294Z","shell.execute_reply":"2023-12-09T15:18:17.849136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.852279Z","iopub.execute_input":"2023-12-09T15:18:17.852973Z","iopub.status.idle":"2023-12-09T15:18:17.879296Z","shell.execute_reply.started":"2023-12-09T15:18:17.852934Z","shell.execute_reply":"2023-12-09T15:18:17.878208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Total Number Of Unique Images In Training: \", train_df['image_id'].nunique())","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.880595Z","iopub.execute_input":"2023-12-09T15:18:17.880981Z","iopub.status.idle":"2023-12-09T15:18:17.892224Z","shell.execute_reply.started":"2023-12-09T15:18:17.880948Z","shell.execute_reply":"2023-12-09T15:18:17.890723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"encode = {lbl: idx for idx, lbl in enumerate(train_df.label.unique())}\nencode","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.893687Z","iopub.execute_input":"2023-12-09T15:18:17.894328Z","iopub.status.idle":"2023-12-09T15:18:17.909144Z","shell.execute_reply.started":"2023-12-09T15:18:17.894102Z","shell.execute_reply":"2023-12-09T15:18:17.907874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"decode = {lbl: idx for idx, lbl in encode.items()}\ndecode","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.914654Z","iopub.execute_input":"2023-12-09T15:18:17.915179Z","iopub.status.idle":"2023-12-09T15:18:17.925058Z","shell.execute_reply.started":"2023-12-09T15:18:17.915128Z","shell.execute_reply":"2023-12-09T15:18:17.923525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def get_file_path(image_id):\n#     if os.path.exists(f\"{PATH_DIR}/train_thumbnails/{image_id}_thumbnail.png\"):\n#         return f\"{PATH_DIR}/train_thumbnails/{image_id}_thumbnail.png\"\n#     else:\n#         return f\"{PATH_DIR}/train_images/{image_id}.png\"\n\ndef get_file_path(image_id):\n    return f\"{PATH_DIR_2964_PNG}/{image_id}.png\"\n    \n\ntrain_df['file_path'] = train_df['image_id'].apply(get_file_path)\ntrain_df['label_id'] = train_df['label'].map(encode)\n\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.926981Z","iopub.execute_input":"2023-12-09T15:18:17.927562Z","iopub.status.idle":"2023-12-09T15:18:17.95156Z","shell.execute_reply.started":"2023-12-09T15:18:17.927456Z","shell.execute_reply":"2023-12-09T15:18:17.950339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Class Distribution","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,6))\n\ntmp = train_df.groupby(['label'])['image_id'].nunique().plot(kind='pie', autopct=\"%0.2f\")\nplt.gca().get_yaxis().set_visible(False)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:17.953152Z","iopub.execute_input":"2023-12-09T15:18:17.954004Z","iopub.status.idle":"2023-12-09T15:18:18.202774Z","shell.execute_reply.started":"2023-12-09T15:18:17.953957Z","shell.execute_reply":"2023-12-09T15:18:18.201106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## How many are TMA images?","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,6))\ntrain_df.groupby('is_tma')['image_id'].nunique().plot(kind='pie', autopct=\"%0.2f\")\nplt.gca().get_yaxis().set_visible(False)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:18.204638Z","iopub.execute_input":"2023-12-09T15:18:18.205449Z","iopub.status.idle":"2023-12-09T15:18:18.372017Z","shell.execute_reply.started":"2023-12-09T15:18:18.205382Z","shell.execute_reply":"2023-12-09T15:18:18.368753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Image Visualization - Thumbnail","metadata":{}},{"cell_type":"code","source":"img = Image.open(\"/kaggle/input/UBC-OCEAN/train_thumbnails/4_thumbnail.png\")\nprint(\"Image Size: \", img.size)\nprint(\"Image Labels: \", train_df.loc[train_df['image_id']== 4, 'label'].values[0])\nimg","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:18.374541Z","iopub.execute_input":"2023-12-09T15:18:18.375566Z","iopub.status.idle":"2023-12-09T15:18:20.997177Z","shell.execute_reply.started":"2023-12-09T15:18:18.375499Z","shell.execute_reply":"2023-12-09T15:18:20.99475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = train_df.copy()\ndf.rename(columns={'image_id':'org', 'file_path':'image_id'}, inplace=True)\ndf","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:21.000393Z","iopub.execute_input":"2023-12-09T15:18:21.000982Z","iopub.status.idle":"2023-12-09T15:18:21.039892Z","shell.execute_reply.started":"2023-12-09T15:18:21.000922Z","shell.execute_reply":"2023-12-09T15:18:21.038871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Splitting data into Train and Validation","metadata":{}},{"cell_type":"code","source":"# gkf  = GroupKFold(n_splits = 4)\n\n# train_df['fold'] = -1\n\n# for fold, (train_idx, val_idx) in enumerate(gkf.split(train_df, \n#                                                       groups = train_df.image_id.tolist())):\n#     train_df.loc[val_idx, 'fold'] = fold\n    \n# train_df.head()\n\nx_train, x_valid = train_test_split(train_df, \n                                    test_size=0.3,\n                                    stratify=train_df['label'],\n                                    random_state=143\n                                   )\nprint(x_train.shape)\nprint(x_valid.shape)","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:21.041463Z","iopub.execute_input":"2023-12-09T15:18:21.04211Z","iopub.status.idle":"2023-12-09T15:18:21.053688Z","shell.execute_reply.started":"2023-12-09T15:18:21.042072Z","shell.execute_reply":"2023-12-09T15:18:21.052666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train_files = []\n# valid_files   = []\n# valid_files += list(train_df[train_df.fold==1]['image_id'].unique())\n# train_files += list(train_df[train_df.fold!=1]['image_id'].unique())\n\ntrain_files = x_train['image_id'].unique().tolist()\nvalid_files = x_valid['image_id'].unique().tolist()\n\nprint(\"Training Images: \", len(train_files))\nprint(\"Validation Images: \", len(valid_files))","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:21.055302Z","iopub.execute_input":"2023-12-09T15:18:21.055964Z","iopub.status.idle":"2023-12-09T15:18:21.067078Z","shell.execute_reply.started":"2023-12-09T15:18:21.055925Z","shell.execute_reply":"2023-12-09T15:18:21.066026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Validation that Validation images are not in training Files\n(pd.Series(valid_files).isin(pd.Series(train_files))).sum()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:21.06863Z","iopub.execute_input":"2023-12-09T15:18:21.06905Z","iopub.status.idle":"2023-12-09T15:18:21.091244Z","shell.execute_reply.started":"2023-12-09T15:18:21.069014Z","shell.execute_reply":"2023-12-09T15:18:21.090147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_image(filename):\n    img = load_img(filename, target_size=(IMG_SIZE, IMG_SIZE))\n    img = img_to_array(img)\n    return img\n\nX_train = []\ny_train = []\n\nX_valid = []\ny_valid = []\n\n## Training \nfor i in tqdm(range(len(train_files))):\n    file_path = train_df.iloc[i]['file_path']\n    label = train_df.iloc[i]['label_id']\n    X_train.append(load_image(file_path))\n    y_train.append(label)\n\n# Convert the data to numpy arrays\nX_train = np.array(X_train)\ny_train = np.array(y_train)\n\n# Print the shape of the data arrays\nprint('X_train shape:', X_train.shape)\nprint('y_train shape:', y_train.shape)\n\n\n## Validation\nfor i in tqdm(range(len(valid_files))):\n    file_path = train_df.iloc[i]['file_path']\n    label = train_df.iloc[i]['label_id']\n    X_valid.append(load_image(file_path))\n    y_valid.append(label)\n\n# Convert the data to numpy arrays\nX_valid = np.array(X_valid)\ny_valid = np.array(y_valid)\n\n# Print the shape of the data arrays\nprint('X_valid shape:', X_valid.shape)\nprint('y_valid shape:', y_valid.shape)\n\n\n# Converting into tensor flow dataset\nds_train = tf.data.Dataset.from_tensor_slices((X_train, y_train))\nds_valid = tf.data.Dataset.from_tensor_slices((X_valid, y_valid))","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:18:21.093042Z","iopub.execute_input":"2023-12-09T15:18:21.093491Z","iopub.status.idle":"2023-12-09T15:22:16.101174Z","shell.execute_reply.started":"2023-12-09T15:18:21.093452Z","shell.execute_reply":"2023-12-09T15:22:16.099688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualizing Images\nThough not able to understand any thing from image :-)","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,10))\n\nfor i, (image, label) in enumerate(ds_train.take(9)):\n    ax = plt.subplot(3, 3, i + 1)\n    plt.imshow(image.numpy().astype(\"uint16\"))\n    plt.title(\"{}\".format(decode[label.numpy()]))\n    plt.axis(\"off\")\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:22:16.103203Z","iopub.execute_input":"2023-12-09T15:22:16.103615Z","iopub.status.idle":"2023-12-09T15:22:21.395838Z","shell.execute_reply.started":"2023-12-09T15:22:16.103566Z","shell.execute_reply":"2023-12-09T15:22:21.393095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Augmentation","metadata":{}},{"cell_type":"code","source":"img_augmentation = Sequential(\n    [\n        layers.RandomRotation(factor=0.15),\n        layers.RandomTranslation(height_factor=0.1, width_factor=0.1),\n        layers.RandomFlip(),\n        layers.RandomContrast(factor=0.1),\n    ],\n    name=\"img_augmentation\",\n)","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:22:21.398423Z","iopub.execute_input":"2023-12-09T15:22:21.398807Z","iopub.status.idle":"2023-12-09T15:22:21.426649Z","shell.execute_reply.started":"2023-12-09T15:22:21.398754Z","shell.execute_reply":"2023-12-09T15:22:21.425603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualizing Augmentated Images","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,10))\n\nfor image, label in ds_train.take(1):\n    for i in range(9):\n        ax = plt.subplot(3, 3, i + 1)\n        aug_img = img_augmentation(tf.expand_dims(image, axis=0))\n        plt.imshow(aug_img[0].numpy().astype(\"uint8\"))\n        plt.title(\"{}\".format(decode[label.numpy()]))\n        plt.axis(\"off\")\n        \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:22:21.428016Z","iopub.execute_input":"2023-12-09T15:22:21.428336Z","iopub.status.idle":"2023-12-09T15:22:26.009828Z","shell.execute_reply.started":"2023-12-09T15:22:21.428307Z","shell.execute_reply":"2023-12-09T15:22:26.008432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Converting labels into One hot ","metadata":{}},{"cell_type":"code","source":"def input_preprocess(image, label):\n    label = tf.one_hot(label, NUM_CLASSES)\n    return image, label\n\n\nds_train = ds_train.map(\n    input_preprocess, num_parallel_calls=tf.data.AUTOTUNE\n)\n\nds_train = ds_train.batch(batch_size=batch_size)\nds_train = ds_train.prefetch(tf.data.AUTOTUNE)\n\nds_valid = ds_valid.map(input_preprocess)\nds_valid = ds_valid.batch(batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:22:26.011649Z","iopub.execute_input":"2023-12-09T15:22:26.01205Z","iopub.status.idle":"2023-12-09T15:22:26.104083Z","shell.execute_reply.started":"2023-12-09T15:22:26.012013Z","shell.execute_reply":"2023-12-09T15:22:26.102685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model(num_classes):\n    \n    inputs = layers.Input(shape=(IMG_SIZE, IMG_SIZE, 3))\n    x = img_augmentation(inputs)\n    \n    model = EfficientNetV2S(include_top=False, input_tensor=x, weights=\"imagenet\")\n\n    # Freeze the pretrained weights\n    model.trainable = False\n    \n    no_of_layers = len(model.layers)\n    no_of_layers_to_train = int(np.round(no_of_layers/1.5))\n    \n    for layer in model.layers[-no_of_layers_to_train:]:\n        if not isinstance(layer, layers.BatchNormalization):\n            layer.trainable = True\n\n    # Rebuild top\n    x = layers.GlobalAveragePooling2D(name=\"avg_pool\")(model.output)\n    x = layers.BatchNormalization()(x)\n\n    top_dropout_rate = 0.2\n    x = layers.Dropout(top_dropout_rate, name=\"top_dropout\")(x)\n    outputs = layers.Dense(num_classes, activation=\"softmax\", name=\"pred\")(x)\n\n    # Compile\n    model = tf.keras.Model(inputs, outputs, name=\"EfficientNet\")\n    \n    \n    optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4)\n    \n    METRICS = [\n      keras.metrics.Recall(name='recall'),\n      keras.metrics.AUC(name='prc', curve='PR')]\n    \n    model.compile(\n        optimizer=optimizer,\n        loss=\"categorical_crossentropy\",\n        metrics= [METRICS]\n    )\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:22:26.1059Z","iopub.execute_input":"2023-12-09T15:22:26.106777Z","iopub.status.idle":"2023-12-09T15:22:26.118152Z","shell.execute_reply.started":"2023-12-09T15:22:26.106729Z","shell.execute_reply":"2023-12-09T15:22:26.116946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_hist(hist, monitor='loss'):\n    plt.plot(hist.history[monitor])\n    plt.plot(hist.history[f\"val_{monitor}\"])\n    plt.title(f\"model {monitor}\")\n    plt.ylabel(f\"{monitor}\")\n    plt.xlabel(\"epoch\")\n    plt.legend([\"train\", \"validation\"], loc=\"upper left\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:22:26.120061Z","iopub.execute_input":"2023-12-09T15:22:26.120472Z","iopub.status.idle":"2023-12-09T15:22:26.139871Z","shell.execute_reply.started":"2023-12-09T15:22:26.120438Z","shell.execute_reply":"2023-12-09T15:22:26.138897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [\n    keras.callbacks.ModelCheckpoint(\"UBC-OCEAN_{epoch}_2964.h5\",\n                                    monitor='val_loss',\n                                    save_best_only=True\n                                   ),\n    keras.callbacks.EarlyStopping(monitor='val_loss', \n                                  verbose=1,\n                                  patience=10, \n                                  mode='min',\n                                  restore_best_weights=True)\n]\n\nEPOCHS = 50\n\nwith strategy.scope():\n    model = build_model(num_classes=NUM_CLASSES)\n\n\n\nhist = model.fit(ds_train, \n                 epochs=EPOCHS, \n                 callbacks=callbacks,\n                 validation_data=ds_valid\n                )\n\nplot_hist(hist)","metadata":{"execution":{"iopub.status.busy":"2023-12-09T15:22:26.141445Z","iopub.execute_input":"2023-12-09T15:22:26.142537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def cal_bal_acc(y_true, y_pred):\n    \n    bal_acc = balanced_accuracy_score(y_true,pred)\n    cm = confusion_matrix(y_true, y_pred)\n    cmd = ConfusionMatrixDisplay(cm, display_labels=encode.keys())\n    cmd.plot()\n    print(\"Balanced Accuracy: \", bal_acc)\n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred = model.predict(ds_valid)\npred = pred.argmax(axis=-1)\ncal_bal_acc(y_valid, pred)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}