{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":45867,"databundleVersionId":6924515,"sourceType":"competition"},{"sourceId":6774400,"sourceType":"datasetVersion","datasetId":3895136},{"sourceId":6774553,"sourceType":"datasetVersion","datasetId":3898019},{"sourceId":7341804,"sourceType":"datasetVersion","datasetId":4262797},{"sourceId":154459349,"sourceType":"kernelVersion"}],"dockerImageVersionId":30616,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Installing Keras_cv_attention_models & Pyvips","metadata":{}},{"cell_type":"code","source":"!pip install /kaggle/input/keras-cv-attention-models-1-3-22/wcwidth-0.2.12-py2.py3-none-any.whl\n!pip install /kaggle/input/keras-cv-attention-models-1-3-22/ftfy-6.1.3-py3-none-any.whl\n!pip install /kaggle/input/keras-cv-attention-models-1-3-22/keras_cv_attention_models-1.3.22-py3-none-any.whl","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-01-05T06:28:09.905047Z","iopub.execute_input":"2024-01-05T06:28:09.905722Z","iopub.status.idle":"2024-01-05T06:29:47.469503Z","shell.execute_reply.started":"2024-01-05T06:28:09.905681Z","shell.execute_reply":"2024-01-05T06:29:47.468371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# https://www.kaggle.com/code/jirkaborovec/cancer-subtype-lightning-torch-inference-tiles\n\n!ls /kaggle/input/pyvips-python-and-deb-package-gpu\n# intall the deb packages\n!yes | dpkg -i --force-depends /kaggle/input/pyvips-python-and-deb-package-gpu/linux_packages/archives/*.deb\n# install the python wrapper\n!pip install pyvips -f /kaggle/input/pyvips-python-and-deb-package-gpu/python_packages/ --no-index","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-01-05T06:29:47.471472Z","iopub.execute_input":"2024-01-05T06:29:47.471783Z","iopub.status.idle":"2024-01-05T06:30:50.962723Z","shell.execute_reply.started":"2024-01-05T06:29:47.471756Z","shell.execute_reply":"2024-01-05T06:30:50.961752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pyvips\nimport numpy as np\nimport pandas as pd\nimport os, random, math, gc, cv2\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import GroupKFold, StratifiedKFold, KFold\nimport tensorflow as tf\nfrom tqdm import tqdm\nfrom keras_cv_attention_models import convnext, efficientnet, hornet, beit, davit\n\nos.environ['VIPS_CONCURRENCY'] = '4'\nos.environ['VIPS_DISC_THRESHOLD'] = '15gb'\n\nSEED=8677\nrandom.seed(SEED)\nos.environ['PYTHONHASHSEED'] = str(SEED)\nnp.random.seed(SEED)\ntf.random.set_seed(SEED)","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-01-05T06:30:50.964144Z","iopub.execute_input":"2024-01-05T06:30:50.964461Z","iopub.status.idle":"2024-01-05T06:31:04.718182Z","shell.execute_reply.started":"2024-01-05T06:30:50.964433Z","shell.execute_reply":"2024-01-05T06:31:04.717219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# FPN MODEL\n\nA single Convnext Base with FPN is used to select tiles from WSI using thumbnails.","metadata":{}},{"cell_type":"code","source":"def FPNBlock(inputs0, inputs1, output_channel, activation=\"gelu\", name=''):\n    nn0 = tf.keras.layers.Conv2D(output_channel, kernel_size=1, strides=1, padding=\"same\", name=name+'_conv2d_0')(inputs0)\n    nn1 = tf.keras.layers.Conv2D(output_channel, kernel_size=1, strides=1, padding=\"same\", name=name+'_conv2d_1')(inputs1)\n    nn1 = tf.keras.layers.UpSampling2D(2, name=name+'_up_0')(nn1)\n    nn = tf.keras.layers.Concatenate(name=name+'_merge_0')([nn0, nn1])\n    return nn\n\ndef UpBlockFinal(inputs, output_channel, activation=\"gelu\", name=''):\n    nn = tf.keras.layers.UpSampling2D(2, name=name+'_up_0')(inputs)\n    nn = tf.keras.layers.Conv2D(output_channel, kernel_size=3, strides=1, padding=\"same\", name=name+'_conv2d_0')(nn)\n    nn = tf.keras.layers.LayerNormalization(axis=-1, epsilon=1e-6, name=name+'_ln_0')(nn)\n    nn = tf.keras.layers.Activation(activation=activation, name=name+'_act_0')(nn)\n    nn = tf.keras.layers.Conv2D(output_channel, kernel_size=3, strides=1, padding=\"same\", name=name+'_conv2d_1')(nn)\n    nn = tf.keras.layers.LayerNormalization(axis=-1, epsilon=1e-6, name=name+'_ln_1')(nn)\n    nn = tf.keras.layers.Activation(activation=activation, name=name+'_act_1')(nn)\n    return nn\n\ndef ConvBlock(inputs, output_channel, activation=\"gelu\", name=''):\n    nn = tf.keras.layers.Conv2D(output_channel, kernel_size=3, strides=1, padding=\"same\", name=name+'_conv2d_0')(inputs)\n    nn = tf.keras.layers.LayerNormalization(axis=-1, epsilon=1e-6, name=name+'_ln_0')(nn)\n    nn = tf.keras.layers.Activation(activation=activation, name=name+'_act_0')(nn)\n    nn = tf.keras.layers.Conv2D(output_channel, kernel_size=3, strides=1, padding=\"same\", name=name+'_conv2d_1')(nn)\n    nn = tf.keras.layers.LayerNormalization(axis=-1, epsilon=1e-6, name=name+'_ln_1')(nn)\n    nn = tf.keras.layers.Activation(activation=activation, name=name+'_act_1')(nn)\n    return nn","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:31:04.720438Z","iopub.execute_input":"2024-01-05T06:31:04.720986Z","iopub.status.idle":"2024-01-05T06:31:04.735536Z","shell.execute_reply.started":"2024-01-05T06:31:04.720956Z","shell.execute_reply":"2024-01-05T06:31:04.734403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model_fpn(model_name='convnext', model_size='b'):\n    \n    if model_name == 'convnext':\n        \n        if model_size == 'b':\n    \n            base_layer = convnext.ConvNeXtBase(input_shape=(512,512,3), pretrained=None, \n                                               drop_connect_rate=0.1, num_classes=0)\n        else:\n            \n            base_layer = convnext.ConvNeXtSmall(input_shape=(512,512,3), pretrained=None, \n                                                drop_connect_rate=0.1, num_classes=0)\n\n        inputs = base_layer.input\n\n        nn0 = base_layer.get_layer('stack1_block1_output').output\n        nn1 = base_layer.get_layer('stack1_block3_output').output\n        nn2 = base_layer.get_layer('stack2_block3_output').output\n        nn3 = base_layer.get_layer('stack3_block27_output').output\n        nn4 = base_layer.get_layer('stack4_block3_output').output\n        \n    elif model_name == 'hornet':\n        \n        if model_size == 'b':\n            \n            base_layer = hornet.HorNetBase(input_shape=(512,512,3), pretrained=None, \n                                           drop_connect_rate=0.1, num_classes=0)\n        else:\n            \n            base_layer = hornet.HorNetSmall(input_shape=(512,512,3), pretrained=None, \n                                            drop_connect_rate=0.1, num_classes=0)\n    \n        inputs = base_layer.input\n\n        nn0 = base_layer.get_layer('stack1_block1_2_output').output\n        nn1 = base_layer.get_layer('stack1_block2_2_output').output\n        nn2 = base_layer.get_layer('stack2_block3_2_output').output\n        nn3 = base_layer.get_layer('stack3_block18_2_output').output\n        nn4 = base_layer.get_layer('stack4_block2_2_output').output\n        \n    y = nn4\n    y = tf.keras.layers.GlobalAveragePooling2D(name='global_ave')(y)\n    y = tf.keras.layers.Dropout(0.2, name='dropout')(y)\n    y = tf.keras.layers.Dense(5, dtype=\"float32\", activation='sigmoid', \n                              name='class_output')(y)\n        \n    nn0 = tf.keras.layers.UpSampling2D(2, name='up_0')(nn0)\n    nn0 = ConvBlock(nn0, 48, activation=\"gelu\", name='feat_conv_0')    \n    \n    nn3 = FPNBlock(nn3, nn4, 256, activation=\"gelu\", name='fpn3')\n    nn2 = FPNBlock(nn2, nn3, 256, activation=\"gelu\", name='fpn2')\n    nn1 = FPNBlock(nn1, nn2, 256, activation=\"gelu\", name='fpn1')\n    nn0 = FPNBlock(nn0, nn1, 256, activation=\"gelu\", name='fpn0')\n    \n    nn3 = ConvBlock(nn3, 256, activation=\"gelu\", name='convblock_3')\n    nn2 = ConvBlock(nn2, 256, activation=\"gelu\", name='convblock_2')\n    nn1 = ConvBlock(nn1, 256, activation=\"gelu\", name='convblock_1')\n    nn0 = ConvBlock(nn0, 256, activation=\"gelu\", name='convblock_0')\n    \n    nn3 = tf.keras.layers.UpSampling2D(8, name='fpn_up_3')(nn3)\n    nn2 = tf.keras.layers.UpSampling2D(4, name='fpn_up_2')(nn2)\n    nn1 = tf.keras.layers.UpSampling2D(2, name='fpn_up_1')(nn1)\n    \n    nn = tf.keras.layers.Add(name='fpn_merge_0')([nn0, nn1, nn2, nn3])\n    nn = ConvBlock(nn, 128, activation=\"gelu\", name='fpn_final')\n    \n    nn = tf.keras.layers.Conv2D(3, kernel_size=3, padding=\"same\", \n                                dtype=\"float32\", activation='sigmoid', \n                                name='mask_output')(nn)\n    \n    model = tf.keras.Model(inputs=inputs, outputs=[nn,y])\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:31:04.736946Z","iopub.execute_input":"2024-01-05T06:31:04.737303Z","iopub.status.idle":"2024-01-05T06:31:04.782133Z","shell.execute_reply.started":"2024-01-05T06:31:04.737271Z","shell.execute_reply":"2024-01-05T06:31:04.781154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Classifier Models","metadata":{}},{"cell_type":"code","source":"def get_model(model_name='convnext', model_size='l'):\n    \n    if model_name == 'convnext':\n        \n        if model_size == 'l':\n    \n            base_layer = convnext.ConvNeXtLarge(input_shape=(None,None,3), pretrained=None, \n                                                drop_connect_rate=0.1, num_classes=0)\n        elif model_size == 'b':\n            \n            base_layer = convnext.ConvNeXtBase(input_shape=(None,None,3), pretrained=None, \n                                               drop_connect_rate=0.1, num_classes=0)\n        elif model_size == 's':\n            \n            base_layer = convnext.ConvNeXtSmall(input_shape=(None,None,3), pretrained=None, \n                                                drop_connect_rate=0.1, num_classes=0)\n        else:\n            base_layer = convnext.ConvNeXtTiny(input_shape=(None,None,3), pretrained=None, \n                                               drop_connect_rate=0.1, num_classes=0)\n\n        inputs = base_layer.input\n        y = base_layer.get_layer('stack4_block3_output').output\n        \n    elif model_name == 'hornet':\n        \n        if model_size == 'l':\n            \n            base_layer = hornet.HorNetLarge(input_shape=(None,None,3), pretrained=None, \n                                            drop_connect_rate=0.1, num_classes=0)\n        elif model_size == 'b':\n            \n            base_layer = hornet.HorNetBase(input_shape=(None,None,3), pretrained=None, \n                                           drop_connect_rate=0.1, num_classes=0)\n        elif model_size == 's':\n            \n            base_layer = hornet.HorNetSmall(input_shape=(None,None,3), pretrained=None, \n                                            drop_connect_rate=0.1, num_classes=0)\n        else:\n            base_layer = hornet.HorNetTiny(input_shape=(None,None,3), pretrained=None, \n                                           drop_connect_rate=0.1, num_classes=0)\n    \n        inputs = base_layer.input\n        y = base_layer.get_layer('stack4_block2_2_output').output\n        \n    elif model_name == 'efficientnetv1':\n        \n        if model_size == 'b3':\n    \n            base_layer = efficientnet.EfficientNetV1B3(input_shape=(None,None,3), pretrained=None, \n                                                       drop_connect_rate=0.1, num_classes=0)        \n        elif model_size == 'b2':\n            \n            base_layer = efficientnet.EfficientNetV1B2(input_shape=(None,None,3), pretrained=None, \n                                                       drop_connect_rate=0.1, num_classes=0)\n        else :\n            \n            base_layer = efficientnet.EfficientNetV1B1(input_shape=(None,None,3), pretrained=None, \n                                                       drop_connect_rate=0.1, num_classes=0)\n        inputs = base_layer.input\n        y = base_layer.get_layer('post_swish').output\n        \n    elif model_name == 'efficientnetv2':\n        \n        if model_size == 's':\n        \n            base_layer = efficientnet.EfficientNetV2S(input_shape=(None,None,3), pretrained=None, \n                                                  drop_connect_rate=0.1, num_classes=0)\n        elif model_size == 'b3':\n    \n            base_layer = efficientnet.EfficientNetV2B3(input_shape=(None,None,3), pretrained=None, \n                                                       drop_connect_rate=0.1, num_classes=0)        \n        elif model_size == 'b2':\n            \n            base_layer = efficientnet.EfficientNetV2B2(input_shape=(None,None,3), pretrained=None, \n                                                       drop_connect_rate=0.1, num_classes=0)\n        else :\n            \n            base_layer = efficientnet.EfficientNetV2B1(input_shape=(None,None,3), pretrained=None, \n                                                       drop_connect_rate=0.1, num_classes=0)\n    \n        inputs = base_layer.input\n        y = base_layer.get_layer('post_swish').output\n        \n    y = tf.keras.layers.GlobalAveragePooling2D(name='global_ave')(y)\n    y = tf.keras.layers.Dropout(0.2, name='dropout')(y)\n    y = tf.keras.layers.Dense(5, dtype=\"float32\", activation='sigmoid', \n                              name='class_output')(y)\n    \n    model = tf.keras.Model(inputs=inputs, outputs=y)\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:31:04.783501Z","iopub.execute_input":"2024-01-05T06:31:04.783771Z","iopub.status.idle":"2024-01-05T06:31:04.802293Z","shell.execute_reply.started":"2024-01-05T06:31:04.783747Z","shell.execute_reply":"2024-01-05T06:31:04.801504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"with tf.device(\"GPU:0\"):\n    model_fpn = get_model_fpn(model_name='convnext', model_size='b')\n    model_fpn.load_weights('/kaggle/input/ubc-ocean-model-weights/model_convnextbase_fpn_1.h5')\n\nwith tf.device(\"GPU:1\"):\n    \n    model = get_model(model_name='convnext', model_size='b')\n    model.load_weights('/kaggle/input/ubc-ocean-model-weights/model_convnextbase_2.h5')","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:31:04.80341Z","iopub.execute_input":"2024-01-05T06:31:04.803708Z","iopub.status.idle":"2024-01-05T06:31:21.028555Z","shell.execute_reply.started":"2024-01-05T06:31:04.803685Z","shell.execute_reply":"2024-01-05T06:31:21.027754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Images with area(width X height) less than 6000p X 6000p are considered as TMA.\ndf_test = pd.read_csv('/kaggle/input/UBC-OCEAN/test.csv')\ndf_test['image_size'] = (df_test['image_width']/6000)*(df_test['image_height']/6000)\ndf_test['is_tma'] = df_test['image_size'] < 1.0","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:31:21.029914Z","iopub.execute_input":"2024-01-05T06:31:21.030287Z","iopub.status.idle":"2024-01-05T06:31:21.051707Z","shell.execute_reply.started":"2024-01-05T06:31:21.030252Z","shell.execute_reply":"2024-01-05T06:31:21.051033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subtype_map = {0:'CC', 1:'EC', 2:'HGSC', 3:'LGSC', 4:'MC'}","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:31:21.052905Z","iopub.execute_input":"2024-01-05T06:31:21.053257Z","iopub.status.idle":"2024-01-05T06:31:21.057968Z","shell.execute_reply.started":"2024-01-05T06:31:21.053224Z","shell.execute_reply":"2024-01-05T06:31:21.057084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MEAN = np.array([0.485, 0.456, 0.406]).astype(np.float32).reshape((1,1,1,3))\nSTD = np.array([0.229, 0.224, 0.225]).astype(np.float32).reshape((1,1,1,3))\nTILE_SIZE = 768 # Resize Width and Height\nCROP_SIZE = 1536 # Crop size around the best pixel selected by the segmentation model.\n\ny_ls = []\ny_max_value_ls = [] # Predicted score - for predicting Outliers.\n\nfor img_id,w,h,istma in zip(df_test['image_id'].values,df_test['image_width'].values,df_test['image_height'].values,df_test['is_tma'].values):\n        \n    try:\n        \n        if istma:\n            img_path = f'/kaggle/input/UBC-OCEAN/test_images/{img_id}.png'\n            img = pyvips.Image.new_from_file(img_path).numpy()[:,:,:3]\n            img = img[256:img.shape[0]-256,256:img.shape[1]-256,:3]\n            img = cv2.resize(img, (TILE_SIZE, TILE_SIZE), interpolation = cv2.INTER_CUBIC)\n            img = np.expand_dims(img, axis=0)\n            img = img.astype(np.float32)/255.0\n            img = (img-MEAN)/STD\n            \n            with tf.device(\"GPU:1\"):\n                p = model.predict(img,batch_size=1,verbose=False)[0]\n                    \n            pl = np.argmax(p)\n            y_ls.append(subtype_map[pl])\n            y_max_value_ls.append(np.max(p))\n\n            del img, p\n            gc.collect()\n            \n        else:\n            img_path = f'/kaggle/input/UBC-OCEAN/test_thumbnails/{img_id}_thumbnail.png'\n            img = pyvips.Image.new_from_file(img_path).numpy()\n            h_tn,w_tn = img.shape[:2]\n            \n            # If thumbnail image is small, a new thumbnail is generated using WSI.\n            if min(h_tn,w_tn) < 2048:\n                if h<=w:\n                    h_tn = 2048\n                    w_tn = int(w*2048/h)\n                else:\n                    w_tn = 2048\n                    h_tn = int(h*2048/w)\n                        \n                img_path = f'/kaggle/input/UBC-OCEAN/test_images/{img_id}.png'\n                img = pyvips.Image.thumbnail(img_path, w_tn).numpy()[:,:,:3]\n                gc.collect()\n                    \n            #if h<=w:\n            #    h_tn = 2048\n            #    w_tn = int(w*2048/h)\n            #else:\n            #    w_tn = 2048\n            #    h_tn = int(h*2048/w)\n                    \n            #img = cv2.resize(img, (w_tn, h_tn), interpolation = cv2.INTER_CUBIC)\n            gc.collect()\n            \n            # A single pixel in thumbnail image with high probability of being cancerous is selected for each label.\n            # Then the region around the selected pixel on WSI is croped and resized for classification.\n            \n            h_tn,w_tn = img.shape[:2]\n            i_max = 0\n            j_max = 0\n            pos_i_ls = []\n            pos_j_ls = []\n            imgs = []\n            for i in range(0,512*(img.shape[0]//512),512):\n                for j in range(0,512*(img.shape[1]//512),512):\n                    if img[i:i+512, j:j+512,0].sum() > 15000000: # To filter out blank areas.\n                        pos_i_ls.append(i)\n                        pos_j_ls.append(j)\n                        imgs.append(img[i:i+512, j:j+512,:])\n\n            imgs = np.stack(imgs, axis=0)\n            imgs = imgs.astype(np.float32)/255.0\n            imgs = (imgs-MEAN)/STD\n            \n            del img\n            gc.collect()\n            \n            i_max_ls = []\n            j_max_ls = []\n            with tf.device(\"GPU:0\"):\n                p0,p1 = model_fpn.predict(imgs,batch_size=8,verbose=False)\n                p1 = np.max(p1,axis=0)\n                p0 = p0[:,:,:,0]\n                idx0 = np.argmax(np.max(p0,axis=(1,2)))\n                idx0_ = idx0\n                i_max, j_max = np.unravel_index(p0[idx0].argmax(), (256,256))\n                i_max = pos_i_ls[idx0]+2*i_max\n                j_max = pos_j_ls[idx0]+2*j_max\n                i_max = int(i_max*(h/h_tn))\n                j_max = int(j_max*(w/w_tn))\n                i_max_ls.append(i_max)\n                j_max_ls.append(j_max)\n                \n                for j in range(5):\n                    if np.max(p1[j]) > 0.05: # A single title is selected for each label above threshold.\n                        idx0 = np.argmax(p1[j])\n                        if idx0 != idx0_ :\n                            i_max, j_max = np.unravel_index(p0[idx0].argmax(), (256,256))\n                            i_max = pos_i_ls[idx0]+2*i_max\n                            j_max = pos_j_ls[idx0]+2*j_max\n                            i_max = int(i_max*(h/h_tn))\n                            j_max = int(j_max*(w/w_tn))\n                            i_max_ls.append(i_max)\n                            j_max_ls.append(j_max)\n            \n            del imgs,p0,p1\n            gc.collect()\n            \n            img_path = f'/kaggle/input/UBC-OCEAN/test_images/{img_id}.png'\n            img = pyvips.Image.new_from_file(img_path)\n            imgs = []\n            for i_max,j_max in zip(i_max_ls,j_max_ls):\n                img0 = img.crop(min(max(j_max - CROP_SIZE//2,0),w-CROP_SIZE-10), \n                                min(max(i_max - CROP_SIZE//2,0),h-CROP_SIZE-10), \n                                CROP_SIZE, CROP_SIZE).numpy()[:,:,:3]\n\n                img0 = cv2.resize(img0, (TILE_SIZE, TILE_SIZE), interpolation = cv2.INTER_CUBIC)\n                imgs.append(img0)\n            imgs = np.stack(imgs, axis=0)\n            \n            gc.collect()\n        \n            imgs = imgs.astype(np.float32)/255.0\n            imgs = (imgs-MEAN)/STD                \n            with tf.device(\"GPU:1\"):\n                p = model.predict(imgs,batch_size=6,verbose=False)\n                p = np.max(p,axis=0)\n                    \n            pl = np.argmax(p)\n            y_ls.append(subtype_map[pl])\n            y_max_value_ls.append(np.max(p))\n\n            del img, imgs, img0, p\n            gc.collect()\n        \n    except:\n        y_ls.append('HGSC')\n        y_max_value_ls.append(1.0)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pl,y_max_value_ls[-1]","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:32:28.833885Z","iopub.execute_input":"2024-01-05T06:32:28.834265Z","iopub.status.idle":"2024-01-05T06:32:28.84167Z","shell.execute_reply.started":"2024-01-05T06:32:28.83423Z","shell.execute_reply":"2024-01-05T06:32:28.840698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test['label'] = y_ls\ndf_test['label_max_value'] = y_max_value_ls\n\ny_ls = np.array(y_ls)\ny_max_value_ls = np.array(y_max_value_ls)\n\n# Bottom 10 percentile predictions are labeled as Other.\n# It is done seperately for WSI and TMA.\nif df_test.shape[0] > 10:\n    max10 = np.percentile(y_max_value_ls[df_test[\"is_tma\"].values==True], 10)\n    df_test.loc[(df_test[\"is_tma\"] == True) & (df_test[\"label_max_value\"] < max10), \"label\"] = 'Other'\n    max10 = np.percentile(y_max_value_ls[df_test[\"is_tma\"].values==False], 10)\n    df_test.loc[(df_test[\"is_tma\"] == False) & (df_test[\"label_max_value\"] < max10), \"label\"] = 'Other'\ndf_test[['image_id','label']].to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-01-05T06:32:28.842983Z","iopub.execute_input":"2024-01-05T06:32:28.84337Z","iopub.status.idle":"2024-01-05T06:32:28.864022Z","shell.execute_reply.started":"2024-01-05T06:32:28.843338Z","shell.execute_reply":"2024-01-05T06:32:28.863231Z"},"trusted":true},"execution_count":null,"outputs":[]}]}