{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":8089,"databundleVersionId":44321,"sourceType":"competition"}],"dockerImageVersionId":30747,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nimport os\nimport numpy as np\nimport random\nfrom tqdm import tqdm\nfrom skimage.io import imread, imshow\nfrom skimage.transform import resize\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:06:16.729515Z","iopub.execute_input":"2024-10-23T21:06:16.730541Z","iopub.status.idle":"2024-10-23T21:06:31.784812Z","shell.execute_reply.started":"2024-10-23T21:06:16.730485Z","shell.execute_reply":"2024-10-23T21:06:31.783740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile\nTRAIN_ZIP = '/kaggle/input/data-science-bowl-2018/stage1_train.zip'\nTEST_ZIP = '/kaggle/input/data-science-bowl-2018/stage1_test.zip'\n# Directory where to extract\nTRAIN_PATH = '/kaggle/working/stage1_train/'\nTEST_PATH = '/kaggle/working/stage1_test/'\n\n# Unzip the train data\nwith zipfile.ZipFile(TRAIN_ZIP, 'r') as zip_ref:\n    zip_ref.extractall(TRAIN_PATH)\n\n# Unzip the test data\nwith zipfile.ZipFile(TEST_ZIP, 'r') as zip_ref:\n    zip_ref.extractall(TEST_PATH)\n\nprint(\"Extraction complete!\")","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:07:32.183791Z","iopub.execute_input":"2024-10-23T21:07:32.184863Z","iopub.status.idle":"2024-10-23T21:07:37.208120Z","shell.execute_reply.started":"2024-10-23T21:07:32.184829Z","shell.execute_reply":"2024-10-23T21:07:37.207173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ids = next(os.walk(TRAIN_PATH))[1] #gives the folder names\ntest_ids = next(os.walk(TEST_PATH))[1]","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:07:45.523023Z","iopub.execute_input":"2024-10-23T21:07:45.523917Z","iopub.status.idle":"2024-10-23T21:07:45.530005Z","shell.execute_reply.started":"2024-10-23T21:07:45.523883Z","shell.execute_reply":"2024-10-23T21:07:45.529179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_WIDTH = 128\nIMG_HEIGHT = 128\nIMG_CHANNELS = 3","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:07:52.614184Z","iopub.execute_input":"2024-10-23T21:07:52.614567Z","iopub.status.idle":"2024-10-23T21:07:52.619232Z","shell.execute_reply.started":"2024-10-23T21:07:52.614537Z","shell.execute_reply":"2024-10-23T21:07:52.618288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\nY_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, 1), dtype=bool)","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:07:57.708681Z","iopub.execute_input":"2024-10-23T21:07:57.709018Z","iopub.status.idle":"2024-10-23T21:07:57.714136Z","shell.execute_reply.started":"2024-10-23T21:07:57.708993Z","shell.execute_reply":"2024-10-23T21:07:57.713182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train.shape, Y_train.shape","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:08:03.492085Z","iopub.execute_input":"2024-10-23T21:08:03.492493Z","iopub.status.idle":"2024-10-23T21:08:03.500573Z","shell.execute_reply.started":"2024-10-23T21:08:03.492462Z","shell.execute_reply":"2024-10-23T21:08:03.499560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed = 42\nnp.random.seed = seed","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:08:15.124348Z","iopub.execute_input":"2024-10-23T21:08:15.125184Z","iopub.status.idle":"2024-10-23T21:08:15.129486Z","shell.execute_reply.started":"2024-10-23T21:08:15.125152Z","shell.execute_reply":"2024-10-23T21:08:15.128350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for n, id_ in tqdm(enumerate(train_ids), total=len(train_ids)):   \n    path = TRAIN_PATH + id_\n    img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS]  \n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    # After resizing, ensure the data is in uint8 format and the range [0, 255]\n    if img.dtype != np.uint8:\n        img = np.clip(img, 0, 255)  # Clip values\n        img = img.astype(np.uint8)  # Convert to uint8\n    X_train[n] = img  #Fill empty X_train with values from img\n    mask = np.zeros((IMG_HEIGHT, IMG_WIDTH, 1), dtype=bool)\n    for mask_file in next(os.walk(path + '/masks/'))[2]:\n        mask_ = imread(path + '/masks/' + mask_file)\n        mask_ = np.expand_dims(resize(mask_, (IMG_HEIGHT, IMG_WIDTH), mode='constant',  \n                                      preserve_range=True), axis=-1)\n        mask_ = mask_.astype(np.uint8)\n        \n        mask = np.maximum(mask, mask_)  \n    # Convert the mask to boolean\n    mask = (mask > 0).astype(bool)    \n    Y_train[n] = mask   ","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:08:20.292656Z","iopub.execute_input":"2024-10-23T21:08:20.293666Z","iopub.status.idle":"2024-10-23T21:12:28.891402Z","shell.execute_reply.started":"2024-10-23T21:08:20.293610Z","shell.execute_reply":"2024-10-23T21:12:28.890489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train[0].shape, Y_train[0].shape","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:12:37.995381Z","iopub.execute_input":"2024-10-23T21:12:37.996405Z","iopub.status.idle":"2024-10-23T21:12:38.003549Z","shell.execute_reply.started":"2024-10-23T21:12:37.996355Z","shell.execute_reply":"2024-10-23T21:12:38.002549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imshow(X_train[0])\nplt.show()\nimshow(Y_train[0])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:13:48.815016Z","iopub.execute_input":"2024-10-23T21:13:48.815937Z","iopub.status.idle":"2024-10-23T21:13:49.273458Z","shell.execute_reply.started":"2024-10-23T21:13:48.815903Z","shell.execute_reply":"2024-10-23T21:13:49.272367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test images\nX_test = np.zeros((len(test_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\nsizes_test = []\nprint('Resizing test images') \nfor n, id_ in tqdm(enumerate(test_ids), total=len(test_ids)):\n    path = TEST_PATH + id_\n    img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS]\n    sizes_test.append([img.shape[0], img.shape[1]])\n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    # print(img.dtype)\n    if img.dtype != np.uint8:\n        img = np.clip(img, 0, 255)  # Clip values\n        img = img.astype(np.uint8)  # Convert to uint8\n    X_test[n] = img\n\nprint('Done!')","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:14:09.885538Z","iopub.execute_input":"2024-10-23T21:14:09.885942Z","iopub.status.idle":"2024-10-23T21:14:11.185311Z","shell.execute_reply.started":"2024-10-23T21:14:09.885912Z","shell.execute_reply":"2024-10-23T21:14:11.184376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sizes_test[1]\nimshow(X_test[1])\nX_test[1].max()","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:14:21.140262Z","iopub.execute_input":"2024-10-23T21:14:21.141166Z","iopub.status.idle":"2024-10-23T21:14:21.469117Z","shell.execute_reply.started":"2024-10-23T21:14:21.141129Z","shell.execute_reply":"2024-10-23T21:14:21.468193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_x = random.randint(0, len(train_ids))\nprint(image_x)\n\nimshow(X_train[image_x])\nplt.show()\nimshow(np.squeeze(Y_train[image_x]))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:14:31.227986Z","iopub.execute_input":"2024-10-23T21:14:31.228463Z","iopub.status.idle":"2024-10-23T21:14:31.863108Z","shell.execute_reply.started":"2024-10-23T21:14:31.228407Z","shell.execute_reply":"2024-10-23T21:14:31.862199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Build the model\ninputs = tf.keras.layers.Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\ns = tf.keras.layers.Lambda(lambda x: x / 255)(inputs)\n\n#Contraction path\nc1 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(s)\nc1 = tf.keras.layers.Dropout(0.1)(c1)\nc1 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c1)\np1 = tf.keras.layers.MaxPooling2D((2, 2))(c1)\n\nc2 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p1)\nc2 = tf.keras.layers.Dropout(0.1)(c2)\nc2 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c2)\np2 = tf.keras.layers.MaxPooling2D((2, 2))(c2)\n \nc3 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p2)\nc3 = tf.keras.layers.Dropout(0.2)(c3)\nc3 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c3)\np3 = tf.keras.layers.MaxPooling2D((2, 2))(c3)\n \nc4 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p3)\nc4 = tf.keras.layers.Dropout(0.2)(c4)\nc4 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c4)\np4 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(c4)\n \nc5 = tf.keras.layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p4)\nc5 = tf.keras.layers.Dropout(0.3)(c5)\nc5 = tf.keras.layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c5)\n\n#Expansive path \nu6 = tf.keras.layers.Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(c5)\nu6 = tf.keras.layers.concatenate([u6, c4])\nc6 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u6)\nc6 = tf.keras.layers.Dropout(0.2)(c6)\nc6 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c6)\n \nu7 = tf.keras.layers.Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(c6)\nu7 = tf.keras.layers.concatenate([u7, c3])\nc7 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u7)\nc7 = tf.keras.layers.Dropout(0.2)(c7)\nc7 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c7)\n \nu8 = tf.keras.layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(c7)\nu8 = tf.keras.layers.concatenate([u8, c2])\nc8 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u8)\nc8 = tf.keras.layers.Dropout(0.1)(c8)\nc8 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c8)\n \nu9 = tf.keras.layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c8)\nu9 = tf.keras.layers.concatenate([u9, c1], axis=3)\nc9 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(u9)\nc9 = tf.keras.layers.Dropout(0.1)(c9)\nc9 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c9)\n \noutputs = tf.keras.layers.Conv2D(1, (1, 1), activation='sigmoid')(c9)\n \nmodel = tf.keras.Model(inputs=[inputs], outputs=[outputs])\nmodel.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\nmodel.summary()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-23T21:51:03.531925Z","iopub.execute_input":"2024-10-23T21:51:03.532935Z","iopub.status.idle":"2024-10-23T21:51:03.870127Z","shell.execute_reply.started":"2024-10-23T21:51:03.532899Z","shell.execute_reply":"2024-10-23T21:51:03.869070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n# Define GELU activation as it's not available by default in Keras\ndef gelu(x):\n    return 0.5 * x * (1 + tf.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * tf.pow(x, 3))))\nfrom tensorflow.keras import layers\nclass FCA_Block(tf.keras.layers.Layer):\n    def __init__(self, filters):\n        super(FCA_Block, self).__init__()\n        self.filters = filters\n\n        # 3x3 convolution layers followed by GELU activation\n        self.conv1 = layers.Conv2D(filters, (3, 3), padding='same')\n        self.conv2 = layers.Conv2D(filters, (3, 3), padding='same')\n        self.gelu = layers.Activation(gelu)\n\n        # 1x1 convolution followed by ReLU activation\n        self.conv1x1 = layers.Conv2D(filters, (1, 1), padding='same')\n        self.relu = layers.ReLU()\n\n        # Global Average Pooling\n        self.global_avg_pool = layers.GlobalAveragePooling2D()\n\n        # Dense layer to calculate channel weights (with sigmoid activation)\n        self.dense = layers.Dense(filters, activation='sigmoid')\n\n        # Project the input to match the output's shape (1x1 convolution to match filter size)\n        self.input_projection = layers.Conv2D(filters, (1, 1), padding='same')\n\n    def call(self, inputs):\n        # 3x3 convolution layers with GELU activation\n        x = self.conv1(inputs)\n        x = self.gelu(x)\n        x = self.conv2(x)\n        x = self.gelu(x)\n        feature = x\n\n        # Apply FFT to the feature map\n        x_fft = tf.signal.fft2d(tf.cast(x, tf.complex64))\n        x_fft = tf.cast(x_fft, tf.float32)  # Convert back to float32 after FFT\n\n        # 1x1 convolution followed by ReLU\n        x = self.conv1x1(x_fft)\n        x = self.relu(x)\n\n        # Global Average Pooling to get channel-wise information\n        x_pool = self.global_avg_pool(x)\n\n        # Dense layer to compute channel-wise weights using Sigmoid activation\n        channel_weights = self.dense(x_pool)\n\n        # Reshape the channel weights for channel-wise multiplication\n        channel_weights = tf.reshape(channel_weights, [-1, 1, 1, self.filters])\n\n        # Multiply input features by the channel-wise weights\n        output = feature * channel_weights\n\n        # Project the input to match the output's shape (to make addition possible)\n        projected_input = self.input_projection(inputs)\n\n        # Add the output to the projected input (residual connection)\n        final_output = output + projected_input\n        \n        return final_output\ndef Residual_Block(inputTensor, numFilters, kernelSize=3, doBatchNorm=True):\n    print(f\"Input Tensor Shape: {inputTensor.shape}\")  # Debugging shape\n    x = FCA_Block(filters=numFilters)(inputTensor)\n    print(f\"After FCA_Block, Shape: {x.shape}\")  # Debugging shape\n    if doBatchNorm:\n        x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.Activation('relu')(x)\n    \n    x = FCA_Block(filters=numFilters)(x)\n    print(f\"After second FCA_Block, Shape: {x.shape}\")  # Debugging shape\n    if doBatchNorm:\n        x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.Activation('relu')(x)\n\n    if inputTensor.shape[-1] != numFilters:\n        inputTensor = tf.keras.layers.Conv2D(numFilters, (1, 1), padding='same')(inputTensor)\n        print(f\"After 1x1 Conv Projection, Input Tensor Shape: {inputTensor.shape}\")  # Debugging shape\n    \n    return tf.keras.layers.add([x, inputTensor])\n\n\n# U-Net with FCA Block\ndef FRUNet(inputImage, numFilters=64, dropouts=0.1, doBatchNorm=True):\n    # Encoder Path with FCA block after each Conv block\n    \n    c1 = Residual_Block(inputImage, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    p1 = tf.keras.layers.MaxPooling2D((2, 2))(c1)\n    p1 = tf.keras.layers.Dropout(dropouts)(p1)\n\n    c2 = Residual_Block(p1, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    p2 = tf.keras.layers.MaxPooling2D((2, 2))(c2)\n    p2 = tf.keras.layers.Dropout(dropouts)(p2)\n\n    c3 = Residual_Block(p2, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    p3 = tf.keras.layers.MaxPooling2D((2, 2))(c3)\n    p3 = tf.keras.layers.Dropout(dropouts)(p3)\n\n    # Bridge\n    c4 = Residual_Block(p3, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n\n    # Decoder Path with FCA block before each ConvTranspose (deconvolution)\n    u6 = tf.keras.layers.Conv2DTranspose(numFilters * 1, (3, 3), strides=(2, 2), padding='same')(c4)\n    u6 = tf.keras.layers.concatenate([u6, c3])\n    u6 = tf.keras.layers.Dropout(dropouts)(u6)\n    c6 = Residual_Block(u6, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n\n    u7 = tf.keras.layers.Conv2DTranspose(numFilters * 1, (3, 3), strides=(2, 2), padding='same')(c6)\n    u7 = tf.keras.layers.concatenate([u7, c2])\n    u7 = tf.keras.layers.Dropout(dropouts)(u7)\n    c7 = Residual_Block(u7, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    u9 = tf.keras.layers.Conv2DTranspose(numFilters * 1, (3, 3), strides=(2, 2), padding='same')(c7)\n    u9 = tf.keras.layers.concatenate([u9, c1])\n    u9 = tf.keras.layers.Dropout(dropouts)(u9)\n    c9 = Residual_Block(u9, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n\n    # Final output layer\n    output = tf.keras.layers.Conv2D(1, (1, 1), activation='sigmoid')(c9)\n    model = tf.keras.Model(inputs=[inputImage], outputs=[output])\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:42:38.862919Z","iopub.execute_input":"2024-10-23T22:42:38.863535Z","iopub.status.idle":"2024-10-23T22:42:38.895875Z","shell.execute_reply.started":"2024-10-23T22:42:38.863500Z","shell.execute_reply":"2024-10-23T22:42:38.894662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n# Define GELU activation as it's not available by default in Keras\ndef gelu(x):\n    return 0.5 * x * (1 + tf.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * tf.pow(x, 3))))\nfrom tensorflow.keras import layers\nclass FCA_Block(tf.keras.layers.Layer):\n    def __init__(self, filters):\n        super(FCA_Block, self).__init__()\n        self.filters = filters\n\n        # 3x3 depthwise convolution (reducing parameters significantly)\n        self.depthwise_conv = layers.DepthwiseConv2D((3, 3), padding='same')\n\n        # 3x3 dilated convolution with dilation rate (2, 2) (increasing receptive field)\n        self.dilated_conv = layers.Conv2D(filters, (3, 3), dilation_rate=(2, 2), padding='same')\n        self.gelu = layers.Activation(gelu)\n\n        # 1x1 convolution followed by ReLU activation\n        self.conv1x1 = layers.Conv2D(filters, (1, 1), padding='same')\n        self.relu = layers.ReLU()\n\n        # Global Average Pooling\n        self.global_avg_pool = layers.GlobalAveragePooling2D()\n\n        # Dense layer to calculate channel weights (with sigmoid activation)\n        self.dense = layers.Dense(filters, activation='sigmoid')\n\n        # Project the input to match the output's shape (1x1 convolution to match filter size)\n        self.input_projection = layers.Conv2D(filters, (1, 1), padding='same')\n\n    def call(self, inputs):\n        # 3x3 convolution layers with GELU activation\n        x = self.depthwise_conv(inputs)\n        x = self.gelu(x)\n        x = self.dilated_conv(x)\n        x = self.gelu(x)\n        feature = x\n\n        # Apply FFT to the feature map\n        x_fft = tf.signal.fft2d(tf.cast(x, tf.complex64))\n        x_fft = tf.cast(x_fft, tf.float32)  # Convert back to float32 after FFT\n\n        # 1x1 convolution followed by ReLU\n        x = self.conv1x1(x_fft)\n        x = self.relu(x)\n\n        # Global Average Pooling to get channel-wise information\n        x_pool = self.global_avg_pool(x)\n\n        # Dense layer to compute channel-wise weights using Sigmoid activation\n        channel_weights = self.dense(x_pool)\n\n        # Reshape the channel weights for channel-wise multiplication\n        channel_weights = tf.reshape(channel_weights, [-1, 1, 1, self.filters])\n\n        # Multiply input features by the channel-wise weights\n        output = feature * channel_weights\n\n        # Project the input to match the output's shape (to make addition possible)\n        projected_input = self.input_projection(inputs)\n\n        # Add the output to the projected input (residual connection)\n        final_output = output + projected_input\n        \n        return final_output\ndef Residual_Block(inputTensor, numFilters, kernelSize=3, doBatchNorm=True):\n    print(f\"Input Tensor Shape: {inputTensor.shape}\")  # Debugging shape\n    x = FCA_Block(filters=numFilters)(inputTensor)\n    print(f\"After FCA_Block, Shape: {x.shape}\")  # Debugging shape\n    if doBatchNorm:\n        x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.Activation('relu')(x)\n    \n    x = FCA_Block(filters=numFilters)(x)\n    print(f\"After second FCA_Block, Shape: {x.shape}\")  # Debugging shape\n    if doBatchNorm:\n        x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.Activation('relu')(x)\n\n    if inputTensor.shape[-1] != numFilters:\n        inputTensor = tf.keras.layers.Conv2D(numFilters, (1, 1), padding='same')(inputTensor)\n        print(f\"After 1x1 Conv Projection, Input Tensor Shape: {inputTensor.shape}\")  # Debugging shape\n    \n    return tf.keras.layers.add([x, inputTensor])\n\n\n# U-Net with FCA Block\ndef FRUNetm(inputImage, numFilters=64, dropouts=0.1, doBatchNorm=True):\n    # Encoder Path with FCA block after each Conv block\n    \n    c1 = Residual_Block(inputImage, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    p1 = tf.keras.layers.MaxPooling2D((2, 2))(c1)\n    p1 = tf.keras.layers.Dropout(dropouts)(p1)\n\n    c2 = Residual_Block(p1, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    p2 = tf.keras.layers.MaxPooling2D((2, 2))(c2)\n    p2 = tf.keras.layers.Dropout(dropouts)(p2)\n\n    c3 = Residual_Block(p2, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    p3 = tf.keras.layers.MaxPooling2D((2, 2))(c3)\n    p3 = tf.keras.layers.Dropout(dropouts)(p3)\n\n    # Bridge\n    c4 = Residual_Block(p3, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n\n    # Decoder Path with FCA block before each ConvTranspose (deconvolution)\n    u6 = tf.keras.layers.Conv2DTranspose(numFilters * 1, (3, 3), strides=(2, 2), padding='same')(c4)\n    u6 = tf.keras.layers.concatenate([u6, c3])\n    u6 = tf.keras.layers.Dropout(dropouts)(u6)\n    c6 = Residual_Block(u6, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n\n    u7 = tf.keras.layers.Conv2DTranspose(numFilters * 1, (3, 3), strides=(2, 2), padding='same')(c6)\n    u7 = tf.keras.layers.concatenate([u7, c2])\n    u7 = tf.keras.layers.Dropout(dropouts)(u7)\n    c7 = Residual_Block(u7, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n    u9 = tf.keras.layers.Conv2DTranspose(numFilters * 1, (3, 3), strides=(2, 2), padding='same')(c7)\n    u9 = tf.keras.layers.concatenate([u9, c1])\n    u9 = tf.keras.layers.Dropout(dropouts)(u9)\n    c9 = Residual_Block(u9, numFilters * 1, kernelSize=3, doBatchNorm=doBatchNorm)\n\n    # Final output layer\n    output = tf.keras.layers.Conv2D(1, (1, 1), activation='sigmoid')(c9)\n    model = tf.keras.Model(inputs=[inputImage], outputs=[output])\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:51:06.519152Z","iopub.execute_input":"2024-10-23T22:51:06.519609Z","iopub.status.idle":"2024-10-23T22:51:06.550195Z","shell.execute_reply.started":"2024-10-23T22:51:06.519575Z","shell.execute_reply":"2024-10-23T22:51:06.549294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n\n# Binary Cross-Entropy is already built into Keras, so we just need to define the Dice coefficient loss.\ndef dice_coefficient_loss(y_true, y_pred):\n    smooth = 1.0  # Smoothing factor to avoid division by zero\n    y_true_f = tf.keras.backend.flatten(y_true)\n    y_pred_f = tf.keras.backend.flatten(y_pred)\n    \n    intersection = tf.keras.backend.sum(y_true_f * y_pred_f)\n    \n    dice_loss = 1 - (2. * intersection + smooth) / (tf.keras.backend.sum(y_true_f) + tf.keras.backend.sum(y_pred_f) + smooth)\n    \n    return dice_loss\n\n# Define combined loss: BCE + Dice Loss\ndef combined_bce_dice_loss(y_true, y_pred):\n    bce_loss = tf.keras.losses.binary_crossentropy(y_true, y_pred)\n    dice_loss = dice_coefficient_loss(y_true, y_pred)\n    \n    return bce_loss + dice_loss\n","metadata":{"execution":{"iopub.status.busy":"2024-10-23T23:11:57.034027Z","iopub.execute_input":"2024-10-23T23:11:57.034885Z","iopub.status.idle":"2024-10-23T23:11:57.042483Z","shell.execute_reply.started":"2024-10-23T23:11:57.034849Z","shell.execute_reply":"2024-10-23T23:11:57.041449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\n\n# Define Dice coefficient metric\ndef dice_coefficient(y_true, y_pred):\n    smooth = 1.0  # To avoid division by zero\n    y_true_f = tf.keras.backend.flatten(y_true)\n    y_pred_f = tf.keras.backend.flatten(y_pred)\n    \n    intersection = tf.keras.backend.sum(y_true_f * y_pred_f)\n    dice = (2. * intersection + smooth) / (tf.keras.backend.sum(y_true_f) + tf.keras.backend.sum(y_pred_f) + smooth)\n    \n    return dice\n\n# Define Mean IoU (Intersection over Union)\ndef mean_iou(y_true, y_pred):\n    y_pred = tf.cast(y_pred > 0.5, tf.float32)\n    y_true = tf.cast(y_true > 0.5, tf.float32)\n    \n    intersection = tf.keras.backend.sum(y_true * y_pred)\n    union = tf.keras.backend.sum(y_true) + tf.keras.backend.sum(y_pred) - intersection\n    iou = (intersection + 1.0) / (union + 1.0)  # Smooth factor to avoid division by zero\n    \n    return iou\n\n# Define Recall (True Positive Rate)\ndef recall_m(y_true, y_pred):\n    y_pred = tf.cast(y_pred > 0.5, tf.float32)\n    true_positives = tf.keras.backend.sum(y_true * y_pred)\n    possible_positives = tf.keras.backend.sum(y_true)\n    recall = true_positives / (possible_positives + tf.keras.backend.epsilon())\n    \n    return recall\n\n# Define Precision\ndef precision_m(y_true, y_pred):\n    y_pred = tf.cast(y_pred > 0.5, tf.float32)\n    true_positives = tf.keras.backend.sum(y_true * y_pred)\n    predicted_positives = tf.keras.backend.sum(y_pred)\n    precision = true_positives / (predicted_positives + tf.keras.backend.epsilon())\n    \n    return precision\n\n# Define F1-score\ndef f1_m(y_true, y_pred):\n    precision = precision_m(y_true, y_pred)\n    recall = recall_m(y_true, y_pred)\n    f1 = 2 * ((precision * recall) / (precision + recall + tf.keras.backend.epsilon()))\n    \n    return f1\n","metadata":{"execution":{"iopub.status.busy":"2024-10-23T23:13:29.937316Z","iopub.execute_input":"2024-10-23T23:13:29.937727Z","iopub.status.idle":"2024-10-23T23:13:29.950021Z","shell.execute_reply.started":"2024-10-23T23:13:29.937695Z","shell.execute_reply":"2024-10-23T23:13:29.948993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inputs = tf.keras.layers.Input((128, 128, 3))\n\n# Create the FRUNet model using the input shape\nunet = FRUNetm(inputs, dropouts=0.07)\n\n# Compile the model\nunet.compile(optimizer='Adam', loss=combined_bce_dice_loss, \n             metrics=[dice_coefficient, mean_iou, precision_m, recall_m, f1_m, 'accuracy'])\nunet.summary()","metadata":{"execution":{"iopub.status.busy":"2024-10-23T23:13:40.124301Z","iopub.execute_input":"2024-10-23T23:13:40.124727Z","iopub.status.idle":"2024-10-23T23:13:42.994335Z","shell.execute_reply.started":"2024-10-23T23:13:40.124695Z","shell.execute_reply":"2024-10-23T23:13:42.993345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import datetime","metadata":{"execution":{"iopub.status.busy":"2024-10-23T23:13:59.335350Z","iopub.execute_input":"2024-10-23T23:13:59.335770Z","iopub.status.idle":"2024-10-23T23:13:59.340440Z","shell.execute_reply.started":"2024-10-23T23:13:59.335737Z","shell.execute_reply":"2024-10-23T23:13:59.339479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"log_dir = \"logs/fit/\" + datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\ntensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n\n# Defining callbacks\ncheckpointer = tf.keras.callbacks.ModelCheckpoint('model_for_nuclei.keras', verbose=1, save_best_only=True)\ncallbacks = [\n    tf.keras.callbacks.ModelCheckpoint(filepath='model_for_nuclei.keras', verbose=1, save_best_only=True),\n    tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),\n#     tf.keras.callbacks.TensorBoard(log_dir='logs')\n    tensorboard_callback\n]","metadata":{"execution":{"iopub.status.busy":"2024-10-23T23:14:06.874569Z","iopub.execute_input":"2024-10-23T23:14:06.875463Z","iopub.status.idle":"2024-10-23T23:14:06.882557Z","shell.execute_reply.started":"2024-10-23T23:14:06.875431Z","shell.execute_reply":"2024-10-23T23:14:06.881372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Clear any logs from previous runs\n!rm -rf /kaggle/working/logs","metadata":{"execution":{"iopub.status.busy":"2024-10-23T23:14:12.478386Z","iopub.execute_input":"2024-10-23T23:14:12.478771Z","iopub.status.idle":"2024-10-23T23:14:13.631912Z","shell.execute_reply.started":"2024-10-23T23:14:12.478743Z","shell.execute_reply":"2024-10-23T23:14:13.630427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = model.fit(X_train, Y_train, validation_split=0.1, batch_size=16, epochs=35, callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2024-10-23T23:14:16.449369Z","iopub.execute_input":"2024-10-23T23:14:16.449802Z","iopub.status.idle":"2024-10-23T23:14:23.057111Z","shell.execute_reply.started":"2024-10-23T23:14:16.449765Z","shell.execute_reply":"2024-10-23T23:14:23.056201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# type(results)\nresults.history","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:52:40.160298Z","iopub.execute_input":"2024-10-23T22:52:40.160977Z","iopub.status.idle":"2024-10-23T22:52:40.170548Z","shell.execute_reply.started":"2024-10-23T22:52:40.160944Z","shell.execute_reply":"2024-10-23T22:52:40.169480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = results.history\nplt.plot(history['loss'], label='Training Loss')\nplt.plot(history['val_loss'], label='Validation Loss')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:52:54.126188Z","iopub.execute_input":"2024-10-23T22:52:54.126619Z","iopub.status.idle":"2024-10-23T22:52:54.413095Z","shell.execute_reply.started":"2024-10-23T22:52:54.126588Z","shell.execute_reply":"2024-10-23T22:52:54.412006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = results.history\nplt.plot(history['accuracy'], label='Accuracy')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:53:18.026604Z","iopub.execute_input":"2024-10-23T22:53:18.026978Z","iopub.status.idle":"2024-10-23T22:53:18.198275Z","shell.execute_reply.started":"2024-10-23T22:53:18.026947Z","shell.execute_reply":"2024-10-23T22:53:18.197251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.input_shape","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:53:26.917509Z","iopub.execute_input":"2024-10-23T22:53:26.918271Z","iopub.status.idle":"2024-10-23T22:53:26.924203Z","shell.execute_reply.started":"2024-10-23T22:53:26.918239Z","shell.execute_reply":"2024-10-23T22:53:26.923243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display(display_list):\n    plt.figure(figsize=(15, 15))\n    title = ['Input image', 'True mask', 'Predicted mask']\n    for i in range(len(display_list)):\n        plt.subplot(1, len(display_list), i+1)\n        plt.title(title[i])\n        plt.imshow(display_list[i])\n        plt.axis('off')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:53:40.417000Z","iopub.execute_input":"2024-10-23T22:53:40.417448Z","iopub.status.idle":"2024-10-23T22:53:40.423921Z","shell.execute_reply.started":"2024-10-23T22:53:40.417400Z","shell.execute_reply":"2024-10-23T22:53:40.422880Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"idx = random.randint(0, len(X_train))\ntrue_image = X_train[idx]\ntrue_mask = np.squeeze(Y_train[idx])\n# Add batch dimension and then predict\nprediction = model.predict(true_image[tf.newaxis, ...])[0]\n\npredicted_mask = (prediction > 0.5).astype(np.uint8)\nprint(predicted_mask.shape)\ndisplay([true_image, true_mask,predicted_mask])","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:53:50.815099Z","iopub.execute_input":"2024-10-23T22:53:50.816067Z","iopub.status.idle":"2024-10-23T22:53:54.221040Z","shell.execute_reply.started":"2024-10-23T22:53:50.816031Z","shell.execute_reply":"2024-10-23T22:53:54.220103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('/kaggle/working/unet.h5')","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:54:15.467198Z","iopub.execute_input":"2024-10-23T22:54:15.467619Z","iopub.status.idle":"2024-10-23T22:54:15.623333Z","shell.execute_reply.started":"2024-10-23T22:54:15.467588Z","shell.execute_reply":"2024-10-23T22:54:15.622479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predicted_masks = model.predict(X_train)\n# For binary segmentation, we usually apply a threshold of 0.5\npredicted_masks = (predicted_masks > 0.5).astype(np.uint8)\n\n# Now `predicted_masks` is an array of shape (670, 128, 128, 1), similar to `y_train`\nprint(predicted_masks.shape) ","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:54:22.188375Z","iopub.execute_input":"2024-10-23T22:54:22.188791Z","iopub.status.idle":"2024-10-23T22:54:34.426858Z","shell.execute_reply.started":"2024-10-23T22:54:22.188761Z","shell.execute_reply":"2024-10-23T22:54:34.425783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create directories to save the true and predicted masks\ntrue_masks_folder = '/kaggle/working/true_masks'\npredicted_masks_folder = '/kaggle/working/predicted_masks'\nos.makedirs(true_masks_folder, exist_ok=True)\nos.makedirs(predicted_masks_folder, exist_ok=True)\n","metadata":{"execution":{"iopub.status.busy":"2024-10-23T22:54:47.782512Z","iopub.execute_input":"2024-10-23T22:54:47.782912Z","iopub.status.idle":"2024-10-23T22:54:47.788746Z","shell.execute_reply.started":"2024-10-23T22:54:47.782879Z","shell.execute_reply":"2024-10-23T22:54:47.787648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nimport imageio\n# Assuming `true_masks` and `predicted_masks` are numpy arrays of shape (670, 128, 128, 1)\n# Iterate through all masks and save them as PNG images\nfor i in range(len(X_train)):  # Adjust the range based on the number of masks\n    # Get the i-th true and predicted mask\n    true_mask = np.squeeze(Y_train[i])  # Squeeze to remove the single channel dimension (128, 128)\n    predicted_mask = np.squeeze(predicted_masks[i])\n\n    # Create the paths to save the images\n    true_mask_save_path = os.path.join(true_masks_folder, f'true_mask_{i}.png')\n    predicted_mask_save_path = os.path.join(predicted_masks_folder, f'predicted_mask_{i}.png')\n\n    # Save the true and predicted masks as images\n    imageio.imwrite(true_mask_save_path, (true_mask * 255).astype(np.uint8))  # Scale if necessary\n    imageio.imwrite(predicted_mask_save_path, (predicted_mask * 255).astype(np.uint8))\n\nprint(\"True and Predicted masks saved in their respective folders.\")","metadata":{"execution":{"iopub.status.busy":"2024-08-24T08:58:19.69489Z","iopub.execute_input":"2024-08-24T08:58:19.695607Z","iopub.status.idle":"2024-08-24T08:58:21.564524Z","shell.execute_reply.started":"2024-08-24T08:58:19.695568Z","shell.execute_reply":"2024-08-24T08:58:21.563505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now create zip archives for both directories\nshutil.make_archive('/kaggle/working/true_masks_archive', 'zip', true_masks_folder)\nshutil.make_archive('/kaggle/working/predicted_masks_archive', 'zip', predicted_masks_folder)\n\nprint(\"Masks folders zipped successfully.\")","metadata":{"execution":{"iopub.status.busy":"2024-08-24T08:58:35.214891Z","iopub.execute_input":"2024-08-24T08:58:35.21528Z","iopub.status.idle":"2024-08-24T08:58:35.448868Z","shell.execute_reply.started":"2024-08-24T08:58:35.215246Z","shell.execute_reply":"2024-08-24T08:58:35.447929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}