From e0bfc924e4b622ab6bf4a965a0076acf51bac946 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 9 Oct 2024 20:34:13 +1000 Subject: [PATCH 001/102] prototype dataloaders and initial commit --- recognition/47049358/.gitignore | 11 ++ recognition/47049358/README.md | 0 recognition/47049358/dataset.py | 237 ++++++++++++++++++++++++++++++++ recognition/47049358/modules.py | 5 + recognition/47049358/predict.py | 4 + recognition/47049358/train.py | 22 +++ 6 files changed, 279 insertions(+) create mode 100644 recognition/47049358/.gitignore create mode 100644 recognition/47049358/README.md create mode 100644 recognition/47049358/dataset.py create mode 100644 recognition/47049358/modules.py create mode 100644 recognition/47049358/predict.py create mode 100644 recognition/47049358/train.py diff --git a/recognition/47049358/.gitignore b/recognition/47049358/.gitignore new file mode 100644 index 000000000..b459636a0 --- /dev/null +++ b/recognition/47049358/.gitignore @@ -0,0 +1,11 @@ +semantic_labels_anon +semantic_MRs_anon + +**__pycache__** + + +*.ipynb + +*.pkl + +*.txt \ No newline at end of file diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py new file mode 100644 index 000000000..1bcbbd1c9 --- /dev/null +++ b/recognition/47049358/dataset.py @@ -0,0 +1,237 @@ +import os +from sklearn.model_selection import train_test_split +import numpy as np +import nibabel as nib +from tqdm import tqdm +import pickle +import numpy as np +from torch.utils.data import Dataset +from PIL import Image +import torch + +IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') +LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') +RANDOM_STATE = 47049358 + +def to_channels(arr: np.ndarray, dtype=np.uint8) -> np.ndarray: + channels = np.unique(arr) + res = np.zeros(arr.shape + (len(channels),), dtype=dtype) + for c in channels: + c = int(c) + res[..., c:c+1][arr == c] = 1 + return res + +# Load medical image functions +def load_data_2D(imageNames, normImage=False, categorical=False, dtype=np.float32, getAffines=False, early_stop=False): + ''' + Load medical image data from names, cases list provided into a list for each. + This function pre-allocates 4D arrays for conv2d to avoid excessive memory usage. + + normImage : bool (normalize the image 0.0-1.0) + early_stop : Stop loading prematurely, leaves arrays mostly empty, for quick loading and testing scripts. + ''' + affines = [] + num = len(imageNames) + first_case = nib.load(imageNames[0]).get_fdata(caching='unchanged') + + if len(first_case.shape) == 3: + first_case = first_case[:, :, 0] # sometimes extra dims, remove + + if categorical: + first_case = to_channels(first_case, dtype=dtype) + rows, cols, channels = first_case.shape + images = np.zeros((num, rows, cols, channels), dtype=dtype) + else: + rows, cols = first_case.shape + images = np.zeros((num, rows, cols), dtype=dtype) + + for i, inName in enumerate(tqdm(imageNames)): + niftiImage = nib.load(inName) + inImage = niftiImage.get_fdata(caching='unchanged') # read disk only + affine = niftiImage.affine + + if len(inImage.shape) == 3: + inImage = inImage[:, :, 0] # sometimes extra dims in HipMRI_study data + + inImage = inImage.astype(dtype) + + if normImage: + inImage = (inImage - inImage.mean()) / inImage.std() + + if categorical: + # inImage = utils.to_channels(inImage, dtype=dtype) + images[i, :, :, :] = inImage + else: + images[i, :, :] = inImage + + affines.append(affine) + + if i > 20 and early_stop: + break + + return (images, affines) if getAffines else images + +def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float32, getAffines=False, early_stop=False): + ''' + Load medical image data from names, cases list provided into a list for each. + This function pre-allocates 5D arrays for conv3d to avoid excessive memory usage. + + normImage : bool (normalize the image 0.0-1.0) + dtype : Type of the data. If dtype=np.uint8, it is assumed that the data has labels. + early_stop : Stop loading prematurely. Leaves arrays mostly empty, for quick loading and testing scripts. + ''' + affines = [] + interp = 'linear' + if dtype == np.uint8: # assume labels + interp = 'nearest' + + num = len(imageNames) + niftiImage = nib.load(imageNames[0]) + + first_case = niftiImage.get_fdata(caching='unchanged') + + if len(first_case.shape) == 4: + first_case = first_case[:, :, :, 0] # sometimes extra dims, remove + + if categorical: + first_case = to_channels(first_case, dtype=dtype) + rows, cols, depth, channels = first_case.shape + images = np.zeros((num, rows, cols, depth, channels), dtype=dtype) + else: + rows, cols, depth = first_case.shape + images = np.zeros((num, rows, cols, depth), dtype=dtype) + + for i, inName in enumerate(tqdm(imageNames)): + + niftiImage = nib.load(inName) + + inImage = niftiImage.get_fdata(caching='unchanged') # read disk only + affine = niftiImage.affine + + if len(inImage.shape) == 4: + inImage = inImage[ : , : , : , 0] # sometimes extra dims in HipMRI_study data + + inImage = inImage[ : , : , : depth] # clip slices + inImage = inImage.astype(dtype) + + if normImage: + inImage = (inImage - inImage.mean()) / inImage.std() + + if categorical: + inImage = to_channels(inImage, dtype=dtype) + images[i, : inImage.shape[0], : inImage.shape[1], : inImage.shape[2], : inImage.shape[3]] = inImage # with pad + else: + images[i, : inImage.shape[0], : inImage.shape[1], : inImage.shape[2]] = inImage # with pad + + affines.append(affine) + + if i > 20 and early_stop: + break + + return (images, affines) if getAffines else images + +def load_images_and_labels(image_file_name, label_file_name, early_stop = False): + images = load_data_3D(imageNames=image_file_name, early_stop=early_stop) + labels = load_data_3D(imageNames=label_file_name, categorical=True, dtype=np.uint8, early_stop=early_stop) + return images, labels + +def save_data(images, labels, image_save_path, label_save_path): + with open(image_save_path, 'wb') as f: + pickle.dump(images, f) + with open(label_save_path, 'wb') as f: + pickle.dump(labels, f) + +def load_saved_data(image_save_path, label_save_path): + with open(image_save_path, 'rb') as f: + images = pickle.load(f) + with open(label_save_path, 'rb') as f: + labels = pickle.load(f) + return images, labels + +# Global constants for the dimensions to which images and masks will be resized +# TRANSFORMED_X = 256 # width after resizing +# TRANSFORMED_Y= 256 # height after resizing + +""" + PyTorch Dataset class for loading ISIC melanoma detection dataset. + + Parameters: + - img_path (str): Path to the directory containing image files. + - mask_path (str): Path to the directory containing mask files. + - transform (call): Transform to be applied on the images and masks. + + Methods: + - __len__(): Returns the total number of images in the dataset. + - __getitem__(idx): Returns the image and its corresponding mask at the given index `idx`. Resizes image and converts to correct colour channels. + """ +class Prostate3dDataset(Dataset): + def __init__(self, images, labels, transform=None): + self.images = images + self.labels = labels + self.transform = transform + + def __len__(self): + return len(self.images) + + # def match_mask_to_image(self, img_filename): + # base_name = os.path.splitext(img_filename)[0] # This removes the .jpg or any extension + # return base_name + '_segmentation.png' + + def __getitem__(self, idx): + img = self.images[idx] + mask = self.labels[idx] + + # img = Image.open(img_name).convert('RGB') # Convert to RGB + # mask = Image.open(mask_name).convert('L') # Convert to grayscale for segmentation masks. + + # img = img.resize((TRANSFORMED_Y, TRANSFORMED_X)) + # mask = mask.resize((TRANSFORMED_Y, TRANSFORMED_X), Image.NEAREST) + + # if self.transform: + # img = self.transform(img) + # mask = torch.from_numpy(np.array(mask)).float().unsqueeze(0) / 255.0 # Convert to single channel tensor + + return img, mask + +rawImageNames = os.listdir(IMAGE_FILE_NAME) +rawLabelNames = os.listdir(LABEL_FILE_NAME) + +# Split the set into train, validation, and test set (70:15:15 for train:valid:test) +X_train, X_rem, y_train, y_rem = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and remaining set +X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, train_size=0.5, random_state=RANDOM_STATE) + +X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] +X_val = [os.path.join(IMAGE_FILE_NAME, image) for image in X_val] +X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] + +y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] +y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] +y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] + +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) +X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) + + +train_set = Prostate3dDataset(X_train, y_train) +validation_set = Prostate3dDataset(X_val, y_val) +test_set = Prostate3dDataset(X_test, y_test) + +# train_dir = os.path.join(os.getcwd(), 'train_set') +# val_dir = os.path.join(os.getcwd(), 'validation_set') +# test_dir = os.path.join(os.getcwd(), 'test_set') +# os.makedirs(train_dir, exist_ok = True) +# os.makedirs(test_dir, exist_ok = True) + +# train_img_file = os.path.join(train_dir, 'train_images.pkl') +# train_label_file = os.path.join(train_dir, 'train_labels.pkl') + +# val_img_file = os.path.join(val_dir, 'validation_images.pkl') +# val_label_file = os.path.join(val_dir, 'validation_labels.pkl') + +# test_img_file = os.path.join(test_dir, 'test_images.pkl') +# test_label_file = os.path.join(test_dir, 'test_labels.pkl') + +# save_data(images=X_train, labels=y_train, image_save_path=train_img_file, label_save_path=train_label_file) +# save_data(images=X_val, labels=y_val, image_save_path=val_img_file, label_save_path=val_label_file) +# save_data(images=X_test, labels=y_test, image_save_path=test_img_file, label_save_path=test_label_file) diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py new file mode 100644 index 000000000..9fd3cfff6 --- /dev/null +++ b/recognition/47049358/modules.py @@ -0,0 +1,5 @@ +""" +containing the source code of the components of your model. Each component must be +implementated as a class or a function +""" + diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py new file mode 100644 index 000000000..07edd9905 --- /dev/null +++ b/recognition/47049358/predict.py @@ -0,0 +1,4 @@ +""" +showing example usage of your trained model. Print out any results and / or provide visualisations +where applicable +""" \ No newline at end of file diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py new file mode 100644 index 000000000..495310ea8 --- /dev/null +++ b/recognition/47049358/train.py @@ -0,0 +1,22 @@ +""" +containing the source code for training, validating, testing and saving your model. The model +should be imported from “modules.py” and the data loader should be imported from “dataset.py”. Make +sure to plot the losses and metrics during training +""" + +from dataset import train_set +import torch +from torchvision.transforms import transforms +import matplotlib.pyplot as plt + +for inputs, masks in train_set: + # Display the original image + plt.imshow(inputs[ :, :, 10], cmap='gray') + plt.axis('off') # Hide axes + plt.show() + + plt.imshow(masks[ :, :, 10, 2], cmap='jet') + plt.axis('off') # Hide axes + plt.show() + +# print("Validation Set: ", validation_set) From df3708aa8e3f7b037efef51c15a3edbfa6374404 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sun, 13 Oct 2024 15:25:24 +1000 Subject: [PATCH 002/102] copy that runs --- recognition/47049358/dataset.py | 12 +- recognition/47049358/modules.py | 345 ++++++++++++++++++++++++++++++++ recognition/47049358/predict.py | 131 +++++++++++- recognition/47049358/train.py | 110 ++++++++-- 4 files changed, 580 insertions(+), 18 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 1bcbbd1c9..3c773a1da 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -8,9 +8,11 @@ from torch.utils.data import Dataset from PIL import Image import torch +from torch.utils.data import DataLoader IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') +BATCH_SIZE = 1 RANDOM_STATE = 47049358 def to_channels(arr: np.ndarray, dtype=np.uint8) -> np.ndarray: @@ -81,9 +83,6 @@ def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float3 early_stop : Stop loading prematurely. Leaves arrays mostly empty, for quick loading and testing scripts. ''' affines = [] - interp = 'linear' - if dtype == np.uint8: # assume labels - interp = 'nearest' num = len(imageNames) niftiImage = nib.load(imageNames[0]) @@ -210,13 +209,16 @@ def __getitem__(self, idx): X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) - +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) train_set = Prostate3dDataset(X_train, y_train) validation_set = Prostate3dDataset(X_val, y_val) test_set = Prostate3dDataset(X_test, y_test) +train_loader = DataLoader(train_set, batch_size = BATCH_SIZE, shuffle = True) +validation_loader = DataLoader(validation_set, batch_size = BATCH_SIZE, shuffle = False) +test_loader = DataLoader(test_set, batch_size = BATCH_SIZE, shuffle = True) + # train_dir = os.path.join(os.getcwd(), 'train_set') # val_dir = os.path.join(os.getcwd(), 'validation_set') # test_dir = os.path.join(os.getcwd(), 'test_set') diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 9fd3cfff6..ddf3a624c 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -3,3 +3,348 @@ implementated as a class or a function """ +# imports +import torch +import torch.nn as nn +import torch.nn.functional as F + +# Global variables +NEGATIVE_SLOPE = 10**2 +DROPOUT_PROB = 0.3 + +""" +Custom convolutional layer with adjusted padding to retain original spatial dimensions +It includes an instance normalization and LeakyReLU activation. + +Parameters: +- in_channels (int): Number of input channels. +- out_channels (int): Number of output channels. +- kernel_size (int, optional): Size of the convolutional kernel (default is 3). +- stride (int, optional): Stride of the convolution operation (default is 1). +- padding (int, optional): Padding size for the convolution (default is 0). +""" +class StandardConv(nn.Module): + def __init__(self, in_channels, out_channels, + kernel_size=3, stride=1, padding=1): + super(StandardConv, self).__init__() + self.conv3d = nn.Conv3d(in_channels, out_channels, + kernel_size=kernel_size, stride=stride, padding=padding) + self.instance_norm = nn.InstanceNorm3d(out_channels, affine=True) + self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE) + + def forward(self, x): + x = self.conv3d(x) + x = self.instance_norm(x) + x = self.relu(x) + return x + +""" +Context module class for enhanced feature mapping using pre-activation residual blocks with dropout between. + +Parameters: +- in_channels (int): Number of input channels. +- out_channels (int): Number of output channels. + +Architecture: +- Conv1: 3x3 convolutional layer with instance normalisation and LeakyReLU activation. +- Dropout: Dropout layer with a specified dropout probability. +- Conv2: 3x3 convolutional layer with instance normalisation and LeakyReLU activation. +""" +class ContextModule(nn.Module): + def __init__(self, in_channels, out_channels): + super(ContextModule, self).__init__() + self.conv1 = nn.Conv3d(in_channels, out_channels, kernel_size=3, padding=1) + self.instance_norm = nn.InstanceNorm3d(out_channels, affine=True) + self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + self.dropout = nn.Dropout(DROPOUT_PROB) + self.conv2 = nn.Conv3d(out_channels, out_channels, kernel_size=3, padding=1) + self.instance_norm2 = nn.InstanceNorm3d(out_channels, affine=True) + self.relu2 = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + + def forward(self, x): + x = self.conv1(x) + x = self.instance_norm(x) + x = self.relu(x) + x = self.dropout(x) + x = self.conv2(x) + x = self.instance_norm2(x) + x = self.relu2(x) + return x + +""" +Convolutional Layer with Stride + +Parameters: +- in_channels (int): Number of input channels. +- out_channels (int): Number of output channels. +- kernel_size (int, optional): Size of the convolutional kernel (default is 3). +- stride (int, optional): Stride of the convolution operation (default is 2). +- padding (int, optional): Padding size for the convolution (default is 0). Adjusted padding to retain spatial dimensions. + +""" +class ConvWithStride(nn.Module): + def __init__(self, in_channels, out_channels, + kernel_size=3, stride=2, padding=1): + super(ConvWithStride, self).__init__() + self.conv = nn.Conv3d(in_channels, out_channels, + kernel_size=kernel_size, stride=stride, padding=padding) + self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + + def forward(self, x): + out = self.conv(x) + out = self.relu(out) + return out + +""" +Upsampling Module + +Parameters: +- in_channels (int): Number of input channels. +- out_channels (int): Number of output channels. + +Architecture: +- ConvTranspose2d: Transposed convolution for upsampling with a kernel size of 2 and stride of 2. +- Conv: 3x3 convolutional layer with padding to maintain spatial dimensions. +- InstanceNorm: Instance normalisation applied to the output. +- LeakyReLU: Leaky ReLU activation function. +""" +class UpsamplingModule(nn.Module): + def __init__(self, in_channels, out_channels): + super(UpsamplingModule, self).__init__() + self.conv_transpose = nn.ConvTranspose3d(in_channels, out_channels, + kernel_size=2, stride=2, padding=0) + self.conv = nn.Conv3d(out_channels, out_channels, + kernel_size=3, stride=1, padding=1) + self.norm = nn.InstanceNorm3d(out_channels, affine=True) + self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + + def forward(self, x): + x = self.conv_transpose(x) + x = self.conv(x) + x = self.relu(x) + return x + + +""" +Localisation Module for recombining features. + +Parameters: +- in_channels (int): Number of input channels. +- out_channels (int): Number of output channels. + +Architecture: +- Conv1: 3x3 convolutional layer with instance normalisation and LeakyReLU activation. +- Conv2: 1x1 convolutional layer with instance normalisation and LeakyReLU activation. +""" +class LocalisationModule(nn.Module): + def __init__(self, in_channels, out_channels): + super(LocalisationModule, self).__init__() + + self.conv1 = nn.Conv3d(in_channels, out_channels, kernel_size=3, padding=1) + self.norm = nn.InstanceNorm3d(out_channels, affine=True) + self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + + self.conv2 = nn.Conv3d(out_channels, out_channels, kernel_size=1, padding=0) + self.norm2 = nn.InstanceNorm3d(out_channels, affine=True) + self.relu2 = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + + def forward(self, x): + x = self.conv1(x) + x = self.norm(x) + x = self.relu(x) + x = self.conv2(x) + x = self.norm2(x) + x = self.relu2(x) + return x + + +""" +Segmentation Module reduces depth of feature maps to 1. + +Parameters: +- in_channels (int): Number of input channels. +- out_channels (int): Number of output channels (set to 1 since just mask is grayscale) + +Architecture: +- Segmentation: 1x1 convolutional layer + +""" +class SegmentationModule(nn.Module): + def __init__(self, in_channels, out_channels): + super(SegmentationModule, self).__init__() + self.segmentation = nn.Conv3d(in_channels, out_channels, + kernel_size=1, stride=1, padding=0) + + def forward(self, x): + return self.segmentation(x) + +""" +UpScale Module used to increase spatial resolution. + +Parameters: +- in_channels (int): Number of input channels. +- out_channels (int): Number of output channels. + +Architecture: +- Upscale: 2x2 transposed convolutional layer with no padding + +""" +class UpScaleModule(nn.Module): + def __init__(self, in_channels, out_channels): + super(UpScaleModule, self).__init__() + self.upscale = nn.ConvTranspose3d(in_channels, out_channels, + kernel_size=2, stride=2, padding=0) + + def forward(self, x): + return self.upscale(x) + +""" +This class defines an improved U-Net architecture. +""" +class ImprovedUnet(nn.Module): + def __init__(self): + super(ImprovedUnet, self).__init__() + # in_channels = 3 # RGB colours have three input channels. + in_channels = 1 + + out_channels = 16 + self.conv_1 = StandardConv(in_channels, out_channels) + in_channels=16 + self.context_1 = ContextModule(in_channels, out_channels) + + in_channels = 16 + out_channels = 32 + self.conv_2 = ConvWithStride(in_channels, out_channels) + in_channels = 32 + self.context_layer_2 = ContextModule(in_channels, out_channels) + + in_channels = 32 + out_channels = 64 + self.conv_3 = ConvWithStride(in_channels, out_channels) + in_channels = 64 + self.context_layer_3 = ContextModule(in_channels, out_channels) + + in_channels = 64 + out_channels = 128 + self.conv_4 = ConvWithStride(in_channels, out_channels) + in_channels = 128 + self.context_layer_4 = ContextModule(in_channels, out_channels) + + in_channels = 128 + out_channels = 256 + self.conv_5 = ConvWithStride(in_channels, out_channels) + in_channels = 256 + self.context_layer_5 = ContextModule(in_channels, out_channels) + + in_channels = 256 + out_channels = 128 + self.upsample_layer_1 = UpsamplingModule(in_channels, out_channels) + + in_channels = 256 + out_channels = 128 + self.localise_layer_1 = LocalisationModule(in_channels,out_channels) + + in_channels = 128 + out_channels = 64 + self.upsample_layer_2 = UpsamplingModule(in_channels, out_channels) + + in_channels = 128 + out_channels = 64 + self.localise_layer_2 = LocalisationModule(in_channels, out_channels) + + in_channels = 64 + out_channels = 32 + self.upsample_layer_3 = UpsamplingModule(in_channels, out_channels) + + in_channels = 64 + out_channels = 32 + self.localise_layer_3 = LocalisationModule(in_channels, out_channels) + + # fourth upsample layer + in_channels = 32 + out_channels = 16 + self.upsample_layer_4 = UpsamplingModule(in_channels, out_channels) + + in_channels = 32 + out_channels = 32 + self.conv_output = StandardConv(in_channels, out_channels) + + # first segmentation layer + in_channels = 64 + # out_channels = 1 + out_channels = 6 + self.segmentation_layer_1 = SegmentationModule(in_channels, out_channels) + + # second segmentation layer + in_channels = 32 + # out_channels = 1 + out_channels = 6 + self.segmentation_layer_2 = SegmentationModule(in_channels, out_channels) + + # third segmentation layer + in_channels = 32 + # out_channels = 1 + out_channels = 6 + self.segmentation_layer_3 = SegmentationModule(in_channels, out_channels) + + # upscaling layers + self.upscale_1 = UpScaleModule(out_channels, out_channels) + self.upscale_2 = UpScaleModule(out_channels, out_channels) + + + def forward(self, x): + conv_out_1 = self.conv_1(x) + context_out_1 = self.context_1(conv_out_1) + element_sum_1 = conv_out_1 + context_out_1 + + # second term + conv_out_2 = self.conv_2(element_sum_1) + context_out_2 = self.context_layer_2(conv_out_2) + element_sum_2 = conv_out_2 + context_out_2 + + # third downsample + conv_out_3 = self.conv_3(element_sum_2) + context_out_3 = self.context_layer_3(conv_out_3) + element_sum_3 = conv_out_3 + context_out_3 + + conv_out_4 = self.conv_4(element_sum_3) + context_out_4 = self.context_layer_4(conv_out_4) + element_sum_4 = conv_out_4 + context_out_4 + + conv_out_5 = self.conv_5(element_sum_4) + context_out_5 = self.context_layer_5(conv_out_5) + element_sum_5 = conv_out_5 + context_out_5 + + # First upsampling module. + upsample_out_1 = self.upsample_layer_1(element_sum_5) + concat_1 = torch.cat((element_sum_4, upsample_out_1), dim=1) + + localisation_out_1 = self.localise_layer_1(concat_1) + upsample_out_2 = self.upsample_layer_2(localisation_out_1) + concat_2 = torch.cat((element_sum_3, upsample_out_2), dim=1) + + localisation_out_2 = self.localise_layer_2(concat_2) + upsample_out_3 = self.upsample_layer_3(localisation_out_2) + concat_3 = torch.cat((element_sum_2, upsample_out_3), dim=1) + + localisation_out_3 = self.localise_layer_3(concat_3) + upsample_out_4 = self.upsample_layer_4(localisation_out_3) + concat_4 = torch.cat((element_sum_1, upsample_out_4), dim=1) + + segment_out_1 = self.segmentation_layer_1(localisation_out_2) + upscale_out_1 = self.upscale_1(segment_out_1) + + segment_out_2 = self.segmentation_layer_2(localisation_out_3) + seg_sum_1 = upscale_out_1 + segment_out_2 + + upscale_out_2 = self.upscale_2(seg_sum_1) + + segment_out_1 = self.segmentation_layer_1(localisation_out_2) + upscale_out_1 = self.upscale_1(segment_out_1) + + convoutput_out = self.conv_output(concat_4) + segment_out_3 = self.segmentation_layer_3(convoutput_out) + + final_sum = upscale_out_2 + segment_out_3 + + return torch.sigmoid(final_sum) \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 07edd9905..284a11509 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -1,4 +1,133 @@ """ showing example usage of your trained model. Print out any results and / or provide visualisations where applicable -""" \ No newline at end of file +""" +# libraries +import torch +import numpy as np +import matplotlib.pyplot as plt +import os +import torchvision.transforms as transforms + + +# import from local files +from train import dice_coefficient, trained_model +from dataset import test_loader + +""" + Tests improved unet on trained model. + Calcualtes dice coeficient for each image and corresponding ground truth. + + Parameters: + - model (nn.Module): The trained model to be tested. + - test_loader (DataLoader): DataLoader for the test dataset. + - device (str): The device (e.g., 'cuda' or 'cpu') to run the evaluation on. + + Returns: + - dice_scores (list): List of Dice coefficients for each image in the test dataset. +""" +def test(model, test_loader, device): + model.eval() # Set the model to evaluation mode + + dice_scores = [] # stores dice scores. + + with torch.no_grad(): + for test_inputs, test_masks in test_loader: + inputs, targets = test_inputs[np.newaxis, :], test_masks[np.newaxis, :] + + inputs, targets = inputs.to(device), targets.to(device) + outputs = model(inputs) + dice = dice_coefficient(outputs, targets) + dice_scores.append(dice.item()) + + return dice_scores + +""" + Visualises model image, predictions and ground truth on first three images from test loader. + + Parameters: + - model (nn.Module): The trained model used for making predictions. + - test_loader (DataLoader): DataLoader for the test dataset. + - device (str): The device (e.g., 'cuda' or 'cpu') to run the visualization on. + - num_images (int): The number of images to visualize (default is 3). + + """ +def visualise_predictions(model, test_loader, device, num_images=3): + model.eval() # Set the model to evaluation mode + + image_count = 0 # Keep track of the number of images processed + + with torch.no_grad(): + for data in test_loader: + inputs, targets = data + inputs, targets = inputs.to(device), targets.to(device) + # get prediction + outputs = model(inputs) + + # Convert PyTorch tensors to NumPy arrays + input_image = inputs[0].cpu().numpy() + target_image = targets[0].cpu().numpy() + predicted_image = outputs[0].cpu().numpy() + + # Create a side-by-side visualization for three images, prediction, ground truth. + plt.figure(figsize=(12, 4)) + plt.subplot(1, 3, 1) + plt.title("Input Image") + plt.imshow(input_image[0], cmap='gray') + + plt.subplot(1, 3, 2) + plt.title("Model Prediction") + plt.imshow(predicted_image[0], cmap='gray') + + plt.subplot(1, 3, 3) + plt.title("Ground Truth") + plt.imshow(target_image[0], cmap='gray') + + plt.show() + + image_count += 1 + + if image_count >= num_images: + break + +""" + Plots dice coefficients of the whole test dataset. + Takes an array of dice scores as input. +""" +def plot_dice(dice): + x_values = np.arange(len(dice)) # Generate x-values as indices + plt.figure(figsize=(8, 6)) + plt.plot(x_values, dice, marker='o', linestyle='-') + plt.xlabel("Image Index") + plt.ylabel("Dice Coefficient") + plt.title("Dice Coefficient across test inputs") + plt.grid(True) + plt.show() + + +""" + Driver method + +""" +if __name__ == "__main__": + # connect to gpu + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + # set up data transform. + data_transform = transforms.Compose([ + transforms.ToTensor(), + #transforms.Normalize(mean=[0.7071, 0.5821, 0.5360], std=[0.1561, 0.1644, 0.1795]) + ]) + + # perform predictions + dice_scores = test(trained_model, test_loader, device) + average_dice = np.mean(dice_scores) + print(f"Average Dice Coefficient: {average_dice:.4f}") + + # plot dice scores across the dataset. + plot_dice(dice_scores) + + # plot three examples of images, prediction and truth. + visualise_predictions(trained_model, test_loader,device) + + diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 495310ea8..39c58fc5b 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -4,19 +4,105 @@ sure to plot the losses and metrics during training """ -from dataset import train_set -import torch -from torchvision.transforms import transforms +from dataset import train_loader, validation_loader +from modules import ImprovedUnet import matplotlib.pyplot as plt +import torch +from tqdm import tqdm +import numpy as np + +NUM_EPOCHS = 1 + +def train(model, train_loader, valid_loader, num_epochs=100, device="cuda"): + # set up criterion, optimiser, and scheduler for learning rate. + + criterion = dice_coefficient + optimiser = torch.optim.Adam(model.parameters(), lr=5e-4, weight_decay=1e-5) + scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma=0.985) + + + model.to(device) + model.train() + + training_losses = [] + validation_losses = [] + + for epoch in range(num_epochs): + running_loss = 0.0 + for inputs, masks in tqdm(train_loader, desc=f'Epoch {epoch + 1}/{num_epochs}'): + + inputs = inputs[np.newaxis, :] + masks = masks[np.newaxis, :] + + inputs, masks = inputs.to(device), masks.to(device) + + optimiser.zero_grad() + outputs = model(inputs) + + print(outputs) + + # we want to maximise the dice coefficient + # loss is then 1 - dice coefficient + loss = 1 - criterion(masks, outputs) + loss.backward() + optimiser.step() + + running_loss += loss.item() + + print(running_loss) + + break + + scheduler.step() + + print(f"Epoch {epoch + 1}, Training Loss: {running_loss / len(train_loader)}") + + model.eval() + val_loss = 0.0 + + # get validation losses. + with torch.no_grad(): + for val_inputs, val_masks in valid_loader: + + val_inputs = val_inputs[np.newaxis, :] + val_masks = val_masks[np.newaxis, :] + + val_inputs, val_masks = val_inputs.to(device), val_masks.to(device) + val_outputs = model(val_inputs) + val_loss += 1 - criterion(val_outputs, val_masks).item() + + print(f"Epoch {epoch + 1}, Validation Loss: {val_loss / len(valid_loader)}") + + training_losses.append(running_loss / len(train_loader)) + validation_losses.append(val_loss / len(valid_loader)) + + return model, training_losses, validation_losses + +def dice_coefficient(y_true, y_pred): + y_true_f = y_true.flatten() + y_pred_f = y_pred.flatten() + smooth = 1e-8 + intersection = torch.sum(y_true_f * y_pred_f) + dice = (2. * intersection) / (2. * intersection + torch.sum(y_true_f) + torch.sum(y_pred_f) + smooth) + return dice + +# connect to gpu +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +if not torch.cuda.is_available(): + print("Warning CUDA not Found. Using CPU") -for inputs, masks in train_set: - # Display the original image - plt.imshow(inputs[ :, :, 10], cmap='gray') - plt.axis('off') # Hide axes - plt.show() +# create model. +model = ImprovedUnet() - plt.imshow(masks[ :, :, 10, 2], cmap='jet') - plt.axis('off') # Hide axes - plt.show() +# train improved unet +trained_model, training_losses, validation_losses = train(model, train_loader, validation_loader, + device=device, num_epochs=NUM_EPOCHS) -# print("Validation Set: ", validation_set) +plt.figure(figsize=(10,5)) +plt.plot(training_losses, label='Training Loss') +plt.plot(validation_losses, label='Validation Loss') +plt.title('Losses over epochs') +plt.xlabel('Epochs') +plt.ylabel('Loss') +plt.legend() +plt.show() \ No newline at end of file From ad5d839cd62d63f163758cb1203fbbae5f84137b Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Mon, 14 Oct 2024 02:20:21 +1000 Subject: [PATCH 003/102] memory inefficient broken implementation, commited for contingency --- recognition/47049358/README.md | 1 + recognition/47049358/dataset.py | 80 +++++++++++------------- recognition/47049358/modules.py | 8 ++- recognition/47049358/predict.py | 14 +++-- recognition/47049358/train.py | 105 ++++++++++++++++++++------------ 5 files changed, 120 insertions(+), 88 deletions(-) diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index e69de29bb..6ed4fb5d1 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -0,0 +1 @@ +(Dice Coefficient)[https://en.wikipedia.org/wiki/Dice-Sørensen_coefficient] \ No newline at end of file diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 3c773a1da..dd753470c 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -147,10 +147,6 @@ def load_saved_data(image_save_path, label_save_path): labels = pickle.load(f) return images, labels -# Global constants for the dimensions to which images and masks will be resized -# TRANSFORMED_X = 256 # width after resizing -# TRANSFORMED_Y= 256 # height after resizing - """ PyTorch Dataset class for loading ISIC melanoma detection dataset. @@ -180,60 +176,58 @@ def __getitem__(self, idx): img = self.images[idx] mask = self.labels[idx] - # img = Image.open(img_name).convert('RGB') # Convert to RGB - # mask = Image.open(mask_name).convert('L') # Convert to grayscale for segmentation masks. - - # img = img.resize((TRANSFORMED_Y, TRANSFORMED_X)) - # mask = mask.resize((TRANSFORMED_Y, TRANSFORMED_X), Image.NEAREST) - - # if self.transform: - # img = self.transform(img) - # mask = torch.from_numpy(np.array(mask)).float().unsqueeze(0) / 255.0 # Convert to single channel tensor - return img, mask -rawImageNames = os.listdir(IMAGE_FILE_NAME) -rawLabelNames = os.listdir(LABEL_FILE_NAME) +# rawImageNames = os.listdir(IMAGE_FILE_NAME) +# rawLabelNames = os.listdir(LABEL_FILE_NAME) # Split the set into train, validation, and test set (70:15:15 for train:valid:test) -X_train, X_rem, y_train, y_rem = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and remaining set -X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, train_size=0.5, random_state=RANDOM_STATE) +# X_train, X_rem, y_train, y_rem = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and remaining set +# X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, train_size=0.5, random_state=RANDOM_STATE) -X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] -X_val = [os.path.join(IMAGE_FILE_NAME, image) for image in X_val] -X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] +# X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] +# X_val = [os.path.join(IMAGE_FILE_NAME, image) for image in X_val] +# X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] -y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] -y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] -y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] +# y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] +# y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] +# y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) -X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) - -train_set = Prostate3dDataset(X_train, y_train) -validation_set = Prostate3dDataset(X_val, y_val) -test_set = Prostate3dDataset(X_test, y_test) +# X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) +# X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) +# X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) -train_loader = DataLoader(train_set, batch_size = BATCH_SIZE, shuffle = True) -validation_loader = DataLoader(validation_set, batch_size = BATCH_SIZE, shuffle = False) -test_loader = DataLoader(test_set, batch_size = BATCH_SIZE, shuffle = True) +train_dir = os.path.join(os.getcwd(), 'train_set') +val_dir = os.path.join(os.getcwd(), 'validation_set') +test_dir = os.path.join(os.getcwd(), 'test_set') -# train_dir = os.path.join(os.getcwd(), 'train_set') -# val_dir = os.path.join(os.getcwd(), 'validation_set') -# test_dir = os.path.join(os.getcwd(), 'test_set') # os.makedirs(train_dir, exist_ok = True) # os.makedirs(test_dir, exist_ok = True) +# os.makedirs(val_dir, exist_ok = True) -# train_img_file = os.path.join(train_dir, 'train_images.pkl') -# train_label_file = os.path.join(train_dir, 'train_labels.pkl') +train_img_file = os.path.join(train_dir, 'train_images.pkl') +train_label_file = os.path.join(train_dir, 'train_labels.pkl') -# val_img_file = os.path.join(val_dir, 'validation_images.pkl') -# val_label_file = os.path.join(val_dir, 'validation_labels.pkl') +val_img_file = os.path.join(val_dir, 'validation_images.pkl') +val_label_file = os.path.join(val_dir, 'validation_labels.pkl') -# test_img_file = os.path.join(test_dir, 'test_images.pkl') -# test_label_file = os.path.join(test_dir, 'test_labels.pkl') +test_img_file = os.path.join(test_dir, 'test_images.pkl') +test_label_file = os.path.join(test_dir, 'test_labels.pkl') # save_data(images=X_train, labels=y_train, image_save_path=train_img_file, label_save_path=train_label_file) # save_data(images=X_val, labels=y_val, image_save_path=val_img_file, label_save_path=val_label_file) # save_data(images=X_test, labels=y_test, image_save_path=test_img_file, label_save_path=test_label_file) + +# Load datasets +X_train, y_train = load_saved_data(train_img_file, train_label_file) +X_val, y_val = load_saved_data(val_img_file, val_label_file) +X_test, y_test = load_saved_data(test_img_file, test_label_file) + +# Recreate datasets and dataloaders +train_set = Prostate3dDataset(X_train, y_train) +validation_set = Prostate3dDataset(X_val, y_val) +test_set = Prostate3dDataset(X_test, y_test) + +train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True, num_workers=4, pin_memory=True) +validation_loader = DataLoader(validation_set, batch_size=BATCH_SIZE, shuffle=False) +test_loader = DataLoader(test_set, batch_size=BATCH_SIZE, shuffle=True) diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index ddf3a624c..18c166448 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -347,4 +347,10 @@ def forward(self, x): final_sum = upscale_out_2 + segment_out_3 - return torch.sigmoid(final_sum) \ No newline at end of file + output = nn.Softmax(dim = 1)(final_sum) + + output = output.unsqueeze(1) + + output = output.permute(0, 1, 3, 4, 5, 2) + + return output \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 284a11509..785d11790 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -58,8 +58,7 @@ def visualise_predictions(model, test_loader, device, num_images=3): image_count = 0 # Keep track of the number of images processed with torch.no_grad(): - for data in test_loader: - inputs, targets = data + for inputs, targets in test_loader: inputs, targets = inputs.to(device), targets.to(device) # get prediction outputs = model(inputs) @@ -75,9 +74,13 @@ def visualise_predictions(model, test_loader, device, num_images=3): plt.title("Input Image") plt.imshow(input_image[0], cmap='gray') + plt.savefig('input_image.png') + plt.subplot(1, 3, 2) plt.title("Model Prediction") - plt.imshow(predicted_image[0], cmap='gray') + plt.imshow(predicted_image[0], cmap='gray') + + plt.savefig('model_prediction.png') plt.subplot(1, 3, 3) plt.title("Ground Truth") @@ -85,6 +88,8 @@ def visualise_predictions(model, test_loader, device, num_images=3): plt.show() + plt.savefig('ground_truth.png') + image_count += 1 if image_count >= num_images: @@ -103,6 +108,7 @@ def plot_dice(dice): plt.title("Dice Coefficient across test inputs") plt.grid(True) plt.show() + plt.savefig('dice_scores_test.png') """ @@ -128,6 +134,6 @@ def plot_dice(dice): plot_dice(dice_scores) # plot three examples of images, prediction and truth. - visualise_predictions(trained_model, test_loader,device) + # visualise_predictions(trained_model, test_loader,device) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 39c58fc5b..224aa5307 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -11,80 +11,103 @@ from tqdm import tqdm import numpy as np -NUM_EPOCHS = 1 +NUM_EPOCHS = 10 -def train(model, train_loader, valid_loader, num_epochs=100, device="cuda"): - # set up criterion, optimiser, and scheduler for learning rate. +from tqdm import tqdm +import numpy as np +import torch +import torch.nn as nn +import torch.optim as optim +NUM_EPOCHS = 10 + +def train(model, train_loader, valid_loader, num_epochs=100, device="cuda"): + # Set up criterion, optimiser, and scheduler for learning rate. criterion = dice_coefficient optimiser = torch.optim.Adam(model.parameters(), lr=5e-4, weight_decay=1e-5) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma=0.985) - model.to(device) model.train() training_losses = [] validation_losses = [] + # Initialize GradScaler for mixed precision training + scaler = torch.cuda.amp.GradScaler() + for epoch in range(num_epochs): running_loss = 0.0 for inputs, masks in tqdm(train_loader, desc=f'Epoch {epoch + 1}/{num_epochs}'): - - inputs = inputs[np.newaxis, :] - masks = masks[np.newaxis, :] + inputs = inputs[:, np.newaxis] + masks = masks[:, np.newaxis] - inputs, masks = inputs.to(device), masks.to(device) + inputs, masks = inputs.to(device, non_blocking=True), masks.to(device, non_blocking=True) optimiser.zero_grad() - outputs = model(inputs) - print(outputs) + # Forward pass with mixed precision + with torch.amp.autocast(): + outputs = model(inputs) + loss = 1 - criterion(masks, outputs) - # we want to maximise the dice coefficient - # loss is then 1 - dice coefficient - loss = 1 - criterion(masks, outputs) - loss.backward() - optimiser.step() + # Backward pass with GradScaler + scaler.scale(loss).backward() + scaler.step(optimiser) + scaler.update() running_loss += loss.item() - print(running_loss) - - break + # Clear cache + torch.cuda.empty_cache() + training_losses.append(running_loss / len(train_loader)) scheduler.step() - print(f"Epoch {epoch + 1}, Training Loss: {running_loss / len(train_loader)}") - + # Validation step (optional) model.eval() - val_loss = 0.0 - - # get validation losses. + validation_loss = 0.0 with torch.no_grad(): - for val_inputs, val_masks in valid_loader: + for inputs, masks in valid_loader: + inputs = inputs[:, np.newaxis] + masks = masks[:, np.newaxis] - val_inputs = val_inputs[np.newaxis, :] - val_masks = val_masks[np.newaxis, :] + inputs, masks = inputs.to(device, non_blocking=True), masks.to(device, non_blocking=True) - val_inputs, val_masks = val_inputs.to(device), val_masks.to(device) - val_outputs = model(val_inputs) - val_loss += 1 - criterion(val_outputs, val_masks).item() + with torch.cuda.amp.autocast(): + outputs = model(inputs) + loss = 1 - criterion(masks, outputs) - print(f"Epoch {epoch + 1}, Validation Loss: {val_loss / len(valid_loader)}") + validation_loss += loss.item() - training_losses.append(running_loss / len(train_loader)) - validation_losses.append(val_loss / len(valid_loader)) + validation_losses.append(validation_loss / len(valid_loader)) + model.train() return model, training_losses, validation_losses -def dice_coefficient(y_true, y_pred): - y_true_f = y_true.flatten() - y_pred_f = y_pred.flatten() - smooth = 1e-8 - intersection = torch.sum(y_true_f * y_pred_f) - dice = (2. * intersection) / (2. * intersection + torch.sum(y_true_f) + torch.sum(y_pred_f) + smooth) - return dice +def dice_coefficient(y_true, y_pred, epsilon=1e-6): + num_masks = y_true.size(-1) # Assuming the masks are in the last dimension + dim_coefs = torch.zeros(num_masks, device=y_true.device) # Initialize a tensor to store the coefficients + + for i in range(num_masks): + # Get the argmax indices along the class dimension + ref = torch.argmax(y_pred, dim=-1) + + # Create binary masks where the predicted elements are set to 1 if they match the argmax indices + y_pred_binary = (ref == i).float() + + y_true_f = y_true[..., i].contiguous().view(-1) # Flatten the mask + y_pred_f = y_pred_binary.contiguous().view(-1) # Flatten the prediction + + intersection = torch.sum(y_true_f * y_pred_f) + denominator = torch.sum(y_true_f) + torch.sum(y_pred_f) + dim_coef = 2 * (intersection / denominator.clamp(min=epsilon)) + print(f'Mask {i}: ', dim_coef) + dim_coefs[i] = dim_coef # Store the coefficient in the tensor + + output = torch.divide(torch.sum(dim_coefs), num_masks) + output.requires_grad = True + return output # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -105,4 +128,6 @@ def dice_coefficient(y_true, y_pred): plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() -plt.show() \ No newline at end of file +plt.show() + +plt.savefig('unet_losses_over_epochs.png') \ No newline at end of file From 25c1841a3b9125e48ceb0e3f3d5c65e3f81cc437 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:55:22 +1000 Subject: [PATCH 004/102] functioning vanilla improved unet --- recognition/47049358/modules.py | 394 ++++++++++---------------------- 1 file changed, 124 insertions(+), 270 deletions(-) diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 18c166448..0155f43bc 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -1,356 +1,210 @@ -""" -containing the source code of the components of your model. Each component must be -implementated as a class or a function -""" - -# imports import torch import torch.nn as nn -import torch.nn.functional as F - -# Global variables -NEGATIVE_SLOPE = 10**2 -DROPOUT_PROB = 0.3 - -""" -Custom convolutional layer with adjusted padding to retain original spatial dimensions -It includes an instance normalization and LeakyReLU activation. - -Parameters: -- in_channels (int): Number of input channels. -- out_channels (int): Number of output channels. -- kernel_size (int, optional): Size of the convolutional kernel (default is 3). -- stride (int, optional): Stride of the convolution operation (default is 1). -- padding (int, optional): Padding size for the convolution (default is 0). -""" -class StandardConv(nn.Module): +import numpy as np + +NEGATIVE_SLOPE = 10 ** -2 +DROP_PROB = 0.3 +NUM_SEGMENTS = 6 + +class StandardModule(nn.Module): def __init__(self, in_channels, out_channels, - kernel_size=3, stride=1, padding=1): - super(StandardConv, self).__init__() - self.conv3d = nn.Conv3d(in_channels, out_channels, - kernel_size=kernel_size, stride=stride, padding=padding) + kernel_size = 3, stride = 1, padding = 1, inplace = False): + super(StandardModule, self).__init__() + self.conv = nn.Conv3d(in_channels = in_channels, out_channels = out_channels, + kernel_size = kernel_size, stride = stride, padding = padding) self.instance_norm = nn.InstanceNorm3d(out_channels, affine=True) - self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE) + self.l_relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace = inplace) def forward(self, x): - x = self.conv3d(x) + x = self.conv(x) x = self.instance_norm(x) - x = self.relu(x) + x = self.l_relu(x) return x - -""" -Context module class for enhanced feature mapping using pre-activation residual blocks with dropout between. - -Parameters: -- in_channels (int): Number of input channels. -- out_channels (int): Number of output channels. - -Architecture: -- Conv1: 3x3 convolutional layer with instance normalisation and LeakyReLU activation. -- Dropout: Dropout layer with a specified dropout probability. -- Conv2: 3x3 convolutional layer with instance normalisation and LeakyReLU activation. -""" + class ContextModule(nn.Module): - def __init__(self, in_channels, out_channels): + def __init__(self, in_channels, out_channels, + kernel_size = 3, stride = 1, padding = 1): super(ContextModule, self).__init__() - self.conv1 = nn.Conv3d(in_channels, out_channels, kernel_size=3, padding=1) - self.instance_norm = nn.InstanceNorm3d(out_channels, affine=True) - self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) - self.dropout = nn.Dropout(DROPOUT_PROB) - self.conv2 = nn.Conv3d(out_channels, out_channels, kernel_size=3, padding=1) - self.instance_norm2 = nn.InstanceNorm3d(out_channels, affine=True) - self.relu2 = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) - + self.block1 = StandardModule(in_channels = in_channels, out_channels = out_channels, inplace = True) + self.dropout = nn.Dropout(DROP_PROB) + self.block2 = StandardModule(in_channels = in_channels, out_channels = out_channels, inplace = True) + def forward(self, x): - x = self.conv1(x) - x = self.instance_norm(x) - x = self.relu(x) + x = self.block1(x) x = self.dropout(x) - x = self.conv2(x) - x = self.instance_norm2(x) - x = self.relu2(x) + x = self.block2(x) return x - -""" -Convolutional Layer with Stride - -Parameters: -- in_channels (int): Number of input channels. -- out_channels (int): Number of output channels. -- kernel_size (int, optional): Size of the convolutional kernel (default is 3). -- stride (int, optional): Stride of the convolution operation (default is 2). -- padding (int, optional): Padding size for the convolution (default is 0). Adjusted padding to retain spatial dimensions. - -""" -class ConvWithStride(nn.Module): + +class Stride2Module(nn.Module): def __init__(self, in_channels, out_channels, - kernel_size=3, stride=2, padding=1): - super(ConvWithStride, self).__init__() - self.conv = nn.Conv3d(in_channels, out_channels, - kernel_size=kernel_size, stride=stride, padding=padding) - self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + kernel_size=3, stride=2, padding=1, inplace = False): + super(Stride2Module, self).__init__() + self.conv = nn.Conv3d(in_channels = in_channels, out_channels = out_channels, + kernel_size = kernel_size, stride = stride, padding = padding) + self.instance_norm = nn.InstanceNorm3d(out_channels, affine=True) + self.l_relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace = inplace) def forward(self, x): - out = self.conv(x) - out = self.relu(out) - return out - -""" -Upsampling Module - -Parameters: -- in_channels (int): Number of input channels. -- out_channels (int): Number of output channels. - -Architecture: -- ConvTranspose2d: Transposed convolution for upsampling with a kernel size of 2 and stride of 2. -- Conv: 3x3 convolutional layer with padding to maintain spatial dimensions. -- InstanceNorm: Instance normalisation applied to the output. -- LeakyReLU: Leaky ReLU activation function. -""" + x = self.conv(x) + x = self.instance_norm(x) + x = self.l_relu(x) + return x + class UpsamplingModule(nn.Module): def __init__(self, in_channels, out_channels): super(UpsamplingModule, self).__init__() - self.conv_transpose = nn.ConvTranspose3d(in_channels, out_channels, - kernel_size=2, stride=2, padding=0) - self.conv = nn.Conv3d(out_channels, out_channels, - kernel_size=3, stride=1, padding=1) - self.norm = nn.InstanceNorm3d(out_channels, affine=True) - self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + self.conv_transpose = nn.ConvTranspose3d(in_channels = in_channels, out_channels = out_channels, + kernel_size = 4, stride = 2, padding = 1) + self.block = StandardModule(in_channels = out_channels, out_channels = out_channels, inplace = True) def forward(self, x): x = self.conv_transpose(x) - x = self.conv(x) - x = self.relu(x) + x = self.block(x) return x -""" -Localisation Module for recombining features. - -Parameters: -- in_channels (int): Number of input channels. -- out_channels (int): Number of output channels. - -Architecture: -- Conv1: 3x3 convolutional layer with instance normalisation and LeakyReLU activation. -- Conv2: 1x1 convolutional layer with instance normalisation and LeakyReLU activation. -""" class LocalisationModule(nn.Module): def __init__(self, in_channels, out_channels): super(LocalisationModule, self).__init__() - self.conv1 = nn.Conv3d(in_channels, out_channels, kernel_size=3, padding=1) - self.norm = nn.InstanceNorm3d(out_channels, affine=True) - self.relu = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + self.block1 = StandardModule(in_channels = in_channels, out_channels = out_channels) - self.conv2 = nn.Conv3d(out_channels, out_channels, kernel_size=1, padding=0) - self.norm2 = nn.InstanceNorm3d(out_channels, affine=True) - self.relu2 = nn.LeakyReLU(negative_slope=NEGATIVE_SLOPE, inplace=True) + self.block2 = StandardModule(in_channels = out_channels, out_channels = out_channels, kernel_size = 1, padding = 0) def forward(self, x): - x = self.conv1(x) - x = self.norm(x) - x = self.relu(x) - x = self.conv2(x) - x = self.norm2(x) - x = self.relu2(x) + x = self.block1(x) + x = self.block2(x) return x - - -""" -Segmentation Module reduces depth of feature maps to 1. - -Parameters: -- in_channels (int): Number of input channels. -- out_channels (int): Number of output channels (set to 1 since just mask is grayscale) - -Architecture: -- Segmentation: 1x1 convolutional layer - -""" -class SegmentationModule(nn.Module): + +class SegmentationLayer(nn.Module): def __init__(self, in_channels, out_channels): - super(SegmentationModule, self).__init__() - self.segmentation = nn.Conv3d(in_channels, out_channels, - kernel_size=1, stride=1, padding=0) + super(SegmentationLayer, self).__init__() + self.seg = nn.Conv3d(in_channels = in_channels, out_channels = out_channels, + kernel_size = 1, stride = 1, padding = 0) def forward(self, x): - return self.segmentation(x) - -""" -UpScale Module used to increase spatial resolution. - -Parameters: -- in_channels (int): Number of input channels. -- out_channels (int): Number of output channels. - -Architecture: -- Upscale: 2x2 transposed convolutional layer with no padding - -""" + return self.seg(x) + class UpScaleModule(nn.Module): def __init__(self, in_channels, out_channels): super(UpScaleModule, self).__init__() - self.upscale = nn.ConvTranspose3d(in_channels, out_channels, - kernel_size=2, stride=2, padding=0) + self.upscale = nn.ConvTranspose3d(in_channels = in_channels, out_channels = out_channels, + kernel_size = 4, stride = 2, padding = 1) def forward(self, x): return self.upscale(x) - -""" -This class defines an improved U-Net architecture. -""" + class ImprovedUnet(nn.Module): def __init__(self): super(ImprovedUnet, self).__init__() - # in_channels = 3 # RGB colours have three input channels. - in_channels = 1 - - out_channels = 16 - self.conv_1 = StandardConv(in_channels, out_channels) - in_channels=16 - self.context_1 = ContextModule(in_channels, out_channels) - - in_channels = 16 - out_channels = 32 - self.conv_2 = ConvWithStride(in_channels, out_channels) - in_channels = 32 - self.context_layer_2 = ContextModule(in_channels, out_channels) - - in_channels = 32 - out_channels = 64 - self.conv_3 = ConvWithStride(in_channels, out_channels) - in_channels = 64 - self.context_layer_3 = ContextModule(in_channels, out_channels) - - in_channels = 64 - out_channels = 128 - self.conv_4 = ConvWithStride(in_channels, out_channels) - in_channels = 128 - self.context_layer_4 = ContextModule(in_channels, out_channels) - - in_channels = 128 - out_channels = 256 - self.conv_5 = ConvWithStride(in_channels, out_channels) - in_channels = 256 - self.context_layer_5 = ContextModule(in_channels, out_channels) - - in_channels = 256 - out_channels = 128 - self.upsample_layer_1 = UpsamplingModule(in_channels, out_channels) - - in_channels = 256 - out_channels = 128 - self.localise_layer_1 = LocalisationModule(in_channels,out_channels) - - in_channels = 128 - out_channels = 64 - self.upsample_layer_2 = UpsamplingModule(in_channels, out_channels) - - in_channels = 128 - out_channels = 64 - self.localise_layer_2 = LocalisationModule(in_channels, out_channels) - - in_channels = 64 - out_channels = 32 - self.upsample_layer_3 = UpsamplingModule(in_channels, out_channels) - - in_channels = 64 - out_channels = 32 - self.localise_layer_3 = LocalisationModule(in_channels, out_channels) - - # fourth upsample layer - in_channels = 32 - out_channels = 16 - self.upsample_layer_4 = UpsamplingModule(in_channels, out_channels) - - in_channels = 32 - out_channels = 32 - self.conv_output = StandardConv(in_channels, out_channels) + self.block1 = StandardModule(1, 16) # Grayscale thus requries 1 input channel + self.context1 = ContextModule(16, 16) + + self.block2 = Stride2Module(16, 32) + self.context2 = ContextModule(32, 32) + + self.block3 = Stride2Module(32, 64) + self.context3 = ContextModule(64, 64) + + self.block4 = Stride2Module(64, 128) + self.context4 = ContextModule(128, 128) + + self.block5 = Stride2Module(128, 256) + self.context5 = ContextModule(256, 256) + + self.upsample1 = UpsamplingModule(256, 128) + + self.localise1 = LocalisationModule(256, 128) + self.upsample2 = UpsamplingModule(128, 64) + + self.localise2 = LocalisationModule(128, 64) + self.upsample3 = UpsamplingModule(64, 32) + + self.localise3 = LocalisationModule(64, 32) + self.upsample4 = UpsamplingModule(32, 16) + + self.conv_output = StandardModule(32, 32) # first segmentation layer - in_channels = 64 - # out_channels = 1 - out_channels = 6 - self.segmentation_layer_1 = SegmentationModule(in_channels, out_channels) + self.segmentation1 = SegmentationLayer(64, NUM_SEGMENTS) # second segmentation layer - in_channels = 32 - # out_channels = 1 - out_channels = 6 - self.segmentation_layer_2 = SegmentationModule(in_channels, out_channels) + self.segmentation2 = SegmentationLayer(32, NUM_SEGMENTS) # third segmentation layer - in_channels = 32 - # out_channels = 1 - out_channels = 6 - self.segmentation_layer_3 = SegmentationModule(in_channels, out_channels) + self.segmentation3 = SegmentationLayer(32, NUM_SEGMENTS) # upscaling layers - self.upscale_1 = UpScaleModule(out_channels, out_channels) - self.upscale_2 = UpScaleModule(out_channels, out_channels) + self.upscale_1 = UpScaleModule(NUM_SEGMENTS, NUM_SEGMENTS) + self.upscale_2 = UpScaleModule(NUM_SEGMENTS, NUM_SEGMENTS) def forward(self, x): - conv_out_1 = self.conv_1(x) - context_out_1 = self.context_1(conv_out_1) + conv_out_1 = self.block1(x) + context_out_1 = self.context1(conv_out_1) element_sum_1 = conv_out_1 + context_out_1 # second term - conv_out_2 = self.conv_2(element_sum_1) - context_out_2 = self.context_layer_2(conv_out_2) + conv_out_2 = self.block2(element_sum_1) + context_out_2 = self.context2(conv_out_2) element_sum_2 = conv_out_2 + context_out_2 # third downsample - conv_out_3 = self.conv_3(element_sum_2) - context_out_3 = self.context_layer_3(conv_out_3) + conv_out_3 = self.block3(element_sum_2) + context_out_3 = self.context3(conv_out_3) element_sum_3 = conv_out_3 + context_out_3 - conv_out_4 = self.conv_4(element_sum_3) - context_out_4 = self.context_layer_4(conv_out_4) + conv_out_4 = self.block4(element_sum_3) + context_out_4 = self.context4(conv_out_4) element_sum_4 = conv_out_4 + context_out_4 - conv_out_5 = self.conv_5(element_sum_4) - context_out_5 = self.context_layer_5(conv_out_5) + conv_out_5 = self.block5(element_sum_4) + context_out_5 = self.context5(conv_out_5) element_sum_5 = conv_out_5 + context_out_5 # First upsampling module. - upsample_out_1 = self.upsample_layer_1(element_sum_5) - concat_1 = torch.cat((element_sum_4, upsample_out_1), dim=1) + upsample_out_1 = self.upsample1(element_sum_5) + concat_1 = torch.cat((element_sum_4, upsample_out_1)) - localisation_out_1 = self.localise_layer_1(concat_1) - upsample_out_2 = self.upsample_layer_2(localisation_out_1) - concat_2 = torch.cat((element_sum_3, upsample_out_2), dim=1) + localisation_out_1 = self.localise1(concat_1) + upsample_out_2 = self.upsample2(localisation_out_1) + concat_2 = torch.cat((element_sum_3, upsample_out_2)) - localisation_out_2 = self.localise_layer_2(concat_2) - upsample_out_3 = self.upsample_layer_3(localisation_out_2) - concat_3 = torch.cat((element_sum_2, upsample_out_3), dim=1) + localisation_out_2 = self.localise2(concat_2) + upsample_out_3 = self.upsample3(localisation_out_2) + concat_3 = torch.cat((element_sum_2, upsample_out_3)) - localisation_out_3 = self.localise_layer_3(concat_3) - upsample_out_4 = self.upsample_layer_4(localisation_out_3) - concat_4 = torch.cat((element_sum_1, upsample_out_4), dim=1) + localisation_out_3 = self.localise3(concat_3) + upsample_out_4 = self.upsample4(localisation_out_3) + concat_4 = torch.cat((element_sum_1, upsample_out_4)) - segment_out_1 = self.segmentation_layer_1(localisation_out_2) + segment_out_1 = self.segmentation1(localisation_out_2) upscale_out_1 = self.upscale_1(segment_out_1) - segment_out_2 = self.segmentation_layer_2(localisation_out_3) + segment_out_2 = self.segmentation2(localisation_out_3) seg_sum_1 = upscale_out_1 + segment_out_2 upscale_out_2 = self.upscale_2(seg_sum_1) - segment_out_1 = self.segmentation_layer_1(localisation_out_2) - upscale_out_1 = self.upscale_1(segment_out_1) - convoutput_out = self.conv_output(concat_4) - segment_out_3 = self.segmentation_layer_3(convoutput_out) + segment_out_3 = self.segmentation3(convoutput_out) final_sum = upscale_out_2 + segment_out_3 - output = nn.Softmax(dim = 1)(final_sum) + output = torch.permute(final_sum,( 1, 2, 3, 0)) + + return torch.softmax(output, dim = -1) + +if __name__ == '__main__': + # Create a tensor of shape (256, 256, 128) with random numbers + random_tensor = torch.randn(256, 256, 128) + + random_tensor = random_tensor[np.newaxis, : , : , :] + + conv = ImprovedUnet() - output = output.unsqueeze(1) + print(random_tensor.shape) - output = output.permute(0, 1, 3, 4, 5, 2) + output = conv(random_tensor) - return output \ No newline at end of file + print(output.shape) \ No newline at end of file From ad86cb6cd12eb79e72a3ca868407cc7d86ebc9ad Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 01:51:00 +1000 Subject: [PATCH 005/102] functioning improved unet 3d --- recognition/47049358/.gitignore | 5 +- recognition/47049358/dataset.py | 74 +++------------ recognition/47049358/modules.py | 8 +- recognition/47049358/predict.py | 90 +++++++++++++----- recognition/47049358/train.py | 156 +++++++++++++++++--------------- 5 files changed, 177 insertions(+), 156 deletions(-) diff --git a/recognition/47049358/.gitignore b/recognition/47049358/.gitignore index b459636a0..4bcd5b813 100644 --- a/recognition/47049358/.gitignore +++ b/recognition/47049358/.gitignore @@ -3,9 +3,10 @@ semantic_MRs_anon **__pycache__** - *.ipynb *.pkl -*.txt \ No newline at end of file +*.txt + +*.png \ No newline at end of file diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index dd753470c..87f469577 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -6,13 +6,10 @@ import pickle import numpy as np from torch.utils.data import Dataset -from PIL import Image -import torch -from torch.utils.data import DataLoader IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') -BATCH_SIZE = 1 +BATCH_SIZE = 2 RANDOM_STATE = 47049358 def to_channels(arr: np.ndarray, dtype=np.uint8) -> np.ndarray: @@ -160,74 +157,33 @@ def load_saved_data(image_save_path, label_save_path): - __getitem__(idx): Returns the image and its corresponding mask at the given index `idx`. Resizes image and converts to correct colour channels. """ class Prostate3dDataset(Dataset): - def __init__(self, images, labels, transform=None): + def __init__(self, images, labels): self.images = images self.labels = labels - self.transform = transform def __len__(self): return len(self.images) - # def match_mask_to_image(self, img_filename): - # base_name = os.path.splitext(img_filename)[0] # This removes the .jpg or any extension - # return base_name + '_segmentation.png' - def __getitem__(self, idx): img = self.images[idx] mask = self.labels[idx] - return img, mask -# rawImageNames = os.listdir(IMAGE_FILE_NAME) -# rawLabelNames = os.listdir(LABEL_FILE_NAME) +rawImageNames = os.listdir(IMAGE_FILE_NAME) +rawLabelNames = os.listdir(LABEL_FILE_NAME) # Split the set into train, validation, and test set (70:15:15 for train:valid:test) -# X_train, X_rem, y_train, y_rem = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and remaining set -# X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, train_size=0.5, random_state=RANDOM_STATE) - -# X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] -# X_val = [os.path.join(IMAGE_FILE_NAME, image) for image in X_val] -# X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] - -# y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] -# y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] -# y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] - -# X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) -# X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) -# X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) - -train_dir = os.path.join(os.getcwd(), 'train_set') -val_dir = os.path.join(os.getcwd(), 'validation_set') -test_dir = os.path.join(os.getcwd(), 'test_set') - -# os.makedirs(train_dir, exist_ok = True) -# os.makedirs(test_dir, exist_ok = True) -# os.makedirs(val_dir, exist_ok = True) - -train_img_file = os.path.join(train_dir, 'train_images.pkl') -train_label_file = os.path.join(train_dir, 'train_labels.pkl') - -val_img_file = os.path.join(val_dir, 'validation_images.pkl') -val_label_file = os.path.join(val_dir, 'validation_labels.pkl') - -test_img_file = os.path.join(test_dir, 'test_images.pkl') -test_label_file = os.path.join(test_dir, 'test_labels.pkl') - -# save_data(images=X_train, labels=y_train, image_save_path=train_img_file, label_save_path=train_label_file) -# save_data(images=X_val, labels=y_val, image_save_path=val_img_file, label_save_path=val_label_file) -# save_data(images=X_test, labels=y_test, image_save_path=test_img_file, label_save_path=test_label_file) +X_train, X_rem, y_train, y_rem = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and remaining set +X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, train_size=0.5, random_state=RANDOM_STATE) -# Load datasets -X_train, y_train = load_saved_data(train_img_file, train_label_file) -X_val, y_val = load_saved_data(val_img_file, val_label_file) -X_test, y_test = load_saved_data(test_img_file, test_label_file) +X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] +X_val = [os.path.join(IMAGE_FILE_NAME, image) for image in X_val] +X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] -# Recreate datasets and dataloaders -train_set = Prostate3dDataset(X_train, y_train) -validation_set = Prostate3dDataset(X_val, y_val) -test_set = Prostate3dDataset(X_test, y_test) +y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] +y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] +y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True, num_workers=4, pin_memory=True) -validation_loader = DataLoader(validation_set, batch_size=BATCH_SIZE, shuffle=False) -test_loader = DataLoader(test_set, batch_size=BATCH_SIZE, shuffle=True) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) +X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 0155f43bc..7ac9ccbdc 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -26,7 +26,7 @@ def __init__(self, in_channels, out_channels, kernel_size = 3, stride = 1, padding = 1): super(ContextModule, self).__init__() self.block1 = StandardModule(in_channels = in_channels, out_channels = out_channels, inplace = True) - self.dropout = nn.Dropout(DROP_PROB) + self.dropout = nn.Dropout(DROP_PROB) # Drop description uncertain, replace it with Dropout3d when poor performance self.block2 = StandardModule(in_channels = in_channels, out_channels = out_channels, inplace = True) def forward(self, x): @@ -193,7 +193,11 @@ def forward(self, x): output = torch.permute(final_sum,( 1, 2, 3, 0)) - return torch.softmax(output, dim = -1) + output = torch.softmax(output, dim = -1) + + output = output[np.newaxis, : , : , : , :] + + return output if __name__ == '__main__': # Create a tensor of shape (256, 256, 128) with random numbers diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 785d11790..1e911468a 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -6,13 +6,12 @@ import torch import numpy as np import matplotlib.pyplot as plt -import os -import torchvision.transforms as transforms +from torch.utils.data import DataLoader # import from local files from train import dice_coefficient, trained_model -from dataset import test_loader +from dataset import X_test, y_test, Prostate3dDataset """ Tests improved unet on trained model. @@ -29,18 +28,38 @@ def test(model, test_loader, device): model.eval() # Set the model to evaluation mode - dice_scores = [] # stores dice scores. + test_scores = [] # stores dice scores. + seg_0_scores = [] + seg_1_scores = [] + seg_2_scores = [] + seg_3_scores = [] + seg_4_scores = [] + seg_5_scores = [] with torch.no_grad(): - for test_inputs, test_masks in test_loader: - inputs, targets = test_inputs[np.newaxis, :], test_masks[np.newaxis, :] - - inputs, targets = inputs.to(device), targets.to(device) + for inputs, masks in test_loader: + inputs, masks = inputs.to(device), masks.to(device) outputs = model(inputs) - dice = dice_coefficient(outputs, targets) - dice_scores.append(dice.item()) - - return dice_scores + test_loss, dice_coefs = dice_coefficient(outputs, masks) + + for i in range(len(dice_coefs)): + if i == 0: + seg_0_scores.append(dice_coefs[i]) + elif i == 1: + seg_1_scores.append(dice_coefs[i]) + elif i == 2: + seg_2_scores.append(dice_coefs[i]) + elif i == 3: + seg_3_scores.append(dice_coefs[i]) + elif i == 4: + seg_4_scores.append(dice_coefs[i]) + else: + seg_5_scores.append(dice_coefs[i]) + + + test_scores.append(-1 * test_loss.item()) + + return test_scores, seg_0_scores, seg_1_scores, seg_2_scores, seg_3_scores, seg_4_scores, seg_5_scores """ Visualises model image, predictions and ground truth on first three images from test loader. @@ -99,16 +118,25 @@ def visualise_predictions(model, test_loader, device, num_images=3): Plots dice coefficients of the whole test dataset. Takes an array of dice scores as input. """ -def plot_dice(dice): +def plot_dice(dice, segment_scores): x_values = np.arange(len(dice)) # Generate x-values as indices plt.figure(figsize=(8, 6)) - plt.plot(x_values, dice, marker='o', linestyle='-') + + # Plot overall dice scores + plt.plot(x_values, dice_scores, label='Overall Dice Scores') + + # Plot segment scores + for i, segment_score in enumerate(segment_scores): + plt.plot(x_values, segment_score, label=f'Segment {i} Dice Scores') + + plt.xlabel("Image Index") plt.ylabel("Dice Coefficient") plt.title("Dice Coefficient across test inputs") + plt.legend() plt.grid(True) - plt.show() plt.savefig('dice_scores_test.png') + plt.close() """ @@ -119,19 +147,37 @@ def plot_dice(dice): # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - # set up data transform. - data_transform = transforms.Compose([ - transforms.ToTensor(), - #transforms.Normalize(mean=[0.7071, 0.5821, 0.5360], std=[0.1561, 0.1644, 0.1795]) - ]) + test_set = Prostate3dDataset(X_test, y_test) + test_loader = DataLoader(test_set) # perform predictions - dice_scores = test(trained_model, test_loader, device) + dice_scores, s0, s1, s2, s3, s4, s5 = test(trained_model, test_loader, device) + average_dice = np.mean(dice_scores) print(f"Average Dice Coefficient: {average_dice:.4f}") + average_s0 = np.mean(s0) + print(f"Segment 0 Dice Coefficient: {average_s0:.4f}") + + average_s1 = np.mean(s1) + print(f"Segment 1 Dice Coefficient: {average_s1:.4f}") + + average_s2 = np.mean(s2) + print(f"Segment 2 Dice Coefficient: {average_s2:.4f}") + + average_s3 = np.mean(s3) + print(f"Segment 3 Dice Coefficient: {average_s3:.4f}") + + average_s4 = np.mean(s4) + print(f"Segment 4 Dice Coefficient: {average_s4:.4f}") + + average_s5 = np.mean(s5) + print(f"Segment 5 Dice Coefficient: {average_s5:.4f}") + + segment_scores = [s0, s1, s2, s3, s4, s5] + # plot dice scores across the dataset. - plot_dice(dice_scores) + plot_dice(dice_scores, segment_scores) # plot three examples of images, prediction and truth. # visualise_predictions(trained_model, test_loader,device) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 224aa5307..9a31adf3f 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -4,28 +4,25 @@ sure to plot the losses and metrics during training """ -from dataset import train_loader, validation_loader +from dataset import X_train, y_train, X_val, y_val, Prostate3dDataset from modules import ImprovedUnet import matplotlib.pyplot as plt import torch +from torch.utils.data import DataLoader +from time import time from tqdm import tqdm -import numpy as np -NUM_EPOCHS = 10 -from tqdm import tqdm -import numpy as np -import torch -import torch.nn as nn -import torch.optim as optim +NUM_EPOCHS = 300 +LEARNING_RATE = 5e-4 +WEIGHT_DECAY = 1e-5 +LR_INITIAL = 0.985 -NUM_EPOCHS = 10 - -def train(model, train_loader, valid_loader, num_epochs=100, device="cuda"): - # Set up criterion, optimiser, and scheduler for learning rate. +def train(model, train_loader, valid_loader, num_epochs=NUM_EPOCHS, device="cuda"): + # set up criterion, optimiser, and scheduler for learning rate. criterion = dice_coefficient - optimiser = torch.optim.Adam(model.parameters(), lr=5e-4, weight_decay=1e-5) - scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma=0.985) + optimiser = torch.optim.Adam(model.parameters(), lr = LEARNING_RATE, weight_decay = WEIGHT_DECAY) + scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma = LR_INITIAL) model.to(device) model.train() @@ -33,94 +30,111 @@ def train(model, train_loader, valid_loader, num_epochs=100, device="cuda"): training_losses = [] validation_losses = [] - # Initialize GradScaler for mixed precision training - scaler = torch.cuda.amp.GradScaler() - for epoch in range(num_epochs): running_loss = 0.0 - for inputs, masks in tqdm(train_loader, desc=f'Epoch {epoch + 1}/{num_epochs}'): - inputs = inputs[:, np.newaxis] - masks = masks[:, np.newaxis] - - inputs, masks = inputs.to(device, non_blocking=True), masks.to(device, non_blocking=True) - + segment_losses = None + for batch_num, (inputs, masks) in enumerate(tqdm(train_loader)): + inputs, masks = inputs.to(device), masks.to(device) optimiser.zero_grad() + outputs = model(inputs) - # Forward pass with mixed precision - with torch.amp.autocast(): - outputs = model(inputs) - loss = 1 - criterion(masks, outputs) + # we want to maximise the dice coefficient + # loss is then 1 - dice coefficient + loss, d_coefs = criterion(y_true = masks, y_pred = outputs) - # Backward pass with GradScaler - scaler.scale(loss).backward() - scaler.step(optimiser) - scaler.update() + if segment_losses == None: + segment_losses = d_coefs + else: + segment_losses += d_coefs - running_loss += loss.item() + loss.backward() + optimiser.step() - # Clear cache - torch.cuda.empty_cache() + running_loss += -1 * loss.item() + + if batch_num >= 0: + break - training_losses.append(running_loss / len(train_loader)) scheduler.step() - # Validation step (optional) + for i in range(len(segment_losses)): + print(f"Epoch {epoch + 1} Segment {i} - Training Dice Coefficient: {segment_losses[i] / len(train_loader)}") + + print(f"Epoch {epoch + 1}, Training Loss: {running_loss / len(train_loader)}") + model.eval() - validation_loss = 0.0 + val_loss = 0.0 + segment_losses = None + + # get validation losses. with torch.no_grad(): - for inputs, masks in valid_loader: - inputs = inputs[:, np.newaxis] - masks = masks[:, np.newaxis] + for val_inputs, val_masks in valid_loader: + val_inputs, val_masks = val_inputs.to(device), val_masks.to(device) + val_outputs = model(val_inputs) - inputs, masks = inputs.to(device, non_blocking=True), masks.to(device, non_blocking=True) + loss, d_coefs = criterion(val_outputs, val_masks) - with torch.cuda.amp.autocast(): - outputs = model(inputs) - loss = 1 - criterion(masks, outputs) + if segment_losses == None: + segment_losses = d_coefs + else: + segment_losses += d_coefs - validation_loss += loss.item() + val_loss += -1 * loss.item() - validation_losses.append(validation_loss / len(valid_loader)) - model.train() + for i in range(len(segment_losses)): - return model, training_losses, validation_losses + print(f"Epoch {epoch + 1} Segment {i} - Validation Dice Coefficient: {segment_losses[i] / len(train_loader)}") -def dice_coefficient(y_true, y_pred, epsilon=1e-6): - num_masks = y_true.size(-1) # Assuming the masks are in the last dimension - dim_coefs = torch.zeros(num_masks, device=y_true.device) # Initialize a tensor to store the coefficients + print(f"Epoch {epoch + 1}, Validation Loss: {val_loss / len(valid_loader)}") + training_losses.append(running_loss / len(train_loader)) + validation_losses.append(val_loss / len(valid_loader)) + + return model, training_losses, validation_losses + +def dice_coefficient(y_true, y_pred, epsilon=1e-7): + num_masks = y_true.size(-1) + d_coefs = torch.zeros(num_masks) for i in range(num_masks): - # Get the argmax indices along the class dimension - ref = torch.argmax(y_pred, dim=-1) - - # Create binary masks where the predicted elements are set to 1 if they match the argmax indices - y_pred_binary = (ref == i).float() - - y_true_f = y_true[..., i].contiguous().view(-1) # Flatten the mask - y_pred_f = y_pred_binary.contiguous().view(-1) # Flatten the prediction - - intersection = torch.sum(y_true_f * y_pred_f) - denominator = torch.sum(y_true_f) + torch.sum(y_pred_f) - dim_coef = 2 * (intersection / denominator.clamp(min=epsilon)) - print(f'Mask {i}: ', dim_coef) - dim_coefs[i] = dim_coef # Store the coefficient in the tensor + ground_truth_seg = y_true[: , : , : , : , i] + pred_seg = y_pred[: , : , : , : , i] - output = torch.divide(torch.sum(dim_coefs), num_masks) - output.requires_grad = True - return output + d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / torch.sum((ground_truth_seg + pred_seg) + epsilon) + d_coefs[i] = d_coef + + overall_loss = (-1 / num_masks) * torch.sum(d_coefs) + return overall_loss, d_coefs # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + if not torch.cuda.is_available(): print("Warning CUDA not Found. Using CPU") # create model. model = ImprovedUnet() +# Importing Dataloader breaks the implementation. Hence they are loaded below instead: + +train_set = Prostate3dDataset(X_train, y_train) +validation_set = Prostate3dDataset(X_val, y_val) + +train_loader = DataLoader(train_set) +validation_loader = DataLoader(validation_set) + +print("> Start Training") + +start = time() + # train improved unet trained_model, training_losses, validation_losses = train(model, train_loader, validation_loader, device=device, num_epochs=NUM_EPOCHS) +end = time() + +elapsed_time = end - start +print(f"Training completed in {elapsed_time:.2f} seconds") + plt.figure(figsize=(10,5)) plt.plot(training_losses, label='Training Loss') plt.plot(validation_losses, label='Validation Loss') @@ -128,6 +142,6 @@ def dice_coefficient(y_true, y_pred, epsilon=1e-6): plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() -plt.show() - -plt.savefig('unet_losses_over_epochs.png') \ No newline at end of file +plt.grid(True) +plt.savefig('unet_losses_over_epochs.png') +plt.close() \ No newline at end of file From 9fa1ffaa8769eb4aa38c666b35c85bc4bb6c4396 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:37:41 +1000 Subject: [PATCH 006/102] early stop disabled for testing --- recognition/47049358/dataset.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 87f469577..602d96439 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -184,6 +184,6 @@ def __getitem__(self, idx): y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) -X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) +X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=False) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) From d1cacc38fa66a35b9ebf621fd7e8e3dc50155e69 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:30:20 +1000 Subject: [PATCH 007/102] batch error is fixed --- recognition/47049358/dataset.py | 12 ++++--- recognition/47049358/modules.py | 34 ++++++++------------ recognition/47049358/predict.py | 4 ++- recognition/47049358/train.py | 55 ++++++++++++++++++++------------- 4 files changed, 58 insertions(+), 47 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 602d96439..ea20b6909 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -6,10 +6,10 @@ import pickle import numpy as np from torch.utils.data import Dataset +from torch.utils.data import DataLoader IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') -BATCH_SIZE = 2 RANDOM_STATE = 47049358 def to_channels(arr: np.ndarray, dtype=np.uint8) -> np.ndarray: @@ -184,6 +184,10 @@ def __getitem__(self, idx): y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) -X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=False) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) +X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) + +X_train = X_train[: ,np.newaxis, :, :, :] +X_val = X_val[:,np.newaxis, :, :, :] +X_test = X_test[:, np.newaxis, :, :, :] \ No newline at end of file diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 7ac9ccbdc..c32983085 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -140,10 +140,10 @@ def __init__(self): def forward(self, x): + conv_out_1 = self.block1(x) context_out_1 = self.context1(conv_out_1) element_sum_1 = conv_out_1 + context_out_1 - # second term conv_out_2 = self.block2(element_sum_1) context_out_2 = self.context2(conv_out_2) @@ -164,26 +164,26 @@ def forward(self, x): # First upsampling module. upsample_out_1 = self.upsample1(element_sum_5) - concat_1 = torch.cat((element_sum_4, upsample_out_1)) + concat_1 = torch.cat((element_sum_4, upsample_out_1), dim = 1) localisation_out_1 = self.localise1(concat_1) upsample_out_2 = self.upsample2(localisation_out_1) - concat_2 = torch.cat((element_sum_3, upsample_out_2)) + concat_2 = torch.cat((element_sum_3, upsample_out_2), dim = 1) localisation_out_2 = self.localise2(concat_2) upsample_out_3 = self.upsample3(localisation_out_2) - concat_3 = torch.cat((element_sum_2, upsample_out_3)) + concat_3 = torch.cat((element_sum_2, upsample_out_3), dim = 1) localisation_out_3 = self.localise3(concat_3) upsample_out_4 = self.upsample4(localisation_out_3) - concat_4 = torch.cat((element_sum_1, upsample_out_4)) + concat_4 = torch.cat((element_sum_1, upsample_out_4), dim = 1) segment_out_1 = self.segmentation1(localisation_out_2) upscale_out_1 = self.upscale_1(segment_out_1) segment_out_2 = self.segmentation2(localisation_out_3) seg_sum_1 = upscale_out_1 + segment_out_2 - + upscale_out_2 = self.upscale_2(seg_sum_1) convoutput_out = self.conv_output(concat_4) @@ -191,24 +191,16 @@ def forward(self, x): final_sum = upscale_out_2 + segment_out_3 - output = torch.permute(final_sum,( 1, 2, 3, 0)) + output = torch.permute(final_sum, (0, 2, 3, 4, 1)) output = torch.softmax(output, dim = -1) - - output = output[np.newaxis, : , : , : , :] return output - -if __name__ == '__main__': - # Create a tensor of shape (256, 256, 128) with random numbers - random_tensor = torch.randn(256, 256, 128) - - random_tensor = random_tensor[np.newaxis, : , : , :] - conv = ImprovedUnet() - - print(random_tensor.shape) - output = conv(random_tensor) - - print(output.shape) \ No newline at end of file +if __name__ == '__main__': + model = ImprovedUnet() + input_tensor = torch.randn(2, 1, 256, 256, 128) # Input tensor with shape [2, 1, 256, 256, 128] + output_tensor = model(input_tensor) + print(f"Input shape: {input_tensor.shape}") + print(f"Output shape: {output_tensor.shape}") \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 1e911468a..036320edb 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -13,6 +13,8 @@ from train import dice_coefficient, trained_model from dataset import X_test, y_test, Prostate3dDataset +BATCH_SIZE = 2 + """ Tests improved unet on trained model. Calcualtes dice coeficient for each image and corresponding ground truth. @@ -148,7 +150,7 @@ def plot_dice(dice, segment_scores): device = torch.device("cuda" if torch.cuda.is_available() else "cpu") test_set = Prostate3dDataset(X_test, y_test) - test_loader = DataLoader(test_set) + test_loader = DataLoader(dataset = test_set, batch_size = BATCH_SIZE) # perform predictions dice_scores, s0, s1, s2, s3, s4, s5 = test(trained_model, test_loader, device) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 9a31adf3f..4927cdd06 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -9,18 +9,41 @@ import matplotlib.pyplot as plt import torch from torch.utils.data import DataLoader +import torch.nn as nn from time import time from tqdm import tqdm +import numpy as np NUM_EPOCHS = 300 +BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -def train(model, train_loader, valid_loader, num_epochs=NUM_EPOCHS, device="cuda"): +class DiceCoefficient(nn.Module): + def __init__(self, epsilon=1e-7): + super(DiceCoefficient, self).__init__() + self.epsilon = epsilon + + def forward(self, y_true, y_pred): + + num_masks = y_true.size(-1) + d_coefs = torch.zeros(num_masks, device=y_true.device) + for i in range(num_masks): + ground_truth_seg = y_true[:, :, :, :, i] + pred_seg = y_pred[:, :, :, :, i] + + d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) + d_coefs[i] = d_coef + + overall_loss = (-1 / num_masks) * torch.sum(d_coefs) + return overall_loss, d_coefs + +def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda"): + # set up criterion, optimiser, and scheduler for learning rate. - criterion = dice_coefficient + criterion = DiceCoefficient() optimiser = torch.optim.Adam(model.parameters(), lr = LEARNING_RATE, weight_decay = WEIGHT_DECAY) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma = LR_INITIAL) @@ -30,16 +53,22 @@ def train(model, train_loader, valid_loader, num_epochs=NUM_EPOCHS, device="cuda training_losses = [] validation_losses = [] + + train_loader = DataLoader(dataset = train_set, batch_size = BATCH_SIZE) + valid_loader = DataLoader(dataset = validation_set, batch_size = BATCH_SIZE) + for epoch in range(num_epochs): running_loss = 0.0 segment_losses = None for batch_num, (inputs, masks) in enumerate(tqdm(train_loader)): + + print(inputs.shape) + print(masks.shape) + inputs, masks = inputs.to(device), masks.to(device) optimiser.zero_grad() outputs = model(inputs) - # we want to maximise the dice coefficient - # loss is then 1 - dice coefficient loss, d_coefs = criterion(y_true = masks, y_pred = outputs) if segment_losses == None: @@ -92,19 +121,6 @@ def train(model, train_loader, valid_loader, num_epochs=NUM_EPOCHS, device="cuda return model, training_losses, validation_losses -def dice_coefficient(y_true, y_pred, epsilon=1e-7): - num_masks = y_true.size(-1) - d_coefs = torch.zeros(num_masks) - for i in range(num_masks): - ground_truth_seg = y_true[: , : , : , : , i] - pred_seg = y_pred[: , : , : , : , i] - - d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / torch.sum((ground_truth_seg + pred_seg) + epsilon) - d_coefs[i] = d_coef - - overall_loss = (-1 / num_masks) * torch.sum(d_coefs) - return overall_loss, d_coefs - # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -119,15 +135,12 @@ def dice_coefficient(y_true, y_pred, epsilon=1e-7): train_set = Prostate3dDataset(X_train, y_train) validation_set = Prostate3dDataset(X_val, y_val) -train_loader = DataLoader(train_set) -validation_loader = DataLoader(validation_set) - print("> Start Training") start = time() # train improved unet -trained_model, training_losses, validation_losses = train(model, train_loader, validation_loader, +trained_model, training_losses, validation_losses = train(model, train_set, validation_set, device=device, num_epochs=NUM_EPOCHS) end = time() From 463696a5c94890f00102601f80edf5cb69e7c66c Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:30:34 +1000 Subject: [PATCH 008/102] prototype with paper-based loss function --- recognition/47049358/.gitignore | 4 +++- recognition/47049358/dataset.py | 6 +++--- recognition/47049358/train.py | 10 ++-------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/recognition/47049358/.gitignore b/recognition/47049358/.gitignore index 4bcd5b813..f381cc8b7 100644 --- a/recognition/47049358/.gitignore +++ b/recognition/47049358/.gitignore @@ -9,4 +9,6 @@ semantic_MRs_anon *.txt -*.png \ No newline at end of file +*.png + +*.sh \ No newline at end of file diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index ea20b6909..46309ba00 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -184,9 +184,9 @@ def __getitem__(self, idx): y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) -X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) +X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=False) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) X_train = X_train[: ,np.newaxis, :, :, :] X_val = X_val[:,np.newaxis, :, :, :] diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 4927cdd06..7e84bbd34 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -60,10 +60,7 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" for epoch in range(num_epochs): running_loss = 0.0 segment_losses = None - for batch_num, (inputs, masks) in enumerate(tqdm(train_loader)): - - print(inputs.shape) - print(masks.shape) + for inputs, masks in tqdm(train_loader): inputs, masks = inputs.to(device), masks.to(device) optimiser.zero_grad() @@ -79,10 +76,7 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" loss.backward() optimiser.step() - running_loss += -1 * loss.item() - - if batch_num >= 0: - break + running_loss += -1 * loss.item() scheduler.step() From 67e6277b71d1ad5e6b7a58084827ac3de5288ce9 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:47:00 +1000 Subject: [PATCH 009/102] alternative loss function implemented --- recognition/47049358/predict.py | 10 +++++---- recognition/47049358/train.py | 36 ++++++++++++++++----------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 036320edb..0702e6568 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -10,7 +10,7 @@ # import from local files -from train import dice_coefficient, trained_model +from train import DiceCoefficientLoss, trained_model from dataset import X_test, y_test, Prostate3dDataset BATCH_SIZE = 2 @@ -39,10 +39,13 @@ def test(model, test_loader, device): seg_5_scores = [] with torch.no_grad(): + + criterion = DiceCoefficientLoss() + for inputs, masks in test_loader: inputs, masks = inputs.to(device), masks.to(device) outputs = model(inputs) - test_loss, dice_coefs = dice_coefficient(outputs, masks) + test_loss, dice_coefs = criterion(outputs, masks) for i in range(len(dice_coefs)): if i == 0: @@ -58,8 +61,7 @@ def test(model, test_loader, device): else: seg_5_scores.append(dice_coefs[i]) - - test_scores.append(-1 * test_loss.item()) + test_scores.append(test_loss.item()) return test_scores, seg_0_scores, seg_1_scores, seg_2_scores, seg_3_scores, seg_4_scores, seg_5_scores diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 7e84bbd34..0ce59efef 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -21,9 +21,9 @@ WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -class DiceCoefficient(nn.Module): +class DiceCoefficientLoss(nn.Module): def __init__(self, epsilon=1e-7): - super(DiceCoefficient, self).__init__() + super(DiceCoefficientLoss, self).__init__() self.epsilon = epsilon def forward(self, y_true, y_pred): @@ -37,13 +37,13 @@ def forward(self, y_true, y_pred): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) d_coefs[i] = d_coef - overall_loss = (-1 / num_masks) * torch.sum(d_coefs) + overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) return overall_loss, d_coefs def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda"): # set up criterion, optimiser, and scheduler for learning rate. - criterion = DiceCoefficient() + criterion = DiceCoefficientLoss() optimiser = torch.optim.Adam(model.parameters(), lr = LEARNING_RATE, weight_decay = WEIGHT_DECAY) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma = LR_INITIAL) @@ -59,7 +59,7 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" for epoch in range(num_epochs): running_loss = 0.0 - segment_losses = None + segment_coefs = None for inputs, masks in tqdm(train_loader): inputs, masks = inputs.to(device), masks.to(device) @@ -68,26 +68,26 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" loss, d_coefs = criterion(y_true = masks, y_pred = outputs) - if segment_losses == None: - segment_losses = d_coefs + if segment_coefs == None: + segment_coefs = d_coefs else: - segment_losses += d_coefs + segment_coefs += d_coefs loss.backward() optimiser.step() - running_loss += -1 * loss.item() + running_loss += loss.item() scheduler.step() - for i in range(len(segment_losses)): - print(f"Epoch {epoch + 1} Segment {i} - Training Dice Coefficient: {segment_losses[i] / len(train_loader)}") + for i in range(len(segment_coefs)): + print(f"Epoch {epoch + 1} Segment {i} - Training Dice Coefficient: {segment_coefs[i] / len(train_loader)}") print(f"Epoch {epoch + 1}, Training Loss: {running_loss / len(train_loader)}") model.eval() val_loss = 0.0 - segment_losses = None + segment_coefs = None # get validation losses. with torch.no_grad(): @@ -97,16 +97,16 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" loss, d_coefs = criterion(val_outputs, val_masks) - if segment_losses == None: - segment_losses = d_coefs + if segment_coefs == None: + segment_coefs = d_coefs else: - segment_losses += d_coefs + segment_coefs += d_coefs - val_loss += -1 * loss.item() + val_loss += loss.item() - for i in range(len(segment_losses)): + for i in range(len(segment_coefs)): - print(f"Epoch {epoch + 1} Segment {i} - Validation Dice Coefficient: {segment_losses[i] / len(train_loader)}") + print(f"Epoch {epoch + 1} Segment {i} - Validation Dice Coefficient: {segment_coefs[i] / len(train_loader)}") print(f"Epoch {epoch + 1}, Validation Loss: {val_loss / len(valid_loader)}") From 69581a21f4e1497214a28608aa615591f72026d4 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:50:09 +1000 Subject: [PATCH 010/102] paper based loss function with negative --- recognition/47049358/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 0ce59efef..299f2ab50 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -37,7 +37,7 @@ def forward(self, y_true, y_pred): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) d_coefs[i] = d_coef - overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) + overall_loss = (-1 / num_masks) * torch.sum(d_coefs) return overall_loss, d_coefs def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda"): From f86711943fdb1e8cc29b2f22ef8b60df64c1db2c Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:55:30 +1000 Subject: [PATCH 011/102] image names adjusted --- recognition/47049358/predict.py | 2 +- recognition/47049358/train.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 0702e6568..fbd6133a1 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -139,7 +139,7 @@ def plot_dice(dice, segment_scores): plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig('dice_scores_test.png') + plt.savefig('dice_scores_test_paper.png') plt.close() diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 299f2ab50..a0b2d04c3 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -150,5 +150,5 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig('unet_losses_over_epochs.png') +plt.savefig('unet_losses_over_epochs_paper.png') plt.close() \ No newline at end of file From 8dc9e31031a4792ee1e81fafb05f46be97234e2c Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:56:21 +1000 Subject: [PATCH 012/102] image names adjusted --- recognition/47049358/predict.py | 2 +- recognition/47049358/train.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 0702e6568..8540852b5 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -139,7 +139,7 @@ def plot_dice(dice, segment_scores): plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig('dice_scores_test.png') + plt.savefig('dice_scores_test_alter_loss.png') plt.close() diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 0ce59efef..97c433e52 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -150,5 +150,5 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig('unet_losses_over_epochs.png') +plt.savefig('unet_losses_over_epochs_alter_loss.png') plt.close() \ No newline at end of file From 60bb93e314c9c350cabed032ee788b36cbcd78de Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:32:47 +1000 Subject: [PATCH 013/102] exponential weights based on the loss --- recognition/47049358/dataset.py | 1 - recognition/47049358/modules.py | 12 +++---- recognition/47049358/predict.py | 57 ++------------------------------- recognition/47049358/train.py | 19 +++++++---- 4 files changed, 21 insertions(+), 68 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 46309ba00..4c5665f0e 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -6,7 +6,6 @@ import pickle import numpy as np from torch.utils.data import Dataset -from torch.utils.data import DataLoader IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index c32983085..f5279f07d 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -198,9 +198,9 @@ def forward(self, x): return output -if __name__ == '__main__': - model = ImprovedUnet() - input_tensor = torch.randn(2, 1, 256, 256, 128) # Input tensor with shape [2, 1, 256, 256, 128] - output_tensor = model(input_tensor) - print(f"Input shape: {input_tensor.shape}") - print(f"Output shape: {output_tensor.shape}") \ No newline at end of file +# if __name__ == '__main__': +# model = ImprovedUnet() +# input_tensor = torch.randn(2, 1, 256, 256, 128) # Input tensor with shape [2, 1, 256, 256, 128] +# output_tensor = model(input_tensor) +# print(f"Input shape: {input_tensor.shape}") +# print(f"Output shape: {output_tensor.shape}") \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 8540852b5..1826809ae 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -45,7 +45,7 @@ def test(model, test_loader, device): for inputs, masks in test_loader: inputs, masks = inputs.to(device), masks.to(device) outputs = model(inputs) - test_loss, dice_coefs = criterion(outputs, masks) + test_loss, dice_coefs, _ = criterion(outputs, masks) for i in range(len(dice_coefs)): if i == 0: @@ -65,59 +65,6 @@ def test(model, test_loader, device): return test_scores, seg_0_scores, seg_1_scores, seg_2_scores, seg_3_scores, seg_4_scores, seg_5_scores -""" - Visualises model image, predictions and ground truth on first three images from test loader. - - Parameters: - - model (nn.Module): The trained model used for making predictions. - - test_loader (DataLoader): DataLoader for the test dataset. - - device (str): The device (e.g., 'cuda' or 'cpu') to run the visualization on. - - num_images (int): The number of images to visualize (default is 3). - - """ -def visualise_predictions(model, test_loader, device, num_images=3): - model.eval() # Set the model to evaluation mode - - image_count = 0 # Keep track of the number of images processed - - with torch.no_grad(): - for inputs, targets in test_loader: - inputs, targets = inputs.to(device), targets.to(device) - # get prediction - outputs = model(inputs) - - # Convert PyTorch tensors to NumPy arrays - input_image = inputs[0].cpu().numpy() - target_image = targets[0].cpu().numpy() - predicted_image = outputs[0].cpu().numpy() - - # Create a side-by-side visualization for three images, prediction, ground truth. - plt.figure(figsize=(12, 4)) - plt.subplot(1, 3, 1) - plt.title("Input Image") - plt.imshow(input_image[0], cmap='gray') - - plt.savefig('input_image.png') - - plt.subplot(1, 3, 2) - plt.title("Model Prediction") - plt.imshow(predicted_image[0], cmap='gray') - - plt.savefig('model_prediction.png') - - plt.subplot(1, 3, 3) - plt.title("Ground Truth") - plt.imshow(target_image[0], cmap='gray') - - plt.show() - - plt.savefig('ground_truth.png') - - image_count += 1 - - if image_count >= num_images: - break - """ Plots dice coefficients of the whole test dataset. Takes an array of dice scores as input. @@ -139,7 +86,7 @@ def plot_dice(dice, segment_scores): plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig('dice_scores_test_alter_loss.png') + plt.savefig('dice_scores_test_weighted_loss.png') plt.close() diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 97c433e52..649683f17 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -12,7 +12,7 @@ import torch.nn as nn from time import time from tqdm import tqdm -import numpy as np +import math NUM_EPOCHS = 300 @@ -36,9 +36,15 @@ def forward(self, y_true, y_pred): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) d_coefs[i] = d_coef + + weighted, _ = torch.sort(d_coefs) + + for i in range(num_masks): + weighted[i] = d_coefs[i] / (math.e ** i) overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) - return overall_loss, d_coefs + weighted_loss = 1 - (1 / num_masks) * torch.sum(weighted) + return overall_loss, d_coefs, weighted_loss def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda"): @@ -66,14 +72,15 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" optimiser.zero_grad() outputs = model(inputs) - loss, d_coefs = criterion(y_true = masks, y_pred = outputs) + # the weighted value is only used for updating gradients! + loss, d_coefs, weighted = criterion(y_true = masks, y_pred = outputs) if segment_coefs == None: segment_coefs = d_coefs else: segment_coefs += d_coefs - loss.backward() + weighted.backward() optimiser.step() running_loss += loss.item() @@ -95,7 +102,7 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" val_inputs, val_masks = val_inputs.to(device), val_masks.to(device) val_outputs = model(val_inputs) - loss, d_coefs = criterion(val_outputs, val_masks) + loss, d_coefs, _ = criterion(val_outputs, val_masks) if segment_coefs == None: segment_coefs = d_coefs @@ -150,5 +157,5 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig('unet_losses_over_epochs_alter_loss.png') +plt.savefig('unet_losses_over_epochs_weighted_loss.png') plt.close() \ No newline at end of file From 3f7987b241326704ce635c1ced54a57624207174 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:12:49 +1000 Subject: [PATCH 014/102] removed redundant function --- recognition/47049358/predict.py | 56 --------------------------------- 1 file changed, 56 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index fbd6133a1..f98418b2f 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -65,59 +65,6 @@ def test(model, test_loader, device): return test_scores, seg_0_scores, seg_1_scores, seg_2_scores, seg_3_scores, seg_4_scores, seg_5_scores -""" - Visualises model image, predictions and ground truth on first three images from test loader. - - Parameters: - - model (nn.Module): The trained model used for making predictions. - - test_loader (DataLoader): DataLoader for the test dataset. - - device (str): The device (e.g., 'cuda' or 'cpu') to run the visualization on. - - num_images (int): The number of images to visualize (default is 3). - - """ -def visualise_predictions(model, test_loader, device, num_images=3): - model.eval() # Set the model to evaluation mode - - image_count = 0 # Keep track of the number of images processed - - with torch.no_grad(): - for inputs, targets in test_loader: - inputs, targets = inputs.to(device), targets.to(device) - # get prediction - outputs = model(inputs) - - # Convert PyTorch tensors to NumPy arrays - input_image = inputs[0].cpu().numpy() - target_image = targets[0].cpu().numpy() - predicted_image = outputs[0].cpu().numpy() - - # Create a side-by-side visualization for three images, prediction, ground truth. - plt.figure(figsize=(12, 4)) - plt.subplot(1, 3, 1) - plt.title("Input Image") - plt.imshow(input_image[0], cmap='gray') - - plt.savefig('input_image.png') - - plt.subplot(1, 3, 2) - plt.title("Model Prediction") - plt.imshow(predicted_image[0], cmap='gray') - - plt.savefig('model_prediction.png') - - plt.subplot(1, 3, 3) - plt.title("Ground Truth") - plt.imshow(target_image[0], cmap='gray') - - plt.show() - - plt.savefig('ground_truth.png') - - image_count += 1 - - if image_count >= num_images: - break - """ Plots dice coefficients of the whole test dataset. Takes an array of dice scores as input. @@ -183,7 +130,4 @@ def plot_dice(dice, segment_scores): # plot dice scores across the dataset. plot_dice(dice_scores, segment_scores) - # plot three examples of images, prediction and truth. - # visualise_predictions(trained_model, test_loader,device) - From 4bfd0fd513fa2efdc34ce056afbc8e4d2cd0ebe5 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:38:48 +1000 Subject: [PATCH 015/102] accessible loss functions --- recognition/47049358/dataset.py | 6 +-- recognition/47049358/predict.py | 11 ++-- recognition/47049358/train.py | 95 +++++++++++++++++++++++++++++---- 3 files changed, 95 insertions(+), 17 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 4c5665f0e..addf0841f 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -183,9 +183,9 @@ def __getitem__(self, idx): y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) -X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=False) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) +X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) X_train = X_train[: ,np.newaxis, :, :, :] X_val = X_val[:,np.newaxis, :, :, :] diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 1826809ae..afcea9d9e 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -10,7 +10,7 @@ # import from local files -from train import DiceCoefficientLoss, trained_model +from train import * from dataset import X_test, y_test, Prostate3dDataset BATCH_SIZE = 2 @@ -27,7 +27,7 @@ Returns: - dice_scores (list): List of Dice coefficients for each image in the test dataset. """ -def test(model, test_loader, device): +def test(model, test_loader, criterion, device): model.eval() # Set the model to evaluation mode test_scores = [] # stores dice scores. @@ -40,7 +40,7 @@ def test(model, test_loader, device): with torch.no_grad(): - criterion = DiceCoefficientLoss() + criterion = criterion for inputs, masks in test_loader: inputs, masks = inputs.to(device), masks.to(device) @@ -98,11 +98,14 @@ def plot_dice(dice, segment_scores): # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + criterion = loss_map.get(LOSS_IDX) + test_set = Prostate3dDataset(X_test, y_test) test_loader = DataLoader(dataset = test_set, batch_size = BATCH_SIZE) # perform predictions - dice_scores, s0, s1, s2, s3, s4, s5 = test(trained_model, test_loader, device) + dice_scores, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, criterion = criterion, + device = device) average_dice = np.mean(dice_scores) print(f"Average Dice Coefficient: {average_dice:.4f}") diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 649683f17..e781efd96 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -15,17 +15,25 @@ import math -NUM_EPOCHS = 300 -BATCH_SIZE = 2 +NUM_EPOCHS = 1 +BATCH_SIZE = 1 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 +LOSS_IDX = 0 -class DiceCoefficientLoss(nn.Module): - def __init__(self, epsilon=1e-7): - super(DiceCoefficientLoss, self).__init__() +class BaseDice(nn.Module): + def __init__(self, epsilon = 1e-7): + super(BaseDice, self).__init__() self.epsilon = epsilon + def forward(self, input, target): + raise NotImplementedError("Sublasses should implement this method.") + +class ExponentialWeightedLoss(BaseDice): + def __init__(self, epsilon=1e-7): + super().__init__(epsilon) + def forward(self, y_true, y_pred): num_masks = y_true.size(-1) @@ -45,11 +53,71 @@ def forward(self, y_true, y_pred): overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) weighted_loss = 1 - (1 / num_masks) * torch.sum(weighted) return overall_loss, d_coefs, weighted_loss + +class ArithmeticWeightedLoss(BaseDice): + def __init__(self, epsilon=1e-7): + super().__init__(epsilon) + + def forward(self, y_true, y_pred): + + num_masks = y_true.size(-1) + d_coefs = torch.zeros(num_masks, device=y_true.device) + for i in range(num_masks): + ground_truth_seg = y_true[:, :, :, :, i] + pred_seg = y_pred[:, :, :, :, i] + + d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) + d_coefs[i] = d_coef + + weighted, _ = torch.sort(d_coefs) + + for i in range(num_masks): + weighted[i] = d_coefs[i] / (i + 1) + + overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) + weighted_loss = 1 - (1 / num_masks) * torch.sum(weighted) + return overall_loss, d_coefs, weighted_loss + +class PaperLoss(BaseDice): + def __init__(self, epsilon=1e-7): + super().__init__(epsilon) -def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda"): + def forward(self, y_true, y_pred): + + num_masks = y_true.size(-1) + d_coefs = torch.zeros(num_masks, device=y_true.device) + for i in range(num_masks): + ground_truth_seg = y_true[:, :, :, :, i] + pred_seg = y_pred[:, :, :, :, i] + + d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) + d_coefs[i] = d_coef + + overall_loss = (- 1 / num_masks) * torch.sum(d_coefs) + return overall_loss, d_coefs, None + +class AlternativeLoss(BaseDice): + def __init__(self, epsilon=1e-7): + super().__init__(epsilon) + + def forward(self, y_true, y_pred): + + num_masks = y_true.size(-1) + d_coefs = torch.zeros(num_masks, device=y_true.device) + for i in range(num_masks): + ground_truth_seg = y_true[:, :, :, :, i] + pred_seg = y_pred[:, :, :, :, i] + + d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) + d_coefs[i] = d_coef + + overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) + return overall_loss, d_coefs, None + +def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): # set up criterion, optimiser, and scheduler for learning rate. - criterion = DiceCoefficientLoss() + criterion = loss optimiser = torch.optim.Adam(model.parameters(), lr = LEARNING_RATE, weight_decay = WEIGHT_DECAY) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma = LR_INITIAL) @@ -58,7 +126,6 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" training_losses = [] validation_losses = [] - train_loader = DataLoader(dataset = train_set, batch_size = BATCH_SIZE) valid_loader = DataLoader(dataset = validation_set, batch_size = BATCH_SIZE) @@ -80,7 +147,11 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" else: segment_coefs += d_coefs - weighted.backward() + if weighted == None: + loss.backward() + else: + weighted.backward() + optimiser.step() running_loss += loss.item() @@ -136,12 +207,16 @@ def train(model, train_set, validation_set, num_epochs=NUM_EPOCHS, device="cuda" train_set = Prostate3dDataset(X_train, y_train) validation_set = Prostate3dDataset(X_val, y_val) +loss_map = {0 : PaperLoss, 1 : AlternativeLoss, 2 : ExponentialWeightedLoss, 3 : ArithmeticWeightedLoss} + +loss = loss_map.get(LOSS_IDX) + print("> Start Training") start = time() # train improved unet -trained_model, training_losses, validation_losses = train(model, train_set, validation_set, +trained_model, training_losses, validation_losses = train(model, train_set, validation_set, loss = loss, device=device, num_epochs=NUM_EPOCHS) end = time() From 0e04cc494d7a7d35aca49963a208a1d8d93a2e56 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:55:58 +1000 Subject: [PATCH 016/102] image save with the model name --- recognition/47049358/train.py | 21 ++++++++++++++++++--- unet_losses_over_epochs_PaperLoss.png | Bin 0 -> 19428 bytes 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 unet_losses_over_epochs_PaperLoss.png diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index e781efd96..9a4003233 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -27,13 +27,16 @@ def __init__(self, epsilon = 1e-7): super(BaseDice, self).__init__() self.epsilon = epsilon - def forward(self, input, target): + def forward(self, y_true, y_pred): raise NotImplementedError("Sublasses should implement this method.") class ExponentialWeightedLoss(BaseDice): def __init__(self, epsilon=1e-7): super().__init__(epsilon) + def __str__(self): + return 'ExponentialWeightedLoss' + def forward(self, y_true, y_pred): num_masks = y_true.size(-1) @@ -58,6 +61,9 @@ class ArithmeticWeightedLoss(BaseDice): def __init__(self, epsilon=1e-7): super().__init__(epsilon) + def __str__(self): + return 'ArithmeticWeightedLoss' + def forward(self, y_true, y_pred): num_masks = y_true.size(-1) @@ -82,6 +88,9 @@ class PaperLoss(BaseDice): def __init__(self, epsilon=1e-7): super().__init__(epsilon) + def __str__(self): + return 'PaperLoss' + def forward(self, y_true, y_pred): num_masks = y_true.size(-1) @@ -100,6 +109,9 @@ class AlternativeLoss(BaseDice): def __init__(self, epsilon=1e-7): super().__init__(epsilon) + def __str__(self): + return 'AlternativeLoss' + def forward(self, y_true, y_pred): num_masks = y_true.size(-1) @@ -207,7 +219,7 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= train_set = Prostate3dDataset(X_train, y_train) validation_set = Prostate3dDataset(X_val, y_val) -loss_map = {0 : PaperLoss, 1 : AlternativeLoss, 2 : ExponentialWeightedLoss, 3 : ArithmeticWeightedLoss} +loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss()} loss = loss_map.get(LOSS_IDX) @@ -224,6 +236,9 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= elapsed_time = end - start print(f"Training completed in {elapsed_time:.2f} seconds") +training_losses = [] +validation_losses = [] + plt.figure(figsize=(10,5)) plt.plot(training_losses, label='Training Loss') plt.plot(validation_losses, label='Validation Loss') @@ -232,5 +247,5 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig('unet_losses_over_epochs_weighted_loss.png') +plt.savefig(f'unet_losses_over_epochs_{str(loss)}.png') plt.close() \ No newline at end of file diff --git a/unet_losses_over_epochs_PaperLoss.png b/unet_losses_over_epochs_PaperLoss.png new file mode 100644 index 0000000000000000000000000000000000000000..e759b4dd433bab24f9f00f8809c3b67e4d1c5b6f GIT binary patch literal 19428 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 E0L>lM`~Uy| literal 0 HcmV?d00001 From 4f02b51fd6f9dde94968bc3159aebfe69169e136 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:56:31 +1000 Subject: [PATCH 017/102] image deleted --- unet_losses_over_epochs_PaperLoss.png | Bin 19428 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 unet_losses_over_epochs_PaperLoss.png diff --git a/unet_losses_over_epochs_PaperLoss.png b/unet_losses_over_epochs_PaperLoss.png deleted file mode 100644 index e759b4dd433bab24f9f00f8809c3b67e4d1c5b6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19428 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 E0L>lM`~Uy| From 7d44724930452005469e2b938d6b189b7e8db9c6 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:58:42 +1000 Subject: [PATCH 018/102] image save in predict fixed --- recognition/47049358/predict.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index dfd386550..58fd84831 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -69,7 +69,7 @@ def test(model, test_loader, criterion, device): Plots dice coefficients of the whole test dataset. Takes an array of dice scores as input. """ -def plot_dice(dice, segment_scores): +def plot_dice(dice, criterion, segment_scores): x_values = np.arange(len(dice)) # Generate x-values as indices plt.figure(figsize=(8, 6)) @@ -86,7 +86,7 @@ def plot_dice(dice, segment_scores): plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig('dice_scores_test_weighted_loss.png') + plt.savefig(f'dice_scores_test_{str(criterion)}.png') plt.close() @@ -131,6 +131,6 @@ def plot_dice(dice, segment_scores): segment_scores = [s0, s1, s2, s3, s4, s5] # plot dice scores across the dataset. - plot_dice(dice_scores, segment_scores) + plot_dice(dice_scores, criterion, segment_scores) From 2631a6035b30c8505a1a81dfb56bc63c993c8d36 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:19:27 +1000 Subject: [PATCH 019/102] validation set removed --- recognition/47049358/dataset.py | 11 ++------ recognition/47049358/predict.py | 2 +- recognition/47049358/train.py | 49 ++++++--------------------------- 3 files changed, 12 insertions(+), 50 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index addf0841f..dd1f7cf29 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -172,21 +172,16 @@ def __getitem__(self, idx): rawLabelNames = os.listdir(LABEL_FILE_NAME) # Split the set into train, validation, and test set (70:15:15 for train:valid:test) -X_train, X_rem, y_train, y_rem = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and remaining set -X_val, X_test, y_val, y_test = train_test_split(X_rem, y_rem, train_size=0.5, random_state=RANDOM_STATE) +X_train, X_test, y_train, y_test = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and test set X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] -X_val = [os.path.join(IMAGE_FILE_NAME, image) for image in X_val] X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] -y_val = [os.path.join(LABEL_FILE_NAME, label) for label in y_val] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) -X_val, y_val = load_images_and_labels(X_val, y_val, early_stop=True) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) X_train = X_train[: ,np.newaxis, :, :, :] -X_val = X_val[:,np.newaxis, :, :, :] X_test = X_test[:, np.newaxis, :, :, :] \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 58fd84831..b46863081 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -86,7 +86,7 @@ def plot_dice(dice, criterion, segment_scores): plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig(f'dice_scores_test_{str(criterion)}.png') + plt.savefig(f'dice_scores_test_{str(criterion)}_without_validation.png') plt.close() diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 9a4003233..32b8aa639 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -4,7 +4,7 @@ sure to plot the losses and metrics during training """ -from dataset import X_train, y_train, X_val, y_val, Prostate3dDataset +from dataset import X_train, y_train, Prostate3dDataset from modules import ImprovedUnet import matplotlib.pyplot as plt import torch @@ -15,12 +15,12 @@ import math -NUM_EPOCHS = 1 -BATCH_SIZE = 1 +NUM_EPOCHS = 300 +BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -LOSS_IDX = 0 +LOSS_IDX = 3 class BaseDice(nn.Module): def __init__(self, epsilon = 1e-7): @@ -126,7 +126,7 @@ def forward(self, y_true, y_pred): overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) return overall_loss, d_coefs, None -def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): +def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): # set up criterion, optimiser, and scheduler for learning rate. criterion = loss @@ -137,10 +137,8 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= model.train() training_losses = [] - validation_losses = [] train_loader = DataLoader(dataset = train_set, batch_size = BATCH_SIZE) - valid_loader = DataLoader(dataset = validation_set, batch_size = BATCH_SIZE) for epoch in range(num_epochs): running_loss = 0.0 @@ -175,35 +173,7 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= print(f"Epoch {epoch + 1}, Training Loss: {running_loss / len(train_loader)}") - model.eval() - val_loss = 0.0 - segment_coefs = None - - # get validation losses. - with torch.no_grad(): - for val_inputs, val_masks in valid_loader: - val_inputs, val_masks = val_inputs.to(device), val_masks.to(device) - val_outputs = model(val_inputs) - - loss, d_coefs, _ = criterion(val_outputs, val_masks) - - if segment_coefs == None: - segment_coefs = d_coefs - else: - segment_coefs += d_coefs - - val_loss += loss.item() - - for i in range(len(segment_coefs)): - - print(f"Epoch {epoch + 1} Segment {i} - Validation Dice Coefficient: {segment_coefs[i] / len(train_loader)}") - - print(f"Epoch {epoch + 1}, Validation Loss: {val_loss / len(valid_loader)}") - - training_losses.append(running_loss / len(train_loader)) - validation_losses.append(val_loss / len(valid_loader)) - - return model, training_losses, validation_losses + return model, training_losses # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -217,7 +187,6 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= # Importing Dataloader breaks the implementation. Hence they are loaded below instead: train_set = Prostate3dDataset(X_train, y_train) -validation_set = Prostate3dDataset(X_val, y_val) loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss()} @@ -228,7 +197,7 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= start = time() # train improved unet -trained_model, training_losses, validation_losses = train(model, train_set, validation_set, loss = loss, +trained_model, training_losses = train(model, train_set, loss = loss, device=device, num_epochs=NUM_EPOCHS) end = time() @@ -237,15 +206,13 @@ def train(model, train_set, validation_set, loss, num_epochs=NUM_EPOCHS, device= print(f"Training completed in {elapsed_time:.2f} seconds") training_losses = [] -validation_losses = [] plt.figure(figsize=(10,5)) plt.plot(training_losses, label='Training Loss') -plt.plot(validation_losses, label='Validation Loss') plt.title('Losses over epochs') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig(f'unet_losses_over_epochs_{str(loss)}.png') +plt.savefig(f'unet_training_losses_over_epochs_{str(loss)}.png') plt.close() \ No newline at end of file From fbf2c983ff42a160b7cd5151e763200f35b145da Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Thu, 17 Oct 2024 03:07:00 +1000 Subject: [PATCH 020/102] data augmentation and dice + bce --- recognition/47049358/README.md | 12 ++++- recognition/47049358/dataset.py | 81 +++++++++++++++++++++++++-------- recognition/47049358/predict.py | 8 ++++ recognition/47049358/train.py | 31 +++++++++++-- 4 files changed, 109 insertions(+), 23 deletions(-) diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index 6ed4fb5d1..ac61610b7 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -1 +1,11 @@ -(Dice Coefficient)[https://en.wikipedia.org/wiki/Dice-Sørensen_coefficient] \ No newline at end of file +(Dice Coefficient)[https://en.wikipedia.org/wiki/Dice-Sørensen_coefficient] + +Updates: + +**Data Augmentation** + +- Random Rotation - Implemented +- Random Scaling - ~~Implemented~~ → Omitted as dimensions disagree with the rest of dataset +- Elastic Transformation - Omitted given the constraint in data type +- Gamma Correction - Implemented +- Mirroring - Implemented as a Horizontal Flip \ No newline at end of file diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index dd1f7cf29..b92227229 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -6,6 +6,11 @@ import pickle import numpy as np from torch.utils.data import Dataset +import torchvision.transforms as transforms +import torchvision.transforms.functional as F +import random +import matplotlib.pyplot as plt +import torch IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') @@ -69,7 +74,7 @@ def load_data_2D(imageNames, normImage=False, categorical=False, dtype=np.float3 return (images, affines) if getAffines else images -def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float32, getAffines=False, early_stop=False): +def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float32, early_stop=False): ''' Load medical image data from names, cases list provided into a list for each. This function pre-allocates 5D arrays for conv3d to avoid excessive memory usage. @@ -123,26 +128,13 @@ def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float3 if i > 20 and early_stop: break - return (images, affines) if getAffines else images + return images def load_images_and_labels(image_file_name, label_file_name, early_stop = False): - images = load_data_3D(imageNames=image_file_name, early_stop=early_stop) + images = load_data_3D(imageNames=image_file_name, normImage = True, early_stop=early_stop) labels = load_data_3D(imageNames=label_file_name, categorical=True, dtype=np.uint8, early_stop=early_stop) return images, labels -def save_data(images, labels, image_save_path, label_save_path): - with open(image_save_path, 'wb') as f: - pickle.dump(images, f) - with open(label_save_path, 'wb') as f: - pickle.dump(labels, f) - -def load_saved_data(image_save_path, label_save_path): - with open(image_save_path, 'rb') as f: - images = pickle.load(f) - with open(label_save_path, 'rb') as f: - labels = pickle.load(f) - return images, labels - """ PyTorch Dataset class for loading ISIC melanoma detection dataset. @@ -180,8 +172,59 @@ def __getitem__(self, idx): y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) + +X_train = torch.Tensor(X_train) +y_train = torch.Tensor(y_train) + +def random_rotation(image: torch.Tensor): + angle = random.uniform(0, 180) + output = F.rotate(image, angle = angle) + return output, angle + +def gamma_correction(image: torch.Tensor): + gamma = random.uniform(0.25, 2) + output = F.adjust_gamma(image, gamma) + output = torch.nan_to_num(output, nan = 0) + return output + +def apply_transformation(image: torch.Tensor, angle = -1, is_mask = False, hflip = False, vflip = False): + + if is_mask: + + mask = image if angle == -1 else F.rotate(image, angle) + mask = F.hflip(mask) + return mask + + if random.randint(0, 1) == 1: + image, angle = random_rotation(image) + if random.randint(0, 1) == 1: + image = gamma_correction(image) + if random.randint(0, 1) == 1: + image = F.hflip(image) + hflip = True + if random.randint(0, 1) == 1: + image = F.vflip(image) + vflip = True + return image, angle, hflip, vflip + +for i in range(X_train.size(0)): + augment = random.randint(0, 1) + x = X_train[i, :, :, :] + y = y_train[i, :, :, :, :] + if augment == 1: + for j in range(x.size(-1)): + slice = x[ : , : , j] + slice = slice[np.newaxis, : , :] + transformed_img, angle, hflip, vflip = apply_transformation(slice) + X_train[i, : , : , j] = transformed_img + for k in range(y.size(-1)): + mask = y[ : , : , j, k] + mask = mask[np.newaxis, :, :] + transformed_mask = apply_transformation(mask, angle = angle, hflip = hflip, vflip = vflip, is_mask = True) + y_train[i, : , : , j, k] = transformed_mask X_train = X_train[: ,np.newaxis, :, :, :] -X_test = X_test[:, np.newaxis, :, :, :] \ No newline at end of file +X_test = X_test[:, np.newaxis, :, :, :] + diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index b46863081..6f7f63bdb 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -106,6 +106,14 @@ def plot_dice(dice, criterion, segment_scores): # perform predictions dice_scores, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, criterion = criterion, device = device) + + dice_scores = dice_scores.cpu().numpy() + s0 = s1.cpu().numpy() + s1 = s1.cpu().numpy() + s2 = s2.cpu().numpy() + s3 = s3.cpu().numpy() + s4 = s4.cpu().numpy() + s5 = s5.cpu().numpy() average_dice = np.mean(dice_scores) print(f"Average Dice Coefficient: {average_dice:.4f}") diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 32b8aa639..472410bd8 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -20,7 +20,7 @@ LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -LOSS_IDX = 3 +LOSS_IDX = 4 class BaseDice(nn.Module): def __init__(self, epsilon = 1e-7): @@ -125,6 +125,31 @@ def forward(self, y_true, y_pred): overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) return overall_loss, d_coefs, None + +class PaperLossPlus(BaseDice): + def __init__(self, epsilon=1e-7): + super().__init__(epsilon) + + def __str__(self): + return 'PaperLoss' + + def forward(self, y_true, y_pred): + + num_masks = y_true.size(-1) + + bce = nn.BCELoss() + + d_coefs = torch.zeros(num_masks, device=y_true.device) + for i in range(num_masks): + ground_truth_seg = y_true[:, :, :, :, i] + pred_seg = y_pred[:, :, :, :, i] + + d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) + d_coefs[i] = d_coef + + overall_loss = (- 1 / num_masks) * torch.sum(d_coefs) + plus = overall_loss + bce(y_true, y_pred) + return overall_loss, d_coefs, plus def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): @@ -157,7 +182,7 @@ def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): else: segment_coefs += d_coefs - if weighted == None: + if weighted == None: loss.backward() else: weighted.backward() @@ -188,7 +213,7 @@ def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): train_set = Prostate3dDataset(X_train, y_train) -loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss()} +loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss(), 4 : PaperLossPlus()} loss = loss_map.get(LOSS_IDX) From 7f799c3aa4b7e6fa72e7e14feebd2f6f3727dfa7 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:13:58 +1000 Subject: [PATCH 021/102] faulty test score calculation fixed --- recognition/47049358/dataset.py | 28 +++++++-------- recognition/47049358/predict.py | 60 ++++++++++++++++----------------- recognition/47049358/train.py | 2 +- 3 files changed, 43 insertions(+), 47 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index b92227229..c2e52608c 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -3,13 +3,10 @@ import numpy as np import nibabel as nib from tqdm import tqdm -import pickle import numpy as np from torch.utils.data import Dataset -import torchvision.transforms as transforms import torchvision.transforms.functional as F import random -import matplotlib.pyplot as plt import torch IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') @@ -132,7 +129,7 @@ def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float3 def load_images_and_labels(image_file_name, label_file_name, early_stop = False): images = load_data_3D(imageNames=image_file_name, normImage = True, early_stop=early_stop) - labels = load_data_3D(imageNames=label_file_name, categorical=True, dtype=np.uint8, early_stop=early_stop) + labels = load_data_3D(imageNames=label_file_name, categorical=True, early_stop=early_stop) return images, labels """ @@ -172,12 +169,9 @@ def __getitem__(self, idx): y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) +# X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) -X_train = torch.Tensor(X_train) -y_train = torch.Tensor(y_train) - def random_rotation(image: torch.Tensor): angle = random.uniform(0, 180) output = F.rotate(image, angle = angle) @@ -209,21 +203,25 @@ def apply_transformation(image: torch.Tensor, angle = -1, is_mask = False, hflip vflip = True return image, angle, hflip, vflip -for i in range(X_train.size(0)): +print('> Start Random Augmentation') + +for i in range(X_train.shape[0]): augment = random.randint(0, 1) x = X_train[i, :, :, :] y = y_train[i, :, :, :, :] if augment == 1: - for j in range(x.size(-1)): + for j in range(x.shape[-1]): slice = x[ : , : , j] - slice = slice[np.newaxis, : , :] + slice = torch.Tensor(slice[np.newaxis, : , :]) transformed_img, angle, hflip, vflip = apply_transformation(slice) - X_train[i, : , : , j] = transformed_img - for k in range(y.size(-1)): + X_train[i, : , : , j] = transformed_img.cpu().numpy() + for k in range(y.shape[-1]): mask = y[ : , : , j, k] - mask = mask[np.newaxis, :, :] + mask = torch.Tensor(mask[np.newaxis, :, :]) transformed_mask = apply_transformation(mask, angle = angle, hflip = hflip, vflip = vflip, is_mask = True) - y_train[i, : , : , j, k] = transformed_mask + y_train[i, : , : , j, k] = transformed_mask.cpu().numpy() + +print('> Augmentation Finished') X_train = X_train[: ,np.newaxis, :, :, :] X_test = X_test[:, np.newaxis, :, :, :] diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 6f7f63bdb..bf36f81d4 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -7,10 +7,11 @@ import numpy as np import matplotlib.pyplot as plt from torch.utils.data import DataLoader +from time import time # import from local files -from train import * +from train import trained_model, loss_map, LOSS_IDX from dataset import X_test, y_test, Prostate3dDataset BATCH_SIZE = 2 @@ -30,38 +31,39 @@ def test(model, test_loader, criterion, device): model.eval() # Set the model to evaluation mode - test_scores = [] # stores dice scores. - seg_0_scores = [] - seg_1_scores = [] - seg_2_scores = [] - seg_3_scores = [] - seg_4_scores = [] - seg_5_scores = [] + test_scores = np.array([]) # stores dice scores. + seg_0_scores = np.array([]) + seg_1_scores = np.array([]) + seg_2_scores = np.array([]) + seg_3_scores = np.array([]) + seg_4_scores = np.array([]) + seg_5_scores = np.array([]) with torch.no_grad(): criterion = criterion - for inputs, masks in test_loader: + for i, (inputs, masks) in enumerate(test_loader): + print(f'Test No.{i}') inputs, masks = inputs.to(device), masks.to(device) outputs = model(inputs) test_loss, dice_coefs, _ = criterion(outputs, masks) for i in range(len(dice_coefs)): if i == 0: - seg_0_scores.append(dice_coefs[i]) + seg_0_scores = np.append(seg_0_scores, dice_coefs[i]) elif i == 1: - seg_1_scores.append(dice_coefs[i]) + seg_1_scores = np.append(seg_1_scores, dice_coefs[i]) elif i == 2: - seg_2_scores.append(dice_coefs[i]) + seg_2_scores = np.append(seg_2_scores, dice_coefs[i]) elif i == 3: - seg_3_scores.append(dice_coefs[i]) + seg_3_scores = np.append(seg_3_scores, dice_coefs[i]) elif i == 4: - seg_4_scores.append(dice_coefs[i]) + seg_4_scores = np.append(seg_4_scores, dice_coefs[i]) else: - seg_5_scores.append(dice_coefs[i]) + seg_5_scores = np.append(seg_5_scores, dice_coefs[i]) - test_scores.append(test_loss.item()) + test_scores = np.append(test_scores, test_loss.item()) return test_scores, seg_0_scores, seg_1_scores, seg_2_scores, seg_3_scores, seg_4_scores, seg_5_scores @@ -70,9 +72,8 @@ def test(model, test_loader, criterion, device): Takes an array of dice scores as input. """ def plot_dice(dice, criterion, segment_scores): - x_values = np.arange(len(dice)) # Generate x-values as indices - plt.figure(figsize=(8, 6)) + x_values = np.arange(len(dice)) # Generate x-values as indices # Plot overall dice scores plt.plot(x_values, dice_scores, label='Overall Dice Scores') @@ -80,20 +81,15 @@ def plot_dice(dice, criterion, segment_scores): for i, segment_score in enumerate(segment_scores): plt.plot(x_values, segment_score, label=f'Segment {i} Dice Scores') - plt.xlabel("Image Index") plt.ylabel("Dice Coefficient") plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig(f'dice_scores_test_{str(criterion)}_without_validation.png') + plt.savefig(f'dice_scores_test_{str(criterion)}.png') plt.close() -""" - Driver method - -""" if __name__ == "__main__": # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -103,17 +99,19 @@ def plot_dice(dice, criterion, segment_scores): test_set = Prostate3dDataset(X_test, y_test) test_loader = DataLoader(dataset = test_set, batch_size = BATCH_SIZE) + print('> Start Testing') + + start = time() + # perform predictions dice_scores, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, criterion = criterion, device = device) - dice_scores = dice_scores.cpu().numpy() - s0 = s1.cpu().numpy() - s1 = s1.cpu().numpy() - s2 = s2.cpu().numpy() - s3 = s3.cpu().numpy() - s4 = s4.cpu().numpy() - s5 = s5.cpu().numpy() + end = time() + + elapsed_time = end - start + + print(f"> Testing completed in {elapsed_time:.2f} seconds") average_dice = np.mean(dice_scores) print(f"Average Dice Coefficient: {average_dice:.4f}") diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 472410bd8..ffe847a91 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -228,7 +228,7 @@ def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): end = time() elapsed_time = end - start -print(f"Training completed in {elapsed_time:.2f} seconds") +print(f"> Training completed in {elapsed_time:.2f} seconds") training_losses = [] From 9eee955959b0282658263a4e8cf592c90f1111d5 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:16:56 +1000 Subject: [PATCH 022/102] faulty mask augmentation fixed --- recognition/47049358/dataset.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index c2e52608c..6dbfb304d 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -188,7 +188,8 @@ def apply_transformation(image: torch.Tensor, angle = -1, is_mask = False, hflip if is_mask: mask = image if angle == -1 else F.rotate(image, angle) - mask = F.hflip(mask) + mask = F.hflip(mask) if hflip else mask + mask = F.vflip(mask) if vflip else mask return mask if random.randint(0, 1) == 1: From b8bc32b42d9df6bd5db6fd26bf37327b7df67da8 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:19:44 +1000 Subject: [PATCH 023/102] user-friendly print statements --- recognition/47049358/dataset.py | 4 +- recognition/47049358/modules.py | 6 +- recognition/47049358/predict.py | 55 ++++++++-------- recognition/47049358/train.py | 107 +++++++++++++++----------------- 4 files changed, 81 insertions(+), 91 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 6dbfb304d..2da4f974a 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -169,8 +169,8 @@ def __getitem__(self, idx): y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] -# X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=True) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=True) +X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) +X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) def random_rotation(image: torch.Tensor): angle = random.uniform(0, 180) diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index f5279f07d..6453a16fd 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -140,7 +140,6 @@ def __init__(self): def forward(self, x): - conv_out_1 = self.block1(x) context_out_1 = self.context1(conv_out_1) element_sum_1 = conv_out_1 + context_out_1 @@ -185,16 +184,13 @@ def forward(self, x): seg_sum_1 = upscale_out_1 + segment_out_2 upscale_out_2 = self.upscale_2(seg_sum_1) - convoutput_out = self.conv_output(concat_4) segment_out_3 = self.segmentation3(convoutput_out) final_sum = upscale_out_2 + segment_out_3 - + output = torch.permute(final_sum, (0, 2, 3, 4, 1)) - output = torch.softmax(output, dim = -1) - return output diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index bf36f81d4..fbd8d0729 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -31,13 +31,13 @@ def test(model, test_loader, criterion, device): model.eval() # Set the model to evaluation mode - test_scores = np.array([]) # stores dice scores. - seg_0_scores = np.array([]) - seg_1_scores = np.array([]) - seg_2_scores = np.array([]) - seg_3_scores = np.array([]) - seg_4_scores = np.array([]) - seg_5_scores = np.array([]) + test_dice_coefs = np.array([]) # stores dice scores. + seg_0_dice_coef = np.array([]) + seg_1_dice_coef = np.array([]) + seg_2_dice_coef = np.array([]) + seg_3_dice_coef = np.array([]) + seg_4_dice_coef = np.array([]) + seg_5_dice_coef = np.array([]) with torch.no_grad(): @@ -45,48 +45,49 @@ def test(model, test_loader, criterion, device): for i, (inputs, masks) in enumerate(test_loader): print(f'Test No.{i}') + inputs, masks = inputs.to(device), masks.to(device) outputs = model(inputs) - test_loss, dice_coefs, _ = criterion(outputs, masks) + test_loss, segment_coefs, test_dice = criterion(outputs, masks) - for i in range(len(dice_coefs)): + for i in range(len(segment_coefs)): if i == 0: - seg_0_scores = np.append(seg_0_scores, dice_coefs[i]) + seg_0_dice_coef = np.append(seg_0_dice_coef, segment_coefs[i]) elif i == 1: - seg_1_scores = np.append(seg_1_scores, dice_coefs[i]) + seg_1_dice_coef = np.append(seg_1_dice_coef, segment_coefs[i]) elif i == 2: - seg_2_scores = np.append(seg_2_scores, dice_coefs[i]) + seg_2_dice_coef = np.append(seg_2_dice_coef, segment_coefs[i]) elif i == 3: - seg_3_scores = np.append(seg_3_scores, dice_coefs[i]) + seg_3_dice_coef = np.append(seg_3_dice_coef, segment_coefs[i]) elif i == 4: - seg_4_scores = np.append(seg_4_scores, dice_coefs[i]) + seg_4_dice_coef = np.append(seg_4_dice_coef, segment_coefs[i]) else: - seg_5_scores = np.append(seg_5_scores, dice_coefs[i]) + seg_5_dice_coef = np.append(seg_5_dice_coef, segment_coefs[i]) - test_scores = np.append(test_scores, test_loss.item()) + test_dice_coefs = np.append(test_dice_coefs, test_dice.item()) - return test_scores, seg_0_scores, seg_1_scores, seg_2_scores, seg_3_scores, seg_4_scores, seg_5_scores + return test_dice_coefs, seg_0_dice_coef, seg_1_dice_coef, seg_2_dice_coef, seg_3_dice_coef, seg_4_dice_coef, seg_5_dice_coef """ Plots dice coefficients of the whole test dataset. Takes an array of dice scores as input. """ -def plot_dice(dice, criterion, segment_scores): +def plot_dice(dice_coefs, criterion, segment_coefs): - x_values = np.arange(len(dice)) # Generate x-values as indices + x_values = np.arange(len(dice_coefs)) # Generate x-values as indices # Plot overall dice scores - plt.plot(x_values, dice_scores, label='Overall Dice Scores') + plt.plot(x_values, dice_coefs, label='Overall Dice Coefficient') # Plot segment scores - for i, segment_score in enumerate(segment_scores): - plt.plot(x_values, segment_score, label=f'Segment {i} Dice Scores') + for i, segment_coef in enumerate(segment_coefs): + plt.plot(x_values, segment_coef, label=f'Segment {i} Dice Coefficients') plt.xlabel("Image Index") plt.ylabel("Dice Coefficient") plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig(f'dice_scores_test_{str(criterion)}.png') + plt.savefig(f'dice_coefs_test_{str(criterion)}.png') plt.close() @@ -104,7 +105,7 @@ def plot_dice(dice, criterion, segment_scores): start = time() # perform predictions - dice_scores, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, criterion = criterion, + dice_coefs, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, criterion = criterion, device = device) end = time() @@ -113,7 +114,7 @@ def plot_dice(dice, criterion, segment_scores): print(f"> Testing completed in {elapsed_time:.2f} seconds") - average_dice = np.mean(dice_scores) + average_dice = np.mean(dice_coefs) print(f"Average Dice Coefficient: {average_dice:.4f}") average_s0 = np.mean(s0) @@ -134,9 +135,9 @@ def plot_dice(dice, criterion, segment_scores): average_s5 = np.mean(s5) print(f"Segment 5 Dice Coefficient: {average_s5:.4f}") - segment_scores = [s0, s1, s2, s3, s4, s5] + segment_coefs = [s0, s1, s2, s3, s4, s5] # plot dice scores across the dataset. - plot_dice(dice_scores, criterion, segment_scores) + plot_dice(dice_coefs, criterion, segment_coefs) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index ffe847a91..6b0c56ded 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -40,22 +40,22 @@ def __str__(self): def forward(self, y_true, y_pred): num_masks = y_true.size(-1) - d_coefs = torch.zeros(num_masks, device=y_true.device) + segment_coefs = torch.zeros(num_masks, device=y_true.device) for i in range(num_masks): ground_truth_seg = y_true[:, :, :, :, i] pred_seg = y_pred[:, :, :, :, i] d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - d_coefs[i] = d_coef + segment_coefs[i] = d_coef - weighted, _ = torch.sort(d_coefs) + weighted, _ = torch.sort(segment_coefs) for i in range(num_masks): - weighted[i] = d_coefs[i] / (math.e ** i) + weighted[i] = segment_coefs[i] / (math.e ** i) - overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) - weighted_loss = 1 - (1 / num_masks) * torch.sum(weighted) - return overall_loss, d_coefs, weighted_loss + d_coef = (1 / num_masks) * torch.sum(segment_coefs) + loss = 1 - (1 / num_masks) * torch.sum(weighted) + return loss, segment_coefs, d_coef class ArithmeticWeightedLoss(BaseDice): def __init__(self, epsilon=1e-7): @@ -67,22 +67,22 @@ def __str__(self): def forward(self, y_true, y_pred): num_masks = y_true.size(-1) - d_coefs = torch.zeros(num_masks, device=y_true.device) + segment_coefs = torch.zeros(num_masks, device=y_true.device) for i in range(num_masks): ground_truth_seg = y_true[:, :, :, :, i] pred_seg = y_pred[:, :, :, :, i] d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - d_coefs[i] = d_coef + segment_coefs[i] = d_coef - weighted, _ = torch.sort(d_coefs) + weighted, _ = torch.sort(segment_coefs) for i in range(num_masks): - weighted[i] = d_coefs[i] / (i + 1) + weighted[i] = segment_coefs[i] / (i + 1) - overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) - weighted_loss = 1 - (1 / num_masks) * torch.sum(weighted) - return overall_loss, d_coefs, weighted_loss + d_coef = (1 / num_masks) * torch.sum(segment_coefs) + loss = 1 - (1 / num_masks) * torch.sum(weighted) + return loss, segment_coefs, d_coef class PaperLoss(BaseDice): def __init__(self, epsilon=1e-7): @@ -94,16 +94,17 @@ def __str__(self): def forward(self, y_true, y_pred): num_masks = y_true.size(-1) - d_coefs = torch.zeros(num_masks, device=y_true.device) + segment_coefs = torch.zeros(num_masks, device=y_true.device) for i in range(num_masks): ground_truth_seg = y_true[:, :, :, :, i] pred_seg = y_pred[:, :, :, :, i] d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - d_coefs[i] = d_coef + segment_coefs[i] = d_coef - overall_loss = (- 1 / num_masks) * torch.sum(d_coefs) - return overall_loss, d_coefs, None + loss = (- 1 / num_masks) * torch.sum(segment_coefs) + d_coef = (1 / num_masks) * torch.sum(segment_coefs) + return loss, segment_coefs, d_coef class AlternativeLoss(BaseDice): def __init__(self, epsilon=1e-7): @@ -115,43 +116,43 @@ def __str__(self): def forward(self, y_true, y_pred): num_masks = y_true.size(-1) - d_coefs = torch.zeros(num_masks, device=y_true.device) + segment_coefs = torch.zeros(num_masks, device=y_true.device) for i in range(num_masks): ground_truth_seg = y_true[:, :, :, :, i] pred_seg = y_pred[:, :, :, :, i] d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - d_coefs[i] = d_coef + segment_coefs[i] = d_coef - overall_loss = 1 - (1 / num_masks) * torch.sum(d_coefs) - return overall_loss, d_coefs, None + d_coef = (1 / num_masks) * torch.sum(segment_coefs) + loss = 1 - (1 / num_masks) * torch.sum(segment_coefs) + return loss, segment_coefs, d_coef class PaperLossPlus(BaseDice): def __init__(self, epsilon=1e-7): super().__init__(epsilon) def __str__(self): - return 'PaperLoss' + return 'PaperLossPlus' def forward(self, y_true, y_pred): num_masks = y_true.size(-1) - bce = nn.BCELoss() + segment_coefs = torch.zeros(num_masks, device=y_true.device) - d_coefs = torch.zeros(num_masks, device=y_true.device) for i in range(num_masks): ground_truth_seg = y_true[:, :, :, :, i] pred_seg = y_pred[:, :, :, :, i] d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - d_coefs[i] = d_coef + segment_coefs[i] = d_coef - overall_loss = (- 1 / num_masks) * torch.sum(d_coefs) - plus = overall_loss + bce(y_true, y_pred) - return overall_loss, d_coefs, plus + d_coef = (1 / num_masks) * torch.sum(segment_coefs) + loss = (- 1 / num_masks) * torch.sum(segment_coefs) + bce(y_true, y_pred) + return loss, segment_coefs, d_coef -def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): +def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): # set up criterion, optimiser, and scheduler for learning rate. criterion = loss @@ -161,44 +162,40 @@ def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): model.to(device) model.train() - training_losses = [] - + training_dice_coefs = [] + + train_set = Prostate3dDataset(X_train, y_train) train_loader = DataLoader(dataset = train_set, batch_size = BATCH_SIZE) for epoch in range(num_epochs): - running_loss = 0.0 - segment_coefs = None - for inputs, masks in tqdm(train_loader): + running_dice = 0.0 + total_segment_coefs = torch.zeros(y_train.shape[-1], device=device) + for inputs, masks in train_loader: inputs, masks = inputs.to(device), masks.to(device) optimiser.zero_grad() outputs = model(inputs) # the weighted value is only used for updating gradients! - loss, d_coefs, weighted = criterion(y_true = masks, y_pred = outputs) + loss, segment_coefs, d_coef = criterion(y_true = masks, y_pred = outputs) - if segment_coefs == None: - segment_coefs = d_coefs - else: - segment_coefs += d_coefs + total_segment_coefs += segment_coefs - if weighted == None: - loss.backward() - else: - weighted.backward() + loss.backward() optimiser.step() - running_loss += loss.item() + running_dice += d_coef.item() scheduler.step() - for i in range(len(segment_coefs)): - print(f"Epoch {epoch + 1} Segment {i} - Training Dice Coefficient: {segment_coefs[i] / len(train_loader)}") + for i in range(len(total_segment_coefs)): + print(f"Epoch {epoch + 1} Segment {i} - Training Dice Coefficient: {total_segment_coefs[i] / len(train_loader)}") - print(f"Epoch {epoch + 1}, Training Loss: {running_loss / len(train_loader)}") + print(f"Epoch {epoch + 1}, Training Overall Dice Coefficient: {running_dice / len(train_loader)}") + training_dice_coefs.append(running_dice / len(train_loader)) - return model, training_losses + return model, training_dice_coefs # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -211,8 +208,6 @@ def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): # Importing Dataloader breaks the implementation. Hence they are loaded below instead: -train_set = Prostate3dDataset(X_train, y_train) - loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss(), 4 : PaperLossPlus()} loss = loss_map.get(LOSS_IDX) @@ -222,7 +217,7 @@ def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): start = time() # train improved unet -trained_model, training_losses = train(model, train_set, loss = loss, +trained_model, training_dice_coefs = train(model, X_train, y_train, loss = loss, device=device, num_epochs=NUM_EPOCHS) end = time() @@ -230,14 +225,12 @@ def train(model, train_set, loss, num_epochs=NUM_EPOCHS, device="cuda"): elapsed_time = end - start print(f"> Training completed in {elapsed_time:.2f} seconds") -training_losses = [] - plt.figure(figsize=(10,5)) -plt.plot(training_losses, label='Training Loss') -plt.title('Losses over epochs') +plt.plot(training_dice_coefs, label='Training Dice Coefficient') +plt.title('Dice Coefficient Over Epochs') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig(f'unet_training_losses_over_epochs_{str(loss)}.png') +plt.savefig(f'unet_dice_coefs_over_epochs_{str(loss)}.png') plt.close() \ No newline at end of file From 6b84280f861379796751d668400a2a7b92b65a92 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Fri, 18 Oct 2024 00:51:32 +1000 Subject: [PATCH 024/102] complete and correct data augmentation --- recognition/47049358/dataset.py | 221 +++++++++++++++++++++++--------- recognition/47049358/modules.py | 2 +- recognition/47049358/predict.py | 5 +- recognition/47049358/train.py | 18 +-- 4 files changed, 171 insertions(+), 75 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 2da4f974a..16a0897bf 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -1,3 +1,6 @@ +# ========================== +# Imports +# ========================== import os from sklearn.model_selection import train_test_split import numpy as np @@ -6,12 +9,20 @@ import numpy as np from torch.utils.data import Dataset import torchvision.transforms.functional as F +import torchvision.transforms as transforms import random import torch +# ========================== +# Constants +# ========================== + IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') -RANDOM_STATE = 47049358 + +# ========================== +# Loading Dataset +# ========================== def to_channels(arr: np.ndarray, dtype=np.uint8) -> np.ndarray: channels = np.unique(arr) @@ -129,21 +140,9 @@ def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float3 def load_images_and_labels(image_file_name, label_file_name, early_stop = False): images = load_data_3D(imageNames=image_file_name, normImage = True, early_stop=early_stop) - labels = load_data_3D(imageNames=label_file_name, categorical=True, early_stop=early_stop) + labels = load_data_3D(imageNames=label_file_name, categorical=True, dtype = np.uint8, early_stop=early_stop) return images, labels -""" - PyTorch Dataset class for loading ISIC melanoma detection dataset. - - Parameters: - - img_path (str): Path to the directory containing image files. - - mask_path (str): Path to the directory containing mask files. - - transform (call): Transform to be applied on the images and masks. - - Methods: - - __len__(): Returns the total number of images in the dataset. - - __getitem__(idx): Returns the image and its corresponding mask at the given index `idx`. Resizes image and converts to correct colour channels. - """ class Prostate3dDataset(Dataset): def __init__(self, images, labels): self.images = images @@ -156,12 +155,133 @@ def __getitem__(self, idx): img = self.images[idx] mask = self.labels[idx] return img, mask + +# ========================== +# Image Augmentation +# ========================== + +def random_rotation(image: torch.Tensor, angle = 0.0): + + image = F.rotate(image, angle = angle, fill = image.min().item()) + + return image + +def random_resize_with_padding(image: torch.Tensor, height = 256, width = 256, is_mask = False): + + original_height = image.size(1) + original_width = image.size(2) + + top_p = (original_height - height) // 2 + bottom_p = (original_height - height) - top_p + right_p = (original_width - width) // 2 + left_p = (original_width - width) - right_p + resized = F.resize(image, size = (height, width)) + padding = (left_p, top_p, right_p, bottom_p) + image = F.pad(resized, padding = padding, fill = image.min().item()) + + if is_mask: + image = torch.clamp(torch.round(image), min = 0, max = 1) + + return image + +def gamma_correction(image: torch.Tensor, gamma = 1): + + image = F.adjust_gamma(image, gamma) + image = torch.nan_to_num(image, nan = 0) + + return image + +def elastic_transformation(image: torch.Tensor, alpha = 5.0, sigma = 0.5, is_mask = False): + + elastic_transformation = transforms.Compose([ + transforms.ToPILImage(), + transforms.ElasticTransform(alpha=alpha, sigma=sigma), + transforms.PILToTensor() + ]) + + if is_mask: + + mask = elastic_transformation(image) + mask = torch.clamp(torch.round(mask), min = 0, mask = 1) + + return mask + + image = elastic_transformation(image) + + return image + +def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor): + + alpha = random.uniform(0.0, 10.0) + sigma = random.uniform(0.0, 1.0) + make_elastic = random.choice([True, False]) + + angle = random.uniform(0, 180) + rotate = random.choice([True, False]) + + height = random.randint(128, 256) + width = random.randint(128, 256) + resize = random.choice([True, False]) + + gamma = random.uniform(0.25, 2) + adjust_gamma = random.choice([True, False]) + + hflip = random.choice([True, False]) + + vflip = random.choice([True, False]) + + for j in range(image.shape[-1]): + + slice = image[ : , : , j] + slice = torch.Tensor(slice[np.newaxis, : , :]) + masks = masks_3d[: , : , j , :] + masks = torch.Tensor(masks[np.newaxis, : , :, : ]) + + slice = elastic_transformation(image = slice, alpha = alpha, sigma = sigma) if make_elastic else slice + slice = random_rotation(image = slice, angle = angle) if rotate else slice + slice = random_resize_with_padding(image = slice, height = height, width = width) if resize else slice + slice = gamma_correction(image = slice, gamma = gamma) if adjust_gamma else slice + slice = F.hflip(slice) if hflip else slice + slice = F.vflip(slice) if vflip else slice + + for i in range(masks.size(-1)): + mask = masks[ : , : , : , i] + + mask = elastic_transformation(image = mask, alpha = alpha, sigma = sigma, is_mask = True) if make_elastic else mask + mask = random_rotation(image = mask, angle = angle) if rotate else mask + mask = random_resize_with_padding(image = mask, height = height, width = width, is_mask=True) if resize else mask + mask = F.hflip(mask) if hflip else mask + mask = F.vflip(mask) if vflip else mask + + masks[ : , : , : , i] = mask + + masks_3d[: , : , j , :] = masks.cpu().numpy() + + image[ : , : , j] = slice.cpu().numpy() + + return image, masks_3d + +def augment_training_set(X_train, y_train): + + for i in range(X_train.shape[0]): + + image = X_train[i, : , : , : ] + masks_3d = y_train[i, : , : , : , :] + + transformed_img, transformed_masks_3d = apply_transformation(image = image, masks_3d = masks_3d) + + X_train[i, : , : , : ] = transformed_img + y_train[i, : , : , : , :] = transformed_masks_3d + + return X_train, y_train + +print('> Loading Dataset') rawImageNames = os.listdir(IMAGE_FILE_NAME) rawLabelNames = os.listdir(LABEL_FILE_NAME) -# Split the set into train, validation, and test set (70:15:15 for train:valid:test) -X_train, X_test, y_train, y_test = train_test_split(rawImageNames, rawLabelNames, train_size=0.8, random_state=RANDOM_STATE) # Split the data in training and test set +# Split the set into train, validation, and test set (80 : 20 for train:test) +X_train, X_test, y_train, y_test = train_test_split(rawImageNames, rawLabelNames, train_size=0.8) # Split the data in training and test set X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] @@ -172,58 +292,33 @@ def __getitem__(self, idx): X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) -def random_rotation(image: torch.Tensor): - angle = random.uniform(0, 180) - output = F.rotate(image, angle = angle) - return output, angle +print('> Start Random Augmentation') -def gamma_correction(image: torch.Tensor): - gamma = random.uniform(0.25, 2) - output = F.adjust_gamma(image, gamma) - output = torch.nan_to_num(output, nan = 0) - return output +X_train, y_train = augment_training_set(X_train, y_train) -def apply_transformation(image: torch.Tensor, angle = -1, is_mask = False, hflip = False, vflip = False): +print('> Augmentation Complete') - if is_mask: +X_train = X_train[: ,np.newaxis, :, :, :] +X_test = X_test[:, np.newaxis, :, :, :] - mask = image if angle == -1 else F.rotate(image, angle) - mask = F.hflip(mask) if hflip else mask - mask = F.vflip(mask) if vflip else mask - return mask - - if random.randint(0, 1) == 1: - image, angle = random_rotation(image) - if random.randint(0, 1) == 1: - image = gamma_correction(image) - if random.randint(0, 1) == 1: - image = F.hflip(image) - hflip = True - if random.randint(0, 1) == 1: - image = F.vflip(image) - vflip = True - return image, angle, hflip, vflip +# if __name__ == '__main__': +# # Generate random noise with shape (256, 256, 128) +# image_file_name = [os.path.join(IMAGE_FILE_NAME, image) for image in os.listdir(IMAGE_FILE_NAME)][0] +# noise = torch.Tensor(load_data_3D(imageNames=[image_file_name], normImage = True, early_stop=True)) -print('> Start Random Augmentation') +# import matplotlib.pyplot as plt -for i in range(X_train.shape[0]): - augment = random.randint(0, 1) - x = X_train[i, :, :, :] - y = y_train[i, :, :, :, :] - if augment == 1: - for j in range(x.shape[-1]): - slice = x[ : , : , j] - slice = torch.Tensor(slice[np.newaxis, : , :]) - transformed_img, angle, hflip, vflip = apply_transformation(slice) - X_train[i, : , : , j] = transformed_img.cpu().numpy() - for k in range(y.shape[-1]): - mask = y[ : , : , j, k] - mask = torch.Tensor(mask[np.newaxis, :, :]) - transformed_mask = apply_transformation(mask, angle = angle, hflip = hflip, vflip = vflip, is_mask = True) - y_train[i, : , : , j, k] = transformed_mask.cpu().numpy() - -print('> Augmentation Finished') +# torch.set_printoptions(threshold=float('inf')) -X_train = X_train[: ,np.newaxis, :, :, :] -X_test = X_test[:, np.newaxis, :, :, :] +# image = noise[: , :, :, 10] + +# print(image) + +# plt.imshow(image[0, :, :], cmap='gray') +# plt.show() +# print(image.shape) +# image = F.hflip(image) +# plt.imshow(image[0, :, :], cmap='gray') +# plt.show() +# print(image) \ No newline at end of file diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 6453a16fd..fdcbf8bbc 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -196,7 +196,7 @@ def forward(self, x): # if __name__ == '__main__': # model = ImprovedUnet() -# input_tensor = torch.randn(2, 1, 256, 256, 128) # Input tensor with shape [2, 1, 256, 256, 128] +# input_tensor = torch.randn(1, 1, 255, 255, 128) # Input tensor with shape [2, 1, 256, 256, 128] # output_tensor = model(input_tensor) # print(f"Input shape: {input_tensor.shape}") # print(f"Output shape: {output_tensor.shape}") \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index fbd8d0729..666575039 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -44,8 +44,7 @@ def test(model, test_loader, criterion, device): criterion = criterion for i, (inputs, masks) in enumerate(test_loader): - print(f'Test No.{i}') - + masks = masks.float() inputs, masks = inputs.to(device), masks.to(device) outputs = model(inputs) test_loss, segment_coefs, test_dice = criterion(outputs, masks) @@ -63,6 +62,8 @@ def test(model, test_loader, criterion, device): seg_4_dice_coef = np.append(seg_4_dice_coef, segment_coefs[i]) else: seg_5_dice_coef = np.append(seg_5_dice_coef, segment_coefs[i]) + + print(f'Test No.{i} - Overall Dice Coefficient: {test_dice}') test_dice_coefs = np.append(test_dice_coefs, test_dice.item()) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 6b0c56ded..125a24a87 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -27,7 +27,7 @@ def __init__(self, epsilon = 1e-7): super(BaseDice, self).__init__() self.epsilon = epsilon - def forward(self, y_true, y_pred): + def forward(self, y_pred, y_true): raise NotImplementedError("Sublasses should implement this method.") class ExponentialWeightedLoss(BaseDice): @@ -37,7 +37,7 @@ def __init__(self, epsilon=1e-7): def __str__(self): return 'ExponentialWeightedLoss' - def forward(self, y_true, y_pred): + def forward(self, y_pred, y_true): num_masks = y_true.size(-1) segment_coefs = torch.zeros(num_masks, device=y_true.device) @@ -64,7 +64,7 @@ def __init__(self, epsilon=1e-7): def __str__(self): return 'ArithmeticWeightedLoss' - def forward(self, y_true, y_pred): + def forward(self, y_pred, y_true): num_masks = y_true.size(-1) segment_coefs = torch.zeros(num_masks, device=y_true.device) @@ -91,7 +91,7 @@ def __init__(self, epsilon=1e-7): def __str__(self): return 'PaperLoss' - def forward(self, y_true, y_pred): + def forward(self, y_pred, y_true): num_masks = y_true.size(-1) segment_coefs = torch.zeros(num_masks, device=y_true.device) @@ -113,7 +113,7 @@ def __init__(self, epsilon=1e-7): def __str__(self): return 'AlternativeLoss' - def forward(self, y_true, y_pred): + def forward(self, y_pred, y_true): num_masks = y_true.size(-1) segment_coefs = torch.zeros(num_masks, device=y_true.device) @@ -135,7 +135,7 @@ def __init__(self, epsilon=1e-7): def __str__(self): return 'PaperLossPlus' - def forward(self, y_true, y_pred): + def forward(self, y_pred, y_true): num_masks = y_true.size(-1) bce = nn.BCELoss() @@ -149,7 +149,7 @@ def forward(self, y_true, y_pred): segment_coefs[i] = d_coef d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = (- 1 / num_masks) * torch.sum(segment_coefs) + bce(y_true, y_pred) + loss = (- 1 / num_masks) * torch.sum(segment_coefs) + bce(y_pred, y_true) return loss, segment_coefs, d_coef def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): @@ -171,13 +171,13 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): running_dice = 0.0 total_segment_coefs = torch.zeros(y_train.shape[-1], device=device) for inputs, masks in train_loader: - + masks = masks.float() inputs, masks = inputs.to(device), masks.to(device) optimiser.zero_grad() outputs = model(inputs) # the weighted value is only used for updating gradients! - loss, segment_coefs, d_coef = criterion(y_true = masks, y_pred = outputs) + loss, segment_coefs, d_coef = criterion(y_pred = outputs, y_true = masks) total_segment_coefs += segment_coefs From 0e243e6feadb55016c1741f49d7a187b485a4e55 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Fri, 18 Oct 2024 01:36:49 +1000 Subject: [PATCH 025/102] incorrect argument fixed for clamp --- recognition/47049358/dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 16a0897bf..6ee75eb85 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -202,7 +202,7 @@ def elastic_transformation(image: torch.Tensor, alpha = 5.0, sigma = 0.5, is_mas if is_mask: mask = elastic_transformation(image) - mask = torch.clamp(torch.round(mask), min = 0, mask = 1) + mask = torch.clamp(torch.round(mask), min = 0, max = 1) return mask From 2cf9693bbd0446f44c34021c145fcfc8b8cbb83c Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:51:25 +1000 Subject: [PATCH 026/102] fixed incompatibility of torch and numpy --- recognition/47049358/predict.py | 12 ++++++------ recognition/47049358/train.py | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 666575039..563118f51 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -51,17 +51,17 @@ def test(model, test_loader, criterion, device): for i in range(len(segment_coefs)): if i == 0: - seg_0_dice_coef = np.append(seg_0_dice_coef, segment_coefs[i]) + seg_0_dice_coef = np.append(seg_0_dice_coef, segment_coefs[i].item()) elif i == 1: - seg_1_dice_coef = np.append(seg_1_dice_coef, segment_coefs[i]) + seg_1_dice_coef = np.append(seg_1_dice_coef, segment_coefs[i].item()) elif i == 2: - seg_2_dice_coef = np.append(seg_2_dice_coef, segment_coefs[i]) + seg_2_dice_coef = np.append(seg_2_dice_coef, segment_coefs[i].item()) elif i == 3: - seg_3_dice_coef = np.append(seg_3_dice_coef, segment_coefs[i]) + seg_3_dice_coef = np.append(seg_3_dice_coef, segment_coefs[i].item()) elif i == 4: - seg_4_dice_coef = np.append(seg_4_dice_coef, segment_coefs[i]) + seg_4_dice_coef = np.append(seg_4_dice_coef, segment_coefs[i].item()) else: - seg_5_dice_coef = np.append(seg_5_dice_coef, segment_coefs[i]) + seg_5_dice_coef = np.append(seg_5_dice_coef, segment_coefs[i].item()) print(f'Test No.{i} - Overall Dice Coefficient: {test_dice}') diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 125a24a87..8c19b56a3 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -11,7 +11,6 @@ from torch.utils.data import DataLoader import torch.nn as nn from time import time -from tqdm import tqdm import math From 6cb800364377713977b14f5d56340f2f7cdd591f Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Fri, 18 Oct 2024 19:45:55 +1000 Subject: [PATCH 027/102] corrected plots and efficient augmentation --- recognition/47049358/dataset.py | 48 +++++++++++++-------------------- recognition/47049358/modules.py | 10 +------ recognition/47049358/predict.py | 21 +++++---------- recognition/47049358/train.py | 36 +++++++++++++++++-------- 4 files changed, 51 insertions(+), 64 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 6ee75eb85..5c5875fab 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -6,7 +6,6 @@ import numpy as np import nibabel as nib from tqdm import tqdm -import numpy as np from torch.utils.data import Dataset import torchvision.transforms.functional as F import torchvision.transforms as transforms @@ -210,7 +209,7 @@ def elastic_transformation(image: torch.Tensor, alpha = 5.0, sigma = 0.5, is_mas return image -def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor): +def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor, device = 'cpu'): alpha = random.uniform(0.0, 10.0) sigma = random.uniform(0.0, 1.0) @@ -230,12 +229,18 @@ def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor): vflip = random.choice([True, False]) + image = torch.Tensor(image) + masks_3d = torch.Tensor(masks_3d) + + image = image.to(device) + masks_3d = masks_3d.to(device) + for j in range(image.shape[-1]): slice = image[ : , : , j] - slice = torch.Tensor(slice[np.newaxis, : , :]) + slice = slice[np.newaxis, : , :] masks = masks_3d[: , : , j , :] - masks = torch.Tensor(masks[np.newaxis, : , :, : ]) + masks = masks[np.newaxis, : , :, : ] slice = elastic_transformation(image = slice, alpha = alpha, sigma = sigma) if make_elastic else slice slice = random_rotation(image = slice, angle = angle) if rotate else slice @@ -255,20 +260,25 @@ def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor): masks[ : , : , : , i] = mask - masks_3d[: , : , j , :] = masks.cpu().numpy() + masks_3d[: , : , j , :] = masks - image[ : , : , j] = slice.cpu().numpy() + image[ : , : , j] = slice + + image = image.cpu().numpy() + masks_3d = masks_3d.cpu().numpy() return image, masks_3d def augment_training_set(X_train, y_train): + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + for i in range(X_train.shape[0]): image = X_train[i, : , : , : ] masks_3d = y_train[i, : , : , : , :] - transformed_img, transformed_masks_3d = apply_transformation(image = image, masks_3d = masks_3d) + transformed_img, transformed_masks_3d = apply_transformation(image = image, masks_3d = masks_3d, device = device) X_train[i, : , : , : ] = transformed_img y_train[i, : , : , : , :] = transformed_masks_3d @@ -299,26 +309,4 @@ def augment_training_set(X_train, y_train): print('> Augmentation Complete') X_train = X_train[: ,np.newaxis, :, :, :] -X_test = X_test[:, np.newaxis, :, :, :] - -# if __name__ == '__main__': -# # Generate random noise with shape (256, 256, 128) -# image_file_name = [os.path.join(IMAGE_FILE_NAME, image) for image in os.listdir(IMAGE_FILE_NAME)][0] -# noise = torch.Tensor(load_data_3D(imageNames=[image_file_name], normImage = True, early_stop=True)) - -# import matplotlib.pyplot as plt - -# torch.set_printoptions(threshold=float('inf')) - -# image = noise[: , :, :, 10] - -# print(image) - -# plt.imshow(image[0, :, :], cmap='gray') -# plt.show() -# print(image.shape) -# image = F.hflip(image) -# plt.imshow(image[0, :, :], cmap='gray') -# plt.show() - -# print(image) \ No newline at end of file +X_test = X_test[:, np.newaxis, :, :, :] \ No newline at end of file diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index fdcbf8bbc..94505fdd8 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -191,12 +191,4 @@ def forward(self, x): output = torch.permute(final_sum, (0, 2, 3, 4, 1)) output = torch.softmax(output, dim = -1) - return output - - -# if __name__ == '__main__': -# model = ImprovedUnet() -# input_tensor = torch.randn(1, 1, 255, 255, 128) # Input tensor with shape [2, 1, 256, 256, 128] -# output_tensor = model(input_tensor) -# print(f"Input shape: {input_tensor.shape}") -# print(f"Output shape: {output_tensor.shape}") \ No newline at end of file + return output \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 563118f51..05c757bc8 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -49,20 +49,13 @@ def test(model, test_loader, criterion, device): outputs = model(inputs) test_loss, segment_coefs, test_dice = criterion(outputs, masks) - for i in range(len(segment_coefs)): - if i == 0: - seg_0_dice_coef = np.append(seg_0_dice_coef, segment_coefs[i].item()) - elif i == 1: - seg_1_dice_coef = np.append(seg_1_dice_coef, segment_coefs[i].item()) - elif i == 2: - seg_2_dice_coef = np.append(seg_2_dice_coef, segment_coefs[i].item()) - elif i == 3: - seg_3_dice_coef = np.append(seg_3_dice_coef, segment_coefs[i].item()) - elif i == 4: - seg_4_dice_coef = np.append(seg_4_dice_coef, segment_coefs[i].item()) - else: - seg_5_dice_coef = np.append(seg_5_dice_coef, segment_coefs[i].item()) - + seg_0_dice_coef = np.append(seg_0_dice_coef, segment_coefs[0].item()) + seg_1_dice_coef = np.append(seg_1_dice_coef, segment_coefs[1].item()) + seg_2_dice_coef = np.append(seg_2_dice_coef, segment_coefs[2].item()) + seg_3_dice_coef = np.append(seg_3_dice_coef, segment_coefs[3].item()) + seg_4_dice_coef = np.append(seg_4_dice_coef, segment_coefs[4].item()) + seg_5_dice_coef = np.append(seg_5_dice_coef, segment_coefs[5].item()) + print(f'Test No.{i} - Overall Dice Coefficient: {test_dice}') test_dice_coefs = np.append(test_dice_coefs, test_dice.item()) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 8c19b56a3..de415f767 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -1,9 +1,3 @@ -""" -containing the source code for training, validating, testing and saving your model. The model -should be imported from “modules.py” and the data loader should be imported from “dataset.py”. Make -sure to plot the losses and metrics during training -""" - from dataset import X_train, y_train, Prostate3dDataset from modules import ImprovedUnet import matplotlib.pyplot as plt @@ -12,6 +6,7 @@ import torch.nn as nn from time import time import math +import numpy as np NUM_EPOCHS = 300 @@ -161,7 +156,13 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): model.to(device) model.train() - training_dice_coefs = [] + training_dice_coefs = np.zeros(NUM_EPOCHS) + seg_0_dice_coefs = np.zeros(NUM_EPOCHS) + seg_1_dice_coefs = np.zeros(NUM_EPOCHS) + seg_2_dice_coefs = np.zeros(NUM_EPOCHS) + seg_3_dice_coefs = np.zeros(NUM_EPOCHS) + seg_4_dice_coefs = np.zeros(NUM_EPOCHS) + seg_5_dice_coefs = np.zeros(NUM_EPOCHS) train_set = Prostate3dDataset(X_train, y_train) train_loader = DataLoader(dataset = train_set, batch_size = BATCH_SIZE) @@ -191,10 +192,18 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): for i in range(len(total_segment_coefs)): print(f"Epoch {epoch + 1} Segment {i} - Training Dice Coefficient: {total_segment_coefs[i] / len(train_loader)}") + seg_0_dice_coefs[epoch] = (total_segment_coefs[0] / len(train_loader)) + seg_1_dice_coefs[epoch] = (total_segment_coefs[1] / len(train_loader)) + seg_2_dice_coefs[epoch] = (total_segment_coefs[2] / len(train_loader)) + seg_3_dice_coefs[epoch] = (total_segment_coefs[3] / len(train_loader)) + seg_4_dice_coefs[epoch] = (total_segment_coefs[4] / len(train_loader)) + seg_5_dice_coefs[epoch] = (total_segment_coefs[5] / len(train_loader)) + print(f"Epoch {epoch + 1}, Training Overall Dice Coefficient: {running_dice / len(train_loader)}") - training_dice_coefs.append(running_dice / len(train_loader)) + training_dice_coefs[epoch] = (running_dice / len(train_loader)) - return model, training_dice_coefs + return (model, training_dice_coefs, seg_0_dice_coefs, seg_1_dice_coefs, + seg_2_dice_coefs, seg_3_dice_coefs, seg_4_dice_coefs, seg_5_dice_coefs) # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") @@ -216,7 +225,7 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): start = time() # train improved unet -trained_model, training_dice_coefs = train(model, X_train, y_train, loss = loss, +trained_model, training_dice_coefs, seg0, seg1, seg2, seg3, seg4, seg5 = train(model, X_train, y_train, loss = loss, device=device, num_epochs=NUM_EPOCHS) end = time() @@ -224,8 +233,13 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): elapsed_time = end - start print(f"> Training completed in {elapsed_time:.2f} seconds") -plt.figure(figsize=(10,5)) plt.plot(training_dice_coefs, label='Training Dice Coefficient') +plt.plot(seg0, label='Segment 0 Dice Coefficient') +plt.plot(seg1, label='Segment 1 Dice Coefficient') +plt.plot(seg2, label='Segment 2 Dice Coefficient') +plt.plot(seg3, label='Segment 3 Dice Coefficient') +plt.plot(seg4, label='Segment 4 Dice Coefficient') +plt.plot(seg5, label='Segment 5 Dice Coefficient') plt.title('Dice Coefficient Over Epochs') plt.xlabel('Epochs') plt.ylabel('Loss') From 9a358cf4fb4e95994f912fa53d5186b659dd28e4 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 20:22:52 +1000 Subject: [PATCH 028/102] Created dataset.py for loading and preprocessing Facebook page data. --- recognition/facebook_gnn_classification/dataset.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 recognition/facebook_gnn_classification/dataset.py diff --git a/recognition/facebook_gnn_classification/dataset.py b/recognition/facebook_gnn_classification/dataset.py new file mode 100644 index 000000000..e69de29bb From 4efa1c8db3f8fcf73a420e98048ad4480bc96c4d Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 20:23:03 +1000 Subject: [PATCH 029/102] Created modules.py for defining the GNN model structure. --- recognition/facebook_gnn_classification/modules.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 recognition/facebook_gnn_classification/modules.py diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py new file mode 100644 index 000000000..e69de29bb From 5dcb97a47f08e4ce4efaabcedd06fd998aea512c Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 20:23:16 +1000 Subject: [PATCH 030/102] Created train.py for implementing GNN training procedures. --- recognition/facebook_gnn_classification/train.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 recognition/facebook_gnn_classification/train.py diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py new file mode 100644 index 000000000..e69de29bb From 24b6a734bc0a74fa5c31c32dc668f083e2fec1b7 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 20:23:39 +1000 Subject: [PATCH 031/102] Created predict.py for the prediction using the trained GNN. --- recognition/facebook_gnn_classification/predict.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 recognition/facebook_gnn_classification/predict.py diff --git a/recognition/facebook_gnn_classification/predict.py b/recognition/facebook_gnn_classification/predict.py new file mode 100644 index 000000000..e69de29bb From 56e21b18036e36aae461481abd02657197fee4a4 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 20:24:10 +1000 Subject: [PATCH 032/102] Created README.md for project descriptions. --- recognition/facebook_gnn_classification/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 recognition/facebook_gnn_classification/README.md diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md new file mode 100644 index 000000000..e69de29bb From cb01dc324ab4c3ecbf6ae23ecf37d3822bfa3041 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 21:53:06 +1000 Subject: [PATCH 033/102] Initialized dataset.py --- .../facebook_gnn_classification/dataset.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/recognition/facebook_gnn_classification/dataset.py b/recognition/facebook_gnn_classification/dataset.py index e69de29bb..0e5fa20b6 100644 --- a/recognition/facebook_gnn_classification/dataset.py +++ b/recognition/facebook_gnn_classification/dataset.py @@ -0,0 +1,22 @@ +# dataset.py + +# Google Colab setup and data loading + +from google.colab import drive +import os +import sys + +# Mount Google Drive +drive.mount('/content/drive') + +# Define paths for this project +base_path = "/content/drive/My Drive/COMP3710/Project" +data_path = os.path.join(base_path, "facebook_large") + +# Add the project directory to the system path +sys.path.append(base_path) + +# Paths to dataset files +edges_path = os.path.join(data_path, "musae_facebook_edges.csv") +features_path = os.path.join(data_path, "musae_facebook_features.json") +labels_path = os.path.join(data_path, "musae_facebook_target.csv") \ No newline at end of file From 38b13ca85a6494f122736b3ef8f2757646a70683 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 21:53:19 +1000 Subject: [PATCH 034/102] Initialized train.py --- recognition/facebook_gnn_classification/train.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index e69de29bb..7fc32f326 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -0,0 +1,7 @@ +# train.py + +import torch +from torch.optim import Adam +from torch_geometric.data import Data +from modules import GNN +from dataset import load_data, edges_path, features_path, labels_path \ No newline at end of file From cad635e36a6a54ea0279469bd8462c5738deeb2b Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 21:54:13 +1000 Subject: [PATCH 035/102] Update dataset.py --- .../facebook_gnn_classification/dataset.py | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/recognition/facebook_gnn_classification/dataset.py b/recognition/facebook_gnn_classification/dataset.py index 0e5fa20b6..32d2f618e 100644 --- a/recognition/facebook_gnn_classification/dataset.py +++ b/recognition/facebook_gnn_classification/dataset.py @@ -1,10 +1,14 @@ # dataset.py -# Google Colab setup and data loading - from google.colab import drive import os import sys +import pandas as pd +import torch +import json +import numpy as np + +# Google Colab setup and data loading # Mount Google Drive drive.mount('/content/drive') @@ -19,4 +23,44 @@ # Paths to dataset files edges_path = os.path.join(data_path, "musae_facebook_edges.csv") features_path = os.path.join(data_path, "musae_facebook_features.json") -labels_path = os.path.join(data_path, "musae_facebook_target.csv") \ No newline at end of file +labels_path = os.path.join(data_path, "musae_facebook_target.csv") + +# Data loading + +def load_data(edges_path, features_path, labels_path): + # Load edges + edges_df = pd.read_csv(edges_path) + edge_index = torch.tensor(edges_df.values, dtype=torch.long).t().contiguous() + + # Load features from JSON + with open(features_path) as f: + features_dict = json.load(f) + + # Ensure consistent order by sorting nodes + nodes = sorted(features_dict.keys(), key=lambda x: int(x)) + features = [] + + # Pad features to make sure all vectors have the same length + expected_length = 128 + for node in nodes: + feature_vector = features_dict[node] + if len(feature_vector) < expected_length: + feature_vector += [0] * (expected_length - len(feature_vector)) + elif len(feature_vector) > expected_length: + feature_vector = feature_vector[:expected_length] + features.append(feature_vector) + + features = torch.tensor(features, dtype=torch.float) + + # Load labels and convert categorical labels to numeric + labels_df = pd.read_csv(labels_path) + page_types = labels_df['page_type'].unique() + page_type_mapping = {page_type: idx for idx, page_type in enumerate(page_types)} + labels = labels_df['page_type'].map(page_type_mapping).values + labels = torch.tensor(labels, dtype=torch.long) + + return features, edge_index, labels, page_type_mapping + +# Load dataset + +features, edge_index, labels, page_type_mapping = load_data(edges_path, features_path, labels_path) \ No newline at end of file From eb431d957969c9851da999ed9e66d6e08c44e85c Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 21:55:59 +1000 Subject: [PATCH 036/102] Update train.py --- recognition/facebook_gnn_classification/train.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index 7fc32f326..ffc051ed0 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -4,4 +4,10 @@ from torch.optim import Adam from torch_geometric.data import Data from modules import GNN -from dataset import load_data, edges_path, features_path, labels_path \ No newline at end of file +from dataset import load_data, edges_path, features_path, labels_path + +device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + +# Load the dataset +features, edge_index, labels, page_type_mapping = load_data(edges_path, features_path, labels_path) +data = Data(x=features, edge_index=edge_index, y=labels).to(device) \ No newline at end of file From b95ff7f566924dafbdf9d2b4a88595431e0c2dab Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:00:06 +1000 Subject: [PATCH 037/102] Initialized predict.py --- recognition/facebook_gnn_classification/predict.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/recognition/facebook_gnn_classification/predict.py b/recognition/facebook_gnn_classification/predict.py index e69de29bb..95370a363 100644 --- a/recognition/facebook_gnn_classification/predict.py +++ b/recognition/facebook_gnn_classification/predict.py @@ -0,0 +1,7 @@ +# predict.py +import torch +from torch_geometric.data import Data +from modules import GNN +from dataset import load_data, edges_path, features_path, labels_path + +device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') \ No newline at end of file From 001b02590193b119ffdd4e4faec5a3059b8b4181 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:02:10 +1000 Subject: [PATCH 038/102] Initialized modules.py --- .../facebook_gnn_classification/modules.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py index e69de29bb..1f7d25115 100644 --- a/recognition/facebook_gnn_classification/modules.py +++ b/recognition/facebook_gnn_classification/modules.py @@ -0,0 +1,24 @@ +# modules.py +import torch +import torch.nn.functional as F +from torch_geometric.nn import BatchNorm + +class GNN(torch.nn.Module): + def __init__(self, input_dim, hidden_dim, output_dim): + super(GNN, self).__init__() + self.conv1 = GATConv(input_dim, hidden_dim, heads=4) + self.bn1 = BatchNorm(hidden_dim * 4) + self.conv2 = GATConv(hidden_dim * 4, hidden_dim, heads=4) + self.bn2 = BatchNorm(hidden_dim * 4) + + def forward(self, data): + x, edge_index = data.x, data.edge_index + x = self.conv1(x, edge_index) + x = self.bn1(x) + x = F.relu(x) + x = F.dropout(x, p=0.5, training=self.training) + x = self.conv2(x, edge_index) + x = self.bn2(x) + x = F.relu(x) + x = F.dropout(x, p=0.5, training=self.training) + return F.log_softmax(x, dim=1) \ No newline at end of file From 7ad6891b2c6f760100a2de091d1b3f770deac590 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:09:42 +1000 Subject: [PATCH 039/102] Update train.py --- .../facebook_gnn_classification/train.py | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index ffc051ed0..c6020f12e 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -10,4 +10,71 @@ # Load the dataset features, edge_index, labels, page_type_mapping = load_data(edges_path, features_path, labels_path) -data = Data(x=features, edge_index=edge_index, y=labels).to(device) \ No newline at end of file +data = Data(x=features, edge_index=edge_index, y=labels).to(device) + + +# Define the GNN model with updated architecture +input_dim = features.shape[1] +hidden_dim = 128 +output_dim = len(page_type_mapping) +model = GNN(input_dim, hidden_dim, output_dim).to(device) + +# Split nodes into training and validation sets +from sklearn.model_selection import train_test_split +train_idx, val_idx = train_test_split(range(data.num_nodes), test_size=0.2, random_state=42) +data.train_mask = torch.zeros(data.num_nodes, dtype=torch.bool) +data.val_mask = torch.zeros(data.num_nodes, dtype=torch.bool) +data.train_mask[train_idx] = True +data.val_mask[val_idx] = True + +# Define optimizer and loss function +optimizer = Adam(model.parameters(), lr=0.001, weight_decay=5e-4) +criterion = torch.nn.CrossEntropyLoss() + +# Training function +def train(): + model.train() + optimizer.zero_grad() + out = model(data) + loss = criterion(out[data.train_mask], data.y[data.train_mask]) + loss.backward() + optimizer.step() + return loss.item() + +# Validation function +def validate(): + model.eval() + with torch.no_grad(): + out = model(data) + val_loss = criterion(out[data.val_mask], data.y[data.val_mask]) + return val_loss.item() + +# Train the model +num_epochs = 1000 +losses = [] +val_losses = [] + +for epoch in range(num_epochs): + loss = train() + val_loss = validate() + losses.append(loss) + val_losses.append(val_loss) + + if epoch % 10 == 0: + print(f'Epoch {epoch}, Training Loss: {loss:.4f}, Validation Loss: {val_loss:.4f}') + +# Save the model after training +model_path = "/content/drive/My Drive/COMP3710/Project/gnn_model_weights.pth" +torch.save(model.state_dict(), model_path) +print(f"Model saved to {model_path}") + +# Plotting the training and validation loss +import matplotlib.pyplot as plt + +plt.plot(range(len(losses)), losses, label='Training Loss') +plt.plot(range(len(val_losses)), val_losses, label='Validation Loss') +plt.xlabel('Epoch') +plt.ylabel('Loss') +plt.title('Training and Validation Loss Over Epochs') +plt.legend() +plt.show() \ No newline at end of file From 0860240079cc57bcda04b8f84acf9c9927ae7ab1 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:11:00 +1000 Subject: [PATCH 040/102] Update predict.py --- .../facebook_gnn_classification/predict.py | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/predict.py b/recognition/facebook_gnn_classification/predict.py index 95370a363..aeb2471bc 100644 --- a/recognition/facebook_gnn_classification/predict.py +++ b/recognition/facebook_gnn_classification/predict.py @@ -4,4 +4,37 @@ from modules import GNN from dataset import load_data, edges_path, features_path, labels_path -device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') \ No newline at end of file +device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + +# Load the dataset +features, edge_index, labels, page_type_mapping = load_data(edges_path, features_path, labels_path) +data = Data(x=features, edge_index=edge_index, y=labels).to(device) + +# Define the GNN model with matching dimensions +input_dim = features.shape[1] +hidden_dim = 128 +output_dim = len(page_type_mapping) +model = GNN(input_dim, hidden_dim, output_dim).to(device) + +# Load the trained model weights +model_path = "/content/drive/My Drive/COMP3710/Project/gnn_model_weights.pth" +model.load_state_dict(torch.load(model_path, map_location=device)) +model.eval() +print(f"Model loaded successfully from {model_path}") + +# Make predictions +with torch.no_grad(): + out = model(data) + predictions = out.argmax(dim=1) + +# Evaluate accuracy +correct = (predictions == data.y).sum().item() +accuracy = correct / data.num_nodes +print(f"Prediction Accuracy: {accuracy:.4f}") + +# Example predictions +print("Sample Predictions:") +for i in range(5): + node_label = list(page_type_mapping.keys())[list(page_type_mapping.values()).index(predictions[i].item())] + true_label = list(page_type_mapping.keys())[list(page_type_mapping.values()).index(labels[i].item())] + print(f"Node {i}: Predicted = {node_label}, True = {true_label}") \ No newline at end of file From 805a89b7be7f326c55c37ee48cced5963da9c6dc Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:15:55 +1000 Subject: [PATCH 041/102] Update modules.py Added layers --- .../facebook_gnn_classification/modules.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py index 1f7d25115..f4351dd37 100644 --- a/recognition/facebook_gnn_classification/modules.py +++ b/recognition/facebook_gnn_classification/modules.py @@ -1,24 +1,26 @@ # modules.py import torch import torch.nn.functional as F -from torch_geometric.nn import BatchNorm +from torch_geometric.nn import GATConv class GNN(torch.nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super(GNN, self).__init__() - self.conv1 = GATConv(input_dim, hidden_dim, heads=4) - self.bn1 = BatchNorm(hidden_dim * 4) - self.conv2 = GATConv(hidden_dim * 4, hidden_dim, heads=4) - self.bn2 = BatchNorm(hidden_dim * 4) + self.conv1 = GATConv(input_dim, hidden_dim, heads=4) # First GAT layer with multi-head attention + self.conv2 = GATConv(hidden_dim * 4, hidden_dim, heads=4) # Second GAT layer, increasing feature capacity + self.conv3 = GATConv(hidden_dim * 4, hidden_dim, heads=4) # Third GAT layer to increase depth + self.conv4 = GATConv(hidden_dim * 4, output_dim, heads=1) # Output layer with single head def forward(self, data): x, edge_index = data.x, data.edge_index x = self.conv1(x, edge_index) - x = self.bn1(x) x = F.relu(x) x = F.dropout(x, p=0.5, training=self.training) x = self.conv2(x, edge_index) - x = self.bn2(x) x = F.relu(x) x = F.dropout(x, p=0.5, training=self.training) + x = self.conv3(x, edge_index) + x = F.relu(x) + x = F.dropout(x, p=0.5, training=self.training) + x = self.conv4(x, edge_index) return F.log_softmax(x, dim=1) \ No newline at end of file From 1ae0e2b4aa186af27a5cc21b041944757b3dd23e Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:20:07 +1000 Subject: [PATCH 042/102] Update modules.py Increased dropout rate --- recognition/facebook_gnn_classification/modules.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py index f4351dd37..2db7c5714 100644 --- a/recognition/facebook_gnn_classification/modules.py +++ b/recognition/facebook_gnn_classification/modules.py @@ -15,12 +15,12 @@ def forward(self, data): x, edge_index = data.x, data.edge_index x = self.conv1(x, edge_index) x = F.relu(x) - x = F.dropout(x, p=0.5, training=self.training) + x = F.dropout(x, p=0.6, training=self.training) x = self.conv2(x, edge_index) x = F.relu(x) - x = F.dropout(x, p=0.5, training=self.training) + x = F.dropout(x, p=0.6, training=self.training) x = self.conv3(x, edge_index) x = F.relu(x) - x = F.dropout(x, p=0.5, training=self.training) + x = F.dropout(x, p=0.6, training=self.training) x = self.conv4(x, edge_index) return F.log_softmax(x, dim=1) \ No newline at end of file From 03b954d3fd253960a3b04bbf729c107c58b53dcc Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:21:41 +1000 Subject: [PATCH 043/102] Update modules.py Increased dropout rate --- recognition/facebook_gnn_classification/modules.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py index 2db7c5714..41aba07eb 100644 --- a/recognition/facebook_gnn_classification/modules.py +++ b/recognition/facebook_gnn_classification/modules.py @@ -15,12 +15,12 @@ def forward(self, data): x, edge_index = data.x, data.edge_index x = self.conv1(x, edge_index) x = F.relu(x) - x = F.dropout(x, p=0.6, training=self.training) + x = F.dropout(x, p=0.7, training=self.training) x = self.conv2(x, edge_index) x = F.relu(x) - x = F.dropout(x, p=0.6, training=self.training) + x = F.dropout(x, p=0.7, training=self.training) x = self.conv3(x, edge_index) x = F.relu(x) - x = F.dropout(x, p=0.6, training=self.training) + x = F.dropout(x, p=0.7, training=self.training) x = self.conv4(x, edge_index) return F.log_softmax(x, dim=1) \ No newline at end of file From 0ad5da1120e1c504ebb17fe3acb05fca00b6b892 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:22:45 +1000 Subject: [PATCH 044/102] Increased hidden_dim --- recognition/facebook_gnn_classification/predict.py | 2 +- recognition/facebook_gnn_classification/train.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/facebook_gnn_classification/predict.py b/recognition/facebook_gnn_classification/predict.py index aeb2471bc..1db7e85f5 100644 --- a/recognition/facebook_gnn_classification/predict.py +++ b/recognition/facebook_gnn_classification/predict.py @@ -12,7 +12,7 @@ # Define the GNN model with matching dimensions input_dim = features.shape[1] -hidden_dim = 128 +hidden_dim = 256 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index c6020f12e..5cc11db85 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -15,7 +15,7 @@ # Define the GNN model with updated architecture input_dim = features.shape[1] -hidden_dim = 128 +hidden_dim = 256 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) From 044d1077e112c6f98c046fac1b0f7e268f333c33 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:24:12 +1000 Subject: [PATCH 045/102] Update train.py Increased epochs --- recognition/facebook_gnn_classification/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index 5cc11db85..1b7347f43 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -50,7 +50,7 @@ def validate(): return val_loss.item() # Train the model -num_epochs = 1000 +num_epochs = 1500 losses = [] val_losses = [] From 59811649db49f73174ddd49df1276988863c4abb Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:32:13 +1000 Subject: [PATCH 046/102] Update train.py Increased number of epochs --- recognition/facebook_gnn_classification/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index 1b7347f43..17704f3fa 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -50,7 +50,7 @@ def validate(): return val_loss.item() # Train the model -num_epochs = 1500 +num_epochs = 2000 losses = [] val_losses = [] From c61764f7ecd4e53ad831cb8b3f3fc5d46aa88ea8 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:38:11 +1000 Subject: [PATCH 047/102] Increased hidden_dim --- recognition/facebook_gnn_classification/predict.py | 2 +- recognition/facebook_gnn_classification/train.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/facebook_gnn_classification/predict.py b/recognition/facebook_gnn_classification/predict.py index 1db7e85f5..5a8b3162f 100644 --- a/recognition/facebook_gnn_classification/predict.py +++ b/recognition/facebook_gnn_classification/predict.py @@ -12,7 +12,7 @@ # Define the GNN model with matching dimensions input_dim = features.shape[1] -hidden_dim = 256 +hidden_dim = 1024 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index 17704f3fa..ed86e4ff0 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -15,7 +15,7 @@ # Define the GNN model with updated architecture input_dim = features.shape[1] -hidden_dim = 256 +hidden_dim = 1024 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) From 6ce8eb9733ce929dececdcb7e0098a91f9f487b5 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 22:44:16 +1000 Subject: [PATCH 048/102] Update modules.py Increased the number of attention heads to 8 --- recognition/facebook_gnn_classification/modules.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py index 41aba07eb..fe69d90fe 100644 --- a/recognition/facebook_gnn_classification/modules.py +++ b/recognition/facebook_gnn_classification/modules.py @@ -6,10 +6,10 @@ class GNN(torch.nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super(GNN, self).__init__() - self.conv1 = GATConv(input_dim, hidden_dim, heads=4) # First GAT layer with multi-head attention - self.conv2 = GATConv(hidden_dim * 4, hidden_dim, heads=4) # Second GAT layer, increasing feature capacity - self.conv3 = GATConv(hidden_dim * 4, hidden_dim, heads=4) # Third GAT layer to increase depth - self.conv4 = GATConv(hidden_dim * 4, output_dim, heads=1) # Output layer with single head + self.conv1 = GATConv(input_dim, hidden_dim, heads=8) # First GAT layer with 8 attention heads + self.conv2 = GATConv(hidden_dim * 8, hidden_dim, heads=8) # Second GAT layer with 8 attention heads + self.conv3 = GATConv(hidden_dim * 8, hidden_dim, heads=8) # Third GAT layer with 8 attention heads + self.conv4 = GATConv(hidden_dim * 8, output_dim, heads=1) # Output layer with single head def forward(self, data): x, edge_index = data.x, data.edge_index From bb0f4645f7849e15bd4f977d33dce64398cffcaf Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Fri, 18 Oct 2024 23:04:20 +1000 Subject: [PATCH 049/102] Update train.py Increased number of epochs again --- recognition/facebook_gnn_classification/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index ed86e4ff0..de56bd9de 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -50,7 +50,7 @@ def validate(): return val_loss.item() # Train the model -num_epochs = 2000 +num_epochs = 4000 losses = [] val_losses = [] From 8753018d350cbe4ae1858bcf18b999cdc5051e57 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sat, 19 Oct 2024 01:34:48 +1000 Subject: [PATCH 050/102] correct weight assignment --- recognition/47049358/train.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index de415f767..5a7b71e2a 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -42,7 +42,7 @@ def forward(self, y_pred, y_true): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) segment_coefs[i] = d_coef - weighted, _ = torch.sort(segment_coefs) + weighted, _ = torch.sort(segment_coefs, descending=True) for i in range(num_masks): weighted[i] = segment_coefs[i] / (math.e ** i) @@ -69,7 +69,7 @@ def forward(self, y_pred, y_true): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) segment_coefs[i] = d_coef - weighted, _ = torch.sort(segment_coefs) + weighted, _ = torch.sort(segment_coefs, descending=True) for i in range(num_masks): weighted[i] = segment_coefs[i] / (i + 1) From 5be48fa27c4966b77f3fee70a9f6de570457373b Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sat, 19 Oct 2024 01:39:18 +1000 Subject: [PATCH 051/102] truly correct weight assignment --- recognition/47049358/train.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 5a7b71e2a..9dd0a9752 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -42,10 +42,10 @@ def forward(self, y_pred, y_true): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) segment_coefs[i] = d_coef - weighted, _ = torch.sort(segment_coefs, descending=True) + weighted, _ = torch.sort(segment_coefs) for i in range(num_masks): - weighted[i] = segment_coefs[i] / (math.e ** i) + weighted[i] = segment_coefs[i] * (math.e ** i) d_coef = (1 / num_masks) * torch.sum(segment_coefs) loss = 1 - (1 / num_masks) * torch.sum(weighted) @@ -69,10 +69,10 @@ def forward(self, y_pred, y_true): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) segment_coefs[i] = d_coef - weighted, _ = torch.sort(segment_coefs, descending=True) + weighted, _ = torch.sort(segment_coefs) for i in range(num_masks): - weighted[i] = segment_coefs[i] / (i + 1) + weighted[i] = segment_coefs[i] * (i + 1) d_coef = (1 / num_masks) * torch.sum(segment_coefs) loss = 1 - (1 / num_masks) * torch.sum(weighted) From 3e7d3e8cd46312cd0a6659e9a6c02fd3383856ac Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sat, 19 Oct 2024 12:44:09 +1000 Subject: [PATCH 052/102] changed the name of loss + bce --- recognition/47049358/.gitignore | 4 +++- recognition/47049358/train.py | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/recognition/47049358/.gitignore b/recognition/47049358/.gitignore index f381cc8b7..0fafdc99a 100644 --- a/recognition/47049358/.gitignore +++ b/recognition/47049358/.gitignore @@ -11,4 +11,6 @@ semantic_MRs_anon *.png -*.sh \ No newline at end of file +*.sh + +*.out \ No newline at end of file diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 9dd0a9752..72fd13ad1 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -122,12 +122,12 @@ def forward(self, y_pred, y_true): loss = 1 - (1 / num_masks) * torch.sum(segment_coefs) return loss, segment_coefs, d_coef -class PaperLossPlus(BaseDice): +class DiceBCELoss(BaseDice): def __init__(self, epsilon=1e-7): super().__init__(epsilon) def __str__(self): - return 'PaperLossPlus' + return 'DiceBCELoss' def forward(self, y_pred, y_true): @@ -216,7 +216,7 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): # Importing Dataloader breaks the implementation. Hence they are loaded below instead: -loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss(), 4 : PaperLossPlus()} +loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss(), 4 : DiceBCELoss()} loss = loss_map.get(LOSS_IDX) From 3a99b91b4e887ed4b03fceff7b52cd67663de89a Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sun, 20 Oct 2024 03:56:30 +1000 Subject: [PATCH 053/102] updated diceBCE loss based on the FFANet Report --- recognition/47049358/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 72fd13ad1..ea1523c23 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -143,7 +143,7 @@ def forward(self, y_pred, y_true): segment_coefs[i] = d_coef d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = (- 1 / num_masks) * torch.sum(segment_coefs) + bce(y_pred, y_true) + loss = (1 - (1 / num_masks) * torch.sum(segment_coefs)) + 0.2 * bce(y_pred, y_true) # Based on the FFANet Report return loss, segment_coefs, d_coef def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): From 6f7c882b04bc359d5fc5d96918bcbd446b5c4ad8 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sun, 20 Oct 2024 17:02:11 +1000 Subject: [PATCH 054/102] redundant d_coef removed --- recognition/47049358/train.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index ea1523c23..48f5e1a12 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -14,7 +14,7 @@ LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -LOSS_IDX = 4 +LOSS_IDX = 3 class BaseDice(nn.Module): def __init__(self, epsilon = 1e-7): @@ -42,7 +42,7 @@ def forward(self, y_pred, y_true): d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) segment_coefs[i] = d_coef - weighted, _ = torch.sort(segment_coefs) + weighted, _ = torch.sort(segment_coefs, descending=True) for i in range(num_masks): weighted[i] = segment_coefs[i] * (math.e ** i) @@ -119,7 +119,7 @@ def forward(self, y_pred, y_true): segment_coefs[i] = d_coef d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = 1 - (1 / num_masks) * torch.sum(segment_coefs) + loss = 1 - d_coef return loss, segment_coefs, d_coef class DiceBCELoss(BaseDice): @@ -143,7 +143,7 @@ def forward(self, y_pred, y_true): segment_coefs[i] = d_coef d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = (1 - (1 / num_masks) * torch.sum(segment_coefs)) + 0.2 * bce(y_pred, y_true) # Based on the FFANet Report + loss = (1 - d_coef) + 0.2 * bce(y_pred, y_true) # Based on the FFANet Report return loss, segment_coefs, d_coef def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): @@ -240,7 +240,7 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): plt.plot(seg3, label='Segment 3 Dice Coefficient') plt.plot(seg4, label='Segment 4 Dice Coefficient') plt.plot(seg5, label='Segment 5 Dice Coefficient') -plt.title('Dice Coefficient Over Epochs') +plt.title(f'Dice Coefficient Over Epochs for {str(loss)}') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() From 69963d296092896ad3a07357653c2259f92db35a Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 01:27:28 +1000 Subject: [PATCH 055/102] Update modules.py Added return_embeddings parameter to output node embeddings from the model before the final layer --- recognition/facebook_gnn_classification/modules.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py index fe69d90fe..cc96c1aab 100644 --- a/recognition/facebook_gnn_classification/modules.py +++ b/recognition/facebook_gnn_classification/modules.py @@ -22,5 +22,9 @@ def forward(self, data): x = self.conv3(x, edge_index) x = F.relu(x) x = F.dropout(x, p=0.7, training=self.training) + + if return_embeddings: + return x # Return embeddings before the final layer + x = self.conv4(x, edge_index) return F.log_softmax(x, dim=1) \ No newline at end of file From 0c864053bdad4780be490ad2a1661d55ca605b72 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 01:29:14 +1000 Subject: [PATCH 056/102] Adjusted & decreased hidden_dim --- recognition/facebook_gnn_classification/predict.py | 2 +- recognition/facebook_gnn_classification/train.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/facebook_gnn_classification/predict.py b/recognition/facebook_gnn_classification/predict.py index 5a8b3162f..6c1b039dd 100644 --- a/recognition/facebook_gnn_classification/predict.py +++ b/recognition/facebook_gnn_classification/predict.py @@ -12,7 +12,7 @@ # Define the GNN model with matching dimensions input_dim = features.shape[1] -hidden_dim = 1024 +hidden_dim = 512 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index de56bd9de..aad9afacc 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -15,7 +15,7 @@ # Define the GNN model with updated architecture input_dim = features.shape[1] -hidden_dim = 1024 +hidden_dim = 512 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) From ef4609ae016e93bb0248b4f151d1b22d359adaa9 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 01:48:50 +1000 Subject: [PATCH 057/102] Update README.md --- recognition/facebook_gnn_classification/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index e69de29bb..96a4334c1 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -0,0 +1,7 @@ +# Facebook Page-Page Network Node Classification + +## Overview +This project implements a Graph Neural Network (GNN) model to carry out semi-supervised multi-class node classification on the Facebook Large Page-Page Network dataset. + +The model uses the Graph Attention Network (GAT) architecture and includes visualization of learned embeddings using UMAP. + From 8b8a4f0c5fa77d749f572d4bb965ba3eae25999e Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 02:16:34 +1000 Subject: [PATCH 058/102] Update train.py Added Plot of UMAP embeddings save plots to graphs folder Changed adam into adamw decreased learning rate --- .../facebook_gnn_classification/train.py | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index aad9afacc..dfb5c6ffe 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -1,10 +1,12 @@ # train.py import torch -from torch.optim import Adam +from torch.optim import AdamW from torch_geometric.data import Data from modules import GNN from dataset import load_data, edges_path, features_path, labels_path +import matplotlib.pyplot as plt +import umap device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') @@ -28,7 +30,7 @@ data.val_mask[val_idx] = True # Define optimizer and loss function -optimizer = Adam(model.parameters(), lr=0.001, weight_decay=5e-4) +optimizer = AdamW(model.parameters(), lr=0.0005, weight_decay=5e-4) criterion = torch.nn.CrossEntropyLoss() # Training function @@ -77,4 +79,27 @@ def validate(): plt.ylabel('Loss') plt.title('Training and Validation Loss Over Epochs') plt.legend() -plt.show() \ No newline at end of file +plt.savefig("/content/drive/My Drive/COMP3710/Project/graphs/training_validation_loss.png") +plt.show() + +# UMAP Visualization of Embeddings +model.eval() +with torch.no_grad(): + embeddings = model(data, return_embeddings=True).cpu().numpy() + +# Apply UMAP to reduce embeddings to 2D for visualization +umap_reducer = umap.UMAP(n_components=2, random_state=42) +embeddings_2d = umap_reducer.fit_transform(embeddings) + +# Plot UMAP embeddings +plt.figure(figsize=(10, 8)) +for label in range(len(page_type_mapping)): + idx = (labels.cpu().numpy() == label) + plt.scatter(embeddings_2d[idx, 0], embeddings_2d[idx, 1], label=list(page_type_mapping.keys())[label], alpha=0.6) + +plt.xlabel("UMAP Component 1") +plt.ylabel("UMAP Component 2") +plt.title("UMAP Plot of Node Embeddings with Ground Truth Labels") +plt.legend() +plt.savefig("/content/drive/My Drive/COMP3710/Project/graphs/umap_embeddings.png") +plt.show() From d8cec5eb4305c533b4cd222a80e8ce9f4df09a14 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 03:02:02 +1000 Subject: [PATCH 059/102] Update train.py --- recognition/facebook_gnn_classification/train.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index dfb5c6ffe..84ef7eebe 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -1,5 +1,6 @@ # train.py + import torch from torch.optim import AdamW from torch_geometric.data import Data @@ -17,7 +18,7 @@ # Define the GNN model with updated architecture input_dim = features.shape[1] -hidden_dim = 512 +hidden_dim = 1024 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) @@ -30,7 +31,7 @@ data.val_mask[val_idx] = True # Define optimizer and loss function -optimizer = AdamW(model.parameters(), lr=0.0005, weight_decay=5e-4) +optimizer = Adam(model.parameters(), lr=0.0005, weight_decay=2e-4) criterion = torch.nn.CrossEntropyLoss() # Training function @@ -52,7 +53,7 @@ def validate(): return val_loss.item() # Train the model -num_epochs = 4000 +num_epochs = 2000 losses = [] val_losses = [] From 09b19dc30cc966da0b428c8a367a7a16ccaeb93d Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 04:03:07 +1000 Subject: [PATCH 060/102] Update train.py --- recognition/facebook_gnn_classification/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index 84ef7eebe..6db3b1999 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -31,7 +31,7 @@ data.val_mask[val_idx] = True # Define optimizer and loss function -optimizer = Adam(model.parameters(), lr=0.0005, weight_decay=2e-4) +optimizer = AdamW(model.parameters(), lr=0.0005, weight_decay=2e-4) criterion = torch.nn.CrossEntropyLoss() # Training function From 70dc8d64b042df55fbf658c85f22fbfacc480f0f Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 04:44:17 +1000 Subject: [PATCH 061/102] Update dataset.py Use partially processed dataset facebook.npz instead --- .../facebook_gnn_classification/dataset.py | 59 ++++++------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/recognition/facebook_gnn_classification/dataset.py b/recognition/facebook_gnn_classification/dataset.py index 32d2f618e..55257f3a7 100644 --- a/recognition/facebook_gnn_classification/dataset.py +++ b/recognition/facebook_gnn_classification/dataset.py @@ -1,66 +1,43 @@ # dataset.py -from google.colab import drive import os import sys -import pandas as pd import torch -import json import numpy as np # Google Colab setup and data loading +from google.colab import drive # Mount Google Drive drive.mount('/content/drive') # Define paths for this project base_path = "/content/drive/My Drive/COMP3710/Project" -data_path = os.path.join(base_path, "facebook_large") +npz_path = os.path.join(base_path, "facebook.npz") # Add the project directory to the system path sys.path.append(base_path) -# Paths to dataset files -edges_path = os.path.join(data_path, "musae_facebook_edges.csv") -features_path = os.path.join(data_path, "musae_facebook_features.json") -labels_path = os.path.join(data_path, "musae_facebook_target.csv") - # Data loading +def load_data(npz_path): + # Load data from the .npz file + data = np.load(npz_path) -def load_data(edges_path, features_path, labels_path): - # Load edges - edges_df = pd.read_csv(edges_path) - edge_index = torch.tensor(edges_df.values, dtype=torch.long).t().contiguous() + # Extract edges, features, and labels + edge_index = torch.tensor(data['edges'], dtype=torch.long).t().contiguous() + features = torch.tensor(data['features'], dtype=torch.float) + labels = torch.tensor(data['target'], dtype=torch.long) - # Load features from JSON - with open(features_path) as f: - features_dict = json.load(f) - - # Ensure consistent order by sorting nodes - nodes = sorted(features_dict.keys(), key=lambda x: int(x)) - features = [] + # Create page type mapping based on unique labels + unique_labels = torch.unique(labels) + page_type_mapping = {int(label): idx for idx, label in enumerate(unique_labels)} - # Pad features to make sure all vectors have the same length - expected_length = 128 - for node in nodes: - feature_vector = features_dict[node] - if len(feature_vector) < expected_length: - feature_vector += [0] * (expected_length - len(feature_vector)) - elif len(feature_vector) > expected_length: - feature_vector = feature_vector[:expected_length] - features.append(feature_vector) - - features = torch.tensor(features, dtype=torch.float) - - # Load labels and convert categorical labels to numeric - labels_df = pd.read_csv(labels_path) - page_types = labels_df['page_type'].unique() - page_type_mapping = {page_type: idx for idx, page_type in enumerate(page_types)} - labels = labels_df['page_type'].map(page_type_mapping).values - labels = torch.tensor(labels, dtype=torch.long) + # Convert labels to match the numeric mapping + labels = torch.tensor([page_type_mapping[label.item()] for label in labels], dtype=torch.long) return features, edge_index, labels, page_type_mapping -# Load dataset - -features, edge_index, labels, page_type_mapping = load_data(edges_path, features_path, labels_path) \ No newline at end of file +# Test loading function +if __name__ == "__main__": + features, edge_index, labels, page_type_mapping = load_data(npz_path) + print("Dataset loaded successfully.") From 28cdfc94e21c302b5d582b2ce0a1b5eeb9cfd468 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 05:14:45 +1000 Subject: [PATCH 062/102] Update train.py Updated with the new dataset and path. Reduced num_epochs. --- .../facebook_gnn_classification/train.py | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/recognition/facebook_gnn_classification/train.py b/recognition/facebook_gnn_classification/train.py index 6db3b1999..5859244f8 100644 --- a/recognition/facebook_gnn_classification/train.py +++ b/recognition/facebook_gnn_classification/train.py @@ -4,21 +4,23 @@ import torch from torch.optim import AdamW from torch_geometric.data import Data +from torch.cuda.amp import GradScaler, autocast from modules import GNN -from dataset import load_data, edges_path, features_path, labels_path -import matplotlib.pyplot as plt -import umap +from dataset import load_data, npz_path + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') +# Define paths +npz_path = "/content/drive/My Drive/COMP3710/Project/facebook.npz" + # Load the dataset -features, edge_index, labels, page_type_mapping = load_data(edges_path, features_path, labels_path) +features, edge_index, labels, page_type_mapping = load_data(npz_path) data = Data(x=features, edge_index=edge_index, y=labels).to(device) - # Define the GNN model with updated architecture input_dim = features.shape[1] -hidden_dim = 1024 +hidden_dim = 512 output_dim = len(page_type_mapping) model = GNN(input_dim, hidden_dim, output_dim).to(device) @@ -31,17 +33,22 @@ data.val_mask[val_idx] = True # Define optimizer and loss function -optimizer = AdamW(model.parameters(), lr=0.0005, weight_decay=2e-4) +optimizer = AdamW(model.parameters(), lr=0.0005, weight_decay=5e-4) criterion = torch.nn.CrossEntropyLoss() -# Training function +# Initialize GradScaler for mixed precision training +scaler = GradScaler() + +# Training function with mixed precision def train(): model.train() optimizer.zero_grad() - out = model(data) - loss = criterion(out[data.train_mask], data.y[data.train_mask]) - loss.backward() - optimizer.step() + with autocast(): + out = model(data) + loss = criterion(out[data.train_mask], data.y[data.train_mask]) + scaler.scale(loss).backward() + scaler.step(optimizer) + scaler.update() return loss.item() # Validation function @@ -53,7 +60,7 @@ def validate(): return val_loss.item() # Train the model -num_epochs = 2000 +num_epochs = 300 losses = [] val_losses = [] @@ -84,6 +91,7 @@ def validate(): plt.show() # UMAP Visualization of Embeddings + model.eval() with torch.no_grad(): embeddings = model(data, return_embeddings=True).cpu().numpy() @@ -96,11 +104,11 @@ def validate(): plt.figure(figsize=(10, 8)) for label in range(len(page_type_mapping)): idx = (labels.cpu().numpy() == label) - plt.scatter(embeddings_2d[idx, 0], embeddings_2d[idx, 1], label=list(page_type_mapping.keys())[label], alpha=0.6) + plt.scatter(embeddings_2d[idx, 0], embeddings_2d[idx, 1], label=str(label), alpha=0.6) plt.xlabel("UMAP Component 1") plt.ylabel("UMAP Component 2") plt.title("UMAP Plot of Node Embeddings with Ground Truth Labels") plt.legend() plt.savefig("/content/drive/My Drive/COMP3710/Project/graphs/umap_embeddings.png") -plt.show() +plt.show() \ No newline at end of file From a2b1b6a70a1a1909766c671a20ee151cb2acc029 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 05:17:53 +1000 Subject: [PATCH 063/102] Update modules.py Added more documentation. use x1 - x3 to differ the layers. --- .../facebook_gnn_classification/modules.py | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/recognition/facebook_gnn_classification/modules.py b/recognition/facebook_gnn_classification/modules.py index cc96c1aab..8de63f382 100644 --- a/recognition/facebook_gnn_classification/modules.py +++ b/recognition/facebook_gnn_classification/modules.py @@ -1,4 +1,5 @@ # modules.py + import torch import torch.nn.functional as F from torch_geometric.nn import GATConv @@ -11,20 +12,26 @@ def __init__(self, input_dim, hidden_dim, output_dim): self.conv3 = GATConv(hidden_dim * 8, hidden_dim, heads=8) # Third GAT layer with 8 attention heads self.conv4 = GATConv(hidden_dim * 8, output_dim, heads=1) # Output layer with single head - def forward(self, data): + def forward(self, data, return_embeddings=False): x, edge_index = data.x, data.edge_index - x = self.conv1(x, edge_index) - x = F.relu(x) - x = F.dropout(x, p=0.7, training=self.training) - x = self.conv2(x, edge_index) - x = F.relu(x) - x = F.dropout(x, p=0.7, training=self.training) - x = self.conv3(x, edge_index) - x = F.relu(x) - x = F.dropout(x, p=0.7, training=self.training) + + # First GAT Layer + x1 = F.relu(self.conv1(x, edge_index)) + x1 = F.dropout(x1, p=0.5, training=self.training) + + # Second GAT Layer with Residual Connection + x2 = F.relu(self.conv2(x1, edge_index)) + x2 = x2 + x1 # Add residual connection + x2 = F.dropout(x2, p=0.5, training=self.training) + + # Third GAT Layer with Residual Connection + x3 = F.relu(self.conv3(x2, edge_index)) + x3 = x3 + x2 # Add residual connection + x3 = F.dropout(x3, p=0.5, training=self.training) if return_embeddings: - return x # Return embeddings before the final layer + return x3 # Return embeddings before the final layer - x = self.conv4(x, edge_index) - return F.log_softmax(x, dim=1) \ No newline at end of file + # Output Layer + x_out = self.conv4(x3, edge_index) + return F.log_softmax(x_out, dim=1) \ No newline at end of file From ec1345c79729d3302d6cf7b323f40b73f2b265a2 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 05:45:47 +1000 Subject: [PATCH 064/102] Update predict.py Update predict.py with new dataset as well. --- .../facebook_gnn_classification/predict.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/recognition/facebook_gnn_classification/predict.py b/recognition/facebook_gnn_classification/predict.py index 6c1b039dd..6b4060ea6 100644 --- a/recognition/facebook_gnn_classification/predict.py +++ b/recognition/facebook_gnn_classification/predict.py @@ -1,13 +1,14 @@ # predict.py + import torch from torch_geometric.data import Data from modules import GNN -from dataset import load_data, edges_path, features_path, labels_path +from dataset import load_data, npz_path device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') -# Load the dataset -features, edge_index, labels, page_type_mapping = load_data(edges_path, features_path, labels_path) +# Load the dataset from the .npz file +features, edge_index, labels, page_type_mapping = load_data(npz_path) data = Data(x=features, edge_index=edge_index, y=labels).to(device) # Define the GNN model with matching dimensions @@ -19,13 +20,13 @@ # Load the trained model weights model_path = "/content/drive/My Drive/COMP3710/Project/gnn_model_weights.pth" model.load_state_dict(torch.load(model_path, map_location=device)) -model.eval() +model.eval() # Set the model to evaluation mode print(f"Model loaded successfully from {model_path}") # Make predictions -with torch.no_grad(): - out = model(data) - predictions = out.argmax(dim=1) +with torch.no_grad(): # No need to track gradients during inference + out = model(data) # Get the model's output + predictions = out.argmax(dim=1) # Get the class with the highest probability # Evaluate accuracy correct = (predictions == data.y).sum().item() From fe99e4f7641145a3ee5fefe0ee1cea2da4d16cfe Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 07:57:10 +1000 Subject: [PATCH 065/102] Added training and validation loss plot and UMAP plot --- .../graphs/training_validation_loss.png | Bin 0 -> 26071 bytes .../graphs/umap_embeddings.png | Bin 0 -> 115496 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 recognition/facebook_gnn_classification/graphs/training_validation_loss.png create mode 100644 recognition/facebook_gnn_classification/graphs/umap_embeddings.png diff --git a/recognition/facebook_gnn_classification/graphs/training_validation_loss.png b/recognition/facebook_gnn_classification/graphs/training_validation_loss.png new file mode 100644 index 0000000000000000000000000000000000000000..561f8ceaa2a6cc61933f4bedcff58407ba1e99a1 GIT binary patch literal 26071 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 literal 0 HcmV?d00001 diff --git a/recognition/facebook_gnn_classification/graphs/umap_embeddings.png b/recognition/facebook_gnn_classification/graphs/umap_embeddings.png new file mode 100644 index 0000000000000000000000000000000000000000..987151fa9733e242443ac729a383627413c220c3 GIT binary patch literal 115496 zcmeFZ^;?x&*EY-+#UjK2B$X8DkPa0PP(nqzTe`bcl#r5cFi->p1f)wEBo>0OfCVgi zNq5&fF8AK|{k%Us-yiTD?>dfk2zae)&TGyw&vBmT7!dqWNtWmwBo3@ z_`l(O?F<3@cP0>Sa@Jl>(+Llc#1MJ^^;t600`D(8JbCFmPux=$ zM%=t(H+PR$(LU*^;&OKr&U&3&5`Xlw!v2?t*3XiDtzY@Yz5Roh1r7Z}=^w(gUDQb} zid{&CFFiULd%^74g}bg@HIlWG#KISO<*rTQE#oF5Pp9mAFYVVXMLR|5Y@6%E@ibqf z|NC|LV`&*r`k&X?il9F)x%&@aaQ^-OQ72;FhW!203_Paa|9pz|_J1xt_x~>ae=G3+ zw-t~hVP$0HT5b>j$p4drTQK1#>B*IxKUu53fVc! zr=s*EQC9iY0j8Q&TSHbDYp+I9S$lXh(&cLuoMzBJVwwr?O>Tyk0}#~EpoUA=mhCe5w(aI2w^eW`3R+%>%xMvKN3u%EBRq7rzF z%ci0peE#xfc*e!1Jl_UGNXZ{$93fuPa`aZK(v<@lAl-XSK7!ir0iSu-R1r#IvYE_(E4mVnpkzuPZ7LgeOOfVAwNxSjm~3=)V6#& zjz*%ZUn_6Cfkbj))i@+*gTT%2^fmg4?R}4ppR(n1**RJ^c9xb#qg5U|heyQQy09H| z-Yb7GF)@i9tTgC&uQt(?9Cq6IN?BO2zIzxXi1m&ZT`KcGKH9Ej*ZLOp?b|mcW3ib8 zW1;1$b?)Y`-n)*rwTG_ZB6By=e6}>hC69KNbXU~+^K{!c(fZ1;H!7J*BkzoDSSbkC zx(=Jk&&w5zLYcRTHb7Qgj=WzT6bntk9l>>yhy=XGsBEqj~u z9WfOH`v%F=W_Cwey)Fd-9RiFdYaDrYhTH--|_xJDc1L3?6jnu?fe3PrMmc9 zD+BUy?Oe6qfe}pfg?uW2*oRA0*c}38@y*NU$vI7a#IUw4uFrHbTnx4!c4%4s!IuB6 za#@N*T-wm^I;;|(d5Qx8o7$J(D-jzoEr~(@gTrON^n(NMqXV2IpWUcfm&E>pk})-( z86oy)t28(p}x?JohWhd##P7BULoMS4lKCo_<~zxi>xm z;qPVcJ>B-Fk-A|h+gG4MT!ZN8D^pUJOJ4;oI1-Dk+`j+dfyY#& ztd@=6&Um0OoPgH$_IZ1(EUm{&zAhpEOUh!A3kwSZEx$V+$xeLr#k(k z0Ck=`dBSbnOvua2d*jB9u}sNBi{y7heSLl2u+P`o*g{fLsLi@k+Uj4O$51;R?rrM8 z%m}aYo=iu{IymrTra0culjki|}AeP1e?nHaDV?V}7`WApw93B4yaYNgfXxT62tg;AqnPjy!x<{OO$Ci!1@Y z#)q9yiW0UScH$7aIxc;xgtTG_-@ftB&Cfs2^U*8Od+@fYf4!+Rg=A#ScV*Xmp>ny# zd!_EQ&DQdq`Pa&l&`H=0`Q`%m)rqNo|$PQllZ|Z`@c4(eU3JroQ|F_^x4EiTPGqM0iddW~ zZK3l^Y3HmYOh>gWmSVdcT4-AKmupcO^3l&4y~dv56U%YlRDbyJJ8Yk1&35(jBYpjJ z>Mklmf7=TE_pbsT(!~jVAy-TGn87GS6HUefm%sqmT}bY*oU)b$EZ1s zs-?7FXcwpBIr|aV%2&e%0zL0l8MR!kzH!BOQpCb1+Y1vU{Up2= z3QptMRjm?~*sRYa+c9HQRaIA;$n~9tWG25h5KqEoR&K}|4>b> z`KozJ-FD5kIC91%k5);#B#*tfM!oEql~M-A=Qq-i4^F@BO`8Zm0K5Y-u-2P?6k{(G zik@Fw!+orzh5S!RNr}MQSN0IegK-ihBx2&@StPkeb_s3s_m?Uo9^Pmq@m<09me9`> zR4d(ry-xzP>;IzJ09!`>cJb?OvTem#Ov&!7vfq7OT^hfg20EebVJ9TwU4^#x_B??i z(Ly4#=B!$|iwp;gohacWvRr%Yo17(k45`lI=~Dx^nhSF^~w!$jn^N_d5)^%4f!H-bJk>zWK}5I9Qq<*&KVJj*szrKfXW5&-(m% zEYUpeT}eqCWF49sJyLmxd(s(!I$n##1l+K)ixQF!6VgtQt61o`^lOIkW+MC!K4^Y> z8u?cTm0gu#D9=m@#+DE8^;1?>TStm;FAQ8NJjxWWV-!G4V@ch@(@e2mf1ZotJG;i$ zx2lz}P$;|^7@imIZninsH&f6;%LhlA`NElmTUPzfp1RL=N4IOtv$L~10*I(Oyq2rY z0jJFHoYp%9SujL&62mYI-|o&@JC~h{Vlzc=ceep#RYiIEUW!D+xSkg3#Wch9yx&c?VP;i|ajw?tmk`)kD`dtOw* z(h7!#?-KbfqRtZdw@r$zckmH#qjj7V9WlSMR1_T?3bJx@6>Y6{^BA*(bSKw$JCuFb zqLn5^H-D)RbKFs&s_Zuk$)_2I}b^Yt*5tFyZVU30eDR!5tYC4N(9`n@S2&cC5@0P>6{0c$wG=nN_c{|T^~J) z++A|3#ms1x9#yZxs=!b?Es{#M$pSV>iDDjwXJ6fIvk9L}@Fx~&4W$*YXh0hQuOi@9 z7F(6hL^IJ>auPX^N5*i&Awk$Cq8+aNWOM$(n(18TuFXz1x!OX9)5h+pIr0?20>7@W zze@{A)OA~U@An7R8#fGocfU(<>DL4%#O=1ELqI}X)w#1&y{&id+_@X<>?VNcILHJO zui5f`JKy<$Bw2)BQ#-a^Z?l0@hwyBJrq@?M+qfs=Mzq9eaj(er44Ol)=FS9=k&`=h z3FB4}m<;T-&5zUDcy*rKRU>W@xRyyn0MWs3SxL)VsNI*BlnjQ;9NG*I=KFIeqm?BL zk$v#=4HurFU{*-zo=bq|JqeXChx9xxRNnAKGVo z1pR5m1DA@b12DU zu~m0!V?w8yj`56WrFx3qxuj3Z=}G{SbbbdsZ`|`Q!=nI(Ge*S6#r0cW=iJ$IIUXnR z8?f|U-o>S3bJL0u`khNl=lS~`0?Txg0Icp}w1A}bQv#Th#9LNsIfo~n7MF72nZk`cnJ9sn5nj|otKt` ztoHU4P`A{}moGEcmK=DOLi%EUe*4;PSx$QV;%cs)Pss4_@YH0Sl}&lgk~e`{<7{TS z(w#eZB53Ta$aU=R$=NA-QUMUW4?UDt% zYa^>mjX)Aan)^gB3qqzK_0Oa@bG> z6rpTNN18*pYFcyhYkq(zgbZ)Kw=t{xdOt=*X&e&m6oB^xFm&U|<}f6+r*a;AbDX~4 z98QBV^J-tg#ImWo&JJq>e!nj-FK?I>32&I|%c=Ak&P@e^7fN|6yP^CyM?oohOPRxD z6sq(<)N|vvz+%a$+icIrUwwU#G&BZo{&n-ljkg5_k#NGDS+@{<`5{80q7RK==BE)L z2U_B`yAAI1h7%B#LgBq;N9JB=evmQ10kdFakgr2ST1yr4c>-vJl;JVvTTK6mMMm$$ z8PB6Xe?a$6u71<($YJoUtyQFtO-{z#tkWxZWNK<^vax+*BmS`gx4ycMJx)V7|K%%J z93W||21*{hd%(1akmLSb?f8Q#?YO2tFz(<7f9W8>mVJcs*G?OOwTdsOe86xmXM3*Z+pnThP_6rMnLwR(7m)l6}LmYG54wOVe@+${`D8r?BQE(gJ^=2yL zASd@8I7N;G%>dtyu$aAij=+CW0t1j9NcfgDSN&`KICGG7N# z{S{{ITBiR1wSKU>j>KAi_11mPE|>Y-(w>2VRv^x0tIbqyH)<9SeZ#2)iJ!@YkU0R1 zvy_t1i12${Vi6RK52F$+8FXtOU0*6>&lwpI$u1pLSw_?Jjoxx|mU8v7Y}uZ1kpPCD zf=nD_BcgmSlaWn0mII}BbZRynrU60pwy;@|Bni+A! zF8*}Emu9@hdWSrcwztr72Q=*9C-TDb^2ELzb+;sE5-NdEe-eoV*p@IjKNO{vhjfoP zHh#b%fiBfh8A72$jNcJ z{|aJbl#d5cl_93g?o_n4c(C7O}&{$PAOYn*$c!#a2M+`45aC|_%gD4;M@|-lGdsyIMN7dXZYqFEUoTg z)ouD&JG+6ct*t^g9N$2%mS?$@m6f)Q-LjVF{QkfdWr56? z*#W-Cif1)=N;EbB30N1jZlh6wO+R5Rva(=)mV-VKwdRA=o0OCU{F4mKpnJ*rhz$cS zqO->P?0nFA*fG#ExKy`Md0XH|6M2ztIsuiCL z3!@M}2QR~7ZmAArt`V0sW|Uw@VbFSvXa z%)Dtplc%?&*8yj(`A#2q@SzxKBi7+Sl_;_oXnc8)udMG06Vd8a)~)uu1>;Q)7)LZs zJB~Y+3xVuTQWJ=JQ`z19|UFf=~l?Gb0V_TW4S_vPz`|e?m4TEerBOhPUgY;VP<6;0fUTtIjBop5% zr;5Y^nYOK%Wj^uzc8ef(v=OBq`cf171NseR+Mc-51K%2;7`eW#cC(N_ZEpo0AX@-w z=fROL8$0_{5JUJFn2n-9SgeYUYYsX$S#e^VfmC z6RGRETnVIcr2zk$7fxCgI5J{D!VvgNaqf{%rJV$y0SE8pZ=DdR3ckL+fgf8DM|i1b z-xmDWL8bPWn?=nQ7n6mWcpb?rviXSpGYzty197->7Qu*s{J)JD zQHb%90yAhUd<0(dABtL%3U&ZXiv0=XcG$xux4~}~mk>ugLCC=SvEQ6nQOIA|u7Ow+Jq2_|PV(zwCegJ>Ad?x6e*i6GtD zsaH{O6@1=8pd(J>ugG}~>rV>U3^jtU(D8t)I)?qM8~k+b_y~JES+(9Z33=juSy=+& z26s~1N3=8$2@ZdkA=hmLJF}^@W|ITprVHVT)55=XdBBj{!q`cIP)J8aIuL@L?b_qi z(9)0btB@p&hQ3*(c+4a!Byj&#is>9Kcgp(mW$H^&*U*dyl7oRt8?v|GC-!hF*P(Xq zz9R-i2=Q%l$q1}aAl4kpbq;_rXXfP*r=#L^xE*DI^GQ*IAC9B}#NUSLCJhhk^yllN z;At8m2bFsCl2&YcAhMtxTmf@fjV?rt30Mz&2LxyXVN~k%S8JXxffpi@guz28Tl>L= ztUkE1VvxISEyCQv%!N`-8DG>h^KXloPj zpr5FzAr*kHW}TEkX9sLk@~hU)#p^hpMN}WKO2PsS#G>c+Xi%1R#Xl@`tqNM`q4oTI z-3d(O1Tg#%#Rlu&0lSXP9uDQv<-#v9O)Lg$ZPK-})2(Jbl^7!^D3}a23X}4jyqLjR zLIbnTq~cCj?RY=l<^#GHV>?&@ zkeskO*+K z1I-V)?G!E>5*GR12JK!G?*eIgKgdQ1NTj0{;Qotod)Z&U@E4hN@=65~-=d9ZA*2@S zR!A1;L~frul&e$TlLBbU%)!w~NWuO60DF9>U)VU@-%<@oqG(}}wYuwV2Kdgijzih0 zq~(0zwOWj2w=Qqy0H-4ngjfqQw}l03CvdrvOGiE1@&0%p%@jorllS!z{ge?1Dl^#j=4r=b&uU2RwutV9 zvccyVO|KVqZ=qJD-GSti!otE(%%TAPX<~lJ%kL4N0#w+8lEvTEeeXfBfDzgXRf~G? zNcg}xSO+uIO~Wj=8pUpqSG_f)hCxtTLDm%VuP~S>yiQQ)Le?M5{*HX#O}6!k5Uvsr zeL(?%B;*lc_rKjd?*C~uG`e3Yu6=Z1xoia{PqPE{dL{O-3knZnyPCc;iRL0copv?5 zW_-@SA0m+ln=zDqc`Od?3)(92IsR$Nh!$f|!`8?lSw|d3jJ2*=ZdKK=_jV=r7Gw>6 z-&!nSZz4m4SP$Ydrs`z|Er_ri@3~(gh1VdfIOM|=h>)t?nPgEhE^TNW7<&AtSHR|^ zf1O&$X49lYxcHWa#KDRboc~%C_9+&6`of~0)XwmEi^-k`Tuc;%j$_YHUnCCnn9Is^ z2hp@Uvh15Vr6Vn!5sxGnxTQN(bIM={RyH<<%jbB&i$SbSq{@0ktSBvQ694feavi)F zPkko-w`<{lwjz9!8@7c7f~wvFAZu}^n{GmXdKY?>LwWf5`MIGkX|3&3nsxi^o-Gp6 zgft@GY8x&fPZ@c+z;n|wfbeP$*6_^zZa2}y#KhYZQVFrKeW;&*_ec0;<>#A&%g{!B zXD|KY#)v}u*R3yK*#GH|c%PNeDt(FQ?+Hpjeg;+CKd;EkZ~r^(r~gcQp=4rJ=;u=y z{Pz{wh|}@yeON;|!5eqTk&i@i|Z+;ThY-I+J-KC|~st|IFF-LFLfbt*r%ObQ#;D|IhXi z(L^9SVNp>Rkt)V=tt4W#`UNtI|JyXu>gq@><)O-OULE~duP+|^=r1Jf-hG&irjjF1qD1 zb+RgkP>zLV4893o47oYyIb9Vg_Y$enLM9U_?<}zim)LuX_!D}#ksnRN(ZZ8CgqZTWiTSId=Z-eDim^No`ZaIm#(xNhDwf*P2(uf(kO zKf5PgVJPEr$&`wcwTt*$7N4yqS<~QOakftlWL#7vWp0SF{b#K13$IDTMNU@bxu%o2 z>%ROzO!Q78BHatBiDf#RP!-X($^Y`jWbFI%|NHjWdzYJW1!wO~EK1OYHm-VD^B#)V zGMA#~O##|xrsMVha8poSiTEU9Ut3TtJ`eus?2!|UnabqL=Jt1Sxf5z3jvA(DsHnL1 z;XEH}oAPq(y1qlxm0`e3v6b)m?3#ryL3Aa2`t)fkd#P~!apEn&3ZIzT6USnk^DVf} zSERC=`eJ|sDup&7z1x&`WfZxE$;HQ9NJASn)yWyTM%pdBh?+}sZRo5;z2~*Dh}B?~ zSB``}0-#6{OW=GaC|)6Lm6_XpAA2v0adCTO&#cX zCwc#(#D^(OujiO4@AB{-+TLI5^~%NRxcVUbWr9{ax{t2 zJDCZHO?1h0%6i&UKs)-L2mgD|)WT3#GNxz|31`n>Rm;qez=736aoa1BMmMtHh~4{g6eJM06-apNLUo^Q#d@KzizkN^VJn@(+0)ebi@z1 z<4<6yNd|>wXXMPu{j;5|O7F9>f>~8Q*<)-!&nj#2 z|KwECK~3RiL)F8Zlpn%O+<7VDZV_VUAkbhP^ZF(sNuWSuW5dDjM z7(@BZi$~Q9SoR$4dyHgt^IN>UUW_aeVu`D}llzPTPz}TbHoG_F-BbCW;OLE-V;U}B zQL?PRb@}5JQn~XNLQm~h?K$-ev_zuj=S4;}&`0h?qLv>Ffi9bsn#pEOPALJ8i z9>=yHDJqr)kPb3@Wk3In(2ig>&H2atk6l#ZF}Hx7bw06MIy`j<8OKDYAaOyg7nkcEceyx%WS{43aj&twM z!Rmqi50b4WSPPgdng6}cIuLgGYO-LQ>SoT-&Wd_CyH>Wso=?Onu_>S1H{I=5ujWUA`yp(cqUXZG!!Ku$yWrmD%~-rl#zCIQPuCZa2%aj z#MC)>ic?2&?k=27SU=2-a(c$yk$mbnvk7+ZCG%Pp{%XpTd;2^mlNWWKMPUU2G zUh)0{&%l$>%7P$g8L>FIE>V@En+G@+pG(R&y>>d%Y#_57-iO$3&FczwuC^)5+n%^E zo4vifpj8>M^!({(H)DC1Vm7amR7j(L2uGy|2D4dGvoIPWm64NHTQP5gJqb&nhCcYUq=S9B2lvoJiW2A7?rqqz)9dzx6<_G*nycn^C17z|C6H0a1k3%XoD3HQ zmqfhv#}9gF2m+Sz2J!w6Y2r36ARAa&@xtL*@uKVLL%Gdvrdt|md8H#G^WG#w=e;#k zOIJ;qhJsr;4WYAU*tu8H8+4L4h%IWDUyo88f3PC04Tm&I8+eCI%=Cq#WqEN*(awON zPaIbd;6B@4)#NQ*-%G|1%)iq-J@#pcW?yFn^|{QHjYr4;Pir9dPha&(rH?EgZy-5&-9~-3lQ0t zL;bA;x7;pg%@?tZm1A%BX6KiFB=Mijd)|g!s4a7qMfcUYq_S%z@KKu$ze|3=@jCN+ zuwQ^br~DJ+6;qb}nC^Lo9;>?{!B&wx@h47b4(KiTVr+T7t%$aA9m$7pyiw%=D^a56P9$c$ioToXFvv3`S6 zkT{3jHYSWlG!AUDmjLHrugW7GCG+{Ud5k{fe-auat(BxOwkKt|;iby0;p+TF2Qmeb zO9HVu<{HwE@0m>Br*DrN=cG*dgSW3LpI(bBG?iA%YgE@7n#65;R)lm;Csx$I{+tnA8xuhfmCXxv}wa9CKdFz)#l z`O|Osf2G({WEK?IO*l~3kK3oGJn)S7ZTR>GiY`Tv{-P2S<-rx@GwT?G(u{Q~%0qC15=UCZzGgKmiyxVI&ee&yaGHak%iO7RZ{)mu4Tg zLi+=HZWSz9Wmo|^pAAyP6LxWN8HPp^F)*W$1B*8dy_BJJl4mjtnLs2^NCG<(8Zd$@#BO8?4n%+ zoyy}t&u$eBsAl7VMTmz$gY<_-Ak==FBtxq-kM#gIqS#y`NQnbMt=nw^NNbn>F3u~a za%OM58{G5*5zjN}+}9u7x0zr}sSu%OQ=jM9;ai`|mPBxk(fau^Vbanfs$#`fi)*~^gyS^i!P0Q` zIy!p^f}ArlMNq)V++>VKqDtMf%XIs#o6>6}J0lbVx^*z`CUu}94U&eb7K-{KQlzhg z7L4*R_wsl2_}4T!#g-A=nciv5*r5-w+C-c&toQBq0}$`v=?BETuk$rxeA>k zs5jT8qA;h4spS|iLI+ZbDwn6JDHAwV*4r8q=_KhWH0F9p&;n&%j{m9SmmcxH)i&J) z!D;JZ`gakk8uw=qx%_T@3f4x72Ix4d2ZIa{- zAP}V=$VOjiHMA~P_EciQk0(^<+;CX84!-{uaDU<^l|9kBKtu;+U_oDXB;5)@Dml=D z5(&;qih3GCNG@E17RhCwWiK5NmS91Fuxmp4sQ`sOUjd%u`FQp6jieNfTydTF1gA8? zyW%*2P@8H=x71FeQ*Z`@J74j%MrJXvZ7>6}Gq%cVn_RPp?v)$*%NGPLa@Em|A1 zz2)F6?h8GJr2ot&CnhPVmGj5sDqi>Su)?(qzj04J)t#L9RyJ=vuq+C-&00`{Hqo}O zu1`RJpzL%+EDKvITc@>yR`{$1Yj^Gn4mNXbV>|g%Kum4o%+q$4iqDS4f`9JTh%(uj**D0dDkNJ$%$M17-l1Az# z{E;#l+omLogRVW5B}!eTPgV^lJYZ;tKZ+w`J9YOqa*IpZ%R<6-k5;b_^V9QeR9hHh z8=+~P>hIqhspfhUedA+);)}Cd*Ep|qRF_#T-t7xET=t_r>qm*LT-wYHbe)W{ky=QDf@S2^ppDYu-xJAEc@MFv4 zq(qGioL*0jG%7v2RAjqWq*3l}xAGJT-IVFN*Z&N_ZX7zhd@W=77aAQ60SUMQO}vLR z;jQRA)agrBxU=LsrCF#3h+>;pbK{>Db-v_3<<&VbLp3wdSKlkYGxzg?8|kbc4KohU zp^URs8M!idx9H->UnR1Wdud_d9|$5=+8+ATno`s{8F7`z1AS=*dipn?oodA8J)6I$ zMIhI_|8osZplj~P1N2>Q?cge)WeMl?1N8F(3Rvzg4dg94jrLYkMggBw0#>(?|I`VM ziK`v;a)3S6K4KTzH{7Y+zHa;wXTwKe@mz>Bk|qPWXFN;pyiGEH=_Bb3?18g<3k>p2&tz68> z9CK5yYg8Fe-rn|*qo?OUYRP+8m*n3YEsySzQhQ%5b5?!?$LqFN+isjh`g!FPEX%u~ zpl?X?O-8`H<=F3eZ9Aur4d2BL_QJS#lMgS&gIPi;QBiBP2$x6NvK!o_@A3cNHd0P| zRl}%w>(eIWa|U8{6gVjh3AJ=*=Ovar_YeI}wxE`(-K8JDboBrAq1ID|vAArQ+fxfD z4B*Ub4DrkCrV&i0na6S?EEy5y#Gl`ftNe7u&P`JIbSuZ=t_CRje;m#QPwLZYHSYUc zsje=lW-x?g{?^|n=%Os@q@0Rc{aK#uK=^%)d+=!RTJWrQG4QIa#dffGNsy67a{i+w zv)G5vppFPFgnPuRfkP}*-J$h}4dn0(_HS^u3mJ2ouLlRUH z%OeSULz}w>M*5QB0`<9GFQx;ma*#7V`zD|aQEVCSLD+D_)+V{@i2$|Rw5IS78k-xE zm_1cZ`8a(@L>L;<|Z zk+MM{)zi_k$YN~m8+X+!c`r^7j5rBe;1g`PY0zhJ44)}FZC5!Gdj-Q@UIHC07DC4_ z@&%`6c&$f!Gswx74Bm*cw#au>6Qh~#7fgo@xOjGHTi;av(qF?7&+)LWcq9dhH(o0U z5~~`KgEJGcv286%F1Of7gfFW4=6( zLv{mkOIN$`0>*C9;H~I&Ou%0s_C#Ng#tPDd5moeRg1t1#Df05SkP*(yu)+l{jx`_M zO_}s*e5J7jjDvoSlE#IuXae%ucWE%! zPr|<|uXgg0M%FwOn0)dcIv_h;(;Ox#HaCVPg5-u=FwY+rmo09+ILkesS`#7bs^JD$ zx~`ZF4JABrnnrqMu~gJ1-gn4?aDODs=Q3i7 z0JR2d$yK&!RGx8s@e$2Ns#=@m5|e%RokdAa?q@&K*&jM`(nr<*Z&(W{tJJ^-(6*uv z(AHeyZQ8o-?F{HV6daaw-n0~x3ViI|m%nOef*hhKBZL$&!M^*P`D19EgzxF01^91E z^S_Sd|7~6(XNJD8*MYj>f732wCb}#}0el(96$h=>jY- zyv1>`H2LS<3-BeM6LmvK2ztFEb6!K8yuO6pn-(eGq|~4m- zb{nq{K<$o@#Vb*DeqoT^-f;;I+BiK;kR>Y)aX}wdsC991=+hZ4PEAw_3Hsp(HB(Kw zR~-QXZqI_a<@4vWj)UK%*Tis>w_;QU9`{lk`uLnFwJFe-rxol>P|!-s9C7O0&v?O> zz85+pS2co@;%P`vJ3e@e_)+R)VHQYUGqV&x@fatBQL{+(1!Z?)|KT8%%7I5?91@wg?`~t4(zW*P$QE*HA~rh&CVP1G~-z&=d-o;BTJSpRJGdJP>PzvbyjZ161kX#Z4^ za(ax$c=dVlWezcMjUFf;X8c_Uopo{||6;i17yq#Df_xWOEiP=jjD3$$*skE+bp^&H zZXpb6Z7z?*$*r9K!9zGXX}(bG36e{%SnT_Fun_#pdVpTo?q__PFr(+s<1NRlnakoC z+J2XJ#pfn3kVd9uB5)$T*HN!}Yk2Ga)q*9(-6hp&RYi6k6_oHk$>N&CPj~7}Dya#G z^NPEFlK;ldKWm?)i+tXk*;F6Ce72qQ{|#{9 z_I_29p5CWXh&VEq&4H4tfRA^Dm@eFOULtED>29ZCn%{5iuUdihVV9g0(w0S+BD+R< z!H3`58@3EJyT}Ub?i3P*<`km9T9OV>6lQim9n_<)Y4Q zy`+eT{7OkJO=+zX@s<7p{Cp-jdz)PefQXS37fc$@XU)MlB25qqV-OsZh& zLsy;;R_KS9hZ`A;BNkT~ecl(p=+#-jYNI;FaG!$YL8n35Yr1CKr;LU}>J})3I__JU zW_anE?2nxMz+;r${uM)ZvPxi9f~4~&1+fJ0;m9$cWuMiy%E6E_MJrj`;g9rtnjTsrSZy7!l7 zHQzObcpPU_vFfhL^YYk@*T12%Fmc>;jGH26VH@svlp~oTR!L#J*&!Dd+<%VK33WZ5 zpg+<3#m<=vW`(L<7u>FtHY+W2%ahpXr7jh{_N?Lzsp99NEmcfHznXkzqwTIk7S8kJ zmNZ2S&09vvYVFlrubF!UemjB0`)i7QMqe<*Polu-rTXLd;v2oY(6@c$KNBHQe^y|U zR_r8Z^7`I1`ODg!iz!NK^{<&N-g-i{V;I|xU;1)kF1PQ2Q2 zBj<&R?z$#5RY~XgQe>H-vC2z@+TRNzir zo@Hou`0V3Jn;aK6>6&7~OB~E=)<2UUckGo)(Nt$?d7zmgTdC(&#mA(^^da|Lf8qg0 z*J!;_YMXhe>YZTKHb<4J&dDZfDMm{3hf2=^>{H$vf8|)IuqLL6MDbjDT|t{N*}d_D zPL5%?com>(#`%f z?w2??)BpXs33LEPu1#x@xyy#tt7~O9O)-9yQOjd2w7z;hK0-l(_qyHBsD#qXOhsQ? z&z#QMH0_x>yCFxI$Un(&|AKxc>hvn_n;VJzZo3JJj{?IK4Vei$noHg>QSyk#lR&Jo0H>7`=B<=VPNlCk=*W)%uCo@kbf@aF^XURD$CW=^=f?9b_=2sEO1pIa zm8Td;Yp3<}tnyvdnB#LB)%8QQk@z zEAD6lb2}%=79PN&_t!5Q-yZSg{Th|uB4FxPO$#`=pat-}k%1_MQ-bviv3@%Ybu#JOyX7(^O`_gHqmc|eeX7zA?p-Xd ztvRkWT`oV>Sa8AlQU%!;SOxa{xZTT?380CEW>B`B^+oq2rAAKKwB)g%p>=A-e zJPQz|+<%9zteki+)9j>E>7&!tY(E4E5)W&+Bqx5Ql9*B(JbF9HoQ}4mxQrNbxV&~ix+u*YSo!82~UX-ePKv{Gs%K^$r|j}WV+-s zOetF3khTX4j}8cQ*yiyFZ4>xHPozJ7<353jtDUMlOvm)kbOLpVxpa#bUCSHlN*Av@ zW4iSU{$2xmy(K3nt76ghHRrM9!6i@IqrBGee;b+(r~7^p^j=$^@9SaXJr{M1O=L0G z5K5UzQsyMeC3}y#yj~Ps7g~5zsP9%fEFsO-Kuee+x7A61mMguY#%F+Fn3wP!r(Krk zIIS~W?D`?%c@=3jRmjFU7P1dVl0LP!hx?PT?*2e4=)bu;_yy9RV7&jjbJv~dyjtHw zs!*5Fk_e+YqJII}dx%V-NW*;Xsc>TC&z^UZ@{F@f8@Xxrb=`+!8jjSK>6QQ)Y;SLvB<4|wRHV$c_5-WP3gtH|_v z`9G-GU@T3&W8%W$B%#+pgt{pY!mOYFG&~5+-X)=x$2(JxJ|A2@5aynBzCn?hww|i< zw2fTXj{1y&FflWkzk8M22}kPwqlx$nA(1{4!PQR0k({j?mBCGJqZ`BZvpw0%vnSh% zC@Jn)A3AvE@XyH5NN5xUuZ4v{Yu*Be9N6&VD1;$$ z27S>9RzVl<;$~0NDfIKSjM0cC43#VQuJk-;yvg=1ekLSYF`4kg6a*$IZ*32kb^Qp2ikQ5M>H zqeod++w5;%waaG=GqWa)GyTeaAXr1kQZf2&U`RTw&459(F?3|cor4;`xbB9&s=y!V zf>?KQ@j_u?7nZ$U=E#;(q_2t}zdU<6j7oOzXuseH<#%08Z`5kF37uyO{rAsMA=4yd zS4CnDmi2CLIkd1oikB#Glb4X7suy*q`@u`>pOhW#(u@9tGj@Gz>se^)k<93QwRf1V zSMHf|D(SZ`KSrgW@%C1j48`S?;>MsKy-e?xL<1lwoVR+}1g1h&+I&W@j9roR4Iy`_T9x4r_~X*OVU9I?Tw zmGaONt7xt?(GtNiv~(!juf}cD7f5LJxpBTRXuwv@lx%hFtB*!p?_u^hO&^CH{q2u! z#z4HjjBGk;$17NAR*%Rg94>IlvnWtg(LJIsv*5Pa`3m72JpR6C>SDvIWFZg!H@2@d z%w9*gXxqMyHow1K@!2YTWhyX-wRMBX^dVX1=q_1%j#MuF-h8{h!`4y5PA6;956C5K zkV`7_Z!I^7w|F1!>~qz>Io#u-mA61Dml0Q`RAib2Fa$&L0r=6(JR9Mnn)~hg7c~n` z7}0DuYtPOm*q8MR=$1Gzq*yQ{zs@FU(aN!HWb6+D8 z20mt#@5oGir2PAKu-J=b%g^U7#yr#Y{Nw1Y}uvUL*0Q=9i)Cf``=`l-Vm4*kgd zV-uoBBR}IGdz=3srrt6rt|nR+Cc%Tdy9IZ*1b0FR?he7-Ew~3ya0?I|g1g(`?lObB zyWGut&Ue3C#T0)is-}1EUTZzpI00`YhTbnsmqlT{)Kxbf`5M1Wxiy(LB9z-#K=E?d zy_umUIV+YRL;TYS+VX zZf-z65Z7yPyI>NmQC@IG_PQ4jaSg+Yn!KCSk!XMV06L|6&VfFU!OzXTZ6R-1-U$m! zbs9JXwbW&s5f_#}{48_eEagDzlB1sf9G9(TN7h5g<1ll8MnBGSGUsqRc90_Nh}9Pp zhEKY*hP+&3x+JF>Fdms;7ZPr-)H?5BlV+3dGGL@oOMoPfjK@Qrc#S)HH<%v}H?^E( zh}4Jd0!ir?UDxWXER36Xa0kABl3z3Eq^NDn=WsWP@Gh6LtK>g`0On`IU=L zzSQRM@WB~Az^CH#+36ZjHuXy#MMtY6H4_X_)HultEL~C5-FW&MUXqWVZ%_Ye7T7;+{c;p~T4Oj6 z*JEYnEB>2igpv&G1gxPZ_JRSi#!No;WyxgGsLktSWV^C%O}EtDBD#YVZv^zhh)&#b z{3>L28;)>HTh5VHYWc!)Hc6m2362S)eJZ<@yi=A6aHkm?1D@5< zM%%y}nMf3aK|zF3K_%57HTJ1PqXS$tpuDgN0YHa0(yt|z`_vs^f;xio{byUM2bBhZ zUUVOxIKXVVH!aPfq?A22X#0GFfvI=<8vU05?CIHNCh0(ptB9hzW1qMRvGo$CeY=y#xKg0 zv@V7E;Y8;N=W;l?a#z!73EI&{rZC_8NLKt|uSDqpgg$j{Zc}z%KYX}!g|vvx9Rg)U zvMsxuNgnK8@Lf#qkW=;Gu1VX#PF|W-{53!>T11B`Us>j2sFzHA3dPu{%r5HqnT;>a>ZG4((Ijny$->_VOn&q)Q^*X zm~+H}pUQN%Nu>MK>z25#J5b!rZ7Q7xoQP?{ew6j;tzSr>(@O|cI#Rss32_LZi*F0r zo83@$eeT~=SuYz9bsJuOdt&=OXqu$fMP3>ytIiKy+#?>X&2cBB|Gtyjng**pc}qJ6 zDDV!}N42K1wQy4i;GNZxkJd*nkyN;T1C-`Mcf{%OlL)T$qy8LIf4Q`R&%ktYxoYxo z6vmAnJ->V9$JPXIy6tcyZk2|BR(9VXpqm7~zIgddlhY6WPh%bIKSdqh=RinEj@u*Z zi3uzEfboJTyk2TX0DY20bT)H#>d7Zu4W$Pk4XFb5MVMigwIECo)1tk9-stGE9iw1K zkTj~HW>yF27^rFg1pfV;dZ_a-Q6Ut52d+m7l3b}d=X31bfco5kHc*3gIn9YQ^nuqI zI4-Ic9%T=Kc3sD$=-*%x$FR11{j35uFVWBrrv;1wdy+=R-!g7bCeA)xJi$03lXW|_ zN}mvVu(*ERCM;y6W9tlm^j>aoa;?w@!;tipbC-ZtMA;0_g0DIl=ONTUcR5!nk= zZM#saaPC4eQowL$2at19@rBpVB!LCRDGxg&qg1C>{Q=ufw)4Xa$C3TTch{8!50C4& zGZ;D%WxBF1+rwL826|r&lo$2AA%c6KqvhHn|>sEgS*)gSuKubB^r2%3U z5a3j^(e0-Y#_jI^awX~&Q>4jE1!vIQ!BN5I!Xz*)z?Uyz8;Wr?0*b`D64 z8oXWruhBqFnYzIMiM#GAOv}HAmnc1(y}+x$Hp0lG744l!cv|ItKo(Vs_{V?5vh0)L zGD=JC`TA?_{j{?8)i36Z{(cFkc9KfjyJPn|V=y(L$Wt*MWn#O-a;f}1fP{aYUTF(K z;f1YPz#q(=OAVZlh$ltbbT#Jke1g%_|3NBR@8}>{j`dmvO1C6C_UP?@>l>T0%zxDd zQrt-OFPAQYSg2A%P1DKsebPZCbrxE!Np zSUGFyV;3WVOk=E@QLUT6uUsZ?HkDL(WuZ`$#onX2f6Kn-2pG%Hu9Xk!wAze~Bf?={ zy@fG^xF9sa=|Y6ROj(s__jOX#tm7iKRLMxkFx^SX1oE{uqQRV;KLn;Cj3zf?*~!5) ztOtL(3aW=pF*sSeJp_f!-DBv74cE%Vy|*+0{vnO4S2*M?n(pnBSr6Fekco@4R!N-n z^mhNuaYSxxfI9!gg}E45o*RG9N|Qf>#D&k#ns~R}(J51&w*H2pRa~hs(XLlq5_y~u zdW|8C;eP7Fq-0dzAY#vxjyog~A%5MP?47HmT3Tpa9bn(yE_<5Ox+_wkU^DvwU=91p z{4Z0S!~+hqfLI5-%u8Tm>m^dk5rwbUQmDr45}i8J-NO}3%E887XJR~O~S3@Ra*1?_+P}_amaRg?$Er9 zI2RE}mTvvVL@1`94_e{-V0WI`_ptqL_LhD)(&sh5Bhlt(il_fjUbvb>Pawn(a5+%} zi3V>`F+_Haflp8M{zo>ndgT zBp(N-*O-0efLqX|b)q}um&`9qNlD{C5t@DazhxzXG>6SEg8e_#4;k=5JKIK&Z^(C5 zD9V3*XX_mp1Dq071(IKJ!w3&aTt@ogI`cT?X|^YFJSWat%>ba{RbyMz9OFW(AL13U zM(-^9n%hA*nq!y zY_(e+-}HTN>b9YQ>+9<`zu~;esudtIX?~tpDiG}6-sbW@Gg{vAK{`((EFtp=@A~II zUk<|ww6?UwO33%znHHa3{;Cq(U1nE5Oo75Hb>&o1+y>GP2 zUiQbs{a)@-NmzkVfR>aF_y_G%Q>2k!y@p#r%?_%?NGaRMg+eXAJ}b@^NC$CwzAsZ8 zAJF8v3{$Xj_m(DG&FmH)fiM#Knf?+@bIvJ!i28~S^KeGv8+UM+5WLRIrc$oJUg%| zpBr|41!H0~1EJKt1PT-RSKaJbdQO^%Qs+Sv0D*vmrwfIGVoTJltLZ0d^?0;;7-0wc zew)7|Gz84VpM9hgt}K(zin6E9I(E;V_rO_5U)_E|@KZG0J7U|+GTgB2Ocsw*6b>!D zrPcqx7M7kfh=N~qC9ezSV@-)86H;YFy;pk#l$kkOe%S{l*HH^c8_kx8>lEh|9WpY? z#>HtClRR%49CIk6R+5`x=(`o%X*%RB_^>$BsSTw$SwI?~mxg(jxd2E$iz_M$8yg!t z#N#u=9Wz8q*V_am%Ji21xSiKoYds#8;@=$_xO-0W0id`$c>uQ)^(Kux+oa`kmP=~X z6A~-X>Ay$+#TEZ~UccvI{q>#2bm3^<46{Q^_4L$P4C!dVsb7O~$8CQ09i9P+lO<&q z$rsn#)dDiN1vl1aI$=i429?`X8W; z?5M&1{ZjXeT>rhq$NCaPNRQdb4*!A9_-)nyh4pGyYM=F%y<#8dA9trZsl8$Czzg_1 z35p|)0!PX2T4$;DirbA5eQDMJkCpx=S|%hS0-U|_BKm+w4~S(z1O&W*uTn`e<{(<>u`&Ch}JxWefS` zS0zmEKTq-f#*x}#FPQzewl5(g&Ox_~C zE{8qms7hSgE8lG-0^UK=yy$9%GmJkeSEg-O0vri#7rQMl1LEiTf9Zk%c7&=Q_dI4O zsM*){t@Kq#FZKsZ?Q;UbKZI|YsQ`-%1Um!g`CEz^5E>W&1UbQ>5cUGfW01Z7qfTUG zvwr)Z_Vz5mN`G*00Jt>{hR$gELU38l?|H|AJz7`$elr=K1-(*Rulqg<)arF7Ksw%m zQr)e|G>j<3?K{flqxylrE(GSui1|4~JZxh^!tnWd2u%7pGLh6IO{&W;hoYt8hzC4_ zJaB49aAD!GNN8rN^iU6)6^obXfBgFSeP#2Eo2f1A+w7#ZX>J?QX0!*cPaYiu0@YC#xgZpBp*YmhVYFDC??t#wEZMBK05q;z zJyD*jRFT59;NJ}L4($9UvG6fpySohdxizmjBJ@i%zi4#AfdBwn}k2nsuxg6dj3|@Rn){k1DS}IyLinh89Mz&OC@N)6!wqd-_I+}@GHx3 z+J@}LV@fJQQwLR?>oqQ?aw)jx(sKl*v{A^jZzZbctX6H2Qcd z&b0(c%etW^Sv$a`;%H`ftL{anZTmE*Lh_?={<2E8(cLLAj6BufUxTbh&N?>N zT2W!~KEclWE(k}D$1Li;x0#~?su$? zaYzm-r*4VKvx8L+a)sqD0T)N$W5Sd6I@?i|N{Uh<*AZr+-s%W@rAr+RFV?!bO)5Do zzb6SttO4mHxkUN+x(I+pZ*m-EOHt>pp06U7gDb#_?!C8BB*EeS%#zNd4QPD^?En~h z&@Sg-w_{J;yT}X68t7LkH1v|c%048xXZ`V;8y~W=>qyd)vJFoz%81-P|0!Zi=!xe? zmI}GDq_iduYsS;h*~twHuh2#bU=&504|unn$`;zg^|VVs_;QKdsJn4)xX9zCgbK~l zk+FiMY>DGuavf?PHvy&*^g{>9jr64Yo!>o{wyf|769T|5LJJlW{(~{b`)am*T9xZg zC`~rD)(GNK3_4>I8zjim#pU-&1t@>*;A)goKt-@xKD#0~y-0lBL{iqcme*TCJ^nps zg`gKp{;Zcq9$B2|F%pj+|A10Z`#Eq>W`xXJWYebt^>GINX+^p&FfDoKxbaAt`cXz z0Chro=SUbwS47bZ1l>K|kN`|`iyp!Gkk;C zSO3g!Gr5I`UcCwc#X{%!J%{r~zy=~WZgMaJb`spIeXlJTomT>y1)MdvzRt%}59%U| z`$>v&vv&=g`MMAhJGW3=SvLPnxtiowp$0<+Os1b?msHs!S2<x}^ ziUqrL7wBL}X<0jNqW4G+diky6^obavV4R~?f@pWlMfRP#OxUR)A0ZV)IIWZZ~x z^OYL5l$hh*Dj_&!J}Iuz7)J9d;-G5gsg=(^Mn&332!@xgp4M7h-(Z7;o^{{!unyM$ zMil(d^}61a@eYsS2^QRjSagvgUFONEgXGp!R_fti?`?c9DWb?z%sz6}l@8{!tzx#OX;BYEmXm6aY*8oTh(cX4SV00if1r>B@b@jCVmAXGi;U6RT_YtrY zUq5M&L4DVyj%;v`x7vNh{Q^X92d&51&wS)4B9pff$Ca|2fk zv^t63zUK~o%6?8Nh}x>3BacF~~DCJy-SmUcrwl zCLBZ6goA|<=B=jMij4qIG5QV}`j{}f+R-93rfYia5gs0en8A4HMvf^^s{{V`diP;mMis z<#GL3D6lJ5Flp@;EkiRply@!Xe)YE4|Aar|_+#IkoRHGAj{WrAPI{xWvwO4J3X#4a zY=+&6(SBzqqra?Sf*0oFat|J9Z?(T?W+ekwz74R5Kz+Ni{7I`E0LXmsK}r?ib{-R` z7Y~?ad=7=5jb;Fr$&@J5srRY(re-p6v}yv*W?9xplR2u`5vy04vt6V`1St%V;tl=D zRYR<&eGdpK-lPKy`VuGv-_jM}w7It?KM`UOFSLHiP$W)=!|IF?hx;tlJ47ji&5Mdl z(dwZ<44>}8I6|%d(+<`VVu&okjD{QP!Wdk4WM-+0HtkV0C|`xFUQNJBvZ>7 zyu_LZ^uqTnH>6Y~L17YmS;Qtz^8$s7U8g4cmqleqmIv3=52UVzZHKYU%<@lk=nK`D zhAepPjwbJ_R_$uygc8bn(C7fNFJ@e{qsMtx(UzIWuAM-`92f9ax&twC<}Uj1!Z`Q? zMm^;XCwGCm6?Wwm);nyy#*FEWvU=o^KcAlXUSAxL7)-r^%2G-GuT+3 zBqEGejV=c3(*PU{nK3*jCC)H_tlnR-@#9Y&^AsXq^^#Ozhui(!n3lsJ8ggE{k$e=)Xiue3%+EVB|how@c zL+^)Ry+CbgPQXi0Tk04*r2$2~1p5p+4CUVfwCfssHgn>7#U>=BvuS2zbwXmV>f z^5j!*MylHnenSRhkwT1TnEaCMD?P&5W1_6amU3m6Xoy@4QX)1Gl2b4E-Tj4x#Uxyig+U0m>=GqsC=sq+QH?zPjcWT| za&m1ADj*{E_8MlV_J5Fw(T2nLJVLhVr#kFC*j9)>*r__=U?-k%aBXd+P zSMfi}x-76UrGal=pjzS0{OBF${9L_ z2T>kf0JvC-micJcg}TWiMKokU;$mO!RpS3D{xo99WKe?2V~7tQ&_ywTf_qWs)!OSo z=M92r1^~Q<7f5H`+JMrZYBE${106pwgg1yN-nfPgUp z`oE(crsaNKW0-afst3U&mh`(s>j?b|q~Vj6%t7Bc!+Gva@S&(*i<(kJ80@-Flq-OH z(E&cD$M2-;#a8Af1N*|K?N>xu8<*Q9SwW ze>6n?GDG;ymEnLf+1%#P9VFP+{{Jc%-#PuYK=UTR5CW(#m~$*P3b|uBLWO|OHq@hX zSHXe?9USGjr3%zrN*AvYyNVY(xhM<05$U~Dc&L2oj1nGGovCfY>pXyU+wt%De0sPH zucwb+|LfU@yG`I+qqv*ZC=)ug0fd3PY$nCNPX?x$E|~kOMehOgF)^@8FnGS9nem@} z;IUkwC^0e=(;awhDVsf2#XXG&tw()t>3B>nuoj$^FUGPXDyz^HD0l=j{we%;0=d?DHL)Jj87)LItUao zxpf1Hl0M^e%u68x$(5~TkyufFAS0*%?a^tB;#aZR5XmwlkSzdw@e$M%oU-ePNG&Z=sFSpUsxd343JOl!Ns*Y95w z(Cof$c6^WL(w3oXAKq8|a9Ccj>Wv26eDI(0lH#fluh-p$=JuqxlK1F@%w)=d_YKg6%^|#TCL2U@M!&9yzcxJFX}`k$83Okq1KJQE_W%@ywRH)bN8?E z+}X~7vgL(Y`p+91cp^rnG*Co&;YAfLlx7@j8}=gh-9*une<7gANy8AC=1IZ z1Vq6KrU?!Eh}&2Ad&M#smXvLg3~TL+f<@1&C@&2la}@T(G9*{AAvSKj>qh?5Z(6rl z6zC#kE}W9=L1usIlGZ!n;joGRUbo9@h35+w>J1+wJ3Qd<-jf|C%7ujhWG)6U@0q41 z_;$WCWq!$EZGW{LSw>nCTG#NcoSZEM=-UY3jBaASJ0I|MxpC_??wu>ATAPt*t%xlI zLR0NZC*d4(PD(3_9|wHzZWn^UhZVG0#z(fAI^e6RW;28f;ejyV(3y_u# zieOGdXvYRJjs4GMWF9c1tm`oiP88});Ski$oWIBdPmhgZ3dix6k>N70Z&vdbVo*K7 zYn*iP>mC(@-<`OExJfq6jw}nFk_kA@1;Y1Dm@4XP&c9fGYC@P2NnGymk|pGtIE9Pbf^wr>9P z*H{fwLTWpoZRhPu@9(wAII?5^D`E>P4*UF}SL(xIUc{CVt}-^lzs|L%n1905Cof!@ z63$qqO=Q?Q-B^p#Rlt}DAg!9)H=AzYh5oK;TQD4DeVDcZEkHnqH?6?fvIeDNxy~&! z2ByeECmwB^PL0SdqgONe^cxxhl+JtF=rH{2f<$|cqd~x4oEmv(P<|EV4v);5=sg`s;RkIOP_)#C4XFTK99x^OkS0aVrbHBjEVwE z9T1fQ(XpR=%6`2XZSwx9s@k)3STW#IbMOQlyl?qeD%vU>{PvrXF1~A?8o(GZ#J`=C zr1!U7_`dzgmiIua3R`1TKbnGv)dU1(4U9WIS9F7?4h6-VhW0e@P>EGQAWG+puv zTSPALzip^wD!S?!3Iko%$e%&9Yg1^pG`MC+=#=JtgH(g;JDjL>qJ4#jyyM!qag6mP zRs_BJ-^+WXgUR(d5Wq{iw6+8G$h4t%tj=(bi%}>FdY1^0vTakHn71Dc>NiG{6H9@> z#Nhc|W!u9FYBq56KD_1hnWh3s9f6-A{TNzJm_^kXg2I`W&YY$GTu4ArLbCHx2rNv0 zY?syd!i&Ontfwt3gfQ=I-8SZ@{i5LEVT5Rc>66QtNh#no4Xmv_bhauc3%0mu;S{S<5mU_`uPSmt7Q*mzbSYX4m<|A% ztr5ch;fE{JFsl(jjO!bh%jKA1Qm32eH4gQ%Q6I2TVnUp=yur+I9I)HA-k)JkuXntIk0$GHiWlP@QZl7@I+8GTy? z@?qxP?lQ1Q6>K4s!C-Efd{Q4RvjVjNhdiFfvR+<()Ls-)gXo6@mo*No#79;Tfr6(S zJD{f__-BP9UHK9);=u`9tu0412aXFpA25-y;pN|?m6|Ef7b_4a@L%apUn(1P(Oj5i_V*_nUt_ynq# z-dr!=0E6-mVEp>XW`+6YYN_a^ba0&-m>tyy18#9ACH|0&qHK)H@~-4`X_wVzlIVJW zNs*UdI2M_TedGS09VYYC$5B9p{ewsG-*_~Pwd4E?b3X=|nQ%mSyOp6~kiWM67Mz{9 z!L2uQ9>4NNXk3bAgFXTw-m$$a4AM`UK}^{#X(EMXnrq)8ZAqoV6L#)KbL z0;QLDWuM*0ySIt)(ln#|0Y2JH6>xrpZr(TERN*JI$4|PJ(xa*+8vU4oeV=58R>-Ca z;x}mT3}12;!V!%oa$R9?J?J zU-kF4H;^3g+}11)i=0ce(){_h>L@sR+KQACvV9BWXf--HRXzDpf>I$fGcNlc?L&#x zzWQvTgEeN2NKpu>$wrhIfTz2+wAA}P(ko6?L%N4^eBuloh5fW{wgm*n04bC~nF)`by7uxmJXB!6FePP!HBP@8ky50t&uOStfT{i ze1H_Mnwq6KdmLGuen-t)aMX<6Iac^US3Tkr7!O-1^9Lhi>FVa(GAN=?(|vX}xI^F%mwIv^#zql`Re#d@cH*o;y$d?`7zn*&(x}KiFxGcRFUR}qu&EM6) z+HS_o9c&qh`G`+XU*&GILv0t20UJ}YaAcxXmW0)xT(^^HVAzqmEB*7!kZn?YuBJF+ zzcFm`qH!qAk2vV%>@l+j-d8@>QB$oWvfq*lINyLEMEU!yOWfQq(Gl~a%05Ium{D2z zf>3rVW+fKIDo!E$^f-JE-PyOfTw5T@L6c8++b z37fZE)hx`VyLDRu{Iti)maclpY_eQaK=dg~ZQ%2qF;9F%90H&pRMG8qG=gltr5B>JrpzCY5qDF0UNF2)~G)f!fnTE9api9^3N*%g2|Val>1kMg~0 z5vHDgEFdL)GLZt_HNY+L%Y%6NSm|agy|Ci;$8}M;_kH~s=%`Qr@9T@1kk6*k(d99S zAX_x6+S6oN`O{^t)qIwrWkv&+EqLLe^2vG#5yCC#^mgW9$534fdn| zo9GyQ48CpQzYQ>Yy38B{b=mS~3keez3}G1pHPoDlm$IHIeJ4^tGq%fd`7RtFAPr55 z>rl2u!in&)qdEUHrId`=96;lI^R&KqpXExC3Ux}e7EvwdfYX{SzyO-QI@)X$+H~jnVFB>KeHz=Eiy1_)tf#FWydicA0_=W>%SB}ee_#z zZ_n#(QlO1s(u-{HB~te%VsoFQTzT+%AoWHrka&E-Fu^X8zW1i46e)W+7k;Asy}QoR z8j7RFD205p|d;pRKDYr`@uoyt;+rt zwUjv@_S3v1-C4w?y2HI<+{Iw5QY*C3Aa?ihr$J(E$;l9g$n*STn)XUtZA!TcCNV1w zxPkNY5J~m#UVnNKbC}AlvdpUK_7e)?zB(1OQgcj2ItWgLq;>7xz8D-B-0eEVT>AG8 zq7gP}ebn{wVbcCab14CTT5l(wHw2!l0Ldg2O1VtuG2&MQz|xag;o;|9&YR@8r4- z`pr>nJ$NS3!^u@)Nz54{=ml_YURfXtVtCE9_iBWHrtjhEkWc|ihM(KKjYQWNiE@%vqR>cKQM^ekNBQU)IBa0vd4`z zQ`7irxm14YgIPkU`jAk9ZEEu4dO#W>I3y%22#w*L8$$*@K7>zHr4o!>mxVW|xNz4P zAT}W%tydCCW6b&$hR=gf3?nx{G5~64-z`l7XZczexaS-Shf=a_L0qck>Wf&$dsGpY z5Tj5B$@$oS%0C-46M%cB>RV7fDZ(vB6MhUVxrE}t+K)U34UWtw+J_NIvVZ>Qnq}W zy7S<>rLVv%2VN;}A~G`jqL29v)ASv|a?GKdilv~1LVQL13TA84y&I9dB-SX7noIe| zKQ-(jGFC^e)VRqDc##t3m}tPRsiWb2RLx==lG+OPuf4Tf|p-tTIZU>%<>{+ z%-$7!rJ5!c{BU`1q1d^jMVj0m0wp&%{h7W^B3_AzL9j#gkDpC9q&1~M%YO%^IukYz z1uq*jUJ}|dejpD`7GDny(cfKF43^m?H-gV^779uSp)H%fw-Va`Jrb`9%Ec{{b{fv}q6@yVMQR;(-YYDRgCK=Sn| zdAo7DDWdkc_I>v~f(3YAhLTNhIr16@3?vXPY2)kj$RjXys6JL(@7?W>@3lRiusIuj zD!whMN2@pdXZzzOR)tOzc^VWOi#%R;MY)1%TEHEhaVwoJKLp-@7)>80qm-hNMWJ|M z5Iu)5VKOI8Ntf?!xkh*w=cJmc(+k$+Ef1+4KAP6`@RXp(^VAyr08XL4nU+dSL634* zGWlLo^C%^z_ce{ZkJ~lk0ekK)^9W2_%^jb0e=w2aVh9N_HM{(1`*w4x<(#n+62kb7V0&+;)glJs!mb75A*> zHcq%Db~4B)2HjUZlDlUX?%Dw}}3f9e8Cb{M8pWI33A) zOpU`vg*IIlv$+ypra63)9K1E~7me%_RoJiA*?-dWXWECP>Nsh|C*M|dKA_k|;|>p6 zMhuU!mW+{zIllNkx_|qbr)&CgV?r7chcZagL#fzLg=OL+%!j~LGWlCa8I1f4WNu1H z*fy6vYVYF0B&Oto_#l#*sQk(5#T|i}2a)$@=pWy?y{6-+rX?j6{3-ZGZ>&Ad0AocT zHJDAtp@x2UHuKtb#64|~-C#lTw0Xex?8i|cxDjE{S!!Ojp9!=o3Yb(AC~!T|l+8{w zQTF$%zsl$Gtmn`Ltx$%LSPOP<1P5(3$?$JF}XwwPvX ziE@Km$?QS6Uq^A{mtYtU6Rklx!XY?Ftkr>pRZ(eB@d#paD-Sf9+}uXO^=7II?ZVjq zIK!K9CHvf8WKKvf;ZW|oZy&r`g%yi!V#yN`M<03YsIQAeL!QCeuRd2;arxd4hsJ+a z@MQ5QUA%5T6p;D+tU+SsWAMr)Q@k=o!p26xfj$1h(xRz|g(1WtflyV2AQP^Cu$TYU z^^6z^y|@d(lhx5}Z;74exT?5$UAlx-D&Hh%M0t>2KgXjSM+&0jLW3j$Pe6I6xm7Fv z7wVxUC9L}DtTNC%0Qyyme#7XW*7zM)5ivAyqM*_KJE8L26*d9?drk!NvjBO~BRXXi!=0u|QAhGGvC@cv z5;G<#n^^{^VFPbO-#8Ju+}w8-UGH0ky}QG&KJxDMu_ec>*}(p7d69WIr~7q#U8(9d zJmj+OMYNVh`*cF;!b6lofXuh`DAF`QMt6G$>2b$~5r-@88Hh*FmyeQl&JF|=&bxn+ z)QWvjwyRwm^#e(7%*s48T^3jvFGv|@R99$+Jz`v0=^~GN2NP+!r@h!4U@U4rvl3ow z_T(Kvg+#=;$6Ffxw#?Jgz~~astNM}@#WneoVwvz|5G~0Ka(tc1hY7YHjXg+?OJ}m24b88wb?2~Rl z-IXx>uK>g&(Es*c^Bh@qSo?Jtay+u8cw63}VrkiFZ!0N9DRFx!p9QFI_Mhj4!z41$ zavp@rzTzEQ|Hyz>e?7i1opGT4p{FCCTa97i##~3%VqTS^(+k-nC%@bf-{Q5UeBR41 zE-XYm_QPaaO7JAn+aYOfvUYS=9YFMkn|i9VQ36q+$L_EIUw!;;}AFZ_c>S^93vct;;tS zxx4=gHmcdd9QJYJCDJ5i8Rp6aF0?Qe@KLwlB~ts=l@q^xV`LdIMfKp763#LU+EWg5 zmn&TVSm8=_r|KfYNcQ4MQY#E!Eys5vv~c~AOBAt%G>{xE1!?I1i?a|@2ULP{j3F=Z z8W8^X8ek~9Y|Fj1kLFT5wX99*kv9e_(IPW{H=*6{aC5jAcBv@m_Kth|yD!fK1>mgr zLXzMmewqxB@ZL3KgC@`OiT0mnD|37?3*}XVp?X*SX;ssDBb$rc+k>L6EI5jF$KF?Of;Jl+nUSkK0gh*sKoe}(dr!)quN(4%|8%)7 zP!E+vwmQ<2^Bl7i1xY=L>-Ri?-qK~{!KZ)!$Bx;wpCB50H0;P=n_rLc*dnYColR0*$x%av_)>Pq0Wfl~Gsz zXEJURLaksLf94O)dB&8oeWMWG)|Rflfdew%c3$j~OC{8h{aTJm;vh!^r?acd?hdkc zzb)5?r5sNZp-Y_!%(EVjw2MB6AvB|tA?bQejSuzDB!2h(4qv-tyIM|yN(h!N*MJc< z;%!9TEHe`|<4^LHtMMT%>oDXBhPo5|H9=@hbV6$S8Nr%)QFK zMk>CY$CgP;x9wqXpPVl_z`e%wM{6Ms4X^|;dA@N^g^JkqJOR6bb3v4*waeQ(EcU$ynL*54?IO*h)bk8|8KoAO z?mTJ15lk$3Dg%|X#u|1-Ywv`LuY=l{NTWXM`Tc0&Rx!s2dF5;^;-9N+J41pyp+P}Q zY7SFGs2%7iJ_|RjgGV6=i_dwECC(m^5@_^D6QAbQ?pyjo6rXNej;f80OSTd$jTCvf&)2L2xA>9S2i1Pf6ynq^5!JG+_J(V@zc|8}uTd&%*#;#cp1*zg_iJdO^ z7@!#}%Szo+#Vgxth&u%j?T(p!9v@{o<~5#ngJB$0m4~+?>BHiI2Dg5_qC{NSlWJtd zFe|d&{69>6Wl&wwvNZ1Q!Cit&a1QQH5`sIy0>Ry#AO|P7yGwAF;GW=4aMy$LHuv54 z)%Sxcs(>oi-e=A9bob1lMpt@95GrV|=o-0#xcza9a@+<_mSAE0O=pQeaGn zTxPzQEAZ(Te(YNPSuI8{a)3AH&^z}>ZMi)Dv0a{6~y#2_040yO`|P0KF{@ino?wUsN-KKQJ>uy zmE(?Ni>J=Ob2=Y<0%1IN?%6vusAh+M-2Uf4Q&p@K2DefZIDtCn)<@xTYt6#OCysaXrdoM@(SU=3G^9hiXrkYhU|b4=$g$ zp#{-&GOw9XFY!s14F6SHDfYpu)1kdXr|1Y~{y_-KqXn!I^9xos4t_Axc~d*Cr)%^v zo@in~MQ{wO{o^B53d-tL^&Ls#c;=GBdwi9;e>y;qjF&}saayq}P(f|R{)e97w;r-x z8LGlGj24YQ7g@Oj`F_L|SH+xZ>~R?eJrF(IR1a!5V}1YLwLv=5=2K&^3^{1I(Yyp` zG@xU5guT;Jf#!gQ^Jw)DNmQs1KaYdu?gOV78 zG+iBkey2Yy`iyZzAkxpsFpfV*<}KvTx_m>b`9o&SW_^ToF<^BaWXl50 zdi$s^ksN-GT~G^yx|mY~pOX-c?6 zw$uFL>L{h9o){(^YB59@Q5$1vykTjdKDKv#M8@=Em#x!e%h>g*!4n7zu9%F~UA(K9 zd?T&_e~EwW6#K&eVj$IP^=c$p;sbXXP{ArrAZ$u(ix{Iezl#WM6Ge=i47@KUy=%}o zKi02#ajV&cpgnebrEichcguG(3?4M(;vM_K`M#c>bIVTzDSi)$KZKn>St0l;h8LO5 z>Z>2r!*TMTf;Yy!K?BeA*l5xMB*fi+4<+ueQjA;xSBbo|Wckw1aGnN{;B7mjci)Kd zvZOfo&U*SC4P;|H*R!v4UhCY2)IO9QJ|#y!CtmA8Duw$G_mi?bZs{s<q!KoNXOx*Sh;tuLrf-Ik{DB9+g#Q9nZT&&jbBWGajTZT(|{z@69y zs0`+hI6;q-PK#qAPsFMw;Q7e$fCvP>xh}w%yQr7JOuTpIQgxmxC@;m=XCWAe(?Y`2 zjAIvvg@)0ElU%Anru6^DP*tfHC^j!reC)yWD7#iBOU7)@p}ZHA5LY zZ23r0?z7Gx+s4$t$aL`IdME1o2XT6TWE-}+*Y*(6yn&foP^-)8tIOD0;nR74eWCQx zYhEB~uZ|_6%nw#&jN8~+{haoWh=I14UNSBn=HVAb|ikDtrm7FX=mo@j&iQNxJT9nqj17zizWhIkOTXrZu3z z+^1xA(@wkoIwW-0%O}_({4BX7Ev6~=9$H5!P!5(^M9o0blfY(O->;!aq^dcV_i!0MM;sbo;bJg`wx$XdOR+k%+;Q*NP{cH_ zu)pbx>G1Lwa_rGc<))-09dA{)|E#REDx>b`cP3|o)83MjHkMewSFY;A97*`*NVcTN z`V_*^hPvf3)JDKw3k#YSh~cL&+7Ebq#h^gg1~aXq`Q34lzAF5D6<&DeZxBKC#W=QH zQ1q_Qx#UOqs#4x;7~ZInC?8F9~%IOKY^qd2XpOppa01o@AHY?u%va{k5(r zX+0Tma5}Eq1D-%%&X1PzRMnak{Zt?upX(;}jofT7VhpzZXzgO26Q~qIX_^o60Rdp{ z?bR&1btz6#yz+Ao05=D!MUN;6BXH|6FtSEDRmDQ?^@!Z_?B!7$lg@jxilNC^ge$eb zvRslr;Y}4dX`4@2Z%@@e^AiPPTeuvY9wY~hjOYPN7LhaP)WtXE{!Q0$n56pO=8%=y zCjkNcVtHCC26=J@y)gfdPjz1sasK}BT$K-zyNWW9C}(4!_T~wM8g{B005dBrkUGdA z{D99=K&|UX-pFYBb8u$=->$Y z>$7}+enqD8GrQo|M!W`wf(^?c`~gPMF6OEIhD8@F6Lb@U!ookn<6pMIR8taDdQ6r- zX%_V9?z_yGL|NEHj51IbHWwAb5?p_os?FcGf6f7R^3Wx{weHv;h8ppEsUT|JCQL>)su8&W_o`eE{ zBnF_TT8;DW=={hl=ov4{+0HYEop}2^N^R|aaaL0-3l37_|BYyJiD$Ey#3cmq$_R_JcDBH()KYH*N&Z{b$; zo!4DSrjwXU?zjtpTBh2yDs!sUpj;Ck=H?IfOe*P&KX&Kd0tG zKAsBPNB_$|+Lcb|vix5CcKoUMmDd+LL$YwcP&x&d5_`Xg_;w&mHe!ySQNg7fXEI+_ z;Z!aWi+(EX=BSW5GEAAAaKIj2=(>Wmbwy$`eh?p8BAnxa367uh+==u{)!p?yv&X#6 zWTEF`DQzB`JYfN@q!yb*RBTCew$}Fs+s0N5+vE>pXSO9-^WCcP=6z3ld@UG;l`MOT zpYgpbUm;(ZM;HGI_JNBbkH(||rR`IAtjp-7MI5cHtl^0gHy2a$*mGrPezxwreD;$r zrY9c3raM$={tT~fE1w739LWjdUWOpO!x0m<#$N--P|?qR(6t%1)dLdbLDPV(*X+RK zOETA(8KWUmy(*C@%`D=o5kC$m)9ITS$)Ta&5bL<$h#eW{yHB;$1@Uo~9dyRLpW^xy zWupv`ol|#>O}GLVQW@IyQ&IZlDUeX#k8zRVLYwXeuPC8XJp` z3rk|gdn)n3^n@76t76e;6$=@>!-1kULgrmr#V%Hl14W0U!yhY=#zpncCe;>rXhT)@|V=nm`nhWXIiu(o)u%wHP=Z}-aaWE&uLvq6>5&YGPkPxN| zeEHUbf;mWpm9i!huZ&(ASvqr@rq1N9nEfh&xR{V6;=YT_tpUiVUoNCcpSYi{ z18bg%1-}{dVVgWkw_k~1{rj=Z+hNEMDPSWp|IFZrTx-4123z+`&N34M5w@h>0}7cR z|B;h*)H_vys$*E>hG%g+T|E`eea%SU`M4ifPV|=OK=c*<@9al!&%0?kHrdmZ3PENpq3cUO z6pG)1>Y=Ki48*)I-EoxI&V(N*;A)s7ChjI{pP0Xg>Dkjl-^Ihld7Y z6(Dk{Eig2~(qa(*Wgik@p*At%Qo0^>oqCqg*I~27FKUuiketr64s0n7F8vKVrVYF2 z!^wkgEx|DNB7ln6b zNsoQQ_MYSM!};HTr!9!>95X>!SdrNJt$6AmCD-%8Q#X-@QSZ^vpW&dzWf4oeUZVdP zz7Th2OKKb}hjf=#7hmJ=1#aimX;)xt{Qk@v86|a|mVWTCQ$2KcSdHvL8f>0hznG`7 zR!oiWBF4XfN?NP)y5Z7(pUt7rwEWYqOZQ z=MV^Zd_~e7lLj>d$w@~pYQmZmY~Tc_>_5;xbX7ycphk=3{-VUnEtvPG>$UaPW09b$ ztcgpGRtu@2XpD_5K_9R#L*DvZvwMSxk}F`d@rzGvP}6c1Nr#3SIn9l4=HmRdmJ&jW z%!R}wfNhc45t`W=Z~ZE+a{?QU1!1RS|M){@@N4>!+7ZRVq(0QIPSv2JbFh1&kOFSL z>|&c2f;2E!6$!JdSJs!@6A~(8S$k=`2+Jc1@As&>zlz&Q=!ysPE^Q<_1RpuSjhQ{P z%O^Rn|0Izc-iHandazLBg*GUGe~Plo5xK%0;LYkUz%B=sH0&vkhV*aVg7;WDss)sn z3%k4N-*;ye*>{qvz3D_mM1*e_OrQ2;MYoi{d*VW|va*h43Z)n!L`HmiFU^%&P+S}a ztZ6(TkJ%(Dym!jZe(dmXnZqs-aUUZ^2d!Z<1u?9(PRy==UmEQM1@JK_EA^Y@PHSV$nB5_@NL zb60L=mRc|=7q4cn>$B+oa+4Pqo_y0CAO~3 zOSKid2h+WdxqwR+pUHAF)WQM(*rkuoH!rP3AERtQjr|+~^To{-Y$@a1?II;7#}>R; zo?9(4M$Qj$I!{pzk#X!8H%{lV3h7-V>H9P7*!Smlre&%z!lViXx5bWB#V^W7%V;q_ zy(9WBqK`148&S*Ov>py=B3q6t4j3Pp4DZX~_UDuDd%&((QK+t$o9dS1y3xD2rp^Ii z_n;lX>Z`$R|8VLHCQ`*BtnYw(K=M7<{lepi1Azrr+Gf_%tD}9-yB~0r7 zI!>jj9|=U#aj!L7sRzz*jWpX6t1KJ&k8>RX9zx&qz4o}jeYQF+x!#ZEU1B%?pv<^A zYb`|kxm&1phUKPr-#t-SXMtzJ7ap8_Enq#0+um%3c`Lat&i4eHsR&JMI~X?&M?Dnc z(*6P9Dz!gjPId`LQBp{u)M})Wk-d9bRpmN6_>K$l!W#BCwzAplaKzQ6j>B%k?T%<6 z6webTG6@uoo>&UBv%TEP3 z96Lp6Zp0~!TKiixj1RpHNrdm57Oo?GCM!Gf*dE^VPxpzk^(C4%^o;ctG^_fv>NeVM zh7e+aUi@CqUe({a5q{ZR2!rR_cR$SX3kDhQ0+CN9LzQZvARg>eFIdw7SAb#f*ug=| z{TW?b6>5uPV$ZtUjn?|Ydqo?S>6=Z?W8-p(e&@=cdo)(-cd|JbOF0B-GLv&m;7; zU&?jr>boYqp-{E7&hMmTiB1gmA6YJhd0W}&Xru;pzojn*s79LOlI&zeTPYujMZZja z4z;$vZ3}g8v5z1_KFWd!V=S^UR-%WbrJ%2~i|EWHgyu}KuMJvoeMy&(aN;~CCpBxF zi+II6G$i-LS8}Gdm>|CECtr9*dU{#id`!zAEc%u5iDIRh{>K~f09d1pj|_V#s7Oqn zl{Y6*tNp+Dot(!^8u25%U4+D>r0JQN-mQU1#FR{zIY1rX%ha>)fj?gB@FJGA;2871 z^*!^N6$#D{lmtZT$*II^*s)~{Dq9jT3YtO|;yK#j(;=G(*MsxiBj5uE2;WKT0jH ze56mB0MWy;wvOzEY{SA-cbiP^rriqrss3|kAud!!*-~(_W*ZzhnEHc`tx{5{Y+=dP zw7ARPcQ^_>Rg^-0_SM1aQH5a?P7^qh zO{{-&ze~$TQO4j~C08km8l>S1?uwSL{%p>fuT)5<(6iyI2 zZ4N?ZYc@&)BwW&WX1;Et&X}9wrj~*GFQb@WR*sjF&X z9zn*88gc}5gdvz^U;3EN{6qbMRhC^zliShCz$Ad?^QnZwTK3pm)iQ6lACYh|Mv;=` z5H@8XQ+w@O)0s`=?xS($UF`ntkHEpCRgo0~9KnXBTh!Cf_b`M-+@yx*z>_pLHFHnY zhwad)>2uXGIRAMTP5D#yXY{N;63S+S^zf$|pjCHkAy_^C5Km(>>+ZwjPcUq5u#y=&lFz zvKtmN>TYG!;FjyOc^kv7^`NLv_$Nw!eU%G!a;ziLX?a?m`U=Yl-Rc!P9`7vYr(*9p%I;tshoB@8GG0* zk2OrYv)2UfqCHzqv~y}4W4Wlu1xicjyyWQ2sgpM|cX5%>d=j;XcRqKvuExJ)&by;7 z;}`7oy~C7ca5gGt)`7o7a?iedZAUvI*^IsMt26g*;i8_?IsPYoQgSHCmksSi^X!ts^o zBiTEO6MENPzP{%z;aJLokaNt;cVAt_(QkkT3GgSVoc~%UtXEoFC0+G`Hfz*cXe&g% z8zBBQMsJM`+&|tvcdeu$xK^VKR3r}&oHF+rl7Fr^LX(+Be9Z7#%h~U&D-T=7r4z<= zK(twAe)gy9l$AR0VV!UF{DF6{*(HHbX}GVdpRILrYdN2pKUaJA$`%9>6|DD4z)aLP zYol-Sfy6M8#q`)$a0gWr08Fu^>1k7^z^Wt%DeVYBxSZJxU;4ImM}_uhmZ-6!KTcEP zVzDY87v}tdq<1e(_%4XQFAkgt2w#*2@F$a@r+Xs|sf<)v71Vp0({|(3-7s+E7{u?0 zKVU45(+_SU?#Kfb6p)TG_u|lCfZ!;~s9HDd02EVq_7;3DovM`-_Byhy;#KkXui3^9gY9bF1Ka^m?b3&Z zU%$*w+bA-ZzxcKKjTT4zi2&(R?A>aUXnPIlBo}O#I1{JJZOr{m9ctO!H=RhU(O>i} za@J5FfMU^wRkqpOJQMF*pAJE@BI~<+wETq{^lJxE$(d8nxww#)UCM!V9)YOzW@%~= z&Cq3cK1h|@$JRL7?F5C!#tI4?GIA~eGGv6neYJfnwW0I3qw)Ks^xAwi)~jy~b~ z`dUp>lXta`leEuS^p0};%oo$F9(Q@F5&MFl<s6d?y7T|MOpkkm&{Ao;?<=?g=*o zc{{w>LF`%G(`;neiGVS`wRjiE4;j8hbayWN6q;Ssf>0`Q`9d!}f?e2EhMCZi*? z=>{I8udY3^+UmbdG#<$=v=rjj8>9b-K;m^Fa9lW4w}FHjFKLmrdTt{zrW{HF&pxH~ z5Z|!fMvOYmcLKjszkf+q+w;((`Gx}}L>5*q)F#h3kW%)Z5fuh&gUWu2Hc z1++FjkoT;=8YVL{*wP&3c9J@hK2GB(k>kkJe({RYfxKyE<%{xigTHW3X(kl8{QFv5 z^gYLt(XKJv18wtvVXL&2)j`cps!}MV1-x231|In0y35T+Kcrwz9%D(COWi9Xt!nua5ox9{ z;lthw^2UGcNLCAP<6-+z4|(lKbbDD&iQU@BSN0*{t+^V_mKA;Yhh%l*P*&~D@b`;> z$J8Jv5eD64WgD2)uOpzaF5**73PtjcJOZeYX5}|}_$k=c8JPKYC+_i1h%6<1juHE7 zZz7X)=H9fGcEx+V=GJz}z;kwvgzdm)Ix+HcSCVfmh%>W#KBH7REm#WcvB#a}Y4!dJL%fC=F z$79}!v+qjij79GlpFj&oM=?&pTk6hyU=ZJqhhu-4L1(Gba#R~!bbci>6FryDJJ{Tn z?OWp>&D(uGCv_?j07rwm0?CTqkF!g|E*{@(rB?p4mf$3+o{S02czLHbJjh3@KqNt z_i{B8ezJan?nZ5P@2N|y9n68)4VU}XcS-|+)qEZ$DjAY7VI}kjIJrU%%gSk;+2v(L zp4RWX97r&ytw&X`Qf)m(MCtn@Nn;(Sf+#|+v0iqH3v~=Q12*4+B?5*nx0wWH_g&4Z*$m6TH_p#1ew^JjtByh81L6W^BpBf89w3p6jxApe-`m&6}UU8{gz{FNoL zOrfNjb^Bm7?N^-4OGkBB_A=UB-e5zKDiSeS7&((=L^GVpU6KUsYH|nz9A_amaaoXm z_)LYH{#$DR1T(5YRh+R{YZA3~{VX*EYVp-Cj`+GRo4<`B;MEKD30UWwC6~gb)K_hQ z5@{g3nh)d(dBC*^wX?H>M1>_`zv3`RcHWK^IO%&^Kg+=dWO5lfd9z_0YDEk-9YJ6| zdW=xaLKw)o+v)yf`NH)~rrC~2TvX4L_!1&#;{A24nPBpT@9=Sbt2LEWg;qk?aAo|= ze^4w|0lPrsj*P5f)t$z3bdK{if#hMWtjf+4*oi&j=cPYg-Dkv~A;;AGFY$h;L)A&) zid}mPlIJRE!Y`1`zzTmvjSc#!9}x`uP@-C3SNt=g z&xD@Rg2xrlWVq%-RMIZ+rgWTc7cH*Z)}LcW zMtqn+RYw|Mz6`FkI2AhpMt$Qn#2K*x!v*PveY0?~*W^*Z-Us0#`<*4*H(j|tcC z%98oEUBZ9;v5$W~ZdxQMh=W8+w;#vH6P6~7_*obSteZma<3wYdxXhjzM^T_BM~hq7 zzg~3>a|LTOC<>f@U}B)FOqPzcoo1$sOd33_3IJhe`@|}5ssV9zS!myoBUK*PYa)ZXiHit> z8+KP;`H1oRdT=8(TopnRy!n-u@Ucf{_mx#t^!JrQf0;oUXgYQV`^8m3880{2@?Wt%Ksd*terde8uX40b0&7~W2nNS`eUWQHcGbbM z!It3uC9b5Tm|z*60ebOPU2`hePht8?Rxat$_o^PF1qz_<=^=Al=}BL^rk^?BF*i34 zr=n+(Kmts9p)|p#%V#+!y6e5)t&qu@0kBuaa9bq@F!B4{HBGZhX5EWj;R#(NVSl^vzXtJ-FhYn&zCgF*lrFy77mL?m!_ z+Cr#_s@o6=6cY2r}qt6VqwYJS9%0_~7)ksJz_fyx0lF4i8Xx zbBmu5MRV>GvirYV!>nV%7iq+f#(5oDU1AFJ=RV_`#yFP{jRHfYAjrYJ-W#f7Qq%*f zq>HyTwqb(Xs8ExVUgU-BUW?6@*L9P^lAXEGe?dA@<#&^`o`I`>w$D{MKGU^AC< zPP7@*3A2O(5JOnpwbh`JbrSFcgEbNn%Sz6Cm6!+!h2P8Us{uQMK13ipSMyun zw2_76V0A)1KEFrxIp4V1{0^{^`-4CVoci;p|8f1*ckANL8FK(Ia0iYhs7?dcrrx15 zJnGP=sOvj5jx40?5;+PTZ2@ass!DMrDF6~j1G4DS6uMGyl(Z_QSJyc_aElVw0Xz2A za#McTu_3ecSqCKd@po4#*+~b5)@hZ&_*V9_^HVJe+N^jd;u9(V#rcZWBGwP-6UkV_ z9Uv5!LWFf5bk*6eP^5nIQ-sXXKKVD#IY({WRs|3&7j1QS4E>{`uhqRed(~ zYw-_A_yYHCi}Y@M8DpFiaAskL$vb4j0R!R5!6LUribc6}i2$hQuRG$a**h#}IJwqm zk=;T+(u%u-H2^2_qY`Y`u9KsDr;>nn!1{0iTT*4`+Iey!mCP!sh4U_AYi|Cd?}fC~ zm#PBDY1b@d16F#S2Q$j&bsk$3qIcMNbs`U*HRAs#6>lUveUBDWMDXYKYeA*GB7`nq z&d64ibyf@_-7>5Y=s10D!n59@k8DGs~kf79Cl34oUW_37$kTQXV*BI<=|pNV5Bczn zNHyaksO-DUdwgiUvRFTCtEH;@5!bxhlkQ~R5A*LD=cW%v%zB;H`BioT|IR;oFhBvZ zd}5^_2XKep-_^d82pnQk#1JDDtf>W2V|r-C zAW5zKHM3=wOJTiI?TyC>IT4}I+gbPh})l7B&#rzmj6UrUMipTW3oj4uVDU>r@oo4HW(C&L^n{?=|_ zW1k+dH>*J%a48m-bm@P!B9V{~xEL_m8vxpqBx4QZmws;)W?R4JvS_?4(?nsdP*&^( z2V9smP9S^2iFfaTAOgGN>9W*uM!J5j$Hk)0R(9xVPfY}VAr6<@7YH(Kl}(nr--S>9J!J*eOK&DzycJ24A_f>WFwBl7*B z13||6jF%X3nL;0Y>0S`tPHvu=H^`x#jyGsL@uhPt1MCeaFs_Y(&}T;U^V6qA7WndD zD4T_=_gF}ZfblbV6}`a#U`l^@2mBCI$BK_i#0&19PMfV0m>7wPhi5eU*uRO0FAuOX z!<0ZOl|z6g(Mvf?VThI!#iJz@KRG-g4*`(mR{%-E@vS=JiUJALV>W#)*!<)X(`h{I z!?(3|4`SJ`{KsZO|2c@Hoc#R&;pW`j>5-~4megE@@x-90%3t#o>`KEQA{G;g#}Fd{ zJsKiKGeYKGhBOmHo(p~_(5uG?d+Wa1G2l>OK~sAF!0J_daUo^4E|r4NHA$_pyPbH- z%rFh5iN?e-SH%5^QM%Y%-H_4V1T`W`4etF0pzP{v)b(Gu8_7+O#Hf*7Xw6RqyaaMo8ed zO(`$#k!)CuReLR12pT(5{U&BKBGVm4hiQAxj^E_n&rjcMtRAe}&@MMiViIEgX(yIg#@7!sZU*AH%%_eJCfPhVr7cFps5R8C~qt)U_2U+uC z2XyAX9@o$?TnVXKX=uiu%<{1(mq(FB&xln z&6C!sTD*AcbX_LJq0e9d2sg7YZV|<*pqB7?si0rKHL(+soECD2+kA7A2=t@_{v6B! zHS|zPmA9Uam**Yl*Qc<5%fe6HGFoYtg|dzg1WnZ4vL?AusK#v@<~i2LW^G#PjP`mK ze9?^^)zN8ZU~M;y++jTfB$LOapFB&vldWvpOy?mRvN1vB#@bXAMSoCx5a!KQTgE@H zipUfY_ASo$DuUij5kbaSZ&&TtyuqmM`h#X#TAG@I!zgRh`EmWEpb8S!b`nsZ#MIUH!adtbem{^ z@)`a~iC`4jUI8{3DgeV9-Z*DO&a5eoJq?(<}X~YM~3-N%HIPo zFKfRLz-R*k=Hr^;P12W`<{xd&2gcw)JQ}k|?eC1+sbk}Kw|>fT51tiLFvi+|7wa_M z6YyoVes4psR5GvFM3Q83zf76>8@|6JPrD>3|2aTT+aGUJz&bb1|BpWk$B}&yz`2qEm-WzX$i_{sRsJ851{jm?YxJk>KmU%L5%3%IS$^g zE2t-v$`D2X4x;ty2`~)5v&iT%e0`WdAP+SzIv*|qKo~kZCi51+sVA{ z9pA4%0sUz}0=4Zqvt+QelGgl^ufbFi&kt<#qh;6e68q=P7&j1EYi*5`_I0jcEb&G# zdsyzB3|1IrFyLfTHnxEc$rOrUF%VV`;wGXO-{W0)VYggGldPD>5SAUx_Qr|wAzSdv z#?eZjs3{h%kWNvEOM+3f@uot^7lI93n@$5US^i@AiU`eFX@wiuAiqpbanjf5*IThO zD}n>qdnGwwo+%meP#PK=^KK)@SoE6h(`3wkYL4vohViKYCr%IpsD}#^YO!JQJ2@n# zQum|62EPl%k9^IX{C}8^wpag5!XbQI)hA3R?dhoz2!4s^sTihx6KD}1ttqyDJavAlxwYDs_E zdS(NyF+M+$9%$W{m)AmVm)}Iou~cqEPFPP0;76$e4Yu(q1`3mtzPziF0*o?kJ$T!~ ze*Egm-Av4~t!$e20n<*EAACm*^2)z#pU%7V8U37gwhKzW0kB(+=&H!<;P|kH>oRWy zr5G0R@V$lxRv?rdqp}`TqW}iJf`hT3(;uk--WCktVOkQ+sMrnjpZxn_jf$*hfT%c; zHnK^K7D_|<7JL#^LBrc%(TU5QB7-3#4$`4xu%7ZHyDxMYm8Ub~%#=mo9XaMY3Mceh?q8v(7MgX4f_CV#U_f;uz)XXd3B^{qVQ_ zn7C%_q!}ps!&<170+X1(%&dW&UbcCF7m8}N{MHR^^|CLEIePKCoRw9^p0LesT0J+& ztm4)_fX-e;N12wy=*wq~+ruxoKx75lsq?3%`~fFflvH??f%3gH4McoiL4BbGH%WyC z7kQ;skT=@{p|uhhDL+(jR`yX=RA%r4g~gn#sKk!$x?tWEMJv1L?&VDf-xXx_m2z*# zo;Ag>DZ`+PQ1m=PP~D(*1Haw%-lmkjnlEqFo)T~jx29A5)P{llO=VGT99K3kbk-$M zKr-{oybn1*tDZ2EJ*)Q(&hrPoJo>)HoAr^Js|#g%^tl-(1>pc|&ny8(8`USx(1{)w8s z(UFlNE3@tYCtr;1I}oGE!k&oUK?9?P$NN0Tf)0EPzVW=M6|`WIda+!H-nC=(8=S)c zh1@4q%wO3Lv_O!O#apF8J_M+G=jRvA8C6ik`V^Fp&vqv{bYjK@&R3uFpl0S|Oqs#$ zT~^1^guh=>76Tlt0|gPbd{FYNtxe;MxmAFFH=>AycX=ebEG8R47spwa!p zz7gj8Fk`O${I-QA6)#kX_LzeTt%HjsUZ|n>L5B8T&OFTaYT(U2!m)tq%lLn)#Ru!^ zd*f`y=h4mJd5Pg~;h(#!*I`OmO)EhQJfx}6UG zz2R7Sk>%Nf{QofJ1B1Buo&9^*E<$JYv6?{4%y1&~Gq8 z(#F5{o$S+&{?aHch$S)UQKP3p(8;2qB)Q_uun<6@UcM6H^fEfG?EGT@2a9m&X ztmLTj1cI*5N~4M}k8Q>*J$YrP)<9HYu9bMK>v!KB!6Lk+lj8RvGF@IQxO7WFzKK%I zB5V#2r9SAC|uNq*16szJBIXT+4-e~o+2cFW=ZdsLz5)~NV9zC z1{fbB`ZXzTy`uO4Imb_LB^e=1o8eECUOC5QDe7TaBvhYl&q<)KNP|maS1i)DzD$ki zSLRB1c3%QtUzIEae>~LbD@OY<4erVW5S}A|_a@)k*4A?In`E)U3KyzevvLbCX40ez z*Zc(oFbjbGWX@;}i@S{Db|v4^Ls;5$f9S*>5V0d&E$0=c0cJhG z%_#a?Z7MABek6)QVnI7$-T_R~yO4a!J+Te{!W?S!4C!z@UJ?o3!H7Q zayn>U#(qmL3^Y?hR@Qt@Cc+8W+W zV*vj)zMus{6G8}<$?G#$O6Es8G0q?9K|hl%=sTkU%8Xi|wMY;X_l-pZ)&o94{9gGo zGc%oCT`!}*dj~x{cxJh8MI4Z40XH)D?U-v{s!i8Yx}rX`-PTa}<=A<@c42B_C`D#q z1zyf~`AUV|#xWkRM6B0AaxfMxf(YHtN#%9N@(Wb4FQ{+>x?vuqBXRw=!?16X9rvSq z;ycpjSF5#n_=7jkbjo4{OKRW6z)%lQZF(WZ#|5fbP21`6KTE9qO=DB6>v37!6lA$+ zSEm`4ya=w?Ap? zUaf!`8)5iY@HeTN<-cPTC5qMf&j+WE{GFF~d4`djjD?QKpZ-dYew-DFH)h4~E zF?sR|sN)Tf&vvmBjBPii zUF}{imthXI8eT9h4IMmHDF)2@Cx4s|3B~sqDH;{vw)VQO{S%(DUOLm4{OmFW8b)%WhytxIU@YF^)sZ2jf7 z>HY=MHQ9$Lsw6Lu{6-?T1aV|=0o+a`F8Cv4{dN4ZIIG}vZhf0Y+i@u7LlWzB(TITW z3?9n0$P>rG<0-R3L7R(p`AITqn;8cLy7!laWUXfUGX95UP@tn%s^I*p~~b0r!kQy$ z;y8uh?4@Ayo!6!-VAA>74LB(S{eZnmdzYi^dp3rT#KqaZf>4lkKT!&RS9b3sS>rf( z?mYZlz4f`;^Kba1RptFIU)S&(N?~i=r-lM7S@hO6HZ8zs#^d?OQ1oCMK(Bp4nm>S< zQU7Q2Kqt;XWOnOe=zXgZAU5R$6 z2vU}B=;+&dzKkpNaX!_8TOoNJ>~)irD%35vQ8t*js~n^UjPR;2I7>~TY^P#XqeWg` z8Qvo@h%m-h)aIb!0Us%5`VC^=*yD9;C8$E{bsl}4@cbD{yTh8z`;?xmHByu-=-rBd zS9gS45Uk%b3y&yzi)%0Bv&68T*1a{qdDqEXy#s#BaBoji0*S5TTI0!A5^vDKeZFmN zAf@YRN78ZZO>1;JGkCjGm~4vl2^oN#BYd|Jl#g=l4N?VlRcmr3amh#l^Pyt@R~~)C zyCZvXaY%MPB0GeJQou&=Df6c)(O!O+zor5)s$bd~hQm)Hi2g)>z|P@%#|2ppTc7)V z4A$o^k^@)i$#1rUJZiua1cp)eB~-B1A6PPUL17gy_E*j!+^s)hG&eSBhT;R1YQ z)uMv}LbJuMoFc?sH)}zK+zz}luN-RF14f=NC_HKIY)XFBDm_K_HBFA|KYd+# zs+C@yBo|C7ZMn^s{M9m=D%t6V6p!8g8$OH>0_-4JG63Rs}Sz;ea&XKe7Gul9=rtp`&*MKv2*d2-2GeAo~M>;loUdrKKfQ zPG@J9yEjf%hIF0Vcgts8U7?lxmc~Zc^Om@~nUv0c3(?0#NnSPpQ-j`+-Q($7qu0W( z`dU-Yz)sKuxnI;uk@BaG8;y*C$P36RycIO!tr+=;)c1Z&S@V*~e=m|ujRWtZ*#3mr zeq5*xs?z;#etWrN+NeMJ`S(Go{WQKj%z8ez9CrVTkI?6|B@u0tajUxe5j8<@u|&#O zRS!m@3cAUb`1MXH`(5rI_he}b6kN4av}{Kb{j*~y{xhV_23iSOV-otP$3M}#gkMuC zN_5np(#`ojhaqBBB#ulCp{FMff$jaQSBTtetgd>I*iv#F77ZV+%Qm6r} z)HEWNHRB-F{r?-{kf_evS{aWQ0u&0*xuTDsw+JID1tKWZrIV9#mzEhk6JOS8){9i7 z;8YRNwWO=~@Fh$Zd>dq%*_N(`s@LC|v#28p!L7FK?Zi7va1z@|(!=JnT8w60?e>?@ zIw-*yG>145G?K8QvVw9{Lqck)7&gNsyC|-63SZqq!H?8ftd?x;qq-Xp(b5D`^mkZZP~?-QfvZ8npmMN;`b zqcsq>iKt5iZBNZ*&vmw{ZS*>S?bkF7^-V;K#uR^a;;^}Q2LA@o8T8u+%6omUKKq&F zEw;-S&qC4SAg@6>As5-N_u2f?&77)cVRhYBY` z>E0a;LDB)R^A!L$QeVhREn|=On;0R=kQN#h-1}KsyFP@#H3KP^4@z=5m`UXy=>iy3 zIAzJKGKW=2Eya+aO$Ti&R&BFtGr4CYBSOX&gvBm|*PDcltw_ol zqpt3=yHM%tJo>PFCv<3jyJka1Ua)g$h9z~aK2gW@8Pr2ieGpqs4xOv1*%7`b_Boj=x8 z+aPwkQ?ig=Slw@OC2(_G769l^RnAm-eu*$Wb^kQ1xp~{l25NLJbH`4D@5!e0kV|pI z4V{M`r`PRlRmxSrdiBv7c5IeNDiGUDh(RUiV`*wRfpE&!IVK!2x|o&|8;FGnrlIeA z0Nw^TL9h`u5V_y_alQbn#5o3Ua8-rl;86+whpV%Ss;dc`H16*11PC77-Q9via0u@1 zF2NdO$ISmFY3&Jvbwxid{q<|_kZ znr$~G0Ch&n#Do$an_*YreMjK&^*~^<&SXpjP`0w)Z;MlTTp6(Sy{>w@D1bj678?#g ze?lhpIc#5(giY!XWlbL=yx%x%g-P<18czB+r#Ius_xn>2y`4%_)y6xF0KF@n}xAjIwaub99Sy!KN>bedvfusN{ms`Z= z{NC@p@|&EoBS8T!qT+3A$SH`J+ak1c$c2)`UABZpS&>t$h#-Y1(dc-jn%{BgD@uDO z&0x9PA7Gzg2^7qyx)ch!vLYfGiDpS`sA=VSvUl{{hwb` z`0{xj6Vd1Ch?GFjE>P_c0)D-FY0jO%&C_&^4FF^mu-)i+S^kK`Hom~u$vS~sTb4Kp zv>A9p4T|b*%y(U7#wkM2M>Hk+62K2TU#UH`=DIQd`gEgN|K-&3X--8!i5lZm3UWKM z)aPkAr*B^UrrZB1Ck6qo{anYv8ms<;T7>le#NM#YauD!4JnswExH&+N`Z^W*r?OZx zg9phiH@#kwn;<1IOcb_OMZRcX_d+;1G03nP=*3{;&MdN9P`6lbL@(dC_}Q?K1Hwq= zej8AjQM)g^{{?%KL08)NYCDho0Nux0IrAU8zP-Qo)2I+5*jF0u8hGaIi1`4&fW z_CD2CR<+>U(&Z?l$UkKdM}Bt&(u%DmyJ@&=Nq4yF1u|+$I`yqYs97v7b*3_*RgFnp zkR(LUjP$I1sK8v9PgfN{5p^6!DEpIB=S`scr$;nU=fXctx#9T1T_TT?7Q}D3a4XF_ zu1=c_8h+l_BfATg_$GTtk%h1zv{rRrtnihz;FR+mxh}m$>BL7O6^Qxz*1D3cZWtPx zH~3$0zs`f>KkutK{5e^lj7XT|f~YpVuF!2uR%di)>vq5Ac=b8CprL^0RVOrC_nuU0 z< z4RuG9C8?v-W8BoIBWuWk*jRu-^vg%}uT>i)oFFu5(B3v{lmj+pkqG0j=`5a#vjsZr zQ=Hvd0(sY$yrWf9j|@P`&->)%UU#VkQvXw%`UP!v{`BG*1HBnK*zH9j@z~k&r$Ojn z=;kZKi=vq)J{s;e|Ns; z;ET%Edp^BDDD;b%A+Br0`O(Kco`I(H&fD;l@ItH_t53>B&x_&QY~|Zy2eb|X{x~9x zzUA)J#lyF~PNaV-@qYMvPouC9*guvh zeV{B>#7yuJWPNt$`J`M{%a6~lRTYJ)yW5wkEvzl2Ak5|a&hGGJ@X8}c{UT`+w4qAq+feU93fT3RCl zFLa+xiaK%Yjt7}eZ-;-RVn!@igUd=`Ejz67x7rL|n!JbzAq>jvHZKdEBSZrZ%hX!n zv6UC+1#g4?iJqK9qD?N{omjj*bHKE5qtan%pK1Zg73qZ< zka`fKMJj!BXmrI#6^r18C51|tAK)MqPhPB?2>^jsEWx~xlM6|NMT+!`ZMn!)Pr}Vb&@Y>Bbd%(zF3`|dph$(CeH@Cber0>|rxBZ)0jr9%(``6F-Mz_$O+N{t9}n1!-N=dvlPU0_Ilmeb z;a4!w2LCPwxreQ*TEMv>cvH;(Yhe!KUQ`_p3^p0UHmW2s(Y#Pn;FT%7UP3-KJ6w`f zQ@cBv?}*RpWJ%n*Bl$NW`H7juk!3EKa&Pb*HjzUhXCW&O_qW@9FX?=C0P&8UdEH>! z+ntTg^3!gv=|yHS49RR~+0B=dkrIM2BxilS3T^r4POjq)^woZWIKuUdCm^KWFq>o}rsYSg#Nf`Rx_LAL z3Y19dj7P%CO^Ccus%x1s@}XsNQN;g3|G|OSvaYobMe5axNjv6Gds=og@AFx2qw76A z=!VEV9^7cOtYLHmLQa@T``Q1425)U9t2;6Um)N6634wu!ECkda#-cmI3AQt z9J9m$7Z) zH*$jwRG3}I621K1nJA}f>e}<;Kw(%2C4c83MU&pTUr3_5=aI0kgeHHRfXScu^lFQ? z+c=_f*RNh!;#?I3rL4^zmKI=rTr&RAm-uoSYvr1N@3!@yBxmI)+HUZ^bAReZe*i$V z#_P$UZpofu7x*A7e=B}L?yH^6)xOH$yV3327QI)Z@a+ahOfn76 zoR>8##-`?!2E2)x@RQ@0KSAQtVS_l2uc@N2kzt)1ifu!`~RgN zMXAO4{w;j;Kxv8KtM@K$8Dgc3!vAq9k==K_-l`bRU*A7!UsIt=@7?`rLQA#~19J;#%L2 ze5MQc%d`uj1tfD11fnNWCoA}0M;)kMLgM+x^FmRd>j?gH=&b5~_u#*;jj=y#T&VN7 z`$;f_d+)U*nwb_OC=*v>tt9JWx!j0bqnBhK6u34<`rj2#jJ=<)&zr|^qv|D;-Khj>%Z*>OSL=dC>3 zHz*h1_w4P zn{y?qio9SQE+Yjal)O;_I#<_L4N#FP}kAmw~Htq=Vldyq3qTuy?_)w(^B zxcY;6g{P^;t6f11s*2J7pIKL2Ot#Vc&No?P`s|n2U3OJC+?X8(!p`nWHRW$3N^*vr zXN2flz7^V9@HH5VTqsRsdxer44;&ust7GKVdZJ6mY!#LI+Nu#v(#1-p7|S=YaWKmd zp=>eBm_0SW6Mj!1NCGoP-uW1lAa5QUj9TGM-Bi}M;M!2{gl z9VdBac)rv`ziw97e_Y1okLsJI_qjV@^P;>*ab}{RiXn% zKiSikZt$>UP!y02Pem0B(@c{*0mb>AbeUH!+>2<}*Ddr<`Ee*E=je(_tD3ciQqh;a zV;3Ac3*T|R$I{j>x^k+GX7xg#i}PM%bie-;{mXk6;Ncm;eWD7V7(c<#7BD@tf3Zj3 zt+IB#`X|vnY9G^leIJVPuT&8P0&V%@saxmiApNP=8NbN$cZgB!-|ly|R>VSz`#$U_ zO?3K-ck`>-^_u6yY4uq!B-5(c=@E?ngs%q#=Wx3=;FD$XR{)oKvP* z8S`LFHyHRtl#=gaWvIquBEumEb_+gWaTor7^}^H>EY0&?7(eo+GK4iLhs`mXyRxn$ zBX0;f_kVknC5{KG&MuxLP57((U?yjP>f?I%Sro16R#3YUY%Iy;TPGyP2Pyx3@OF6+ zcyCtKaG6>7SQXw7Xqo?cViVFfOUlLQRe{M#X}5innpgL|`JgfvFsF*k_IseZ89HON9Nu2m!&ps+ay# z$NR*Biu1-7hE8qNI}$>F;4q0C&bv#{aztPu+6J(&?$8} zL>R48I*?3%yAFynzJJE}yI7?cDyX~p1xEhF+Zeh;QSQlTXmvTwg|&T;;3NKkIO_f& zOqC6o2SC||gWM#zll^?9(`Bty_nTn=ny3B?3gmo!MsG^mPS3a1lBxA64TE3T5mbnG-5`)mo zv+`?4FyX=vF~wSU2#Q+Z1}VUAHR6wnGY9JUJm`&ABz(GD*mS(SsZnfw$ax<^r3j2Y z&UV>bCw|OzOcAqH10#hz`%iu}d8tPt8srXw#pxObz72fty@e{IliBp_fORaz;Hw8% z5<|sWkUUt^=X>8aV71Gh-0je7wuRl+3&~AOWU*xg-l1PnyM&wk zD)qTPE|G_stYwSYnWCb?0m0-z;N$6Zx$z_n<8XGQe;m2K(+J+ymm1?BlM*4V7E9-_ zA@>_NHh)FSGcxhE<$I;0ebfDxu)8bj^9hf&r>aAgSrhcz*6mdzDwYq zkQD-%Q5o>4D=q_h3Ok2kHo4lldBeSlQq9^ERVrN8C6dAw8qLIi1~G?<%P8 zio;gPO{DiMq~Si@Mg4OqS&BfA=`@h{?#kj zy8Pk{wH6yC4sZ?q8%@@IDL5lRj7w-wdaBchX3Ku@;GJ(ij_x2!y2e!M0ap&KE37nk$xY27HU&0VS46-W(?zh@ z5&@_1pa$!_yE|YoLB3WaBD6YQ95_R4zHwTaUDS59pVrm=dk#}m8%7*@7 zw-dW3b$fsII6f{p)_2bWEsN<2m#eA6 z&j!gj8rUv?{m!RGraL+%X#-VP*=VV1&+k{=e<%CdAi?(=<3Wl<0)}y z+_o)S-)ASYIpKXphI%9V(2vEmv55hvT45c~K(T63M-e5N#7ulZ`p#g!NkF+Gj zh}GUrH848qO>GnpT@DQD9p^In+{tDO)x|fyzCs2o>Mag_rTkTv7X^;CJum7~_tsH$`cJk&wyG zW2UHKrZwO@NDckmq1IUh+P$NQR79-PUxg-lAvSJQx7HrOXTzb zmtYa5PZQR<$4eCE5uw1-$N*3pVnUjyC3R{_#s>)A#60l_IkB_PiS0LbaDkjj$+7|4kqUuwkB?^`B^Ag{ot zjy5f&#Nl}<>>-ySIs5|hm4p>R$h3CM<@`v@Xz~=+jeY6kpe1400Xi38fqs(r(nungnVh7aufXj+K@@1U8IB8-5u>#Jn zdd~r;hrISwvvxr(l8UL;HAW^w+J->N4RD1ww5*5u(v1fMGVLJF>|qapQ$PO9waler z2_*C-vzJeLk)M6M>YKWTvK{olFMQ8c(s6{W&__r~{F_=7hZjMXf~T8-Ts4arvjI{4 zejFv^I$5;w??u4Ho7%e`;ECPHV*JluUmOrWh-WXi<}+pyyIz8GtLbIJ5wi4RdJ@ zrH!KSUGN~}Cf}SE+{Y*gyh<=$#!xEWSiI7{Xj}sb-i})+WfX{jp3ubD$EH8m6!ye) zh2d^nsBLuqHGK+;=(&kOtXh(mi;Gt?~6)qE5twE zZyxArZ$p&yEJBI*4gN#YsvYSeXlTMqz12fOV)1lXKa1XWrp$raoz{3{ zuTAi|^t2J?r$?^r-BE#!zlE-}Us(*sTg^h_ZUB;sM?Q(dNKHr4x7P`IfeEYISKa=^ zx&u@1whC7*rZ~xP(s@D7#ZpzD_&iT6F~em!s2S_U{kts3PWY{1zK&sc_l`w&VY&y+ zfE8IMSHlMG`N_!L?dl~w9u^m`R(`5!6bZ{8?a0I zAj(!p1`V%@(Wc^dLoa#*OB-%EC3k>0dHb0zdA!N~_zU!SaUB&TxLrl+BlNsIY)qD^ zmAC9f^Kb$XR)3wkh`-Po(zb z3A_rl8A>oA4>j-g@Gkpzyi{35=O+_M&+Qb&YWIuXXipei6c2Di9b|XjTUTa;QxOpP ziJ^&5>&}pfk>AMWO&)X`O_Arv-#y~Bm%PSA?AE($cN^5xoF0781Yq9ftRH(&k{+el!Z^d3Cl*YgD2*GpI z`hFQpD=<_rXGB^`)bjXweCIQEofee#N7bSkBhO??P1Yh0vYe4?S0v3Q`EOYdR+I&X z8T@}OD8D`rFP|F3)hFZj$KHMhP+od_K+ck4w_evkGQv&A!*0q2!;kmY;jt zE!zXMMV?_HSJc&k$!34_C&NQI(pkbzi^dby=d;)%HHn`|M&Q4sYysCB@EsWu|BPU_ z{^~#sPIHl8X+}$ZGMr!UzWvMM+oV?tedKu`p8@90$A)%THTN_5G5Fc+j9yw$0?h0i z+oz*m#4#A|{cm*)YpSMMx~^EuVU>Z+2EN??K<#4#9Gxl|3fIq8s23^!unDXjqzhuw zzk*iLMZ+k=RWMRBKozj;bi`ocn&ebAh)j!ELA7z>Bm}q zWUh)i9FR?)QI1!P2=4N|Je#;T66@V5J14S{NxXb;i?WeX&SS;&&zra@IpiR-smY+6qE=R#!*;l0;i&ABz_w9tnZc)hHPC~Gp_jb3 z2%C8*s-f_6BFa0AGrsp3uz4~KtAKYGz7~YI)oTHO<+V@jhWZlQOyp& zcxPYILhqBlK#?@-=M!#fbg|!ZB_cbaF^t}ge&`$)oj?r1^#io*oT8!-s%)=#fK5cy ze&0<{_+~j@VS)EAF5I%UC}}xPx&dLI&(|uy#oS#(ge%a-qe0o22&enq21l4=Y)mS{ z8!L_ynqvtC2o@Z|>kFRyLnHqbkU(z=FpjR-UxMEFsz}Xxb*Rua+BRcTCS8UqT+?7k z6FG`SIHmt4xf>y%-z(xtjMr3QsLnxqaZ*58zNDliEcRq&*p*|d&S;r_!&@Ufy>~gPXORu?!suMxA60^P)wB4aP6%mbTj$t6pp2qG$&2O#NFskLvy54?S)AHB!4za=968#q{z=Q=Fh~$v+g-5;y2vA32&mN5$Ge zCeFv0hmc$Nl=|3*a&>_$pQbLgosh?CxW5Q@AP$X2{2W>FGQbP4`>q|mV+#O%1qyf9vAvd-{%J`&UjdZ^=zMQ0(C zz=#!~y)j&RD_&xZRMP8wq%h8Y-`SK5HKrIDsh8ikE?@r>QAVzU@U^n#wo1mm?5)&b zEOSaAn0BC6#8u6>lFe=nM9ZlC8bX4Lh5r3z4&eO~ize@b{&S`K z(M$%Oir+?QsrX37{MzO4w%d)7LIvx?LoZ;bvWh0s6#0!CQ4~lQoyde1%wK#o;->}Z zdxR-pg4P)2U;x^0=H)>an57$wj9P3q(&fSLNH0dGspJ^>9)zRySR?1Iq#i3WIPweo}cOj-Fa zicrslF}Gc3mJe#L_GhF@dOR@L-wSgnuya;eO`iNnK#?)d^O^q*_Z>< zm%Of0BXka4_kPfAf*&qae=nw-l7)F0YcL;`6MltMo#3joR1;>U;};b`lT}a=M{M>? zij{5gg9L{7;nDRm;6*4VTB33{VOvQK<`iR;y|DVI)>{{fkzySbK7r8WZ4UHx!ooI= zZQVYM58u3%0287MgBPmF!&{v3_k=PSLR>!5;gwkD+zy$9_3b*xr19;|O&Lq^HgQRu zd1-6&NO5F0PQ0yD$soBZkz$j$lz@_%&(f!oFv*u7SU9^rON0AkaKwk7(LAhruuC?N z8yr3BL!h9J+0eEfxQ2TwzH|VQqe|YuzsS>Xl)k>M2Ldp_#qJb?asOXO7*LZYl-uJ- zl^I3UujW=#(r|LD@z{A{k4?`_QMCE@Oa8Hj=7FsNzQzSU2f~kw+4TQ{hsSC#}WS*`I^gKSnZXFr@tTG}{bZtHSEcUKcc`s;9$X&mWl--m4Tuhfyr zbi~-d9%9A^pagCNi|Qo|TVQ3cjvt%b%nYR-j^}}#e+{=cs*74{lKVbtC#$8B$BJ6{ z65Kf?!ClM`neE6AZsuk8^MMO*gAZ|;J^EE=T-q&$#^T#wohbI-?m&VMV%W6)^{(1? zucCee4`Ua+Tcs4^1K_Z@E;??)M9F5k05XjUZmql9S=Js&Bq;Bs?l#7iaK=SnSlV!i zP~ueNMa*%6JF<*+LkcK9Kk_sr?DYNMS+CNK9S_M>pvi4W9FWly1}fn|r@T+Bje!@< zC)V86WyiPj=PNyBode~_jlLYf5ZIj@58JNG{&#QRHs~4eqYIimZOY?D=EA~?I zs_~e;2k9@ApJ9k}v2+kHHHnHTCKfWf8YF^;v6QeVbtpf4o|rPoZh zzH_Oz>1H{2edko~)Lp7G;knt}Sxn<%aWp+oa_TgaADgj zV0rFup^*&kaAIUMW+Ev)uBCBXqP&cV#CbfMl)SJurB43BSQwmRWU+7|3Bny|pqp-! z&zZu19GyE@x@WGW$qW)Y>il8j3zh6DE!~gXg!5K#jXk@#AnDnVY00j~!bsLxS{+V5 zu5FIQkpBa!4>X8NqO}4QX5M4y7iRq#=pi|$O%nNq@0LwWbV2O z9WAjCgiS#*ReCs1?9Cn?ndSgipaX4Yl{ z!`vYJf9EVPBfsF)hu@U0?p#d3+gVF7EA{07yN*oNt~sZP;`yJ>AI_Vt-v zTU5kX|1z8wWl9;K1-l ztl_uR+S2k@{4{*XlsJ*{V~Tj*Xnbyq9!;UB!=N8O2EHNCY^(5M%U*MUB0=#{4>W3*#SF&Y}< z?X3*mq1GZ_C1sRnZ57+x*l6F?il3|bAJk4ao^U2tA9z|$^j={@b3q0=b7V{KP$X4q z+qD*$um>A938GJ5EO6>G!y#D6-U-6$0Jr_co)u59_E9o*_}q|OEG1SsFpctgxY8zwPY70y>j zdOq3%RgK8Q4@vM7pkdVd1n@8_)pku`y{7%zms09gLUg%OP%qzinwzh%AmqyCj9d)r%KTBP&D^ zMyUb29RLOq>D-E~n(X?q*E;hh+y-3aSUXuOcrR)K5_$-v%`t|)*ETxQ)&$cx0`h;r zcmJi@Y=D9x>CC%}H(~4jhaYKw4@d#dN0z!U3bP#63cEr7re=1`_pv;et~PBPq7v_` z*9^-qXn`z|HwGRq$F(+X?U9i(NG)LANUzr^-Mfz2FRKkN0@radmxYYpBbbK_3_~>D zaqnaF3bcWm*@5`#60Q$MO7V5W zE7%eT(@PC(8^TSt`^7JG+7uvdu+snJ&=EWffnW6bgGJQ+WEr#!O(T6cuaim1jptQE zfTVip^q{B%6v9|*%t3={M@lELg`#WjG1TAvi)LQFw{+SL=<*tjCld29``vUqJE!$@ zDu*=P)Rwd-7J5*(vA8mfP4ol?9fGte2@MU6j$VC4NzNik87DbW#hYG`kiqPbz1o^E zQSJRpREDJ~q1WYGA}4Odi-8i=>ucdYXPn+YWSQrALrN+TkiKv!Q6bgbO5tXfF`1(% z(4nbFypWl=8)$rp6Qo0}JK+DQ8my@UhudD#(nk*gyL<(j15tG9)KI05tRTjw4@Ph{ zm7a0UWI0vAo}|pHW;BuesYz>i-9=|m^HQmw*1gbNz^eBscVP+VSzNfdALTun-GdjD zSk2=vg}-PAR)Jt7BKG=A4@Q4WxG0KzJQO@X+BL#u!je6FQI)l_SpMPmxZq%A z{tCYOrYR{w>WkWO!vNE|7O0~m&#vRo4}E{S)c@z#?7~u}!zc{^Lm%Kw3=a;PFa)Wq zt6WW*nGqiBKEdeP^)mmS?#nMQzKj;wMnKxEtn9}npy)J1p6DUrL?R>KQpA?m|7bW^ zw0k$L_~*Rp0OUfwf6y{#3sVpByysq;IYIEAhqma)Ab)Z8X!^_Dj2wBrHF=es|B-ns zPdYViaZ9OmNtG*6WFNvUMdcB`{-$p?UF=vEN~CSJj(M`Z(C#z-KJ23`4;L&>7tO9B${5ZHI1xD z@gd`h{}{1ri%)&{s5oXIjjqDFUd2Uan?Sl@l@p;4r-DG}K?>ff4ivU+O2tq0L~$n! zUc9;KiwVP)2i0Dca)h!M%xW+3VlLzmCq!Q%o%U8U1nbcQ`vz2feNx`VA5njyNdhrIGd6}Q#L&HBz>~%=p(#o2=lQ#5PCoh_O@p|{hr2)CN64&8&_qUfG=v0K@l>Pu zk_3lI?i^vSw#b+1!0Eb_Y_~BLAw7>7_=x!j&YbBtay;Gw3?Z7Kf(8ZO^AdyYxQT|4 zgix^>1ikx>p`u$dug$}#%;Ec$&4&w_(t2~Yw@-ETV&sN?F?0Rph>#sIm(F3J!5Bpx1HAU6I5>>dzHcEQ z#jmzudfK4`3A%OWV0=v=eV>FrIz1~qR>{to8Sm=y;#<(W^L_2OI#``?gRh-K36)N$ zI7}qC{Yw8_H_-V5o}QbfC^|zs+66PkSgbuazxRqpnaB&*TW7AghB?gB%dJqZ#G7{Y zgU#)#*c9W)=;W`8OGLB=^p@)H0+ydSY&x`E9V+%$j!1Xbiu@4Cr(`D1)9O}AwR8Qm z#jcL}d#QAA->)7*Z3`V&@;jbO84?3X1<1>cICc31KrNAlowM^gWiO&$8q(VYz(s_5 z6$MdcLJ!2>lP+2c&=E)HR518DJy)fY z;u7-UbVaFQ;dZNY8%3Y0qQT1Pott@mg?-h@EVFKqSMkEwx*;;~!!F%HVS^wo6&Jm? zL+qd*i0adZ!(o+^CJ1eNVhX3#hyHNruVta9(}8;%Z;jz2Xxf14_FcGrLFc=?ORAD| zwdV?VGw=e-q?)hRpA-Npnc%_3lF z3At=aLnhFKP;giw%s8>wWE06mscwqWelviGJj55Vj%c89);nBIfBy3Cf_h*q=I)y5`__q zmlgW$EPL3FWaZ(Zc9^_3X>raR-?tTn#okuQ4wQv`;S2gg%{<%&KYABZ_V`_@IN4WS z*G_lP_)yMVX4iCed!=elH2I6*T6@-M+uE%(quFYEPyxK7MkQQ%|1j85d80darVjtvyR1X+RwE>^ zA{WC`!3X1S<=T=6y*z5L0@vHdPA^Xt@sdlzJNJVuxJOZu5;ENiU8Imi5p1pfHuStM zX=k4@$ynwF3rZP$4r`t)C`VvgVMZ!Xv7_q&ldMKir@{ zzMH_91o;_GkV}!RB!)ihq{P{@&sHlp$3akOt@w~``feTBiisL|j0T$}B;eVdMnrL~ zxXuVCB`HUt;^Zdf{%e3#uOdnxs4fzUw13=)IGxB;b}{0Sp%3#r6xAI33!;E}MOT1K zite%a1a^e44?IyTQG8%d9hUDy`j6+>F?f*1 zP7$O?FHObRW%ae?U0z(WQ)-wvjWs26ft!t_<5&kI>l!IB^)SGTgjO$=v!zw2DfJ2^ z<-KC$dq6s*uOc+O&XLZeD}OC`3E9QxoVJFaL|fO~Ell0;F2aW03w`LlsaEi=^?N;u zv1GF-7UbX8;|?ZO^Y8|?Btz%;y4o1|-v4}@N^tBB`9E)j9?$g~A|kI#A$HsKPm@Bk z-V_m}-Q~>i;e72svFw2FLUU8It))d)tfMwAn%FDmnje3~Hm>#z6|^YGW%yhR25 z+>B?s8D=gO{JP25WrarX)W&;Alren2oTKV1*F?+Jw>UxZ{Q9f~6evdR_ix|Qzj+lO zYvY8r!4@P|B~3&q`w`o)m!7L+bV<~9$rZc2e6w5T7oz~7sm5xfRLY!RSEd9O(3BSC zCD_4YfU7axu{Aydy4MqT-ETOBG!^ZFU;B0}Nxjmd_s_Vgy~*s1KNCB4F5-VkM{0=t z%x_Dr@vEzm*T0~fYrGexu~H$nr6#OIGV`7F__jPww7IGqfoP2cEz`(pTZy*n;}7iq zgg<$DQ|2Gml?R7?a4OXmT$qmnB%`?U(#S9OYF&f$@meFbu8(0 z*%~S!A#U1IabK5895(iPGilrVrZ2*cyG)0S+HW|_G@OD2`E8s?JFITO-EujcR5sUrW_a$(^=myJY!a0#H0whceXb%uR|z~HAFz+mC@MQ# zx_0;A5)3dP=8^>>K*|Q?6NbFu#_9#uY#2ybG2){Ya)nPN_z&y4qP`sn*tZRNwctl* z^-E%`;o=EDdg1tkh*P^_UyS`^G_rVC=J&b?wNSX1U#<@7vFu+KiTI%MQO$*P0+4Epw2`C z=IAmcl)_!=EaUt)cR&_Alot8it?*3o0nhK^@rA@0nwR8C%TxGmt%ip^5lhHN>yk6o z#8Ap+{a8#)qvwe|${+T~72MPowAhlfIO^3|zpMB+0)8u8_CN`_Yt(V#C&fJ9y$^aD z?$vEkQ{mt7v6R*aalM)+8Yp=3gBQ^ znYsCw5;I!#)e%>6Xl8gPMa}Ik8FVdRZ%i%Q5wtqY=i3foaqHdLvSa*Y!FmBjDF|pH zUlWJsOf`zg7)ys`U=tH^R&b5Q^wte@X^AH7);6-u)E7`p-1VwjTcV%Ef^q(IxMNJ> zZwb7GS5^ChQxVJy>->5`;e5R~-S`>@5(BN@@6j>lP|^CgF4qhEV)>Gx>uQ%HHcGt< zD3x7j7*U``O8zD$$5z3U^EfWkxyT8Dl94)k*=3$~mn9sFOFu!MT}4dzbK$OpGGV1M zn3uF8IVC8QWcObrLQ})i6c|un|2wO;&f<&{OJ3Nyo2*TvrdxPx?9jaVNRX*? zWenD7^rh>oViAc!^!zXV_m)6`O6@FIiFRA)nVJ^jd1A$mV~fGFgZ})J!2*vv)Wkd| zbJlNF19qx<#S<~K%o?^)7eoA8K9CV*KHkXOC!~D~S&w)pWApWO=6g|mo4Whq*4>3t ze_C=&VnvF2{R}oqU?ioqV31O=nEQKBQLqC#P9Mq?Xrv1$3=fxYC}Noq*b8Q@BK~M3 zOxWp4O(&k8xThk}6Crnh9WEYYg_V-ZHp#8CWrO8}k#&0Z@F&+ymom$Lfr>^c2>wxO zt&&4w(j?-aU>rIrBMtMaybV4BqYRbEiIkpK+gjYLFw{FliV3-a5E=GH&t1vqi+b9| z(|p74Lf)|-T3_7W{le&&c3v^3hd^1L`|-3i)U`8t<7o}-0g(Nl5&{Di-#5I$QOOKH zF;z~t*I44vpi%*6X%Uiw0f!t`Qcgv1wn3%^hzI1?V~h7!or4x@SDOoCcMCt_t|tUM zEQRP}28@}eqqi%C2F?_R4$f>=PTI0ri-6(`2aU!j^{UQzZ9Lmt7XJ4q)w={0xx4r< zv9`7duYSW)++v>^Ol93oSiu?yI4qG4^=6Ib$7&Uy*eaTm+^U-BKV9P2yzW3s9Ea$; zlcj&==({+m>YFP=+9F%n}2o5YEmw;kb{({j(t$@CgFA5oG zn7e^31O;MwsctJLRoKy0Jwk%`dRI!SDjyBMaLlMp||wLuM}a z&}%=(*}@#{xh(7;+kk_FR17NI)+BAtV)zUxv{XtO#0-k0^o$-ktvsfQ2np@A+j$h4 zyz{nW+aJ|!uix`s5FajM=&!eDX2jTJYf{Brx1}Fsot_VW`@F!urW$WHclWDn^O%%3 zrq&=tHqUhj+w#3t#$lPpddf9YC7X&J;qiuq?koOoa<(;azY!qyGG~46K6Ij=DCfv4 zpy>1!0G1w1@FjzGhyl*0jOz*gP?zrtjoAz5RfN290NS8|y7a#3h;}GwAS_X=?i8?~ zgcIFW?T^B%gKWkwV%Zv5*tP^#(`=8?V0m>7~{cK zafuo9BB`mk0l7fC`NMJ1$YWsmSC6L+$(xIoB8|a=vLJ<_e#^vRLpZhS^pKPWlimU` z=rkgKc)O_btVMv%-l6otSBw12WJBzP zosxj0o&yNW8MkgJ^!@71@s!%ohm$f>#9^~d!+CX+z1en`g&0!ZLLbLpwe(c`e`CUG0lY0zZoqRpc6BMf5^78X}M5)jk!}`3%TnJwB7jg58Nsg!LIq(CLxbE?*cbJUIIJp@9lFf%3)AIS zsoMPU1B~TWdcJ*60SZck{vYiN5+dxs-mBd~-tizqx`=_FKO{PHv%vZa6KdLcHfX1{RN7Tq>-np(M$S9lV#zJs2>(-q`%i+yCe zw#GREivi_-F9w+YoWsUyQpZCSd=HEju>c|40NK=>yp0})yPAhROI%({OnQ+Qb84%c zqMR=WH@@%6#Mo#2W9iJN z4Ahvcw`ZPesriiYwyPmStlYAczNCFRQ*A5s^mdr)d`QIW&QCLt}Y zSEfF#H`ow#0{kq3S&Ts@#o1pv^ZyKmz>CHZqHEPxT_2^)7OIqht8yAMHI0OvO&W@ zW|g+fg``IUPJsv>Gjp(beseXdVHmRP2s;y^h#7<&kTCj&n|0Nc`hX9W@%#m66`9Y| zj{xDAU5~4&c*JSf~~3Urr#6r3sbe6f(ujp5#EDVWh<=3ZOcR2&<=RmQpPya z6M@=S2Ac)5w?G^^lyRc|e-ZV~VR`;x-^;db+rG113(Ku#Yq^%~R?Ew^Woy~iva!0e zjrZ#JJje6i$I-w2aeZ~3ADyK!u}aivD|;Pz<$)f2?U_U#tEH1^W@t{x;s(Y1?A761 zxVfTxkWooV-9oPsT>Rgf8daJ!G!at@d!x3`;+$U_DH|(hmAja(7|YmaCEa<6sqwM{=`&kFBO@wC4PF%H(gcY^ur4QP$Bm ze6$sxC;au%7g$nB2D?1^1WZkakjls|C;)qk+?lffbe%4UvOabzjwTl=RZW{c@EaR8 zs-xU`%~B!ifI~S2y^z^<6*3h)Dx~^emc1)|m^y7>Q1g<(f&arEkXZA9d35_dr3A3? zjzUh3_4m`@Js-`hw|r&kf4ZYWwcpPHve+gzB=ux2if8{9jLTXpdr3{7ENH)zfY-|47QF;9Eh%>^177jmEt#ziX-=_+v|a-4G5flW|H=N6u2{aJW- zMz^*aqxA`fKFQ}UiN8A6Q&{2y5e4#Pu7KR+vcmGDF61}#pb--ql4zlamm>elM_Wu| zg^~iKqR<*TrmhNv1~4Rfn<|2cQJ&^#_VMWP5BA;gZTkD!M_+mp>okd`FGuuYQPsE| zae1~2nyILt^)=$7eaJ5R%tyY|tw)&&N(#=Do19_fl<4{j-|*ahaEag5HA| zRS&nMP{S<~R>%+3uCS#OMbZ1SFYzNkDu*OG2COs1y`g^u>MXI2cAm-Z9v(a~Hb6?w z2SMU4O?*k_S4Efj-YO~CF3L2&-<8w$(~&KuD#y#{>S}npxNq7JQma=(4?0+G|BcP;MjVk zOl91pJ$}sVKtYcU>saP@QjbLcA1FSwPKt@fz1_DB--YI>6yZgq%`N_r9Y3w_$y(Oh z4^IKF3xRC9ndKv>dh8R@07rfrDh*{KN4_#he9h%Dh2f}qSjxNfXgC$-U~|t>Sl`uX zXBeE57P6lvHp5h1*uz_ot}S7rA9cxo9crQl2W@AVo6}fNKcNa9y3O9lA3`{r-kQ7a zMwc_q57R-cWwSEw_$<$stN{cw(F--!NwqcX&-B>42_Lj*c$Wg*$TzD*)5|AD{-$Y)9Z?l&s=eg9m}S3fVZ%j=Ox&%!s9F{R$=i1F7L7R zdZQ8HazZ-RHiv`HA?Pa#K)NG5fjD;Z?&n$GCX`}AK9JFBS$vDthRF2&JE#BfXi!FR zj@=y%g6^h_aO>&_pll;rO0qKT0wye2xBAhh&iq}2eH6*&MM=OkZmfFnillxULaLqI z$?Iuk_)6_pEU#ykXv9pCbM+8`4=WjlU#8k*c`mH>jRo3E0~0GqNYbkuOh%l0m=kxf zP@PXY!x3@A&R4*Xu%=vxuwmQG9{PUIv;Gjz z`jjBL_m!u=(=s!!HeOgcz;H=W!I$Q`*lwU)l(RZN6@*-1WmO(;F+lvKY{}`lNse=VZr6sQAOzA zX!J&nIEXuX_xf>hSsPw)-Bd?)eBA#+iBy!&Zi2cX&5xpE1@4r}z`c|r3ogOV>h}a2 z%yleJF{c5znem_tt#vyz7n#4GLdwY%XRJ|Cd9iqqCCqIj+#PmQC)dW-rRXF_y3t{o ze9hY*=I(0!Z)^vO!sD4)?=No_{!9YQhuEHQ@ysNg86M81f(boZ2*h+{xtyV@-?YX& zw9a(uG0pZh2R1#W=(4nUw}Qb@eSj92j#~F zl`pMn{=H%d_OzCH(%!k&>|Z>~YDsttXUfOEEMkrnEbUAWI0MPBV~qkPpQKQNu_4n9 zqva7eC=|^&5wpeBlZUGpcJjt+bwL-FBWgnT(RqceOjC6AL_fX@2zF-TW;r*!?rd*w z*LJ->IZ~7uBO@a+9jLIu(2x*4Th&Zc09C@C@tCnV(;fP-PV{aYuWa}$ioYCY4}N>r`4ja@3|cD$pt+I+9sz=H3xQy32QvA$lu5E(DlEmH~b%ku)QR( zfq6|zJ87HvunZLVDb~y|Gwkw+p~_+Z`Y3X|pA~&e+Y(28auyP=7?4ltb&=QF-0UA~ zPR&I~;!xsW;bCtj!3yU%-x}cZvzMuqm+IYx<+;BmsBLlDBw@rzTUsSo!&LUw+ywm*%m5eWk{L|Ftrt+i%NpMJ=9 zd=uq2a{Esl>*j>Q80W5z>|%@D&QsBH6bz9BumnXGI0qk`XZxzK|45)`J9JYomu(0Z ztFnQ1?Xc;7es-`Y2W|j^I68nRlRfQtazI3q)wh>pXxY#4S*$S|9BLfT+|P@f=ca3KHL=Dta>k1_+D(W&G1k0w@O+~>lZ^e^z{Bx zS1~0LJUotRk%yAelZWAIomf#QB#=WP|1QNCNyYW?t~ZHP z+K7<|WfBzZ`GK?y4_g}B(O-?Mik6u+!j7bMaypZQ{N!(#vyo4I$^DFj)i3qZExV|# z>kGyM=6N(R!l3;_3$JfWy+YB0g~e$KB!MIrt#j7|6AOAQR=;a?g{{!#7`H+EACHxA zjkpf0Tcm`wZcT%*qh80*UzYZ52sfcHHSUfFhW@d{c$v`_j_cg6%kbmuN_+J)Yua%C z5{{w!@O7}~rZz`zkk|8AwtC;;#hd1_0bMzyyTcZS6~9%6XWgHL5~*didSuFz z7}n4|6PHi!zl_eEoSmHo#GPRtiCZ2Ihrz1v>3FiQEFoRa7Q?Q9O5ziHVUnHodXJdR zx8)walWUZab_xJWtPjy|u6t0KPbp7#6?ueX{nXz!S+)0OFVdIS4ILc~*?v0L@A;=C zeTal5CB^OK{EWaY!21x0+zrCe(h?c(PWj|<6qv|&f#lZL2u=fO@}Ux$BvU6UD8 zYeiifzGbT-{1&Dy&3IJ2u31WTDFMEIXb*YS<1ny9!fy=|VN0*L;^|V7G{-O3wyIG3 zBD{2cA;#nD0eB71_=_w&_Q7aFJa#Vi^adUb!WvULUD7+tGtl1euC0*NazF|xA1C?EDNAZ+<4$O{3cFeT*9h`N=$b5dTiIsDCc==MUquc4_XX=q9k z>lcgt6vcteM&qR=rHP@Tf+;I6944LK8B_G27(t(DHLRig!bk!R*c4Q2wWD^x{}R$A zjy}>lQerZ&d=*I#aYBm5rc7O$UipQV3@EgMb z`cnw6kdsK@M!?N!lp`A7vS1AUP6Ys#rm|;$w*J&hFY6jL`%dfwPeP@z&>iXFU=YB2 z7n1t9?H&neTdGJvTVI;!i)9LBDz)gGnQ|2ytL*y0nx4_M5#fw43m zJ)*Cl_-X@}#RzYiF$#YxoWqBYOyC0+R%&d`U7Gp?6(sr*#$Gu!*={6EJv+tgmSm$B zb_oQQ=kW1u=q1v9g@vOG4cSRE|C0ful&PEZ8@Rjz=v(HI;&>gh4pDJdm3vp2Kn5jb zQSQ8ep`fND;b+YhyeG>~QUXL?>QcyC%)bab4&L>I>HR$HCSdI94f z71&&a4E4fHzwCSE4C|gkP&Oo8uv87r3Kh1xk*H zdQ4o`ES3vS+y(^I4^nMlUMT^&8)9`_$Svh?1h3j`LPDb|{X`O9z;k*G z>y5#v%Ag@Jx3(CHk}1> zoM0Y>DT{V1+fKKEoG0UhGGOJDB)PF@>`M@!p)^m?bRoRAMWnc{rjm~NyGe;dyx6}I zrAjbB2{-oE@dYG1!n_XS*jDW(Whln!mXa|5Gg87o8OoP7e2-8Cz@HR*N!eDB#;*WT z90o^({7W+08ue_e=LGcu;b1iUvKn_iZ`bOmzURlQkFGC~*aa}i;HLA1;18LM`!BJ~ z-lect58)L&61SCx7o6qhia*c}evx7svJRyD$05dRZ19CZNYitR2|Sb}z8v+tW|1B) z{yafFeK$ZvAam^!7iC$=jxMHIVw5WT3rc z?dyb-^ZuG8%AoTiX9;u+G8cKCnRvQHH`MHYm;5VpVrSfp%}8`zceD;uEsv>-|s>#{(r7>0+A)8{dX6SJSEsKog66;pBSm0ao*q+Q9thu=ZphFS=uB zqfsG35kUmG6Z@PdSFpB%V3YxSfskDX6`$1k~) ziMdLN=T_>c?lMo2X9kE(##S?WH1N_H496sT6;et;uTSGNm2s6NM^^xpKMsS# zSN{@ItvPRzJ2#43cQGQbd#TLCh5|#9i&xpf7ceb#t#LeBL~iw88|6F)c^4mf}f69(mwPrId5dgAqWeCGXYPiW}GgR(Q*K57NVXUG2sy zy5@3vyJ0#Nx^H7~)CT=c*i@AloKYv`KmR~7jaq3Ga1$gm8_jD^$u=*(5bsF6h&L!! z;(Z6ZbykA#>e5)*e~VA5!71%O&}X}Htrzzd8BcEvsp!n{^A}%AtTT;#{a@)WF{5pe zTVgpCYx6=;5EOD=b7LoyaU76&1^*P%T$dI-mD%FvDm_Shg9GD!AxX_^GnZhI1Pmtn{M+po9qZ7AJRs4-=%|fLD<*hLRqd*wl&&vBu=|(<{xt_BSR)m=)ZH zk&?tWXg$`z4aJRht36P@-fn3BUnpufv~hcnT$sxJ;AoZr#LYg`6cr6_aCtMj`@l47 z4dO)40X2}2>vBHEgrmI9NLJs+Omlp%)C8p1qr;Ivn>zG96-m|q63ZX(SE>Qiq_lJl z`+;f5J#VjPZ?z8DPoq8kd!CkdEEbB*(rwN9%l&>M2h;N3wA4|J*b3c+>Uv{MEpT*Uh^o2_AlOUU1GJ~J?%UEFe!>6nok6!=WgIKCsYav6D+9xXeJCY;Pj>iY3){ZU z{dy`Vlm8SZitUpz4k82&&agVcC5t*rmhH)f$%T}<-AT_h?^?c*mc742!{13s`k{~yljICkYrGz+j7Usr17`c31 zl6a?_F%z2JsatwvcPk3gv0{<2eu|Dl?dZvWK5mb#e1)-RGaPEDJdMhR1I5#4bgB%{ zm|5KLP+Ij_m7aI)Eaa%Nvn&6hLJ~RXJTN?(Z^yq&!=DlVR444!>O#hA_%_ssM3^R! z)-4MBWdf^5Eucwz8FI_`!LmP-%N879)}E{?Nr2&bp2!AE1@tX3#=^UEqk(lp2zrMX z7)r7vs4=(39sRlDg)iZc7OLPjHFF>5{=+cMS&=~cK?^# z6QONa6h#Iod$-$(PD$08-W=&=`Su3Jk(0@diQDxP-+!x<)g5*(7{**WKx=ycm#kCi z!f(Y>y()Nc94p7JxaLkF@A1q!q*ZK_r=6c)w+E0o@-OKbrQ4gD zo2Ze}?+2IoCAb$I-A^}?P2*ad*$?X>_x@zm?LQ4%yQX`JTyg$0MZv6Onv@U;J~PX* zA$r1&ml$dLFv^~&FoSbMnG`qm_fK{h$Df%eK*zJX)O{8d&i^B=593j+-^op|O&4RR zq?Wxa9FEF>R8_nlD?M^ryCt<$REj=1f8hFa-&5X2{9|*Jd+XnYm?b8OlFE`ED-z6uPS~QHoDGR zi3HCr&BUr>vV8CWbCEY!m_x%lyLt7{d^y78^&a@F2&DHX&gsSv_BPtDs6@bfQ)A{; zS0^~}D~XGDOQ;U^n~NtZ{KEyFH2hT;x@;hwol)d*%bQj7nU1e%2E6IaRw&Y1+1jKg z6p1Dj#>S>QvB3Jg%z*(`_ETQHeCz0XWQh&gPI~pt)+SXt3JvLiY<__>^Z`9@INj}Q zt>HTQ>TX3BgD2rewae|ow--xevhX)Zo^G5xEP{t8trve*7C(T;Z>tqVNtid$40dp$UvT@0T)G-_!(k=uuP=GC{IrlGu?-`*4tU8u2p zEjLVZ@?iOySs9Q=VdKm=q+jF1LKR1j`GYXUzT00V28y#rE9}eV=rA9 zS>lB#l7kmdGgoJ(SqLeZGk%p^JRbn>|3f5A!-8Pgnwada6D6*5X2^1VSZx&_xJ>u19 zq&&b_eaO2it)MqLC{tEEi{+c~>5VPzJAm6;@`pfK{idc+l0JG|NMyVDIR0;F z6&n!>YP4E+8fM=?xw;UoowpE0dXF5isAXK&Sf9+`SM;i8wyHi3fofUSYSH8&{=l4H zGwRMv%6)tj`-BSI(z%SzT3yDN_wR>hqi>n{PHW-fMn`> zDAUr%CWPF*9VE1Xz@Kz-9elYl$)-AQtU$ppFC?#5T$0g4tR3->ehS7j6fb@cP-05J z`-a8ic>R5z6wBK4`YxO}d`@<8BBcbEhph#LPW-ilEoc3~->YQ%?+P*Q4N_2J4?B!s zKdNeZxLbO!4=mNLd_)E;1q_du7Jf-5iGsG+gWiEdPn$c}^H5be&xdtEVN-YHu@_|~s6b`F=`GL)O9z2pw?Q6$4m1ss(T1I6+S z*mA}k3w!c}e~fIn(&cT{0r?aPn43)h!aD~1m>JLWGTOSO*^E#43Nvr;579ksCpgaD zX-9hY%=qbWweA1!3{w|i47|(LINw#c=yTu~&f!7OEywyzrALkT&0%QHa!m6^2rH}X zM4Y54>sz;^=4l=D@t@njgPt-iSOKR3-j3~&yE!5W3KSx^jHI%Rkree-u|=Qpt%>4M zX6D?Nyp}Z76@5PCg`Dz`PRxc`krL@Kbro#>OG|f4IgDSXP>ooq@FgJ=Ix>@0HmDEN zf0!U4+kf8RHB}7ne_0L{0Z%t<7SGApDRe1UaeLZ~9|$w|5=K7j;WHDmpVN?h21zGg zyY?Fw%#qHVo?^0$L7*?Q2xq%T-K`Wv6DY*MMudJdjNW2$#Qlg&2(7t0|7ypJ0Wzd` zCZ53J4*n4q$)NO0@-Oxy;=`CgZaVLtS8EJb8TEpQ*L(90Xtv|v->hgyOk5I5gmMQg zGI#^b&ddl$>>}a99cD)a!&JXday+I51`eK+BWF+K?hjL)6f&TtT)>RzF0Awnjv>D# z{9!)QFld*oE!5d^u8-X4=JYg)>Q8>>RE3#`RmB3}3t?agq@|^{?s4>us1M3RJ`WNk z7iXKga?AYTzJW$TqbE`#^9Jz397cf1oJa@K2{|w-wQUzX1sb` z{w#r^G*j?OHT=N#hR6)MsdilG--}3B&O&oNeY$zN!DnM^S>C+wHPjYXGP+Dka{`pK zGt<-EXaV<Tj4OkvTT{gpjMgz(OXO$* zMhobQB76J6g9aKJF@DL|<6DkbxNS-q%_0;fnVG@7*fh{)Eat-JW|-uMTBX0+?zRFLptXo##RR8g(O`V_+n z&!6-4Htdd=3HAeeobbPyz6usXj@M*EIR#hk^BTTij)@5 z+>A`bhWiv{jnIUyESsnhC%p2LkN@hKc79TI(Kx3mg{uP6=DSH`^?BrUci2o-^w9i^ z4+@)kAg2OUQOd(8{Y9Dy;j&}b83MZAo!;{ELp}cs^U+LDTcaii_P5*5_=sZmbnRQF z!Mfa+yJ)dLCgEFC zj5|Y01|^@-+`$oEE>73}T+TyG!TE&j6+5%U55?HkixCfL92H7ZLAj$aZ3 zQD5A)tav|YwXxNr>d~c6?!RDx7-W^-g3Oma9n1OQ7T?gH?}2GED_M@S{pLmqm=14e zs{^2~C9Hp)yt;QX`ba23Lqpr&Ue5Mk&H_Z=)2snX+~_}v1TjtF$JOVq(@%p-h zcczE#1M$YMj^pDohwSiP66lCQ8ranCyT190T;Fl$%q7+SPReau#Eiuhw$X7S5N9Pm zT8DmCZRuU8Vi$02+U(aSVSJ+Lo;&y>1BI^8wQlpGgnQGo?f*vBZG{l6qct(rGWFkpZ6gGWC^Cn&l;E)prDz5 zc3>(8_~pb9lu&l&_Tu=E>^|GWh=+55l$omE6v#lxd}*1FfY1s5@L=bNqQ{q^{{+9E z*VE3s#j8HclNr=Y)^=*7*?vUnN-_e(cO*=qVvvmti^iq&XW{wc;);=Je&1vngEW$O zp;e#SKMJCHY1DwS|M5)Y-w+fXP3*k1h7!c#?iRUwUjj_k+2e&xoc13Kqc=0pf7*+8 zIgt2_YQ{$+{|gdk6`PZngtMN0fqY8{`-JQ_kHfKvuLCR z7Xd~<@8)*R9@0HhXB;MYrI9o~?gq@P@gX9El*Ldwg6I5z_)PFlA}#APLnM%U>Ii8_)Os0tUL%UpEQ<*}wSy9uN1L zJ$(Ad@{?0{SRi_W!V0FveZS(EV6|7w#YC!bkdp(j5wIGGT)rY{<*LXt_a${K@^^~} z;)w$+w>8^G6szD)6PtRw&x}c=^rW-1MiADL3A|&89O|>wRzk$J%wK&(e0@zKyjP~I zPcDq;jbP1xcVA1KT?sO_Ul_-q5gr2alV2#wD9bqyF#KHnkCtUMD2JQ`z=MBTTq=H6 z%lvM)z|9u&%A>@YXT9I*Uj6sD*|Zh)Ce)F;&mM;|e%I3hcfG*G8q})jt{plW*>3=I zcah4mQ%l~w0e0P_0mi(Pn}whQgA_#uO?UxZ#Y_MEn-BGondkgM}w6!@{1+CDp9U74d@Q_bg!fFsTq(6UV&sK@!KtKY#$~b zH)>4-qMi%mw$T=HpSZj${T>8SJTx{g5HMD2Fx(QqBNKej6IzO9PE`|r?7&oT){Fkx zs5wnGGigp8B--wY5h5ivWl5iU`^y>QnIJv-92e_$l0q)mMdSXDe|Dr(h|=H2-;JfI znj@-POF5QkM_JQK*w9(}F03Lsq^bYd_C|PgG&WiA@BBLG>mvZc_14mXC}!KqKKnfsNZ;LwmrSCREaf1>A|Xmk*J>&Y}(P$#jG z-^rN6E$bkeE6(bm?Lf>ZM?cPi>*njznI(`o(f;_iYG5b*U(>sCnZuGX9NgL?$h%;l zqjPue+sTue`xhQ!5&^v^9qQHni2tawqgzt+fzwYvw}?3jrvvvIuj{m*t1XEM+vBV= zQ_+T1fKmPWamKsSe-h2pVc$o$Nz`_=*zM4d8lFU2?Z=PSvwJ0@GP9LXlsg2nCgX$G zvpv({e1CiH)XRgRhx02iJuW?MG$^lLH+P!fA@%x9o>=DAcSfEP7|ineEC<{Jbd#^t zXYEhfeJA(Fa7tp7k;Mf-3ton-J(GNp*QL*HP4Tm%KF5}=J#}7=$p`M161|+>AkY-Q zkIPxFw_*-^ZVG7NhxQX{T<})2`} z4IREiRdcZF(u%5ayr%np@t{ z^S!$hJ6><9u7KHPF)I#jvA-)@qdYpUvbnjrnXl^&42-6f4yTEc6RNSeZ+T`&?e{Zc z7sfK>jEyn|k5tMw(F6)xHXia^_xCaev4Ev&zRqmITxm-4Si7zIae?hD+V}ifM#m+7 zi(+!5fNEJ>zwo5=Z+@<^E5)0SKSsy(&r_}(`xjc66dCu8i!#b*09K^RPE5INnb9kH z>NLJBl(d#w$Xe0^F3%3Q|w8W4EDi#umZWb~>?nE!qbn4ugLPAgaK@6HSU zME6#3wdLfuJJ2cz_79rUuIa;k@*0D=PzG#d9o=nopdskEwryLvQs``aNYyRM|DQtRq85MpM$I{j_7M=;c*!yjr~YF>E`%** zDW};*F(ss>aEt&rQoypgy5vizF|OL$VhX?Rb#V-gaPD@tMfWI#?P&kox$e+kQ-mSM=9EtiWu@OpMST+ZTI>1swD0_v!`$9 zRgkz+B$uf|D~QO*{(MZ~U^3h=+GKKD-5JFEh?;`%Y~4>pI?@{cRCl`NUwSgPGT0hU z#ssSw{9Fv?lf5BK`)f3iHt~jOWR@>4=5S5(6hWOW$&sLovd%TlpH0U1xdkh{?HD_LXf@AK#^bEOQj>$aNltnp(+PS*++3Zgq7|H~z)f<3pC^H5Nd& zzeK`1h~0$th=CqI*mBai(){{(v;>56oSd8t`n`!YE#!?3OW8JmuL5*Gh<`#u+LJ}A zWoOlU!0fr8r`apQ29d<4pObv@Lc@GH_pkvruUH5I>)0chxc;M}NpaQAn+4_(CCZ_6}Oypo{`9<$nNDgyBA6DkcsN?65e74*R_4%KhcWjtIEvCLAur5OU zp{U=~wP6!4?H_JzwyKg6$Y~kwz6s^+>l`ImLmqUqS<>wI=0~mNqB4jG4e0Ve{fu!m zdRCrKtH`}2#CoblEBO59*e)Q3H@y!NHd>Iz($Pca>8HLohIyfZSya3n5dQ!>(B2ef z3APr+C>lzR^4%Ozf@qL-cedD}sOCOdzk3|Lik}G7ObBWHXI1m65&+ug zQS$|07Kj@JE%9;of5K?8%Gmu@)SksTlOSggjg;6bHJC9kvEX0xg;s?TDP$uC*pBFju+r+^g>^cD3Ri{LKmwl&Ihfce7o(>6Ud*i z72pLGiq}M*{NMvAHjyEjjc-4bEQ#cV?j(Np+KOo+U9 zG>CB$aNt1Ze=B&52UsPb5{|2HYH}TAX>tPo&?BWhNA=fxcH%`RfI*G8-ZrePZ1AVc zPjs*MU9o+z-VvVmsJP2+{jH^J6}i-}|0Stp<9QrL;)iYa+v3$7jYjXktkO}YnqK71 zg8JecUm_}X@uXiVgS63S*}-uhn*Wp0P=K2rYq?FeEvzG<4IfEuN;fow>_01tDJ_br z_Z#|&DVBli-u=Wz<#bCnXyLrJ-9!MY48j{zM1X7o*M4W??8T$wF6oQ}C(+1QZxTRF z`2$v;WM5aGEn&HW1xWC!A+t2TB9hMbuAi@4zaRs!n6;2HIX-?T6%X{Vcu)@d-ob%i zd~y&N*ELSVKaT<07Ae*F#`-O;X1l18Vb1rW#R1cf&ZpU?6GEZ~f@VmPJGJLX*D%;}T$2;n#KEWFr#NoW%KPhu>ctf#) z6)+XRt^2nc-G-Jji~sDP@G-y&46WOSvLZG|oC*Npc(!uifg$@6xck9qR8i6zD)W$+ z1gC~?3@zuOJ8R$xnGASicKA_&h@^ZlePb;LJ3BH|5q4uOnh$7J`g{ju;epm<;jq9% zM7p(g9W^UohV57pzywDX-t2#LQ>b#BdmTP8IwArAv0D{-sbik4rkm_v#JWp7J zI))R0oj|GaQAcNXetrP2^Ip2+zMoA+;56MbM__;paI!r_o-V2^p!v(4n7|stJ`;rQ ziJ6m?3x4Qq;~#E}Rc0R1mzt5E!8sE=RM$@%Mn&UQkn&D6G0}mC**4CV(|m34&F{Nb?+}=WDMY;@4pKI!tdf zQ%CT7W{@{Cmr7z2i&UjbFgYbVpVRTMmN*TMpY4(S`Q!?CgB?A8dOp--Bm%WD%(j zZIDfgwWylQbTRdku5{zKy0v+0l#m%{I52t>C*(xk;NUdV`2`vrGKkEcirK)L*LzHb zlawYz*kL5F!AWpL#UA~+C`d^9%Wi{hWk?+nWS|FqN)^bebk!(8-Y6Ssna46e@JUoO zn(3(Oi`j#WHcnN3@y{^7Ex*;8C)C%OOFZwH0`QfzHpXv7ox0X9Jefzl``0fzz=@@s zc!bXNI^g1JG&zd$sA&t}OSM)`C*b;;xH&e$C4em=1@Nm)#`TcY$l_^(`TXBaG>ve= z(6Qm8Az>;wBW1nBAA~#;!$U1ZpHO&Ec z>Amk+O>XjgkJ0b$91yrA$kUn?(SEs7a(>%sPLCwXj>18<107~9>5rN7$=)>J@K3w< z-rgX!&5_G9`edKLzRvzG_g85v7@*0cnh%uvjEFU5jv*_VqT1gFI%qVX(!tp+o0SyS z5tcfHSN^G_q%h_kHp3Am@;yWg3E^)zVMnJx#C44)3LCxL@9UVIsCMZrBQL=PyLMW- zM1RYxY~Q`pKu>8pEv$Eh27IbBt3**zbkHruCpDyzwTC z87V>W-Jy&Y9UqbL>2LYTQd~+|>@FtuQ}9P`CUERsQmQq;RVJoqt#lwjgL-9U%<+ea zA-NV^NB1@Pq?<_Z|7OS4fBwiQuh<;AA^PUCt>Qa> zwLD^>HO&a<{Ro!kf&4L#+*ek=VGv?FOo;IEbCt-lN=?-dCLLpWbE7@0L%;p6p7&2v zE~3gk7OL{_aDisu^185>pm!K@CqrVn!uVwd<*BXHE$Bt0BtHc+O&D5~cnUo0tVm4u z01;de@2nF&D=XDGcL6h~rmwjoY7lD56@Cn*H>$m|dV2={w;E%?_5~l+*%IeF4@lNQM`c zSrZKC^m*tbT}efYGC~|nkv-j*;vt-JGn49d^klsz-U<6pxw-T9@7ap)*un4w9a!-? zww<)j8Q6Tle*{h?)%RVbc;7%MNw@?B%I|&XumG@t8GwKw)IDpc8Xv7Y8g*0u@NCD% zy5D3Z|AU$o8!-?Y(NZ^f5=@i(3uI^>eC%yp)|rwdh9KnaaXx}mu7QH= z{0@j63Go~on|0AQUI45AL3c*-d{(EcbL}Mv3v4{%8|f%|VSg&*MmDU3sR(#9PVbLW--BBM^4y6WG(D%GlHGs0`z@-ro$Q&)aQ zrMAI?iGYslN!+ZOB=aX7+H4uMbPB+ycs9uK`TpRH=p8HDy^^*qbXRD)0V=jipG(27 zXvYJIsA23foCFqBJ6}BOU(|C>y$SV~>O)tYQVO`pLjtKtK3ktKnIN#m6MJWbk9s)2 z)_UiVE%v99h?cax$!GlGRVSw2?CuiZ5>LQrMK>|veWD&HY*A&HxZ%YL)d|%3k)>Tt zj6t7XBc1jBDWjv`We$IJj74@{HC08v+gAOVe|Pv_efyXcjw%9eWqOsyg)&c?f;~V% z44`mfbCir`5+gxTkD3>(`i)&&qB4C?C3yS2iwK^VxXsV{Y|UJ*q0^tV)_?R59}ddrN7{Y275df3%d!iYJHm zd#JA0k?jlB_;|-~xO}tmIY@lbiMj(|L3YCd7Uc3s?wN=*iTP}dCAJL!Lilkk0=|fX zX8AZ5($V2B%Y}Kh?Fx&l!pGnD5HN`>h@Z|j;;zqulT^%r8kC^OHH{Ae&Sb)rv zqe1Wv0tmm*@2*j85_hG!4(+$N33A`Xqo8LZrp?#7Md1SaCUUeP^CLnis?~Q*w+DxC z1rCN=>-%n1)R{Dn>BT?A({!7V)EFB%Q$QSGRi~*xs!6fjN1Qfa<=u$I@^7$XXyj>9*&8JiXsS&7DZE{-J*J|273i(@7O^$i41yVfN$PdaZn29~ zM9OC(M}1?LX8>#zk*pk3;FHhKgaa{bON&F^^DAP2A&Tu8JKg^yt%Oc_beQzMieCM@ zHr?5oU;yXfYUq8~xQfWlTxd=hphAlNm;@x(0s(5(`6e(GiSvnmJ2PQide_%`y;L`_ zs#Ul@VBaJ8_PSkIfB&)Da@f{Yujc1Vbb#r)gZwp`3$XYR1;ju{KujpeO{ua2VrhI? zy8A2TOK{?MzI}oj-&@af$e_xLNjB54pZakz4AdFd_d8MUS<1CJQVtkFf?v#DQ=}|o zK^y4`70g3p>-jfI=fZBG4!IZ(PzkMFt*A`loPBl{Cpc@_Jc0g*A~}46yo`6TlWkle zw5~iC7lhK71tRpL&eHKCEz!vVIp}K|V|6aw5Vh{C0SM+7+NRbk0S@sjBxY*fBxLv@ zx#XXnKa_rj7rHp9QGr7=7*kAqY5SG-KJ@Msd-{55Ao(Z8plcwjypBY4XK&Ov&OB>Zbbb9<|9&89X^^KKLcu2f)i=%+5NkD? zO_C533(8UB5G)L~)k(?r*b3pm{jmw+pIss()t8k*OXaZt@|@@`?oS*=rS~%vkvOkT zSWp3*1NgFVu7DFe@#l5^UtLL|sx1z4p&>lwu=URkl2MP>6K@xqqMSz>mZ|h(@jcvqb?v(+A5xFEHlld^o*1uoa2g zNnc&E_~Gm&?z>=vFRRDq^O-bANd(wPg6d(40WDNI5|FoxV_gwne7O9%`gbZ`j-h458c zj)jpXBXTD5z%b!S;2$uU>bhdy=$qeEi3H;?OKj7@SEG?>>orXv7!A;enH9$5Q~&CB zb8Yxpq;WoD?=nw#^B62xw3e`m|LwzI$PWlFhEi~t?2&sPNXNo8Bz_p*qhY<@u);$< z&3I7N=pp&jipSrydDrm)+jlqIpI{#ZPsnSUNBENcQ!R4z_CK#DzPsh|V?P>2vPd)m z*jivU<|C$}?iFdvqzWU^1@4b~_VW)2(6n-a?AT#>8$=TL_rm^3VCxw|8Kn<(bR_yV zpdzoVS4t`qHGwQJypau#*}bn?vuDTI+<%{m8u(1WwU5-JyyCDOt{=e9YLjN~^xk=6 zoP2;#)UeTps+z&qjpT+(=PzbwKuRHr*5?P^4{5KtoTTY=nGivbnq1wPToAC`4+)3? zxTj@njyR)$t%AGl_xEs~vH&kFQG-=}*VtAyLGN{K*yyJQa#e3J3z#;Fo5z`nj8(mc z?p2>UJ~STJVf!>Sg3?_wooBNF*M+qCy5cV=_KCc}-7e~NO1J9abQ(Rygs5|Vxtuns zr%5s{1!$y*M=6rxHt+7``4Nx@@gF*Jb)bR9Y)g`_Jds=kKTN!W7&;9J0B23O*Rycb@ID(?>G{=FYp;cEe#aQXr4J3mt9 zFe(g?+c{IkR|}-OE`#>6H2o%~f81UuRzt6g)RFt-%>accGZvNkzS@1P3Q4Zj=KQC8 ziwgC#(eNaSY}njOL?FU84;!C=Wd`objoXi0l+W3pI_~@(j(8pK7e22-8}mew#AjwR zPys&R`WLpKmZFxlhtX1G?SFHe%>Q|?`ZzfXlXla+?vcqFU9l+-df_wc2??Fe_>eOp z9WhF@vVsOL6A}r$Ka1F%t$@78n)R+~j7t$#288K&zGjk=sRfP8XFm1_#lVhFGU`!`5yDR&H z)}n7V;6`t5o8zY&m$FVkOmpT z&F_GP`(%`(W9N7YWqful?_&)Fq8aOhm4Z4w-q+um(|{#)dpim1)Da1|Ld|;4GW-Xv zJNaWfPv4HR;zp&3MXE^=eWiW3%T?Ri^~zgzrGR(QgL{L6&3&Sm=a5A!=$ZN>nwY=F zLg|KohrN zOcaL@JXmnI;GRHm4ekVYcZVcEkl^kv7w!(h-Q9z`yIp+4{k&hDI(2?fm7+-1-m_1FYclqpN*{+?rUU^ zUI|3D^E2!5qjy~HW-&rmZ1c;>6;obfd#}AYeq&4bO+IqIHmvjNF#GCIs4q)S5cmtO z*6&mpCN( zwI{%e=h!JD&#k>?xXOSJx|i`Js%2en&mssLPdezbzEgXzF6dk8a|mWs+2ryne^gay z@HZ45z>z>5OF5v(7M$(xj%5c%lUJfw`ubt!k{nop1|Ru8gGM!&=2LiqC=u;|)#WXH zVQz&7_x`|_KM*>C%kT7NA6_vng{k)h0f(ZC6(^q6#wUcwS8n=LU%P5sg?ELq=?^x* z*4MP_d@Kel^6B{N#5ew@krDf+w);M&%Ye=LPnDb!<-p0lNwa5jw@EMKd1LhNy-&|Uue2ja;OBW5v-Q3xbbOs1pn8~%#o8Hx?tPyVF*&H_fC4< zir2!f!8e_1Y5zbglwDA=Z1(?2$oKO{>!rosIV{tG#7G{oVH`892`=2jv9a`|5thDx z|9+S5ON?+eHt?^C0!Z{fuTA&2*WtZn6r!D!A7c!T|7lBj=ByJuZqIIe@S;mve=p8^ zJ>1-lx!n^EUcO4p9$ChD5DZU5YgM|*s`;OFp?G8<`Be(LQM*Bnj7?X3Pm0az3I6&3s+@AQ19$EyXIja)BbPVFwPG6uqj+wK3%w`ZOIOK zX9B7X6f=W#Ci=CA3d#F~*QX&eeH?yVYn`d))ISB8<3Ds74c?d%EN=fTQ%m-Vyc@Do zzh?&AsPEHFSl^n*LA=f9 zNEGa6*-TNqA#qV>_jm6GI=3zo!_c=CL`EpN>qfrgz+@FqR|HHl*iRIMk)Lj-^(?Qj z?{m(r$QCswH3bFfGtoZ7+K&Hu`<)B25@<2mqR9QDS1mJdq@$A;2fiCfxo>ap&~=QN z`07R#5(inUx0pJdj7r_pkOO6QkAknui)?WDJ9?s0WX}pyS~CHd#q^_PLi!213})w> zW1^!nXH}5&SYvoi-l(ZGgr;L=b1d_i3*6os%xabZRt->a;gny=Fx!mp;COWT#B2?k zC+%IMD|gPzx0#uK&y{zig$*R{KAp*oniw zxGU8>?SIqUGEgo|(>Hxo?6Kx6JDRj3OoH~C6x~cTso<*{O7#d!jMGN{XEz_;RNn~g z?Z(s(mW*3ygjm~*-NtuvRR482{?x^ZhV55VE(;;?MjLa$DBTa@suoK|UdUfgp*_-@VySzeQewp^G}U4rxDKy2>isX}qy z)T9^5YHq&@wVtnRQQZG~;8@NxBFfuT5AE7B$0n<({n@G3;Qd-{Sxy4LY_c9QgMtT- zyJXo$qTkyI-A9KOuKy^w8ox-e~K}zoX(W$41Ke1;r9W`AqT>DhP-1MVua|XM1Gs?CAz> zRp)^uuRPf5cJ5p1pXXo{0aP~hkmvTRtzeypwK_{MgH3k^lnvvruGv|*Or5FNPJ||H zc`UB|)f?8bW3X1grvO64huf3Z3K#O{#IP_|r<}1OY}tg7pf5CH9qSF&>6#(qRyD1T z`(WoPqM!G}BZbq`9)%eXdQlBIE+R_o(Y7zLhH3G840TsJR0fe7#M!ahpF(3oO}R&G zid#yAQ~7skiBAq|!RPDAA^mb@F+Y5O$eGJ@s;&*D49qIl?#_AwUaC_O$NdDR)qN}A zVQ^RXGgWfJuWQ8xBgj))kSW0uWl|UXUqyscc^9cybOOeT$;^xtZis@J zUM~k={UpDiCfMvHg-SZR$uf!UD3y}k#kCG|4pULvBCmnH8tSg;>-Dn2>(LDi{qhd+ zuv9x5*r_;aa$j$>$JzmEUn}K-fV`Ga2-;;gYQ%JTVZ1G39-^Oc*vD%&$ z6F0pn7urvxkWBHrGvZC(cB&$C1-e7Wo6TV4E2XYktT|+~UY183f2)ydsyeu5l_hfz zWQWTWD@nEI^-?2%WCmp>%QZ)qiUE+Y$7^+Evi>8jhxXmoI2x(A7vu5i$$9UW*E9d2 zo57>h&eX@dH2o!QE5x8cc;!bdC1p)K5UgT*c~>Yqm?lZE@XxoD6!v-|c8AnVLQpw8 z(E&j}9rOLG(WTdnk0f;bjv2;0fjKL;D6rqvBdnsM>*%M!I>^9j8alt!Q^QhHQbOcI z#*VYSp%-{+*wVQjI&V#|UGz?d5;Zli9&&m6q?BMr4Lq!KvX4BSi8PI2fC@MPV%7O9 zxSYQ>>AXnC&60NOh2K|5USV`5lW~gUZ_1%V+TLRUYFlc~`d;jr?d3*KIk#hoOR&xU zX&PTdqwRRmdR;+MPQBdcTude#FErc1twFssY(a;PeBJ%14@nV~(_u3D@>d@YYn}Mt zY_=3CwB3+ZF|A`Orl(|4UpwM`4K%S^l}CWB{lE#Ss7iPo*3SD z_5Jg>s=BLr^MZne`6|j7i3o{5i59{n5&CS>ao8WzxUN}X9-y}?QN%1(EA=tkXIXJi zCf&d52ihyVxAo&K2^_X*&(MK^zh94UHY`4>3yU0@f8kNwq8ogbG9KvC)A@GwNp-}XE%O*L}!z4SJX8lONIQ59Zadl<4YL9~L@Plz3 zaE6jG|0?k$RKF#!-7~*=MQ=0Hvs$qqDj9JE|F+=qEN*oGaY3!~8SUF}eesTJvfI4J?9$@tAMmr*-K~E^b#`d=C2k*n`85xKgnB9>0-0*jjW(=hiuzuhQ z$P7@$S07xMZbfe01WoSsgMuDq*b&3w2!F>3>4)|CMZSv9zaoUcg|9OSFz`04A*y}( zF5dx3NEMJTOn!aqDPiYfk5AtnPxnY=BKWD71p<=vJVOfL6i>FQt@*D^=O5{NkF-3x zg3gnJq>1x-ew9(?mdO@2+m{UrASrNBzZPoGW?~i-npn{t5y*I8?6LfFr5JKJK00>A z#Nps@HtmiNxo`7{*p_348)zUGXr1gaHH=(n$eMII?wmc-oxS+E{%Hw7*RIX4B2;XK z$M53Mf3>xJ0Yj&{Yg->Jp@%C_%W-G{$&O?k135m5f}ETUUEUr*0?881_tb9&=wk_q$Zdwcc*NB_LNLCw-m!GVC3WKQ^A9;5Q9bN%8cJ-}~dwCA8As zZs_8aT&T`&AzUHL+lYMuviD5K{F_TX(Ds1TEn{cz-^cMn>z7x*anc~7OZfclNQ@NH z*XmMAwftTCWTP)@WYj%qOH(&n-uHGA+rj(H z@bE>GeHbVh^r>lR^e*?N4wf37`yct!!hZbtVe1WIiDs_eT!Z~?!G*$yH$r=;JET;P zU-&j(P=92EckMe}>m@~!3(A&?h`^1OkA5pb{lD5Y;7XHTP`X>TrL3VkfE#0s-?l{m zj-@_`$QbUmdC&|~IR0lESE*9^n2naay-_t>PfuJ>Uj<5WK7TPr7rH~LelhkWe`R(kGXfj=1^UGTN+L&4moA9Yaf_+M;?+=rK&BUG`@ zp)_)cHWd`wH1}yE7ieexpxDsx<9{Q*2xD(pezmoxL63`Q)i|uL8_OL?iTEC~nrg19 zU67BPQk?N8g!{uP;Tk@lWC}Ct39ll6f{k%3Q=Yw?)pO(6^x$7!e6YM6)#{=cs^wuA=`|l*G3u8lB499m&9Fpr#QF9A zT>(iPV;~+z68@tujvAZ!y*6B~t|=<%D<`$L0*G)1DigNutjOb3j|->;dV0)!+Ip@SQ=CyaKt1kJW=BDxpg`~=<2bd} z{f1AqwJ5x8=h!iYA40fMaFn;jn}?e~AM?m5?#RK^d%Xp!#=d6k1YW-z`U;wWKbRUG z|J8o|qal+!7Mme0?pho07tc^z=lap{%$!~6p7o7_NE>BN&WLZs`QVA5RKi+`T>okw zfA6&_tHGxxqx_$Du?+eAn9;u!Z%(!xqD_OV#_+9jKdA=xdWEU``^8hFc*ma_dAbD) z+7Q_uIo`SM+PeMU!UAuDHcpq5kJfGzNjv-dSxrsJhzxZ;J%sKdXJ=>sb2i{TS>N^= zjBWJ@L*+dxyZZQg+~>zHR4000o)OpI(h<@g=UpqjG>6G0{F|2#Ha(7uHxO2pCC0um zA*P%xe{see%U)HRbbSApW!cuVOv4{j9uKVGVP55Y*Kr{d>HM5=lH}!)8zy#l(kKp8 zJU|}~{jOK)MF)N;&jL8_)Fs9UDsS3^tAz!(ehR6~IT7D^R@1%pF@;eNin~=*?--g# z1``w0FJD8|dCL{1XJ&?;QLCK6tNa|Bcj1u^_(FsXetd`Fg1}j9gSm}WnoZ+Pyig6{_X@b+P*05hV;RYe&M=(O}K9NFgYz9s+On|J+Y z!o~~{1C{F``SGFbB*5dO3U#86%5l6cLwfJ637v?Qj8#8wN zVWKV~BzJiI94FRz&_4i?gk>dnB+f)jVJGu_7(3@mRUqlR-gu^VLF)`v&JL&vqOwM- zWnbz~_2n}#@UP=jR|gv21KV7e4i8Z~<$lAwR>oTM|0&C{HUpq$m#&hp zk^1s>_Rqv*s_X~uK6%7yPG$(lbR9}2I^?$ae|NnTt-InR0D@Clwp7`JwL zC)%hT8X`KH{})7%t&pE<9tLdNWm9jNv8`t;L-B<~^9dxMa1l(LH}|~iOd2~vkG4@7 zQ{CD5y~hGv=Q3x;)ah@)jH4ytlLx)o>aS(SC)@GHK7%<QusD%vOok z6Me2()2A=N!{qCYEp@3~8C`(QQg5fna19QZs1T?i(wJZGyzMk6_r-Gmy2~W4Vbv%@5v}X^)Xr{cJJt6+43L#>gbW?RNh6E$cjt4Tg^pk>(CBX4#WNh z|Ejohxm!@~e?C!Q(poqBDK!Gtgxwr(a4?j4a?nr4Z_XD97R79g&_yr$7GcA zpT^#w^{v+h7h|7SP2BI<01&_#^qPlr5is@SDbGMyzNR^T|!EgRAr?%C5UaGN)eG9g&plb5LN1fvq~Js z-hVe2nl=`7kWhOY!t{-En`-#kBK``skLT&=WZIoz`PMn0_EE^_&uw?IeR9iS3yK+n zLKQqH+A1DXz6!WTmkBVXvi!$Jt0N>@^op7sB)U)^YAh^^7x0@WmAM+_hZjZH7(jdA z7RL`|k|gFq6+%vG3LX>Cr%V{A#0nv#?8JCE+1t19(IVjhVe986kCpl8|HLm~C<8tU z_%!&tOwojEfju@~Y#XH0N zXOuQ)qpVjf#(la-Y*p$+>W?v0Z6`)Iac)(-ZjCY$V0CbrbfLRS}i~UhrvcuMH z_h0Q?7@lYSVdfo!d0>*dVmox8^Hh`t=&GQX<`5gFN?H0{RMga62zIm0so!%k|3E`+ z8N>w>9O{FE1@Uq5NIQ9jq+03EFLIf7%CdM{?oozyoV!A;BthqhzM`ncZ@4~u zJ$xOj8vz8X?F96R$>srFVQ!_X_Sa6Xo|;>X++gXx#Qg*|N{JEtJD}hje-o5!zd^@%CT z{(51Xd{cTSQ6=F}nD?#1%a`)nOy}pKnXRHxBU(4EC2nVo(JRbD@gGW?A@|Es`MCs@y# z`Ay49&?^BzwI~*c{~L$-gm=hkn{1BJnH=-{`+UIX62#mc!S}@`o<=;3%7SsI@@_XUj3MbrT>ceSKKDKWu7U#gEfice!$+CSnQ6W`rKJ ztY%o;Ifi~vp($A486sVA-@LZ_V61z(d(O|Nrp0<&V^)J zO_dlU-jAsOj9c5!aCc{8-5#$xL`RCHUA5Kyd6O$ zMNEZApLofStb39eQ<`BzNHU1vHxv>0(06%X83Q}`0L7`Go4qOhj{ihd>OX{q*Z%?7 z#37{haL7-~rKm`IhIwDTN5qLU&5#3Ca+X4t9_PE(XKOmG@p;_a^`063g{|S!C%pf# z=9_j%#nglSPhru((AaItzg2A&l}}Dp3U}*yZ>dL0asFGC#kf0`qUp z=BOemu#kaI`}duCgVMo3Wkc=>>0hOXeFXm0O*zl7vOASLRNJle>pIHAxmGlD{`G zrPYzJD;E`(!?rmHdVcGAo4@R0aIOyHKeP_=BqWNryUTYtaRNAbHRzdMU)-6IZYk+H zH~)S%@^M~#L@BvDR}#HNc?MH5go_x?{~fg70$z4JrMj<5y%voQzx0j-mATZQ-Ze8K z*j@=+8-U4;S>v#tG=MY*Wt)AEVbGv89DEwTU)Dc9qv_cVRIAOZHrNh3uGc@eQlK9N zfL<6rQ=MLf)B1CMjsk+oXB8Gy)}j)6ywjNHO87C<+X-D_d0k%!hQXq6E}Cml(GOb+ zG0tL;eGH#m_!R3UyD?8;K_^bx7quk&vaHY>+qrs?t-`wdp0H*57vY???n&rf?O*}X zUDE!_p!CSnSI%Z1BQvhX<-%{?e&q`k^L>bI1F~FaegS@e-@VC(F0{N;e>4b^rr9dV0UTA z`{4lr(!c_9W2SOCJ;2{adxrf@LC$_~pPR9$KAiIC36oHxu}@aG{}uU|g@H2`FywDK zuDT|uzP|z0qJ4_u6%ti&!OY106&cy408md5m`xIJ z%*r2wlP0lf1fLskfMTNYueuWL;y^d|RcscO*k@3@P-(E%*YnlcUKMAw@zVPxb8X9p zKGw(O%DtfE`*c)&Tr6viYj&@)OIUkut7V*PO}mgzMCLXsE6q}lGbEyI#%3GsT<4g>?jn|29dul40TPglH|p z1*^!8>;?MuZf~(blypbxUz36Agb}6H(tiRYce0>8Nq{?Q=>5g(+fsWd?e-~Xobh-l z3Oi2-;O_wC(pRr?^|` zNkfWx;8XHMSLHS`oPaeC9$K= zd2NI_QEO~=)a#2MV;=OK(i??g-Z6|iC!1*Y4dIkk9}z>(yN+6xnr=s|DRSg*eue2Y z->DQaXf=;c*n#Z4jqB7a>N%j+;oJAWH2m8C6QAynj8*;Hbc`G!bkfFk>N70c)kws8 z2o#dVFpL@}Z~%P;6h3??yb*er!oe|}Z!8U%j3P zqe$8ykzH3b%3AB}u;aZ7AnX%6hMt8iPg}kb2LT~Y0{$97PZUI)^>;f{k<2~n?Rw|^ zL+7mJ`T>fO8hF-*OnjUb^m%@q=COWtrm2?t)}+rqBEXAt-04Hw}CNG_+dPxrN z-7EK9aPLumb*j9P7C2UYLIHJg2X&#bd^6|xwTCT-y)vJY{v|=;>fZ5|wHc_@3Q5

K)NGQP_3h*s8Cg99Gqrn45QrCijo}UwentZm3aa_93h9cb{;M z&YS^;9MAk`nHE-b2bb27N|*@9c$HJtQmgKsY-)l zO>BjA?AJE=5!6~LzNH18mcZ>6{QH1laR7+c7E}v1nol7(Mwy&M!Gh(hPwZundx!s< z?MjLGpT-4LF3f>47vm0|+o!`NR}aO@=BLwZu1docczDV7_aEtq=_-0NyTEils=Dfu zy8YvMh@xfne8Xxnc44uSd$YR6=ybK4hI8TN%cFF-A3xCG-nGZV!1o!X9X>$e0)HJ4 z_a*<`-z7y&ux~LQHtsd(z4sWozSmN1k$ZA)_eyz?mKKv`DBP7^NLEH4wpT!|M~X{E z$y?0TFg-PGu)BysrZB8bk|WE8<@Zj1TpvcARvfWl;j5`H@Q1Q5eXB)rYwmjiD`_ol z%erj79P;H>dFi?j6LQOcD8`(4Ov>7>JnDD9s__`4(Q91)46kJ` z2}!YuxHmeGe27?t*jJ@h8ZIQ!p-8iUdMmdqbsNtz1BzC9>#ZEB9I;>p2m-U`5R_|8?- z*`L_g0?}lvrOS(!$SL=SUjMrCa}e@}dM>xdB!7!zmlen2|3aRVVwP=5j%FYZT z@%(n;*B)WBRJS8@EM1DHvi#ePuNQLd>43|?B^7W-aiP>itNpX-r#joObtvZbep(W= z;Pb}4&A}&4ZtGdsyUWv7tLp)i!o^6S-n&oiSpNkz62V?*n)t(fD%0S6nde%&Q@u~>Zvmr4{+ZInlD;bB3Mpd@zYQ0XgL4D7(B zU0pO)n=n1tkl-#VaJoMvfk#qitmL&7<{-r9L| z~%sZ!OxPtc!4?^ZD!XB-O-JWR~bWm{-Iofu>6xJJzZ3FZJ=Sr z2Y7XVq=3eOLXwQn_SAukY!00E6}xlJ}@j=Zg;$=2FdhV64v0F&=c; z0{+<2T{aFwGxOB5n`kT8G{H2U+kJLUz0&zl3;kV9o7Vu7dTq2iSeM^anVJ10w}p=g zYQ$Y!>tsR*qV1oM6&NPSJD4UZOTz3V>@E)Oj4%7URjMj2jGKv3WVkMO3c~iXUr<&< zyPV#It(rQDF(Sq~+OffeeqAaodD5Kd2$|niW)iOX`(dSGbE_u%lxgEQVu~;DI`%P&fASPRD&QX z_wQfPv?*1JxD~M|-x}V!c^t0KD>oFkJ-j0Jb9fxzXIr&KZ#XzEm_{^i8ihEi*{V5~ z!otk|@Iis$q}e;Oec;oBc+TDkvpDUh9Icy4h>m5 znNR_T^e>FoE^2;Ceqh0!Qa?~y_-&%zC=t@dQ7iE2xrzBJYAO}&*;M2E3xUru!4#vD zS}Lk6ka^H%0$Ge)9QI^}-9=v!74i^rFndy9qi_w0T#_z| znN99KaxvLxR>Go-8gQV-hcBd)%N_q*z>5<0)(v)gNLY@LZld^&hdAnFJMH;*Z+EJ5qBRn%+;I6^+{02 zIGD`xl}SxsX;%*zs0}So6GUSCevMI1vPUqZQE*z&Pu=$|RiISJ?2js1bNMYYrV@6a z;iMD>*0-6f-!-wsSrlS-Z~G5z23Bo)S*2nWW2i9T`*b(b{apK&d?{@%c^SrZQ1ozvP*1r6&YAch?>U zqNKX7{_BB_|Fn62WA>x&oBe8@s1&MUj=_}XLAZfhtliaiKKFRTLNEF57OM61O{*g` z+((_h*xqZ;M}f__H`$7V5*Eh&I}$g{zkF6Q)8C8!jZ^F53!a24@BZxb$s`4_@9wv6 zd6yr=gj7qpga<*OCei#;? znh5unERXm0n|1cHy(o7V2km(rMa~_p8~ktlO*~iKx*FFEas1zF!h<_o!OOIzzuoe| zi{o_uy;fl2ta0WQ7$Sdkw#2p_`E4dk8yBMZMfgkOmKB^DF~R*oxw_*nq=sk_WknPE zXL<1=*Xwbvbbq-LZ1qG=o6Iew1pNWrofi(MuN`3ielrcX4wpG_&xBeV_bd{+%kPPU zHwPuHL5|&KW-A5rYb)~3k`5yB{!TH+<1G+R0=t&2jofLv9H$+(OO0`)Vw^)cD|1Rc zfp^jE2m^)Wcde~iOe@B z9U19LETMn7Ptt6^Q`~$fqf*Fqiane>sz`x75;QRgy1_CMSOM{r(b7$v=5HzqlFG9kbNsP4V|;!_|3GaLf7Y=F_R>u1|!{;NlwZ6w_Oq+V>e97SGbw zP85$(XKk`3&&yZj42=-|ejTk6ndhK0v#8E*Jd2;ge1Wuid#;E@r|^UJ%kHv++wco~ ztm!WT{bkd{FdmGJOd2Z9?lJv>0W+k@YvN<$h_UQ9UA!RVS;d}xrb-7#?r408212tJ z$z-M)>yL#ifx?N2y*`~MzFC2!(3a?4j%qgB+Xm~`^Hn9&i}NI49-MgaM3=$httKjP zfvRYmC7O_jr^iMbdv-`eg;Wk?JQQR1C$mW7%*>G)LzdComT*k7s-Bf_+kdgnl4yRY z2-^XRudHzB8NWIGJ;`2mGd!YA`2a=nY;8!fx;&X&bZg172mr^T%ALZybf9qkp0JcJ z#(l5Yp0Jz*`Q=e;Bt7@_rTu~Djat6B`;?oJ<&P|E8m}de!XzpZgNiafDUd9Ho#QSc*j5+prwvc8ID&j z<{eC%l7UL|kYy=v>tc7`@3V zvo(dag{JuX)GSSHT5?j!*_xqC#M!XL=}5Sr4B6{O^?LK`30j=CZ1?Z^U~A_pgp{3y;3=x!ES6B9dF8+*Qi#BHDps2dXyua z$nt`J+(5l!<2H0?*7z&kVNs^+;?F1)o@#={#v zt1GHy-%4)LwtmtnC@*lcxYL&iwOk6BSvhzV;qbPplz>QXIJ$1KrhtnZQw6gY#|A|S z?`6`uQ=OqO9df9wlAdGzVw(gP30g7BD@e5B((I}9>+Zg0N?I23$|Zesa7$ipsK}bM zugpMeR_-tEk0zL zysF#A*fw$RbJ|qdm}&eTu_ZG>{Zn=H;>SOyIQ#t`zC-?EajHi+gXBI)6%906K>}J_#BO75?LNpP~-*%Z#UkoC9Yv{@a1Y8-mw55WC9e zef=FMAO(;A_nGP=3-K4UT7{$UU(smC|6zH`mKo*VB8=#!jcf0{bg>i@a0yT+7&fP0 zs;Ls{-(!&KnCxI7obH!Y-fPO(W}6$fY-qFyWP{m}0=L-b!sio8Fn=V53BViQwxi{I zt2orGwO?pcx(1ncaj$PpDq#H}DfVO{c4-$;sP~XaGPTg#6Mek^}!CgotNH)t?01#D3BskXsA%VN$-K&0f+GCwCq1YmFZ7X1`V$ z&-{PVkWCqaY~nY5dpe5Qp75~{EjGSw>Ku8~Ds#KTdWk z!c4g6w_rpfd4pL;1GNHSfM^2WCnYqs?!c{c zR__S`pb;RFXPiH97His-idpPN|0d=Q$l#`Vspd%zm*ghwy-Z50btf%W&b6c)Q-v08 zYgI@=yqNjZEMslqC6ttsq~tOE5!3os#&(KLfA~BKGbU%st?LR>E47Sz2mO4!*)nqw z{tLy~B)}69+m7ZZ8y^(LhZG&WXoDEl`|7P2h`K8yMTF&?OAf5^mEBVuqi`#~BDm4~vI=Ws?rIuDT>eV)t{EUT|(l~#( ze8OK3i5OW2pqXYFv(yr52?(42}R0aX@c#GZB{62$DZCHeyAF@?*)m^8TGkTQhM37!nD*&?iwLLwp%~pvog_Z*Yj#USl7F~_&Q>3{8 zWCgs63}F*l{c?td+iy&2e;z~1%s9j@mvR0`L61;x9eZG%cN$J-b^&3~Z+cdU4}&j$ zqX_FGV=#?;zQlA-VNG&C%W zaG1Q{lVSl_Hi zmuwdaxb1rrQWPj*(g)B+U!ypw7i za57&FM8rG}vbH^AZge@?TUS&j9Obk2ENptjlsHDqdt)5RtLHYHlX%&Ycb5~{lAo%sWD(Rdy2H4rSQtj0 zr20yh>8G8`Qp@?wq2bBIm;FTv?~eX4??f7?MSAB=ItxlSqSTa|=m!WGyW@P?0GJ%4 z_L)52K$6qJgnZb6Rk>~a~vaL9lVotoXrttZ&FyZSK+Od3*f7VRoY$W z_1Gw(5E~%OG_H#%I~yS>lKU^=oo1{e#$p!IwU{M*Ra4bccqegUBzw-5uc^d310V549bLX~|IYSvmgxEE=pb>i?iGonbM zg~RHfYiDx?gzQS)lZyAC-Tdq;$$~#|G*^;-8fMTH=N}GdmI2M3>I%FJvU$9v#6mq6 zydum-Qo)uAdh*c;k<_INg@ArKdvFCA*oQg$Y`TuUriBF!KI~K_^hpgh5ii3QuREyh z?I4VgRVbkY%+70H%LT=hO7Ru0E0e$ceVDQRe31LirgqYLA^9L3?%kx{HJ1gg(DRyc zOYp*uEROd3W;4&(?uhk0_rMq0{70pGN5C;oc1--2@6mT9VY2Uy>>Pc{Hh-H|oR)f# zhCJM;HxuNK9?ixPyA=LI*HpEi3Zy97#B2w*Y=&mw)UfgBJ9Vs2bOT(iT$N)a$Qf1& z!j{YqSLtTymGg~#_lNR^>tF7UcmF10G$IQd1)4R?uZu0KECFC$cl)F8%`qZ3Pj)6O z;7JuT1A)BmeHFMml@H98if#^_POdA*V3rStDGm#l^MrL6$A9MW_JR%Wpa62Go!1c+ zpD=H)d#kcbUEQXw-mUC$mddKS zKLQEiVi9*_x9~@)!*SlVnZ_==S_Q`X?{8^!{1TE<&#&(0;%0IbUf(Zv=au~EpNZ@U zScXKm%1REbcD#hK=9uLHciGA_Bh$OTyN3*@Fz@*Odv7DbA5L$sXc#_n(G~2457V*8 zqmR=r%FE|qsPLf95%cBjBhCyE?c6Mju#OO&)Vd>`;r<-S$Ai^$*EQ5Uw&fPs|A7@o zj~GjhgJLGtk5jx{+c33#V4Rw<-yIS&p)g5L@qxGG*!Cuqp%g+o{kqLXusxiEz<rFOUtry-P__Y9Fo!kaepSYDk#5UrA21+^RnT0#cHI6ju^&k|_ zHVf(;-JadsXctEGZAHGMGq{)8U8_QQ!Sf|9tf5J02Fi}CV2sQsiFai^y7yxW*?97pE&$2e)EeMzwO7W~E}}1B z{-!=(xq(oRyEMlm^X2E%_K6q3n}v%L|LmloqO zzTtYlel#96G%QxYF7=O5jd$E6v3W=9C|JPsvB#)H!!nZ48+bA})&nVO8t8B!RtyBFTA_5w=G zGRkTqtB`04{6!-}wqyY2U{2!l`FZ8A@efXzom`}Wig~Vf_@#)IeQ-_f}KZ?3_AzhxvaK z4#Ow*^Gm@z$HlJd8nZWUO96XCD>_eiW3BU!gpF#om0!c?=dv@;e8xQhEay?gg)?^+ z&xu@Ls;P4n&=bD!I=XLgzHMI8ldA2x*qNIfaoQnx0~2cTe+*y4-%Iq;8Sz)L<2o(S z;EHSG!t|zp_kU+*k(L5@p-jg@FWoQ`gytqca=AJ0H_ofoD3}JCepoOslGl^p zaCAp?=c;_@e^9PHL?JF`BSDjVQf(Fz-h6?4nDTM`ZweVavkdYj8I`eY0<_*OPbAkh z%MG#BG`?SIcycs5L%r5ot1)hQpN0i?*utTn3+D6n7jWztKIP8fJg!a(m^>rcNe)?Y zw1Q9aYL%6Kr+Jb!jNgE|Jh7qQSeW2n0B{i-ud7QQueX^61c3%YeTtp$v=>JuSwpoX zna@z-yldL;TpdVFL)eAV?h-NJ*CE=VO}z+^#1NYpAfE^l-@m;8Y(`D2m7y!(61H&C zU&Ckt`2w8EKFfwp2iEsBNjr2!L5jPlQ(@*yEsj8`Fr2F^c_> zfeJ(0pa+v43}o!g$s0w>b8GVnTW_@|>__v3*67su5@K;7R**<`ClbDh)Q@8OsOwV` z$0qP?5wNckq0&d05N;K{5Cy`xg8t8{@XTzjL8{7MH6LGvn$o+it31+`O-{Bm;#nK68koa>F<<12#b^ ztJG|Uahzws$?Pz-`Wd+L)nADN-O5?eZ^!I7`8xD18Ip(Z6Jg;~M}@G|qeQ@6zu_pWjm&)R~Ag>ao9&jU|Yp-0^E;sZr( zBN6d3*D-;o3pC)vE*^D{?^A_`+TFfN1eO&wee5EnHlmmpDhX=G_Vl(_PL5vq2%22r3f1K}Cb@feq( zhxFje0L(F~aW8(X$}1l$hPycL7yqb0;#Q-V%zQUjkyd>>TOpSKhT`^959`Y3lZx3{ zR6xD1RAp$sdp~Ex~-)$P#XBnY4E|Se#xq<=XP=>DI;@_q`Cf98Uz~= zJ{LgZn1ZA*28ghEJOWeCM>Gf$Jb!_2HBtOI+p?{NOPpDJ4|hSKBhue=IGhW~^@R^9 z%=2RHWJ4+Y!oP9ER?%O@9xMIe@fFV)Eq;zL88N8Tc~qh~ZSsB?kw|@?fJiJ9SPo?D z`xve0;xEfz`l-uDgsFf^xjG=HmM*1~0bwUF?~@0TXJmGJfBUhDjR~b>?D+bG<9T)x zs(XO|jF0DuDGJOtz}nn>nMa*>v{1^H$kqKsjnVK2NV+WhX=Bf#KlC3o(Z(x0U8(r& zb3M?np7q-F%+FJ8W(!)s)LX5aX*w(sXJhG*#c&V_}Fii;2_x;8cdbh*3u@0;AcfzOQs@OL;tOp+u)XU|8HFO znOr^1OY$JcE=XO2DjKO?VXz#~^_AWf&U?%RQ!C^dCu>&@W_A>tht`Yaq3|j_zQ3n# zn}g0cUmH8`7Y|ui-@Cy0Gy}5gW4}KI@>JQ4t|dRiG+JS>sHW60Zo?nzE3d3QvCC^b zy27pfe`V(4_mFE^{Cq{FItf!-)0zgjnC%e-FJZ5wF#ANA%fMrW>seN*A%agT00$8a zkMG6OEj`XHftUBZPkRmX9q&OI7UrALhuotyC-0=NMyJ8*4^#Gvl!~t%LcOi;udh*y zgxu4M8!XWz=T)?*!gi+zzpz+3qJe}ZS1YG+-b2$)sv(?RGFuW2r^ff=J7Aa4JO=ZS<5z2)5gj!`-6C1f+#Khxe{^fA_9+?_b~dt@W*S^9Lj(oU`}rnP;AvJ=wE+ zV5`0^v2#OgaT0J5ua15>QNJdN&#=tirbZ>w*lu2J!PFKNjN8@UUwpfYORnXX#JPLS zPa{a+-^rX|`rtZT7!Gduu~$kjJi4Sw8SK+5(Ipcm>n-j5^_ZNYu9uhRZj|>s%?Wvx z&o4LyfbBd#jd=;q*Ar(8RUnYNLAUZ=KRu>zkk~ub6X$N#I%Us+%-Q9KvXH?;PJ$%K z-2pc`u_dN{hGkZsW%M~Qg&5oq3J*(7njOx1*mAs46sHBP((j5{v_8k$E0w>J3xrYt z4^_vWFc6Abvf`!DqTA5Ap%JoK3Djs_JshYzkm^=7^75`7scKKE?>;I=kzPbCP_0wLMJJOL9X+nD@HU(Smf(Do7>|*;(I?%pKa7SK7+0SL^|NmQ;1Zgq>XdVQ#(C%{be)6*bKQ5w~U7 z-P0bbu)R<`(P|=$9->&-3gnAQ=n%PIlDJLsG(-JOr6=gFr zpI(F*1?R0vJFoF1{G0m^GrX}l|0fR2Zd4uAWut85*>zH6NfCO`3a=t)MabMdnX&zLI6&f@P)Rm`QCy z!KtfX3rmL+;a*8_SGWE7smS^Tb+>MHv1HD2olC`?c&j5jCoR<&z59uSi0+4 z75RZBjMoZbw`M#_qLM7$IiZAN;UWb}A{^G5jYLBf20%Bv&yQvFIQ(pDFK zhZf~}TlJOPDBxtZ-B;_FjOxDldNVAJ%>%Hsi@%%V{ATN;L%Z#kO1^pEsT;@PEes!* z7>D|f+xt_rY8F0(EKE!7jJQqC+z)S^+lxB=!K@C$;_N=R7g&1lS@hLwdf1*LOvN%mc<1{DG+}R^q-MCUc&d|?ea%F|3|1Z~2L(_UILZ_Ebsr|DXR)`+ zAP*n}@m*u&af3P(nn;>e$J~N+5_8xUy@SBo9Z+JaE!=jcd^aX)F>uKbiaHVG4JWKG z4h1z}u8E3+?c&sT`lY5#R^4|@Kt=xUdD$X~AP==b+-T|C#0!eqz;I|9eyIxzXOu}8 zzNFb?1L5yDe^9yikME;mi2-1N{ks2DqY=*~FAtX!dH_1IRg-kt^^wYBL|AY1GIC3qEb)+2|GO3OUB*%v5DI@jIg|+2i1)xx;Y2 zq#;q2RWd)`hFMrxcpy@E?Z?@Lpek}c2PYR!Gi&YBa{H4-e@wj_+5&pq9_%qtrSk7H z5d5G>>pS0^q%v~t^rZ_IE_el=Idj9v*m$qX=b`B@L(@3TfVB(MsPhrzfBKf=CkyIa zzs88+srw(_i#ukKIuxy@8WH=CGz3&=eGSJ;dsFMBs;&7Y4BCgkK4E=15S>|3VQq#D zaQIhg_s#}bM8*M~lj_xTNYoVX4qM!S-}(3%==RI3U}X&fui=*o}= z1wovnE?dOyWbCKlmqV(9REat|I>RhNnhiJ@%-uVj=@UQiQdP8Dg{fq+AmY69?TwWa zD6kD)li3Md1`HlJ`v~qHUVFEC8&Qw?G7PVR>UYL{`q)caJ6e%arzE_ ztXWK#tb|B#k|i7eO_{O<2^&>NvjJhg|8aV*+kWT0^%Eij+>!XtZcb=v8@P(ZK<{v4 zMdsmg(Jq<3(TWV$9u9=EjsU2rUW#`g|X(2r+AgOzDsHA9dlEQv2fazeWs34QAyp?(r)IvfEJw~I6Ql&M0 znmb{*{=1)UfV=0qMVFbz%t9f`k!0pGYoGdD`e$3SQc)yq>iwHz^%1_?Xo?}#wyH!! zF)^{(BLa9_y>P~p(DeE;~#>}hg? z`lOa@rs>kvfv4(OD+{3&K)0FWZkK5o#yFwa*q7uKvNEcl=Q+}?NpU*8@s>u$!Q z_Gc%G>L&RyyPpjMk)euz-c~~Z`@(6g{XIT*##C-ks|7?JVN>;c7;r;%YVONYBS?41 zz%7sPK0VTsm^tRChG|v+GPj$fa_=4)=SR?B-PDWv@eU7uiBXEl+K;Hqu;%BwxCKJC zGETuYxc4RdNzeEB5%VhNddPM6?>Dsapmu;+2VU*T^XHlE?d_B9kpcs;m1^!6WZOXlIyOqs_$pjr`(=6cj9o!E^Dbdt&rg zTJfnZUwcw_%=+C0o?XXiACIhEm~q)W&Ox*MURpP!bRchlJy+UT^0ld{^WL@tg6_5z z{srtIHMWL>gTrrs)T$p`mNrv6@9`MnTym2>aD zWK4H|WuS?<`FHmhQBj-A`lh(3UHP{8Eom5fIkU>x(a|xdsg7?SI_CTCc9`CuA`X=V zmQg;ovIjqzAnSHDfkc>}>idAw5?C2QpabSrL1n6|%Rc%qzuKNcxK~Y_f*#{UL+M2U5b&h zdmnbl3=|7_zePt^7rt_nYQuGK&#q^>50AhXg35gvMpv$+Zmw}Is2pH+g>i5e1uyvq zRQ5||ZuPARL@K!72O`^> z^bF0dpFB&%g{_));pTHldHlpMDPY~=JS2xt6GT(b3x{jY=v{h{FCKcR& zPpcwKj^v{!w1H5p{R`wJ|9OJC@BhXJq;+ud3LdOEF%hf+O57sJlQ=nDC)$;K=GG2= z{474&Xpg-rADhRp7$ATxHwQ13}x5YKt?fP>3DrB zP@3GLBAMFHpItvk?dd6UF~&t`W;lXC)T@M>eV*+ncK{Jg6&}i1TqxrNNKDBn})qtBS8`COq9sKem%9n$N-OkS+ zn~)&LI7QJE3Hfu`2INNm{q3ljHVp7pf5?)@acqS-G!+SanxkQMO)+t~K~&SRF(KWe z&{3A${Pvj2?=J_)GfhhPP75dP7=VT9EMUU~IQI+p2B4i&NAI~6~nwrL;QyO}xBq`{? ziP=n`w21R5{|YlQGLi{d_E(vuXl%N3wncJd;=!$dId^26B%HL@>XU1ek+uK4`M7PB zazt#(QIDP?ZQ$r8T3UA{%Z9g)jErcOA3XQ9GuH|zuPsyh!`O_=x2K1L#DyGG{|s`n zruwYnx6qM14}`iKb)W4HF)DSpn9j~GHbjoqkm2{c##Ic7HMQc z(=jILwMaKBr!_R_p|A^JOSvzRl!>Qz9zJ>UWY0)S`^D=6V>Zkx(4Dr0+LVbhQ=q2IB*5G zynIwfpWDkgeA~e*bozo+_43=is>O*zrd)qpZV~x*!m(kuuusED!Bbc7p#sz=s;Yq8 zrL99(SeB)p!ZXo`%{{p7(n51+-qE~wsoipW_Uw7!Nj&8caW>_Vw~tS3e0=xDj(rJ) zxyi%fH7$0goi}f;`z#`o9upHI6ZGfW$nfyF@*U^SFq(rQFludWohX45`ki~ z4O51#B)ELKx2-V*{Eb$$O`+ohy|zmb3YEWe#ce31=GsTAnCiwI%cAbOf3E22*X_cg z%hSL(T8vChN#I7hc$`iXHj5~mXJuuvRQVwkLfwrj|HCUvzLOWAhY^tnv$g&$u7+2h z23=)3TGMr9{eKM-mZDYW%*(9v2*eG0<=ih|u_D9`>fFiP!ntpQ7QBPm3u6g#9tmKO z#qhEZOgBN^D~T{m+s61!(S~K(WfQV6l5qNZs<>g&Ym7+1IZ$VOA$jP_930RMfVxu&7izSmN22E$h~adi(M5aa2)eUkog3)!gN6 zLmgk2jbE16KotsnX=XBtmwcEvhKH}h@we(@iGE2CkroHcIQIEcJp>hTnT|~__ta*$ zJkG0T6Dogw;E}z#sHgi}`&J=fm3f6 zXUFXUf85}A=Uv{tsaF5YE+S$Ry{OHgkieR7D6^Jy8+?DGv$zZE21bV|cgH1vu3C+G zok0vC=jl5*q_f(H?DmP4wD6q*0#1oOO$wb;edQpiYwJ%QtA9&ozg=@}$m!ko|EGvK z=8my}f~I^Q&iEDsMNBY=36TMyDyKGUz_19nO88V}A8oFo9L{*zYB%suSZUa|To&|2 ztJ!O}Rv+wMx3y;(7vsiT9oIHfNd)z8YDtj3>za+1j*F|w>`KOWRJ?(ck=s1uce>0k+Dfh z{j`(l0GrfSgBDgoP(^-F5&&+h7}}2n!|#di!i*;689k5gx9MLMB`ar*`fzRfiuBio zMeg0FaxDtA{QB_Eu%RpX6>y%Ot31j&0GO!DW-l+GuwGQpfh4a*f8n&g@=^mOhRg~p zKQxy*2aS4Nz~d_pMM(=5mBK95R*KLY*aS`2S{6B9OlyAe^y#bi_BB8>RGz+l!O2o&-N!nz)w2`!9AjvXS&QxVF2W&;6 zF+-mpv;lfs%`2CcmBBKgaA=@BeGVOJ>nrV^ch}QQ^Q^P(^Gh7rx9?1$V`D3@Tl&Lt zkR}d>>h|I0hKY`xXBF6d&`ZS)>u!+cIyyQM)IzIJcliAI?!;>!H(Hi?JM^)8k{DvT zan7(zaHe1zU&t>`kMD0%`rU%T(qu1xTwnX?)1db3hW8~S9@Uivg$ zgp?MjISB|!+7zpUZ8J-2(YSk=7I8Gsc@|ElP{pEhfKb9RokWuB;esT>TC8;sx>M`G zI_mWe)kX@?V{|1SQyHEVUuYfi?!hlZmv?e8HJIG=L zr-%n8LocC1RYtUGcC;GXTtPtrO-j*)3juo_oSf*l_*5yt`Z7b=GepZbc4zw7&`eu@ z^-rDJY*#hg1X{**Qc^TzeMa?m?%dfCm;^NzU5hKs(0o`QBZCZMGaI}~Uln@kXEwg^ zA#;VqajI8!2a!E1p#p7k$gAunx=P*64LmqdT{=C#x)aWL#eWrhmYJD(9>N!j8he^g zyA_051RAZfNK0#E_i-Y2W@ywWczrb9=^JyNjyj!yfHEwAG~vT7hFML{5Gu9I!YcJmgzm z>_2_wfuO98)6463QTC2bLvPPT2AwDHXLg0y$Ukm)hgaL2Scnr1H68G-ZA2s3h z=k^a>D0%PRnXfL7sj(n6+wSoK{2vg*_CZs6q$K$~NGvus7BwLBk2D`0+0w?+Pt18Y zII}uI5${^bFwQXO=qYxidno-;4qlvneDJ{@X;OcQO5j|(k|VHeFr}QpAfVbguV3p? zOTEm1dEWeBSLsu3EvcWRYyp%=KS}BMas8Mgr)ClGK5mSj;>FoELptkuc+F)1#;nxT z)Tw1|HB3-YMFrOD76B3sQ;^CEOS{=cH__JCzQuquVfE+UVeuU%3BYoIYIa>^F7QZI zBxh$I(T_is?)kz2E#5%E;x3;kwseIr^v^9wGVg;8FJLCJR?J^NYFH4r6pyACN7RpG zFBM+i{lF8*ov?3JT$4>;-rKjQ*8Fl(py#cjD_5=v20!c>8-ERBxwp&nIyWM;^OUr7 zG59qus#!kPM(UiXdwb?ZL0Q+QFq#aoq<1ZHsCqVsvV8!3NmJ-F6{kP(gWCKgco-WS z%i?I1T{UF~Q5Z!B3fRozT0$#A&_F(aagLFLu3bMHeqK6&dFVbZbljrcHy6;AE|PCv za27%(!4r02cQ^0ZUrM!M_Ci#0)GW`vtxN)9Y2LkZ&NNC2Z4(>hS%=9};Q{_t{I;t5!2(&0Vrx)(}~yK@4IAng7&&AV%WRR%Bcjx^l&>Zm9o2 zApnIT2nO4!el3~;<5f#jZC)WWdleErR>$U+XPUcm@~g5@HS+5Z$Ur>^98aq|5H$0E z{VQCJhO!e-_gpKlN)vP&0S2CmX2c;9>4Y@HEL@;;;br)y_3Oxs6FGRGL`UT1&CpMJ zzWc!yPs;l9$A4v5LaimYv_Bho6X*{81GnfUP0c$fUp6HUff;r}FW#)#S=N~)I4(hcn6H- zpf^4AfR;#iJvmqrJQbQZ*xG zyobMV{jiQ{QWz8JyH>+XfO*LHP4&ukxk1S6|6>F6Tr;+WWX@FeY6$p#SSURdGJ)ZP*h^y9tbCWG7c!1cPzrTUXim?=uAu$gE=CyzhHcBMPwEbva1-~TfKga=8 z%!V+Yj?UoIeSTJdATtXSEt0ER*AOoa6ZZONxk8t$02t7*cUk-B=Md9ut3&Wl8f^kb zV#$+l>n9rDhra19baJDXc;KV!qD7^$@b+vlK=-?~)#qWGVXK+-^*dnWEZF4HEZ+e; zRDw}w{%fiM%^AYOj&l|gjB8K+H{bmKItPDamG9=ISH?EmZXQCHKwHz`T;5r`oBsxR C Date: Mon, 21 Oct 2024 09:19:41 +1000 Subject: [PATCH 066/102] Update README.md --- .../facebook_gnn_classification/README.md | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 96a4334c1..fffe324ba 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -1,7 +1,54 @@ # Facebook Page-Page Network Node Classification ## Overview -This project implements a Graph Neural Network (GNN) model to carry out semi-supervised multi-class node classification on the Facebook Large Page-Page Network dataset. + +This project involves training a Graph Neural Network (GNN) for semi-supervised multi-class node classification using the Facebook Large Page-Page Network dataset. The dataset represents various categories of Facebook pages (e.g., government, politician, tvshow, company) connected based on mutual likes. The task is to classify each node (Facebook page) into one of the provided categories using Graph Attention Networks (GAT) layers. The model uses the Graph Attention Network (GAT) architecture and includes visualization of learned embeddings using UMAP. + +## Dataset + +The dataset is provided in the form of an partially processed .npz file containing: + +Edges: Connections between nodes representing mutual page likes. + +Features: 128-dimensional feature vectors extracted from page descriptions. + +Target Labels: Page types (e.g., government, company, tvshow, politician). + +## Model Architecture + +The GNN model uses four layers of Graph Attention Networks (GATConv) with multi-head attention, combined with ReLU activations and dropout to prevent overfitting. The model architecture is as follows: + +GATConv Layers: + +- conv1: 8 attention heads for initial node feature transformation. + +- conv2: 8 attention heads for further feature transformation. + +- conv3: 8 attention heads for deeper representation learning. + +- conv4: 1 attention head for the output layer. + +Mixed precision training with automatic mixed precision (AMP) was utilized to speed up training and reduce GPU memory usage, enabling the use of larger hidden dimensions. + +## Training Details + +Hidden Dimension: 512. + +Optimizer: AdamW with learning rate 0.0005 and weight decay 5e-4. + +Loss Function: CrossEntropyLoss. + +Epochs: 200. + +Mixed Precision Training: Enabled using PyTorch AMP for increased training efficiency. + +Training and Validation Loss + +The following plot shows the training and validation loss over 200 epochs: + + + +The training and validation loss decreased steadily, indicating that the model learned effectively without overfitting. From 49fe6dae8eceb656f43dcdcbcd7eded3b534ebff Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 11:07:27 +1000 Subject: [PATCH 067/102] Update README.md --- .../facebook_gnn_classification/README.md | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index fffe324ba..549fb0e8f 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -49,6 +49,25 @@ Training and Validation Loss The following plot shows the training and validation loss over 200 epochs: - +![Training and Validation Loss](graphs/training_validation_loss.png) The training and validation loss decreased steadily, indicating that the model learned effectively without overfitting. + +## UMAP Embeddings Visualization +To visualize how well the GNN captures the structure of the graph, **UMAP** was used to reduce the node embeddings to 2 dimensions. The following plot shows the reduced embeddings colored according to their ground truth labels: + +![UMAP Embeddings](graphs/umap_embeddings.png) + +The UMAP plot indicates that the model has successfully learned to separate the nodes based on their categories. Different colors represent different page types, and the clustering seen in the visualization suggests that nodes of similar types are grouped together, demonstrating good discriminative power of the learned embeddings. + +## Prediction Accuracy +The model achieved a prediction accuracy of 98.24% on the entire dataset, which shows that it was able to effectively classify nodes into their respective categories. + + +### Sample Predictions +Below are some sample predictions from the model: +- Node 0: Predicted = `0` (True = `0`) +- Node 1: Predicted = `2` (True = `2`) +- Node 2: Predicted = `1` (True = `1`) +- Node 3: Predicted = `2` (True = `2`) +- Node 4: Predicted = `3` (True = `3`) \ No newline at end of file From 7eb6c061ef96bb2ea555f38d912acfa92f840f1d Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 11:09:50 +1000 Subject: [PATCH 068/102] Update README.md --- recognition/facebook_gnn_classification/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 549fb0e8f..53383004c 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -51,7 +51,9 @@ The following plot shows the training and validation loss over 200 epochs: ![Training and Validation Loss](graphs/training_validation_loss.png) -The training and validation loss decreased steadily, indicating that the model learned effectively without overfitting. +From the training and validation loss plot, we can observe that the model's loss decreases rapidly in the initial few epochs, indicating that it is learning efficiently. Both training and validation losses converge to near zero as training proceeds, demonstrating effective learning with little overfitting. This steady decrease suggests that the model generalizes well to unseen data, which is an important indicator of good training performance. + +However, we can also notice that slight fluctuations towards the end of the training process, suggesting that the learning rate may need to be fine-tuned to prevent oscillations. Despite these minor fluctuations, the model overall performs well with low final loss values for both training and validation sets. ## UMAP Embeddings Visualization To visualize how well the GNN captures the structure of the graph, **UMAP** was used to reduce the node embeddings to 2 dimensions. The following plot shows the reduced embeddings colored according to their ground truth labels: From ba5f055e7d68c01fc491d1cfb8bf4fd173bab979 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 11:10:46 +1000 Subject: [PATCH 069/102] Update README.md more UMAP discussion --- recognition/facebook_gnn_classification/README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 53383004c..01d9b76ed 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -60,7 +60,12 @@ To visualize how well the GNN captures the structure of the graph, **UMAP** was ![UMAP Embeddings](graphs/umap_embeddings.png) -The UMAP plot indicates that the model has successfully learned to separate the nodes based on their categories. Different colors represent different page types, and the clustering seen in the visualization suggests that nodes of similar types are grouped together, demonstrating good discriminative power of the learned embeddings. +The UMAP plot indicates that the model has successfully learned to separate the nodes based on their categories. Different colors represent different page types, and the clustering seen in the visualization suggests that nodes of similar types are grouped together, demonstrating good discriminative power of the learned embeddings. Specifically: + +Government (Red): This category is well-clustered and separated from other categories, indicating that the features used to represent government pages are distinct from other node types. +Tvshows (Blue) and Companies (Green): These categories show some overlap, suggesting that certain features between tvshows and companies might be similar, which aligns with the possibility of common public engagement strategies used by both. +Politicians (Orange): This group is relatively distinct but has some overlap with the government cluster, which is expected due to similarities in content between politicians and government pages. +Overall, the UMAP visualization indicates that the embeddings learned by the GNN are effective in capturing the latent structure of the dataset, helping to group nodes of similar types together. ## Prediction Accuracy The model achieved a prediction accuracy of 98.24% on the entire dataset, which shows that it was able to effectively classify nodes into their respective categories. @@ -72,4 +77,5 @@ Below are some sample predictions from the model: - Node 1: Predicted = `2` (True = `2`) - Node 2: Predicted = `1` (True = `1`) - Node 3: Predicted = `2` (True = `2`) -- Node 4: Predicted = `3` (True = `3`) \ No newline at end of file +- Node 4: Predicted = `3` (True = `3`) + From bd5468fd40358f5bcb6163cdc2030c7fb2b0978a Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 11:55:04 +1000 Subject: [PATCH 070/102] Update README.md --- .../facebook_gnn_classification/README.md | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 01d9b76ed..ba049d331 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -1,13 +1,13 @@ # Facebook Page-Page Network Node Classification -## Overview +### Overview This project involves training a Graph Neural Network (GNN) for semi-supervised multi-class node classification using the Facebook Large Page-Page Network dataset. The dataset represents various categories of Facebook pages (e.g., government, politician, tvshow, company) connected based on mutual likes. The task is to classify each node (Facebook page) into one of the provided categories using Graph Attention Networks (GAT) layers. The model uses the Graph Attention Network (GAT) architecture and includes visualization of learned embeddings using UMAP. -## Dataset +### Dataset The dataset is provided in the form of an partially processed .npz file containing: @@ -17,7 +17,7 @@ Features: 128-dimensional feature vectors extracted from page descriptions. Target Labels: Page types (e.g., government, company, tvshow, politician). -## Model Architecture +### Model Architecture The GNN model uses four layers of Graph Attention Networks (GATConv) with multi-head attention, combined with ReLU activations and dropout to prevent overfitting. The model architecture is as follows: @@ -33,7 +33,7 @@ GATConv Layers: Mixed precision training with automatic mixed precision (AMP) was utilized to speed up training and reduce GPU memory usage, enabling the use of larger hidden dimensions. -## Training Details +### Training Details Hidden Dimension: 512. @@ -55,7 +55,7 @@ From the training and validation loss plot, we can observe that the model's loss However, we can also notice that slight fluctuations towards the end of the training process, suggesting that the learning rate may need to be fine-tuned to prevent oscillations. Despite these minor fluctuations, the model overall performs well with low final loss values for both training and validation sets. -## UMAP Embeddings Visualization +### UMAP Embeddings Visualization To visualize how well the GNN captures the structure of the graph, **UMAP** was used to reduce the node embeddings to 2 dimensions. The following plot shows the reduced embeddings colored according to their ground truth labels: ![UMAP Embeddings](graphs/umap_embeddings.png) @@ -67,7 +67,7 @@ Tvshows (Blue) and Companies (Green): These categories show some overlap, sugges Politicians (Orange): This group is relatively distinct but has some overlap with the government cluster, which is expected due to similarities in content between politicians and government pages. Overall, the UMAP visualization indicates that the embeddings learned by the GNN are effective in capturing the latent structure of the dataset, helping to group nodes of similar types together. -## Prediction Accuracy +### Prediction Accuracy The model achieved a prediction accuracy of 98.24% on the entire dataset, which shows that it was able to effectively classify nodes into their respective categories. @@ -79,3 +79,16 @@ Below are some sample predictions from the model: - Node 3: Predicted = `2` (True = `2`) - Node 4: Predicted = `3` (True = `3`) +### Conclusion +The GNN model using GATConv layers was successfully trained on the Facebook Page-Page Network dataset to classify nodes based on their types. The key findings are as follows: + +High Accuracy: The model achieved an impressive prediction accuracy of 98.24%, which suggests strong discriminative ability. +Training Convergence: The training and validation losses converged smoothly, indicating effective training. Only slight fluctuations in the losses towards the end of training suggest potential room for further learning rate optimization. +Embeddings Visualization: The UMAP visualization of node embeddings highlights well-separated clusters, demonstrating that the GNN effectively captures the underlying relationships between nodes, particularly between different page categories. This clustering indicates the robustness of the learned features in differentiating between node classes. +The combination of GAT layers, mixed precision training, and effective regularization techniques contributed to this successful result. The insights provided by UMAP confirm that the learned embeddings provide meaningful structure that is aligned with the graph's underlying properties. + +### Future Improvements +Hyperparameter Tuning: Perform a grid search for optimal hyperparameters such as learning rate, dropout rate, and hidden dimension size. +Regularization: Add L2 regularization to further reduce overfitting. +Further Visualization: Visualize attention coefficients learned by GAT layers to gain insights into important node relationships. + From 3cdbad9690217da62acca3943a3fa76fbc2e103c Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 11:58:17 +1000 Subject: [PATCH 071/102] Update README.md Updated instructions --- .../facebook_gnn_classification/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index ba049d331..4a8da28da 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -92,3 +92,20 @@ Hyperparameter Tuning: Perform a grid search for optimal hyperparameters such as Regularization: Add L2 regularization to further reduce overfitting. Further Visualization: Visualize attention coefficients learned by GAT layers to gain insights into important node relationships. +### Google Colab Usage Instructions +This project was developed using Google Colab. If you are running the project in Colab, make sure to mount your Google Drive to access the dataset and save model files. + +from google.colab import drive +drive.mount('/content/drive') + +Update all paths to include the correct directory, such as: + +base_path = "/content/drive/My Drive/COMP3710/Project" + +### Running Locally +If you are running this project locally (i.e., not using Google Colab), you need to update the paths accordingly to your local directories. For example: + +base_path = "C:/path/to/your/project" + +### Note +The images used in this README (training_validation_loss.png and umap_embeddings.png) are located in the graphs folder of the project directory. Make sure to check the graphs folder if the images do not show up directly. \ No newline at end of file From 56bc119e9b4c4d610b4ea83f72c6fd771a9c3b74 Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 12:25:05 +1000 Subject: [PATCH 072/102] Update README.md Added name & student id num --- recognition/facebook_gnn_classification/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 4a8da28da..3939f57e4 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -1,5 +1,9 @@ # Facebook Page-Page Network Node Classification +Name: Chen Yang +ID: 47867637 + + ### Overview This project involves training a Graph Neural Network (GNN) for semi-supervised multi-class node classification using the Facebook Large Page-Page Network dataset. The dataset represents various categories of Facebook pages (e.g., government, politician, tvshow, company) connected based on mutual likes. The task is to classify each node (Facebook page) into one of the provided categories using Graph Attention Networks (GAT) layers. From c0ed1d899e7afe91bff2a9f5e34320a6065332ee Mon Sep 17 00:00:00 2001 From: Chen <759534580@qq.com> Date: Mon, 21 Oct 2024 12:48:37 +1000 Subject: [PATCH 073/102] Update README.md Added Project File Descriptions --- .../facebook_gnn_classification/README.md | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 3939f57e4..1dd8136b3 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -74,15 +74,34 @@ Overall, the UMAP visualization indicates that the embeddings learned by the GNN ### Prediction Accuracy The model achieved a prediction accuracy of 98.24% on the entire dataset, which shows that it was able to effectively classify nodes into their respective categories. - ### Sample Predictions Below are some sample predictions from the model: + - Node 0: Predicted = `0` (True = `0`) - Node 1: Predicted = `2` (True = `2`) - Node 2: Predicted = `1` (True = `1`) - Node 3: Predicted = `2` (True = `2`) - Node 4: Predicted = `3` (True = `3`) + +### Project File Descriptions +This project contains the following files: + +- train.py: The script used to train the GNN model. It defines the GNN model, sets up the training process, and saves the trained model weights. It also includes mixed precision training for efficiency. + +- predict.py: This script is used to load the trained GNN model and make predictions on the dataset. It evaluates the accuracy of the model and provides sample predictions. + +- modules.py: Defines the architecture of the GNN model. The model uses multiple GATConv layers with ReLU activation and dropout to effectively learn node representations. + +- dataset.py: Contains the code to load the dataset from an .npz file, which includes node features, edge connections, and labels. It transforms the raw data into tensors suitable for training the GNN. + +- README.md: This file provides an overview of the project, the dataset, training details, discussions and the results obtained. + +- graphs (directory): This folder contains the images generated during training and visualization, including: + + -training_validation_loss.png: The plot showing training and validation loss over epochs. + -umap_embeddings.png: The UMAP plot showing the 2D representation of node embeddings learned by the model. + ### Conclusion The GNN model using GATConv layers was successfully trained on the Facebook Page-Page Network dataset to classify nodes based on their types. The key findings are as follows: From ecb5124e6017701ac1f847729fae68d54eab70ac Mon Sep 17 00:00:00 2001 From: Chen <133569959+ycKevin@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:52:03 +1000 Subject: [PATCH 074/102] Update README.md --- recognition/facebook_gnn_classification/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 1dd8136b3..97e4ad2f3 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -1,6 +1,7 @@ # Facebook Page-Page Network Node Classification Name: Chen Yang + ID: 47867637 @@ -131,4 +132,4 @@ If you are running this project locally (i.e., not using Google Colab), you need base_path = "C:/path/to/your/project" ### Note -The images used in this README (training_validation_loss.png and umap_embeddings.png) are located in the graphs folder of the project directory. Make sure to check the graphs folder if the images do not show up directly. \ No newline at end of file +The images used in this README (training_validation_loss.png and umap_embeddings.png) are located in the graphs folder of the project directory. Make sure to check the graphs folder if the images do not show up directly. From 4984b20abe9f519e1d630880c73474c44b91b898 Mon Sep 17 00:00:00 2001 From: Chen <133569959+ycKevin@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:27:12 +1000 Subject: [PATCH 075/102] Update README.md Correct errors --- recognition/facebook_gnn_classification/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 97e4ad2f3..3c11ffd58 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -46,13 +46,13 @@ Optimizer: AdamW with learning rate 0.0005 and weight decay 5e-4. Loss Function: CrossEntropyLoss. -Epochs: 200. +Epochs: 300. Mixed Precision Training: Enabled using PyTorch AMP for increased training efficiency. Training and Validation Loss -The following plot shows the training and validation loss over 200 epochs: +The following plot shows the training and validation loss over 300 epochs: ![Training and Validation Loss](graphs/training_validation_loss.png) From 058fdd7ce466182ddc56c6cbbd1276dc9a942ebf Mon Sep 17 00:00:00 2001 From: Chen <133569959+ycKevin@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:29:25 +1000 Subject: [PATCH 076/102] Update README.md --- recognition/facebook_gnn_classification/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/recognition/facebook_gnn_classification/README.md b/recognition/facebook_gnn_classification/README.md index 3c11ffd58..698226e88 100644 --- a/recognition/facebook_gnn_classification/README.md +++ b/recognition/facebook_gnn_classification/README.md @@ -106,10 +106,10 @@ This project contains the following files: ### Conclusion The GNN model using GATConv layers was successfully trained on the Facebook Page-Page Network dataset to classify nodes based on their types. The key findings are as follows: -High Accuracy: The model achieved an impressive prediction accuracy of 98.24%, which suggests strong discriminative ability. -Training Convergence: The training and validation losses converged smoothly, indicating effective training. Only slight fluctuations in the losses towards the end of training suggest potential room for further learning rate optimization. -Embeddings Visualization: The UMAP visualization of node embeddings highlights well-separated clusters, demonstrating that the GNN effectively captures the underlying relationships between nodes, particularly between different page categories. This clustering indicates the robustness of the learned features in differentiating between node classes. -The combination of GAT layers, mixed precision training, and effective regularization techniques contributed to this successful result. The insights provided by UMAP confirm that the learned embeddings provide meaningful structure that is aligned with the graph's underlying properties. +- High Accuracy: The model achieved an impressive prediction accuracy of 98.24%, which suggests strong discriminative ability. +- Training Convergence: The training and validation losses converged smoothly, indicating effective training. Only slight fluctuations in the losses towards the end of training suggest potential room for further learning rate optimization. +- Embeddings Visualization: The UMAP visualization of node embeddings highlights well-separated clusters, demonstrating that the GNN effectively captures the underlying relationships between nodes, particularly between different page categories. This clustering indicates the robustness of the learned features in differentiating between node classes. +- The combination of GAT layers, mixed precision training, and effective regularization techniques contributed to this successful result. The insights provided by UMAP confirm that the learned embeddings provide meaningful structure that is aligned with the graph's underlying properties. ### Future Improvements Hyperparameter Tuning: Perform a grid search for optimal hyperparameters such as learning rate, dropout rate, and hidden dimension size. From 8c439cf6d7599facee1b90fab47ea979d1f67759 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 22 Oct 2024 01:30:06 +1000 Subject: [PATCH 077/102] monai loss function and imputation of images --- recognition/47049358/README.md | 4 +- recognition/47049358/dataset.py | 87 ++++++++++++++++- recognition/47049358/modules.py | 3 +- recognition/47049358/predict.py | 57 ++++++------ recognition/47049358/train.py | 160 ++++---------------------------- 5 files changed, 139 insertions(+), 172 deletions(-) diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index ac61610b7..9359b941a 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -8,4 +8,6 @@ Updates: - Random Scaling - ~~Implemented~~ → Omitted as dimensions disagree with the rest of dataset - Elastic Transformation - Omitted given the constraint in data type - Gamma Correction - Implemented -- Mirroring - Implemented as a Horizontal Flip \ No newline at end of file +- Mirroring - Implemented as a Horizontal Flip + +(Loss Function)[https://www.sciencedirect.com/science/article/pii/S1746809422007030] \ No newline at end of file diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 5c5875fab..c777448f6 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -11,6 +11,9 @@ import torchvision.transforms as transforms import random import torch +import matplotlib.pyplot as plt + +from modules import * # ========================== # Constants @@ -242,9 +245,16 @@ def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor, device = ' masks = masks_3d[: , : , j , :] masks = masks[np.newaxis, : , :, : ] - slice = elastic_transformation(image = slice, alpha = alpha, sigma = sigma) if make_elastic else slice + unique_elements = np.unique(masks[0, : , : , 0]) + + if len(unique_elements) == 1 and unique_elements[0] == 1: + slice = torch.full((slice.shape), -1) + image[: , : , j] = slice + continue + slice = random_rotation(image = slice, angle = angle) if rotate else slice slice = random_resize_with_padding(image = slice, height = height, width = width) if resize else slice + slice = elastic_transformation(image = slice, alpha = alpha, sigma = sigma) if make_elastic else slice slice = gamma_correction(image = slice, gamma = gamma) if adjust_gamma else slice slice = F.hflip(slice) if hflip else slice slice = F.vflip(slice) if vflip else slice @@ -252,9 +262,9 @@ def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor, device = ' for i in range(masks.size(-1)): mask = masks[ : , : , : , i] - mask = elastic_transformation(image = mask, alpha = alpha, sigma = sigma, is_mask = True) if make_elastic else mask mask = random_rotation(image = mask, angle = angle) if rotate else mask mask = random_resize_with_padding(image = mask, height = height, width = width, is_mask=True) if resize else mask + mask = elastic_transformation(image = mask, alpha = alpha, sigma = sigma, is_mask = True) if make_elastic else mask mask = F.hflip(mask) if hflip else mask mask = F.vflip(mask) if vflip else mask @@ -271,6 +281,7 @@ def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor, device = ' def augment_training_set(X_train, y_train): + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') for i in range(X_train.shape[0]): @@ -285,6 +296,73 @@ def augment_training_set(X_train, y_train): return X_train, y_train +def visualise_ground_truths(images, ground_truths, criterion): + + # Create a 3x3 grid of subplots + fig, axes = plt.subplots(3, 3, figsize=(15, 15)) + + # Plot the images + for i in range(3): + for j in range(3): + + idx = i * 3 + j + + # Original image + + image = images[idx] + + axes[i, j].imshow(image, cmap='gray') + axes[i, j].axis('off') + axes[i, j].set_title(f'Image {idx+1}') + + # Ground truth mask + + ground_truth = ground_truths[idx] + num_masks = ground_truth.shape[0] + + mask_gt = np.zeros((ground_truth.shape[1], y_train.shape[2]), dtype = np.uint8) + + for k in range(num_masks): + mask_gt += (k + 1) * ground_truth[k, : , : ] + axes[i, j].imshow(mask_gt, cmap='jet', alpha=0.3) + + # Show the plot + plt.tight_layout() + plt.savefig(f'ground_truths_{criterion}.png') + plt.show() + + return fig, axes + +def visualise_predictions(images, predictions, criterion): + + # Create a 3x3 grid of subplots + fig, axes = plt.subplots(3, 3, figsize=(15, 15)) + + # Plot the images + for i in range(3): + for j in range(3): + + idx = i * 3 + j + + # Original image + + image = images[idx] + + axes[i, j].imshow(image, cmap='gray') + axes[i, j].axis('off') + axes[i, j].set_title(f'Image {idx+1}') + + mask_pred = predictions[idx] + + axes[i, j].imshow(mask_pred, cmap='jet', alpha=0.3) + + # Show the plot + plt.tight_layout() + plt.savefig(f'predictions_{criterion}.png') + plt.show() + + return fig, axes + print('> Loading Dataset') rawImageNames = os.listdir(IMAGE_FILE_NAME) @@ -309,4 +387,7 @@ def augment_training_set(X_train, y_train): print('> Augmentation Complete') X_train = X_train[: ,np.newaxis, :, :, :] -X_test = X_test[:, np.newaxis, :, :, :] \ No newline at end of file +X_test = X_test[:, np.newaxis, :, :, :] + +y_train = np.transpose(y_train, (0, 4, 1, 2, 3)) +y_test = np.transpose(y_test, (0, 4, 1, 2, 3)) \ No newline at end of file diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 94505fdd8..204910fed 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -189,6 +189,5 @@ def forward(self, x): final_sum = upscale_out_2 + segment_out_3 - output = torch.permute(final_sum, (0, 2, 3, 4, 1)) - output = torch.softmax(output, dim = -1) + output = torch.softmax(final_sum, dim = 1) return output \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 05c757bc8..3e65074f4 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -8,28 +8,18 @@ import matplotlib.pyplot as plt from torch.utils.data import DataLoader from time import time - +from monai.losses import DiceLoss # import from local files -from train import trained_model, loss_map, LOSS_IDX -from dataset import X_test, y_test, Prostate3dDataset - -BATCH_SIZE = 2 - -""" - Tests improved unet on trained model. - Calcualtes dice coeficient for each image and corresponding ground truth. +from train import trained_model, CRITERION, compute_dice_segments +from dataset import X_test, y_test, Prostate3dDataset, visualise_ground_truths, visualise_predictions - Parameters: - - model (nn.Module): The trained model to be tested. - - test_loader (DataLoader): DataLoader for the test dataset. - - device (str): The device (e.g., 'cuda' or 'cpu') to run the evaluation on. +BATCH_SIZE = 1 - Returns: - - dice_scores (list): List of Dice coefficients for each image in the test dataset. -""" -def test(model, test_loader, criterion, device): +def test(model, test_loader, device): model.eval() # Set the model to evaluation mode + + criterion = DiceLoss(batch = True) test_dice_coefs = np.array([]) # stores dice scores. seg_0_dice_coef = np.array([]) @@ -39,15 +29,28 @@ def test(model, test_loader, criterion, device): seg_4_dice_coef = np.array([]) seg_5_dice_coef = np.array([]) + images = [] + ground_truths = [] + predictions = [] + with torch.no_grad(): - - criterion = criterion for i, (inputs, masks) in enumerate(test_loader): masks = masks.float() inputs, masks = inputs.to(device), masks.to(device) outputs = model(inputs) - test_loss, segment_coefs, test_dice = criterion(outputs, masks) + segment_coefs = compute_dice_segments(outputs, masks) + dice_loss = criterion(outputs, masks).item() + + test_dice = 1 - dice_loss + + if len(images) < 9: + image = inputs[0, 0 , : , : , 50].cpu().numpy() + images.append(image) + mask = masks[0, : , : , : , 50].cpu().numpy().astype(np.uint8) + ground_truths.append(mask) + prediction = torch.argmax(outputs[0, : , : , : , 50 ], dim = 0).cpu().numpy().astype(np.uint8) + predictions.append(prediction) seg_0_dice_coef = np.append(seg_0_dice_coef, segment_coefs[0].item()) seg_1_dice_coef = np.append(seg_1_dice_coef, segment_coefs[1].item()) @@ -58,7 +61,10 @@ def test(model, test_loader, criterion, device): print(f'Test No.{i} - Overall Dice Coefficient: {test_dice}') - test_dice_coefs = np.append(test_dice_coefs, test_dice.item()) + test_dice_coefs = np.append(test_dice_coefs, test_dice) + + visualise_ground_truths(images, ground_truths, CRITERION) + visualise_predictions(images, predictions, CRITERION) return test_dice_coefs, seg_0_dice_coef, seg_1_dice_coef, seg_2_dice_coef, seg_3_dice_coef, seg_4_dice_coef, seg_5_dice_coef @@ -66,6 +72,7 @@ def test(model, test_loader, criterion, device): Plots dice coefficients of the whole test dataset. Takes an array of dice scores as input. """ + def plot_dice(dice_coefs, criterion, segment_coefs): x_values = np.arange(len(dice_coefs)) # Generate x-values as indices @@ -81,7 +88,7 @@ def plot_dice(dice_coefs, criterion, segment_coefs): plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig(f'dice_coefs_test_{str(criterion)}.png') + plt.savefig(f'dice_coefs_test_{criterion}_loss.png') plt.close() @@ -89,8 +96,6 @@ def plot_dice(dice_coefs, criterion, segment_coefs): # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - criterion = loss_map.get(LOSS_IDX) - test_set = Prostate3dDataset(X_test, y_test) test_loader = DataLoader(dataset = test_set, batch_size = BATCH_SIZE) @@ -99,7 +104,7 @@ def plot_dice(dice_coefs, criterion, segment_coefs): start = time() # perform predictions - dice_coefs, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, criterion = criterion, + dice_coefs, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, device = device) end = time() @@ -132,6 +137,6 @@ def plot_dice(dice_coefs, criterion, segment_coefs): segment_coefs = [s0, s1, s2, s3, s4, s5] # plot dice scores across the dataset. - plot_dice(dice_coefs, criterion, segment_coefs) + plot_dice(dice_coefs, CRITERION, segment_coefs) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 48f5e1a12..2fd472394 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -3,153 +3,38 @@ import matplotlib.pyplot as plt import torch from torch.utils.data import DataLoader -import torch.nn as nn from time import time -import math import numpy as np - +from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss NUM_EPOCHS = 300 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -LOSS_IDX = 3 - -class BaseDice(nn.Module): - def __init__(self, epsilon = 1e-7): - super(BaseDice, self).__init__() - self.epsilon = epsilon - - def forward(self, y_pred, y_true): - raise NotImplementedError("Sublasses should implement this method.") - -class ExponentialWeightedLoss(BaseDice): - def __init__(self, epsilon=1e-7): - super().__init__(epsilon) +CRITERION = DiceLoss(batch=True) +# CRITERION = DiceCELoss(batch = True, lambda_ce = 0.2) # Based on Thyroid Tumor Segmentation Report +# CRITERION = DiceFocalLoss(batch = True) # Default gamma = 2 - def __str__(self): - return 'ExponentialWeightedLoss' +def compute_dice_segments(predictions, ground_truths): - def forward(self, y_pred, y_true): + criterion = DiceLoss(reduction='none', batch=True) - num_masks = y_true.size(-1) - segment_coefs = torch.zeros(num_masks, device=y_true.device) - for i in range(num_masks): - ground_truth_seg = y_true[:, :, :, :, i] - pred_seg = y_pred[:, :, :, :, i] + num_masks = predictions.size(1) - d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - segment_coefs[i] = d_coef + segment_coefs = torch.zeros(num_masks, device=ground_truths.device) - weighted, _ = torch.sort(segment_coefs, descending=True) + segment_losses = criterion(predictions, ground_truths) - for i in range(num_masks): - weighted[i] = segment_coefs[i] * (math.e ** i) + for i in range(num_masks): - d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = 1 - (1 / num_masks) * torch.sum(weighted) - return loss, segment_coefs, d_coef - -class ArithmeticWeightedLoss(BaseDice): - def __init__(self, epsilon=1e-7): - super().__init__(epsilon) - - def __str__(self): - return 'ArithmeticWeightedLoss' - - def forward(self, y_pred, y_true): - - num_masks = y_true.size(-1) - segment_coefs = torch.zeros(num_masks, device=y_true.device) - for i in range(num_masks): - ground_truth_seg = y_true[:, :, :, :, i] - pred_seg = y_pred[:, :, :, :, i] - - d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - segment_coefs[i] = d_coef - - weighted, _ = torch.sort(segment_coefs) - - for i in range(num_masks): - weighted[i] = segment_coefs[i] * (i + 1) - - d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = 1 - (1 / num_masks) * torch.sum(weighted) - return loss, segment_coefs, d_coef - -class PaperLoss(BaseDice): - def __init__(self, epsilon=1e-7): - super().__init__(epsilon) - - def __str__(self): - return 'PaperLoss' - - def forward(self, y_pred, y_true): - - num_masks = y_true.size(-1) - segment_coefs = torch.zeros(num_masks, device=y_true.device) - for i in range(num_masks): - ground_truth_seg = y_true[:, :, :, :, i] - pred_seg = y_pred[:, :, :, :, i] - - d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - segment_coefs[i] = d_coef + segment_coefs[i] = 1 - segment_losses[i, : , : , : ].item() - loss = (- 1 / num_masks) * torch.sum(segment_coefs) - d_coef = (1 / num_masks) * torch.sum(segment_coefs) - return loss, segment_coefs, d_coef - -class AlternativeLoss(BaseDice): - def __init__(self, epsilon=1e-7): - super().__init__(epsilon) + return segment_coefs - def __str__(self): - return 'AlternativeLoss' - - def forward(self, y_pred, y_true): - - num_masks = y_true.size(-1) - segment_coefs = torch.zeros(num_masks, device=y_true.device) - for i in range(num_masks): - ground_truth_seg = y_true[:, :, :, :, i] - pred_seg = y_pred[:, :, :, :, i] - - d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - segment_coefs[i] = d_coef - - d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = 1 - d_coef - return loss, segment_coefs, d_coef - -class DiceBCELoss(BaseDice): - def __init__(self, epsilon=1e-7): - super().__init__(epsilon) - - def __str__(self): - return 'DiceBCELoss' - - def forward(self, y_pred, y_true): - - num_masks = y_true.size(-1) - bce = nn.BCELoss() - segment_coefs = torch.zeros(num_masks, device=y_true.device) - - for i in range(num_masks): - ground_truth_seg = y_true[:, :, :, :, i] - pred_seg = y_pred[:, :, :, :, i] - - d_coef = (2 * torch.sum(torch.mul(ground_truth_seg, pred_seg))) / (torch.sum(ground_truth_seg + pred_seg) + self.epsilon) - segment_coefs[i] = d_coef - - d_coef = (1 / num_masks) * torch.sum(segment_coefs) - loss = (1 - d_coef) + 0.2 * bce(y_pred, y_true) # Based on the FFANet Report - return loss, segment_coefs, d_coef - -def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): +def train(model, X_train, y_train, criterion, num_epochs=NUM_EPOCHS, device="cuda"): # set up criterion, optimiser, and scheduler for learning rate. - criterion = loss optimiser = torch.optim.Adam(model.parameters(), lr = LEARNING_RATE, weight_decay = WEIGHT_DECAY) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma = LR_INITIAL) @@ -176,8 +61,9 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): optimiser.zero_grad() outputs = model(inputs) - # the weighted value is only used for updating gradients! - loss, segment_coefs, d_coef = criterion(y_pred = outputs, y_true = masks) + loss = criterion(outputs, masks) + + segment_coefs = compute_dice_segments(outputs, masks) total_segment_coefs += segment_coefs @@ -185,7 +71,7 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): optimiser.step() - running_dice += d_coef.item() + running_dice += 1 - loss.item() scheduler.step() @@ -214,18 +100,12 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): # create model. model = ImprovedUnet() -# Importing Dataloader breaks the implementation. Hence they are loaded below instead: - -loss_map = {0 : PaperLoss(), 1 : AlternativeLoss(), 2 : ExponentialWeightedLoss(), 3 : ArithmeticWeightedLoss(), 4 : DiceBCELoss()} - -loss = loss_map.get(LOSS_IDX) - print("> Start Training") start = time() # train improved unet -trained_model, training_dice_coefs, seg0, seg1, seg2, seg3, seg4, seg5 = train(model, X_train, y_train, loss = loss, +trained_model, training_dice_coefs, seg0, seg1, seg2, seg3, seg4, seg5 = train(model, X_train, y_train, criterion = CRITERION, device=device, num_epochs=NUM_EPOCHS) end = time() @@ -240,10 +120,10 @@ def train(model, X_train, y_train, loss, num_epochs=NUM_EPOCHS, device="cuda"): plt.plot(seg3, label='Segment 3 Dice Coefficient') plt.plot(seg4, label='Segment 4 Dice Coefficient') plt.plot(seg5, label='Segment 5 Dice Coefficient') -plt.title(f'Dice Coefficient Over Epochs for {str(loss)}') +plt.title(f'Dice Coefficient Over Epochs for {CRITERION}') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig(f'unet_dice_coefs_over_epochs_{str(loss)}.png') +plt.savefig(f'unet_dice_coefs_over_epochs_{CRITERION}.png') plt.close() \ No newline at end of file From e9bbb79b5ba817c4cc0e7f4dda66d5180f20bdb8 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 22 Oct 2024 01:43:10 +1000 Subject: [PATCH 078/102] fixed the dimension disagreement --- recognition/47049358/train.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 2fd472394..b7366d95f 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -7,7 +7,7 @@ import numpy as np from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss -NUM_EPOCHS = 300 +NUM_EPOCHS = 1 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 @@ -54,7 +54,7 @@ def train(model, X_train, y_train, criterion, num_epochs=NUM_EPOCHS, device="cud for epoch in range(num_epochs): running_dice = 0.0 - total_segment_coefs = torch.zeros(y_train.shape[-1], device=device) + total_segment_coefs = torch.zeros(y_train.shape[1], device=device) for inputs, masks in train_loader: masks = masks.float() inputs, masks = inputs.to(device), masks.to(device) From 34225de0dd0544cf38ba63fc59bc7045e385cc02 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:37:08 +1000 Subject: [PATCH 079/102] moved visualisations to predict.py and fixed the circular import --- recognition/47049358/dataset.py | 70 --------------------------------- recognition/47049358/modules.py | 1 - recognition/47049358/predict.py | 69 +++++++++++++++++++++++++++++++- recognition/47049358/train.py | 2 +- 4 files changed, 69 insertions(+), 73 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index c777448f6..af5ad2d06 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -11,9 +11,6 @@ import torchvision.transforms as transforms import random import torch -import matplotlib.pyplot as plt - -from modules import * # ========================== # Constants @@ -296,73 +293,6 @@ def augment_training_set(X_train, y_train): return X_train, y_train -def visualise_ground_truths(images, ground_truths, criterion): - - # Create a 3x3 grid of subplots - fig, axes = plt.subplots(3, 3, figsize=(15, 15)) - - # Plot the images - for i in range(3): - for j in range(3): - - idx = i * 3 + j - - # Original image - - image = images[idx] - - axes[i, j].imshow(image, cmap='gray') - axes[i, j].axis('off') - axes[i, j].set_title(f'Image {idx+1}') - - # Ground truth mask - - ground_truth = ground_truths[idx] - num_masks = ground_truth.shape[0] - - mask_gt = np.zeros((ground_truth.shape[1], y_train.shape[2]), dtype = np.uint8) - - for k in range(num_masks): - mask_gt += (k + 1) * ground_truth[k, : , : ] - axes[i, j].imshow(mask_gt, cmap='jet', alpha=0.3) - - # Show the plot - plt.tight_layout() - plt.savefig(f'ground_truths_{criterion}.png') - plt.show() - - return fig, axes - -def visualise_predictions(images, predictions, criterion): - - # Create a 3x3 grid of subplots - fig, axes = plt.subplots(3, 3, figsize=(15, 15)) - - # Plot the images - for i in range(3): - for j in range(3): - - idx = i * 3 + j - - # Original image - - image = images[idx] - - axes[i, j].imshow(image, cmap='gray') - axes[i, j].axis('off') - axes[i, j].set_title(f'Image {idx+1}') - - mask_pred = predictions[idx] - - axes[i, j].imshow(mask_pred, cmap='jet', alpha=0.3) - - # Show the plot - plt.tight_layout() - plt.savefig(f'predictions_{criterion}.png') - plt.show() - - return fig, axes - print('> Loading Dataset') rawImageNames = os.listdir(IMAGE_FILE_NAME) diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 204910fed..94cf05a49 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -1,6 +1,5 @@ import torch import torch.nn as nn -import numpy as np NEGATIVE_SLOPE = 10 ** -2 DROP_PROB = 0.3 diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 3e65074f4..1cc32c67c 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -12,10 +12,77 @@ # import from local files from train import trained_model, CRITERION, compute_dice_segments -from dataset import X_test, y_test, Prostate3dDataset, visualise_ground_truths, visualise_predictions +from dataset import X_test, y_test, Prostate3dDataset BATCH_SIZE = 1 +def visualise_ground_truths(images, ground_truths, criterion): + + # Create a 3x3 grid of subplots + fig, axes = plt.subplots(3, 3, figsize=(15, 15)) + + # Plot the images + for i in range(3): + for j in range(3): + + idx = i * 3 + j + + # Original image + + image = images[idx] + + axes[i, j].imshow(image, cmap='gray') + axes[i, j].axis('off') + axes[i, j].set_title(f'Image {idx+1}') + + # Ground truth mask + + ground_truth = ground_truths[idx] + num_masks = ground_truth.shape[0] + + mask_gt = np.zeros((ground_truth.shape[1], ground_truth.shape[2]), dtype = np.uint8) + + for k in range(num_masks): + mask_gt += (k + 1) * ground_truth[k, : , : ] + axes[i, j].imshow(mask_gt, cmap='jet', alpha=0.3) + + # Show the plot + plt.tight_layout() + plt.savefig(f'ground_truths_{criterion}.png') + plt.close() + + return fig, axes + +def visualise_predictions(images, predictions, criterion): + + # Create a 3x3 grid of subplots + fig, axes = plt.subplots(3, 3, figsize=(15, 15)) + + # Plot the images + for i in range(3): + for j in range(3): + + idx = i * 3 + j + + # Original image + + image = images[idx] + + axes[i, j].imshow(image, cmap='gray') + axes[i, j].axis('off') + axes[i, j].set_title(f'Image {idx+1}') + + mask_pred = predictions[idx] + + axes[i, j].imshow(mask_pred, cmap='jet', alpha=0.3) + + # Show the plot + plt.tight_layout() + plt.savefig(f'predictions_{criterion}.png') + plt.close() + + return fig, axes + def test(model, test_loader, device): model.eval() # Set the model to evaluation mode diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index b7366d95f..ba748b9c3 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -7,7 +7,7 @@ import numpy as np from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss -NUM_EPOCHS = 1 +NUM_EPOCHS = 300 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 From 4d21ea9deef922590bfcb0573de002f85f2b5e57 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 07:08:05 +1000 Subject: [PATCH 080/102] functioning monai implementation! --- recognition/47049358/dataset.py | 336 +++----------------------------- recognition/47049358/predict.py | 31 +-- recognition/47049358/train.py | 54 ++--- 3 files changed, 76 insertions(+), 345 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index af5ad2d06..432b5fdfc 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -3,14 +3,9 @@ # ========================== import os from sklearn.model_selection import train_test_split -import numpy as np -import nibabel as nib -from tqdm import tqdm -from torch.utils.data import Dataset -import torchvision.transforms.functional as F -import torchvision.transforms as transforms -import random -import torch +from monai.transforms import (LoadImaged, EnsureChannelFirstd, ScaleIntensityd, + SpatialCropd, RandFlipd, RandRotated, CastToTyped, AsDiscreted, + RandGaussianNoised, Compose) # ========================== # Constants @@ -19,305 +14,34 @@ IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') -# ========================== -# Loading Dataset -# ========================== - -def to_channels(arr: np.ndarray, dtype=np.uint8) -> np.ndarray: - channels = np.unique(arr) - res = np.zeros(arr.shape + (len(channels),), dtype=dtype) - for c in channels: - c = int(c) - res[..., c:c+1][arr == c] = 1 - return res - -# Load medical image functions -def load_data_2D(imageNames, normImage=False, categorical=False, dtype=np.float32, getAffines=False, early_stop=False): - ''' - Load medical image data from names, cases list provided into a list for each. - This function pre-allocates 4D arrays for conv2d to avoid excessive memory usage. - - normImage : bool (normalize the image 0.0-1.0) - early_stop : Stop loading prematurely, leaves arrays mostly empty, for quick loading and testing scripts. - ''' - affines = [] - num = len(imageNames) - first_case = nib.load(imageNames[0]).get_fdata(caching='unchanged') - - if len(first_case.shape) == 3: - first_case = first_case[:, :, 0] # sometimes extra dims, remove - - if categorical: - first_case = to_channels(first_case, dtype=dtype) - rows, cols, channels = first_case.shape - images = np.zeros((num, rows, cols, channels), dtype=dtype) - else: - rows, cols = first_case.shape - images = np.zeros((num, rows, cols), dtype=dtype) - - for i, inName in enumerate(tqdm(imageNames)): - niftiImage = nib.load(inName) - inImage = niftiImage.get_fdata(caching='unchanged') # read disk only - affine = niftiImage.affine - - if len(inImage.shape) == 3: - inImage = inImage[:, :, 0] # sometimes extra dims in HipMRI_study data - - inImage = inImage.astype(dtype) - - if normImage: - inImage = (inImage - inImage.mean()) / inImage.std() - - if categorical: - # inImage = utils.to_channels(inImage, dtype=dtype) - images[i, :, :, :] = inImage - else: - images[i, :, :] = inImage - - affines.append(affine) - - if i > 20 and early_stop: - break - - return (images, affines) if getAffines else images - -def load_data_3D(imageNames, normImage=False, categorical=False, dtype=np.float32, early_stop=False): - ''' - Load medical image data from names, cases list provided into a list for each. - This function pre-allocates 5D arrays for conv3d to avoid excessive memory usage. - - normImage : bool (normalize the image 0.0-1.0) - dtype : Type of the data. If dtype=np.uint8, it is assumed that the data has labels. - early_stop : Stop loading prematurely. Leaves arrays mostly empty, for quick loading and testing scripts. - ''' - affines = [] - - num = len(imageNames) - niftiImage = nib.load(imageNames[0]) - - first_case = niftiImage.get_fdata(caching='unchanged') - - if len(first_case.shape) == 4: - first_case = first_case[:, :, :, 0] # sometimes extra dims, remove - - if categorical: - first_case = to_channels(first_case, dtype=dtype) - rows, cols, depth, channels = first_case.shape - images = np.zeros((num, rows, cols, depth, channels), dtype=dtype) - else: - rows, cols, depth = first_case.shape - images = np.zeros((num, rows, cols, depth), dtype=dtype) - - for i, inName in enumerate(tqdm(imageNames)): - - niftiImage = nib.load(inName) - - inImage = niftiImage.get_fdata(caching='unchanged') # read disk only - affine = niftiImage.affine - - if len(inImage.shape) == 4: - inImage = inImage[ : , : , : , 0] # sometimes extra dims in HipMRI_study data - - inImage = inImage[ : , : , : depth] # clip slices - inImage = inImage.astype(dtype) - - if normImage: - inImage = (inImage - inImage.mean()) / inImage.std() - - if categorical: - inImage = to_channels(inImage, dtype=dtype) - images[i, : inImage.shape[0], : inImage.shape[1], : inImage.shape[2], : inImage.shape[3]] = inImage # with pad - else: - images[i, : inImage.shape[0], : inImage.shape[1], : inImage.shape[2]] = inImage # with pad - - affines.append(affine) - - if i > 20 and early_stop: - break - - return images - -def load_images_and_labels(image_file_name, label_file_name, early_stop = False): - images = load_data_3D(imageNames=image_file_name, normImage = True, early_stop=early_stop) - labels = load_data_3D(imageNames=label_file_name, categorical=True, dtype = np.uint8, early_stop=early_stop) - return images, labels - -class Prostate3dDataset(Dataset): - def __init__(self, images, labels): - self.images = images - self.labels = labels - - def __len__(self): - return len(self.images) - - def __getitem__(self, idx): - img = self.images[idx] - mask = self.labels[idx] - return img, mask - -# ========================== -# Image Augmentation -# ========================== - -def random_rotation(image: torch.Tensor, angle = 0.0): - - image = F.rotate(image, angle = angle, fill = image.min().item()) - - return image - -def random_resize_with_padding(image: torch.Tensor, height = 256, width = 256, is_mask = False): - - original_height = image.size(1) - original_width = image.size(2) - - top_p = (original_height - height) // 2 - bottom_p = (original_height - height) - top_p - right_p = (original_width - width) // 2 - left_p = (original_width - width) - right_p - resized = F.resize(image, size = (height, width)) - padding = (left_p, top_p, right_p, bottom_p) - image = F.pad(resized, padding = padding, fill = image.min().item()) - - if is_mask: - image = torch.clamp(torch.round(image), min = 0, max = 1) - - return image - -def gamma_correction(image: torch.Tensor, gamma = 1): - - image = F.adjust_gamma(image, gamma) - image = torch.nan_to_num(image, nan = 0) - - return image - -def elastic_transformation(image: torch.Tensor, alpha = 5.0, sigma = 0.5, is_mask = False): - - elastic_transformation = transforms.Compose([ - transforms.ToPILImage(), - transforms.ElasticTransform(alpha=alpha, sigma=sigma), - transforms.PILToTensor() - ]) - - if is_mask: - - mask = elastic_transformation(image) - mask = torch.clamp(torch.round(mask), min = 0, max = 1) - - return mask - - image = elastic_transformation(image) - - return image - -def apply_transformation(image: torch.Tensor, masks_3d: torch.Tensor, device = 'cpu'): - - alpha = random.uniform(0.0, 10.0) - sigma = random.uniform(0.0, 1.0) - make_elastic = random.choice([True, False]) - - angle = random.uniform(0, 180) - rotate = random.choice([True, False]) - - height = random.randint(128, 256) - width = random.randint(128, 256) - resize = random.choice([True, False]) - - gamma = random.uniform(0.25, 2) - adjust_gamma = random.choice([True, False]) - - hflip = random.choice([True, False]) - - vflip = random.choice([True, False]) - - image = torch.Tensor(image) - masks_3d = torch.Tensor(masks_3d) - - image = image.to(device) - masks_3d = masks_3d.to(device) - - for j in range(image.shape[-1]): - - slice = image[ : , : , j] - slice = slice[np.newaxis, : , :] - masks = masks_3d[: , : , j , :] - masks = masks[np.newaxis, : , :, : ] - - unique_elements = np.unique(masks[0, : , : , 0]) - - if len(unique_elements) == 1 and unique_elements[0] == 1: - slice = torch.full((slice.shape), -1) - image[: , : , j] = slice - continue - - slice = random_rotation(image = slice, angle = angle) if rotate else slice - slice = random_resize_with_padding(image = slice, height = height, width = width) if resize else slice - slice = elastic_transformation(image = slice, alpha = alpha, sigma = sigma) if make_elastic else slice - slice = gamma_correction(image = slice, gamma = gamma) if adjust_gamma else slice - slice = F.hflip(slice) if hflip else slice - slice = F.vflip(slice) if vflip else slice - - for i in range(masks.size(-1)): - mask = masks[ : , : , : , i] - - mask = random_rotation(image = mask, angle = angle) if rotate else mask - mask = random_resize_with_padding(image = mask, height = height, width = width, is_mask=True) if resize else mask - mask = elastic_transformation(image = mask, alpha = alpha, sigma = sigma, is_mask = True) if make_elastic else mask - mask = F.hflip(mask) if hflip else mask - mask = F.vflip(mask) if vflip else mask - - masks[ : , : , : , i] = mask - - masks_3d[: , : , j , :] = masks - - image[ : , : , j] = slice - - image = image.cpu().numpy() - masks_3d = masks_3d.cpu().numpy() - - return image, masks_3d - -def augment_training_set(X_train, y_train): - - - device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') - - for i in range(X_train.shape[0]): - - image = X_train[i, : , : , : ] - masks_3d = y_train[i, : , : , : , :] - - transformed_img, transformed_masks_3d = apply_transformation(image = image, masks_3d = masks_3d, device = device) - - X_train[i, : , : , : ] = transformed_img - y_train[i, : , : , : , :] = transformed_masks_3d - - return X_train, y_train - -print('> Loading Dataset') - rawImageNames = os.listdir(IMAGE_FILE_NAME) rawLabelNames = os.listdir(LABEL_FILE_NAME) # Split the set into train, validation, and test set (80 : 20 for train:test) -X_train, X_test, y_train, y_test = train_test_split(rawImageNames, rawLabelNames, train_size=0.8) # Split the data in training and test set - -X_train = [os.path.join(IMAGE_FILE_NAME, image) for image in X_train] -X_test = [os.path.join(IMAGE_FILE_NAME, image) for image in X_test] - -y_train = [os.path.join(LABEL_FILE_NAME, label) for label in y_train] -y_test = [os.path.join(LABEL_FILE_NAME, label) for label in y_test] - -X_train, y_train = load_images_and_labels(X_train, y_train, early_stop=False) -X_test, y_test = load_images_and_labels(X_test, y_test, early_stop=False) - -print('> Start Random Augmentation') - -X_train, y_train = augment_training_set(X_train, y_train) - -print('> Augmentation Complete') - -X_train = X_train[: ,np.newaxis, :, :, :] -X_test = X_test[:, np.newaxis, :, :, :] - -y_train = np.transpose(y_train, (0, 4, 1, 2, 3)) -y_test = np.transpose(y_test, (0, 4, 1, 2, 3)) \ No newline at end of file +train_images, test_images, train_labels, test_labels = train_test_split(rawImageNames, rawLabelNames, train_size=0.1) # Split the data in training and test set + +train_transforms = Compose( + [ + LoadImaged(keys=["image", "label"]), + EnsureChannelFirstd(keys=["image", "label"]), + SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), # Crop to depth 128 + RandFlipd(keys=["image", "label"], spatial_axis=0), + RandRotated(keys=["image", "label"], range_x=0.5, range_y=0.5, range_z=0.5, mode='nearest'), + ScaleIntensityd(keys=["image"]), + RandGaussianNoised(keys=["image"], prob=0, std=0.5), + AsDiscreted(keys=["label"], to_onehot=6), + ] +) + +test_transforms = Compose( + [ + LoadImaged(keys=["image", "label"]), + EnsureChannelFirstd(keys=["image", "label"]), + SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), + ScaleIntensityd(keys=["image"]), + AsDiscreted(keys=["label"], to_onehot=6), + ] +) + +train_dict = [{"image": os.path.join(IMAGE_FILE_NAME, image), "label": os.path.join(LABEL_FILE_NAME, label)} for image, label in zip(train_images, train_labels)] +test_dict = [{"image": os.path.join(IMAGE_FILE_NAME, image), "label": os.path.join(LABEL_FILE_NAME, label)} for image, label in zip(test_images, test_labels)] \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 1cc32c67c..af6327e79 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -9,12 +9,11 @@ from torch.utils.data import DataLoader from time import time from monai.losses import DiceLoss +from monai.data import DataLoader, Dataset # import from local files from train import trained_model, CRITERION, compute_dice_segments -from dataset import X_test, y_test, Prostate3dDataset - -BATCH_SIZE = 1 +from dataset import test_dict, test_transforms def visualise_ground_truths(images, ground_truths, criterion): @@ -48,7 +47,7 @@ def visualise_ground_truths(images, ground_truths, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'ground_truths_{criterion}.png') + plt.savefig(f'test_results/ground_truths_{criterion}.png') plt.close() return fig, axes @@ -78,7 +77,7 @@ def visualise_predictions(images, predictions, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'predictions_{criterion}.png') + plt.savefig(f'test_results/predictions_{criterion}.png') plt.close() return fig, axes @@ -102,19 +101,21 @@ def test(model, test_loader, device): with torch.no_grad(): - for i, (inputs, masks) in enumerate(test_loader): - masks = masks.float() - inputs, masks = inputs.to(device), masks.to(device) + for i, batch_data in enumerate(test_loader): + inputs, labels = ( + batch_data["image"].to(device), + batch_data["label"].to(device), + ) outputs = model(inputs) - segment_coefs = compute_dice_segments(outputs, masks) - dice_loss = criterion(outputs, masks).item() + segment_coefs = compute_dice_segments(outputs, labels) + dice_loss = criterion(outputs, labels).item() test_dice = 1 - dice_loss if len(images) < 9: image = inputs[0, 0 , : , : , 50].cpu().numpy() images.append(image) - mask = masks[0, : , : , : , 50].cpu().numpy().astype(np.uint8) + mask = labels[0, : , : , : , 50].cpu().numpy().astype(np.uint8) ground_truths.append(mask) prediction = torch.argmax(outputs[0, : , : , : , 50 ], dim = 0).cpu().numpy().astype(np.uint8) predictions.append(prediction) @@ -155,7 +156,7 @@ def plot_dice(dice_coefs, criterion, segment_coefs): plt.title("Dice Coefficient across test inputs") plt.legend() plt.grid(True) - plt.savefig(f'dice_coefs_test_{criterion}_loss.png') + plt.savefig(f'test_results/dice_coefs_test_{criterion}.png') plt.close() @@ -163,8 +164,8 @@ def plot_dice(dice_coefs, criterion, segment_coefs): # connect to gpu device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - test_set = Prostate3dDataset(X_test, y_test) - test_loader = DataLoader(dataset = test_set, batch_size = BATCH_SIZE) + test_set = Dataset(test_dict, test_transforms) + test_loader = DataLoader(dataset = test_set, batch_size = 1) print('> Start Testing') @@ -178,7 +179,7 @@ def plot_dice(dice_coefs, criterion, segment_coefs): elapsed_time = end - start - print(f"> Testing completed in {elapsed_time:.2f} seconds") + print(f"> Test completed in {elapsed_time:.2f} seconds") average_dice = np.mean(dice_coefs) print(f"Average Dice Coefficient: {average_dice:.4f}") diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index ba748b9c3..7c451b7c6 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -1,4 +1,4 @@ -from dataset import X_train, y_train, Prostate3dDataset +from dataset import train_dict, train_transforms from modules import ImprovedUnet import matplotlib.pyplot as plt import torch @@ -6,15 +6,16 @@ from time import time import numpy as np from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss +from monai.data import DataLoader, Dataset -NUM_EPOCHS = 300 +NUM_EPOCHS = 3 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -CRITERION = DiceLoss(batch=True) -# CRITERION = DiceCELoss(batch = True, lambda_ce = 0.2) # Based on Thyroid Tumor Segmentation Report -# CRITERION = DiceFocalLoss(batch = True) # Default gamma = 2 +CRITERION = DiceLoss(include_background=False, batch=True) +# CRITERION = DiceCELoss(include_background=False, batch = True, lambda_ce = 0.2) # Based on Thyroid Tumor Segmentation Report +# CRITERION = DiceFocalLoss(include_background=False, batch = True) # Default gamma = 2 def compute_dice_segments(predictions, ground_truths): @@ -32,7 +33,7 @@ def compute_dice_segments(predictions, ground_truths): return segment_coefs -def train(model, X_train, y_train, criterion, num_epochs=NUM_EPOCHS, device="cuda"): +def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): # set up criterion, optimiser, and scheduler for learning rate. optimiser = torch.optim.Adam(model.parameters(), lr = LEARNING_RATE, weight_decay = WEIGHT_DECAY) @@ -49,21 +50,21 @@ def train(model, X_train, y_train, criterion, num_epochs=NUM_EPOCHS, device="cud seg_4_dice_coefs = np.zeros(NUM_EPOCHS) seg_5_dice_coefs = np.zeros(NUM_EPOCHS) - train_set = Prostate3dDataset(X_train, y_train) - train_loader = DataLoader(dataset = train_set, batch_size = BATCH_SIZE) - for epoch in range(num_epochs): running_dice = 0.0 - total_segment_coefs = torch.zeros(y_train.shape[1], device=device) - for inputs, masks in train_loader: - masks = masks.float() - inputs, masks = inputs.to(device), masks.to(device) + total_segment_coefs = torch.zeros(6, device=device) + for batch_data in train_loader: + inputs, labels = ( + batch_data["image"].to(device), + batch_data["label"].to(device), + ) + optimiser.zero_grad() outputs = model(inputs) - loss = criterion(outputs, masks) + loss = criterion(outputs, labels) - segment_coefs = compute_dice_segments(outputs, masks) + segment_coefs = compute_dice_segments(outputs, labels) total_segment_coefs += segment_coefs @@ -104,8 +105,11 @@ def train(model, X_train, y_train, criterion, num_epochs=NUM_EPOCHS, device="cud start = time() +train_set = Dataset(data=train_dict, transform=train_transforms) +train_loader = DataLoader(train_set, batch_size=BATCH_SIZE) + # train improved unet -trained_model, training_dice_coefs, seg0, seg1, seg2, seg3, seg4, seg5 = train(model, X_train, y_train, criterion = CRITERION, +trained_model, training_dice_coefs, seg0, seg1, seg2, seg3, seg4, seg5 = train(model, train_loader, criterion = CRITERION, device=device, num_epochs=NUM_EPOCHS) end = time() @@ -113,17 +117,19 @@ def train(model, X_train, y_train, criterion, num_epochs=NUM_EPOCHS, device="cud elapsed_time = end - start print(f"> Training completed in {elapsed_time:.2f} seconds") -plt.plot(training_dice_coefs, label='Training Dice Coefficient') -plt.plot(seg0, label='Segment 0 Dice Coefficient') -plt.plot(seg1, label='Segment 1 Dice Coefficient') -plt.plot(seg2, label='Segment 2 Dice Coefficient') -plt.plot(seg3, label='Segment 3 Dice Coefficient') -plt.plot(seg4, label='Segment 4 Dice Coefficient') -plt.plot(seg5, label='Segment 5 Dice Coefficient') +epochs = range(1, NUM_EPOCHS + 1) + +plt.plot(epochs, training_dice_coefs, label='Training Dice Coefficient') +plt.plot(epochs, seg0, label='Segment 0 Dice Coefficient') +plt.plot(epochs, seg1, label='Segment 1 Dice Coefficient') +plt.plot(epochs, seg2, label='Segment 2 Dice Coefficient') +plt.plot(epochs, seg3, label='Segment 3 Dice Coefficient') +plt.plot(epochs, seg4, label='Segment 4 Dice Coefficient') +plt.plot(epochs, seg5, label='Segment 5 Dice Coefficient') plt.title(f'Dice Coefficient Over Epochs for {CRITERION}') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig(f'unet_dice_coefs_over_epochs_{CRITERION}.png') +plt.savefig(f'training_results/unet_dice_coefs_over_epochs_{CRITERION}.png') plt.close() \ No newline at end of file From ef5a4dfddadd8c344fbf5f7207061922b1131f4b Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:06:05 +1000 Subject: [PATCH 081/102] normalisation added --- recognition/47049358/dataset.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 432b5fdfc..43040c246 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -4,8 +4,8 @@ import os from sklearn.model_selection import train_test_split from monai.transforms import (LoadImaged, EnsureChannelFirstd, ScaleIntensityd, - SpatialCropd, RandFlipd, RandRotated, CastToTyped, AsDiscreted, - RandGaussianNoised, Compose) + SpatialCropd, RandFlipd, RandRotated, AsDiscreted, + RandGaussianNoised, Compose, NormalizeIntensityd) # ========================== # Constants @@ -14,11 +14,11 @@ IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') -rawImageNames = os.listdir(IMAGE_FILE_NAME) -rawLabelNames = os.listdir(LABEL_FILE_NAME) +rawImageNames = sorted(os.listdir(IMAGE_FILE_NAME)) +rawLabelNames = sorted(os.listdir(LABEL_FILE_NAME)) # Split the set into train, validation, and test set (80 : 20 for train:test) -train_images, test_images, train_labels, test_labels = train_test_split(rawImageNames, rawLabelNames, train_size=0.1) # Split the data in training and test set +train_images, test_images, train_labels, test_labels = train_test_split(rawImageNames, rawLabelNames, train_size=0.8) # Split the data in training and test set train_transforms = Compose( [ @@ -27,6 +27,7 @@ SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), # Crop to depth 128 RandFlipd(keys=["image", "label"], spatial_axis=0), RandRotated(keys=["image", "label"], range_x=0.5, range_y=0.5, range_z=0.5, mode='nearest'), + NormalizeIntensityd(keys=["image"]), ScaleIntensityd(keys=["image"]), RandGaussianNoised(keys=["image"], prob=0, std=0.5), AsDiscreted(keys=["label"], to_onehot=6), @@ -38,6 +39,7 @@ LoadImaged(keys=["image", "label"]), EnsureChannelFirstd(keys=["image", "label"]), SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), + NormalizeIntensityd(keys=["image"]), ScaleIntensityd(keys=["image"]), AsDiscreted(keys=["label"], to_onehot=6), ] From fb86049b752ad10b21289498c9b97243189ac078 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:17:12 +1000 Subject: [PATCH 082/102] memory storage integer conversion --- recognition/47049358/README.md | 26 +++++++++++++++++----- recognition/47049358/dataset.py | 18 +++++++-------- recognition/47049358/predict.py | 38 +++++++++++++++++++------------- recognition/47049358/train.py | 4 ++-- requirements.txt | Bin 0 -> 14052 bytes 5 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 requirements.txt diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index 9359b941a..33fc6d24a 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -1,13 +1,29 @@ +# Improved 3D Improved UNet + +## The Model + +

+ Improved 3D UNet Architecture +

+ + UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. + + ## The Problem + + Segmentation is a task that requires a machine learning models to divide image components into meaningful parts. In other words, the model is required to classify components of an image correctly into given labels. + + + (Dice Coefficient)[https://en.wikipedia.org/wiki/Dice-Sørensen_coefficient] Updates: **Data Augmentation** -- Random Rotation - Implemented -- Random Scaling - ~~Implemented~~ → Omitted as dimensions disagree with the rest of dataset -- Elastic Transformation - Omitted given the constraint in data type -- Gamma Correction - Implemented -- Mirroring - Implemented as a Horizontal Flip +- Random Rotation +- Random Scaling +- Normalisation +- Gamma Correction +- Vertical Flip (Loss Function)[https://www.sciencedirect.com/science/article/pii/S1746809422007030] \ No newline at end of file diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 43040c246..5a1e0740a 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -3,9 +3,10 @@ # ========================== import os from sklearn.model_selection import train_test_split -from monai.transforms import (LoadImaged, EnsureChannelFirstd, ScaleIntensityd, +from monai.transforms import (LoadImaged, EnsureChannelFirstd, RandScaleIntensityd, SpatialCropd, RandFlipd, RandRotated, AsDiscreted, - RandGaussianNoised, Compose, NormalizeIntensityd) + RandGaussianNoised, Compose, CastToTyped) +import torch # ========================== # Constants @@ -25,12 +26,12 @@ LoadImaged(keys=["image", "label"]), EnsureChannelFirstd(keys=["image", "label"]), SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), # Crop to depth 128 - RandFlipd(keys=["image", "label"], spatial_axis=0), - RandRotated(keys=["image", "label"], range_x=0.5, range_y=0.5, range_z=0.5, mode='nearest'), - NormalizeIntensityd(keys=["image"]), - ScaleIntensityd(keys=["image"]), - RandGaussianNoised(keys=["image"], prob=0, std=0.5), + RandFlipd(keys=["image", "label"], spatial_axis=0, prob=0.5), + RandRotated(keys=["image", "label"], range_x=0.5, range_y=0.5, range_z=0.5, mode='nearest', prob=0.5), + RandScaleIntensityd(keys=["image"], factors=0.5, prob=0.5), + RandGaussianNoised(keys=["image"], prob=0.5, mean=0, std=0.5), AsDiscreted(keys=["label"], to_onehot=6), + CastToTyped(keys=["label"], dtype=torch.uint8), ] ) @@ -39,9 +40,8 @@ LoadImaged(keys=["image", "label"]), EnsureChannelFirstd(keys=["image", "label"]), SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), - NormalizeIntensityd(keys=["image"]), - ScaleIntensityd(keys=["image"]), AsDiscreted(keys=["label"], to_onehot=6), + CastToTyped(keys=["label"], dtype=torch.uint8), ] ) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index af6327e79..8afcc0130 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -10,6 +10,7 @@ from time import time from monai.losses import DiceLoss from monai.data import DataLoader, Dataset +from monai.transforms import (AsDiscrete, Compose, CastToType) # import from local files from train import trained_model, CRITERION, compute_dice_segments @@ -47,7 +48,7 @@ def visualise_ground_truths(images, ground_truths, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'test_results/ground_truths_{criterion}.png') + plt.savefig(f'ground_truths_{criterion}.png') plt.close() return fig, axes @@ -77,7 +78,7 @@ def visualise_predictions(images, predictions, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'test_results/predictions_{criterion}.png') + plt.savefig(f'predictions_{criterion}.png') plt.close() return fig, axes @@ -99,6 +100,13 @@ def test(model, test_loader, device): ground_truths = [] predictions = [] + output_transform = Compose( + [ + AsDiscrete(to_onehot=6), + CastToType(dtype=torch.uint8), + ] +) + with torch.no_grad(): for i, batch_data in enumerate(test_loader): @@ -107,6 +115,7 @@ def test(model, test_loader, device): batch_data["label"].to(device), ) outputs = model(inputs) + outputs = output_transform(torch.argmax(outputs, dim=1))[np.newaxis, : , : , : , :] segment_coefs = compute_dice_segments(outputs, labels) dice_loss = criterion(outputs, labels).item() @@ -141,22 +150,20 @@ def test(model, test_loader, device): Takes an array of dice scores as input. """ -def plot_dice(dice_coefs, criterion, segment_coefs): +def plot_dice(criterion, segment_coefs): + + x_values = np.arange(len(segment_coefs)) # Generate x-values as indices + bar_width = 0.1 # Width of the bars - x_values = np.arange(len(dice_coefs)) # Generate x-values as indices # Plot overall dice scores - plt.plot(x_values, dice_coefs, label='Overall Dice Coefficient') - - # Plot segment scores - for i, segment_coef in enumerate(segment_coefs): - plt.plot(x_values, segment_coef, label=f'Segment {i} Dice Coefficients') + plt.bar(x_values, segment_coefs, width=bar_width) - plt.xlabel("Image Index") - plt.ylabel("Dice Coefficient") - plt.title("Dice Coefficient across test inputs") + plt.xlabel("Segment No.") + plt.ylabel("Dice Score") + plt.title("Dice Score for Each Segment") plt.legend() plt.grid(True) - plt.savefig(f'test_results/dice_coefs_test_{criterion}.png') + plt.savefig(f'dice_coefs_test_{criterion}.png') plt.close() @@ -202,9 +209,10 @@ def plot_dice(dice_coefs, criterion, segment_coefs): average_s5 = np.mean(s5) print(f"Segment 5 Dice Coefficient: {average_s5:.4f}") - segment_coefs = [s0, s1, s2, s3, s4, s5] + segment_coefs = np.array([average_s0, average_s1, average_s2, average_s3, + average_s4, average_s5]) # plot dice scores across the dataset. - plot_dice(dice_coefs, CRITERION, segment_coefs) + plot_dice(CRITERION, segment_coefs) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 7c451b7c6..fea0a0e48 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -8,7 +8,7 @@ from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss from monai.data import DataLoader, Dataset -NUM_EPOCHS = 3 +NUM_EPOCHS = 300 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 @@ -131,5 +131,5 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig(f'training_results/unet_dice_coefs_over_epochs_{CRITERION}.png') +plt.savefig(f'unet_dice_coefs_over_epochs_{CRITERION}.png') plt.close() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..f5aa83199de7cafe2ce807e11235ec14b5df4d1a GIT binary patch literal 14052 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⪚=~G==w4v|?B@D|2KmOs8I9FE716nI7dcTT`JEARwxpp8 zDnB#*dmoeY0Dfg25JCH%hz!WG@U|UY#a1`3M+$EYd6DbU}!<;t;dt*aCRu8{d28ofScCBLoW?(ooi%mIgQDM9-s z%Ae_6=jkDBbB_KL+Obc}(+nQQKWxF+5p?A_Z^691Bcpj6gy|#ZZR3LXH1udpZ}jl= zlzhg!&<*w|%S`570KYBA&M?161C@7l#5r4NBatn%Z`o$A!T}4}C+9~4NY8A{-)w*b zIk69sacJS@^P&GK8+#f6gNO~P4&TqwU?VwrGmSsjvY=}Zh?w7wLY{KAI-Z-sk<7s- z$2gv)o8k&@mfY=Q2C!cxS0fv0q#&Bki#l>B@~VQv;nplucE+O;5jz z%elVSbX?c*vWHHp|>^j+*fMPR6M@*N*cJx!o(UU#vw{P^!yxBfe zO!~$S`LWe`*||+qJW)(!#CuKNII~COmL%#YaZBd0l|f%9noyJ4%bP)1l{*qw->tB2 zF7J4s&O6ZgwznUZjT4Lq!eIZ+)eVgyJ z*h9p*Xd9h-jqk$w;dTBm~`k0*dXBnV(t8j^(GxSGyKP-9=AT=D_w#20zAoc zyldrmFWD1O(+iow?E^l6H!~S1&@>A*qwc%3 zVAmCMEB$khhqmmr1$eiV%w#Wmm=pP}0AlvIZbnvj%VX)n{(UQdxnf4eN3-v6ioP2Q zN7Q+0|44Yoy{V)5Ly`EpvmH Date: Wed, 23 Oct 2024 18:26:24 +1000 Subject: [PATCH 083/102] redundant bar width remove --- recognition/47049358/predict.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 8afcc0130..dc64a85ca 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -153,10 +153,9 @@ def test(model, test_loader, device): def plot_dice(criterion, segment_coefs): x_values = np.arange(len(segment_coefs)) # Generate x-values as indices - bar_width = 0.1 # Width of the bars # Plot overall dice scores - plt.bar(x_values, segment_coefs, width=bar_width) + plt.bar(x_values, segment_coefs) plt.xlabel("Segment No.") plt.ylabel("Dice Score") From 00b26cbb9feb2e227496f388342eb3ed77e1d7f9 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:16:37 +1000 Subject: [PATCH 084/102] grdient accumulation and mixed precision --- recognition/47049358/README.md | 20 ++++++++++++++++- recognition/47049358/predict.py | 6 ++--- recognition/47049358/train.py | 39 ++++++++++++++++++--------------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index 33fc6d24a..26b0976bf 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -6,7 +6,25 @@ Improved 3D UNet Architecture

- UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. + UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network.\ + + + || Role | +| --------------- | ---------------------------------------- | +| William Mercado | Team Leader | +| Brian Zhang | Machine Learning Developer | +| Hongyingzi Lu | Design Coordinator / Front-End Developer | +| Shan Liu | Design Coordinator / Front-End Developer | +| Yang Xiao | Back-End Developer | +| Ryuto Hisamoto | Back-End Developer | + + ### Training + +The model takes in an raw image as its input, and its goal is to learn the best feature map which ends up being a smulti-channel segmentation of the original image. + + ### Testing + + ## The Problem diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index dc64a85ca..8d7625c77 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -13,7 +13,7 @@ from monai.transforms import (AsDiscrete, Compose, CastToType) # import from local files -from train import trained_model, CRITERION, compute_dice_segments +from train import trained_model, CRITERION, compute_dice_segments, DEVICE from dataset import test_dict, test_transforms def visualise_ground_truths(images, ground_truths, criterion): @@ -84,6 +84,7 @@ def visualise_predictions(images, predictions, criterion): return fig, axes def test(model, test_loader, device): + model.to(device) model.eval() # Set the model to evaluation mode criterion = DiceLoss(batch = True) @@ -168,7 +169,6 @@ def plot_dice(criterion, segment_coefs): if __name__ == "__main__": # connect to gpu - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") test_set = Dataset(test_dict, test_transforms) test_loader = DataLoader(dataset = test_set, batch_size = 1) @@ -179,7 +179,7 @@ def plot_dice(criterion, segment_coefs): # perform predictions dice_coefs, s0, s1, s2, s3, s4, s5 = test(model = trained_model, test_loader = test_loader, - device = device) + device = DEVICE) end = time() diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index fea0a0e48..d63f8b7f8 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -7,15 +7,17 @@ import numpy as np from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss from monai.data import DataLoader, Dataset +from torch.cuda.amp import autocast, GradScaler NUM_EPOCHS = 300 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 -CRITERION = DiceLoss(include_background=False, batch=True) -# CRITERION = DiceCELoss(include_background=False, batch = True, lambda_ce = 0.2) # Based on Thyroid Tumor Segmentation Report -# CRITERION = DiceFocalLoss(include_background=False, batch = True) # Default gamma = 2 +DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") +CRITERION = DiceLoss(include_background=False, batch=True).to(DEVICE) +# CRITERION = DiceCELoss(include_background=False, batch = True, lambda_ce = 0.2).to(DEVICE) # Based on Thyroid Tumor Segmentation Report +# CRITERION = DiceFocalLoss(include_background=False, batch = True).to(DEVICE) # Default gamma = 2 def compute_dice_segments(predictions, ground_truths): @@ -23,7 +25,7 @@ def compute_dice_segments(predictions, ground_truths): num_masks = predictions.size(1) - segment_coefs = torch.zeros(num_masks, device=ground_truths.device) + segment_coefs = torch.zeros(num_masks, DEVICE) segment_losses = criterion(predictions, ground_truths) @@ -50,27 +52,31 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): seg_4_dice_coefs = np.zeros(NUM_EPOCHS) seg_5_dice_coefs = np.zeros(NUM_EPOCHS) + scaler = GradScaler() + + accumuldation_steps = 2 + for epoch in range(num_epochs): running_dice = 0.0 total_segment_coefs = torch.zeros(6, device=device) - for batch_data in train_loader: + for i, batch_data in enumerate(train_loader): inputs, labels = ( batch_data["image"].to(device), batch_data["label"].to(device), ) - - optimiser.zero_grad() - outputs = model(inputs) - - loss = criterion(outputs, labels) + + with autocast(): + optimiser.zero_grad() + outputs = model(inputs) + loss = criterion(outputs, labels) segment_coefs = compute_dice_segments(outputs, labels) - total_segment_coefs += segment_coefs + scaler.scale(loss).backward() - loss.backward() - - optimiser.step() + if (i + 1) % accumuldation_steps == 0: # Gradient Accumulation + scaler.step(optimiser) + scaler.update() running_dice += 1 - loss.item() @@ -92,9 +98,6 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): return (model, training_dice_coefs, seg_0_dice_coefs, seg_1_dice_coefs, seg_2_dice_coefs, seg_3_dice_coefs, seg_4_dice_coefs, seg_5_dice_coefs) -# connect to gpu -device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - if not torch.cuda.is_available(): print("Warning CUDA not Found. Using CPU") @@ -110,7 +113,7 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): # train improved unet trained_model, training_dice_coefs, seg0, seg1, seg2, seg3, seg4, seg5 = train(model, train_loader, criterion = CRITERION, - device=device, num_epochs=NUM_EPOCHS) + device=DEVICE, num_epochs=NUM_EPOCHS) end = time() From 36bf504563d8234191b04498ab902cad0dc95a54 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:27:11 +1000 Subject: [PATCH 085/102] correct assignment to device --- recognition/47049358/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index d63f8b7f8..03d1eb575 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -25,7 +25,7 @@ def compute_dice_segments(predictions, ground_truths): num_masks = predictions.size(1) - segment_coefs = torch.zeros(num_masks, DEVICE) + segment_coefs = torch.zeros(num_masks).to(DEVICE) segment_losses = criterion(predictions, ground_truths) From 518d06aa8117ed68438d0f95796cf01ca9282451 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:31:38 +1000 Subject: [PATCH 086/102] table of segments inserted --- recognition/47049358/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index 26b0976bf..a3b47c6e9 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -9,14 +9,14 @@ UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network.\ - || Role | + |Labels|Segment| | --------------- | ---------------------------------------- | -| William Mercado | Team Leader | -| Brian Zhang | Machine Learning Developer | -| Hongyingzi Lu | Design Coordinator / Front-End Developer | -| Shan Liu | Design Coordinator / Front-End Developer | -| Yang Xiao | Back-End Developer | -| Ryuto Hisamoto | Back-End Developer | +|0| Background | +|1| Body | +|2| Bones | +|3| Bladder | +|4| Rectum | +|5| Prostate | ### Training From 9561d0219a0fd3ff09394eae8525818146f17e30 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:42:19 +1000 Subject: [PATCH 087/102] using device for loss cal as well --- recognition/47049358/modules.py | 4 ++-- recognition/47049358/predict.py | 2 +- recognition/47049358/train.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 94cf05a49..947033a73 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -21,8 +21,7 @@ def forward(self, x): return x class ContextModule(nn.Module): - def __init__(self, in_channels, out_channels, - kernel_size = 3, stride = 1, padding = 1): + def __init__(self, in_channels, out_channels): super(ContextModule, self).__init__() self.block1 = StandardModule(in_channels = in_channels, out_channels = out_channels, inplace = True) self.dropout = nn.Dropout(DROP_PROB) # Drop description uncertain, replace it with Dropout3d when poor performance @@ -189,4 +188,5 @@ def forward(self, x): final_sum = upscale_out_2 + segment_out_3 output = torch.softmax(final_sum, dim = 1) + return output \ No newline at end of file diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 8d7625c77..76a2e0876 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -117,7 +117,7 @@ def test(model, test_loader, device): ) outputs = model(inputs) outputs = output_transform(torch.argmax(outputs, dim=1))[np.newaxis, : , : , : , :] - segment_coefs = compute_dice_segments(outputs, labels) + segment_coefs = compute_dice_segments(outputs, labels, device) dice_loss = criterion(outputs, labels).item() test_dice = 1 - dice_loss diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 03d1eb575..c0b0189a4 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -19,13 +19,13 @@ # CRITERION = DiceCELoss(include_background=False, batch = True, lambda_ce = 0.2).to(DEVICE) # Based on Thyroid Tumor Segmentation Report # CRITERION = DiceFocalLoss(include_background=False, batch = True).to(DEVICE) # Default gamma = 2 -def compute_dice_segments(predictions, ground_truths): +def compute_dice_segments(predictions, ground_truths, device): - criterion = DiceLoss(reduction='none', batch=True) + criterion = DiceLoss(reduction='none', batch=True).to(device) num_masks = predictions.size(1) - segment_coefs = torch.zeros(num_masks).to(DEVICE) + segment_coefs = torch.zeros(num_masks).to(device) segment_losses = criterion(predictions, ground_truths) @@ -70,7 +70,7 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): outputs = model(inputs) loss = criterion(outputs, labels) - segment_coefs = compute_dice_segments(outputs, labels) + segment_coefs = compute_dice_segments(outputs, labels, device) total_segment_coefs += segment_coefs scaler.scale(loss).backward() From b2d08e34c60becd30a0b259e156195a4cc0bb579 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 21:21:14 +1000 Subject: [PATCH 088/102] more memory savings --- recognition/47049358/dataset.py | 7 +++++-- recognition/47049358/train.py | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 5a1e0740a..459d995bf 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -12,8 +12,11 @@ # Constants # ========================== -IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') -LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') +IMAGE_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_MRs' +LABEL_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_labels_only' + +# IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') +# LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') rawImageNames = sorted(os.listdir(IMAGE_FILE_NAME)) rawLabelNames = sorted(os.listdir(LABEL_FILE_NAME)) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index c0b0189a4..770b4283d 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -60,6 +60,7 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): running_dice = 0.0 total_segment_coefs = torch.zeros(6, device=device) for i, batch_data in enumerate(train_loader): + inputs, labels = ( batch_data["image"].to(device), batch_data["label"].to(device), @@ -70,6 +71,8 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): outputs = model(inputs) loss = criterion(outputs, labels) + torch.cuda.empty_cache() + segment_coefs = compute_dice_segments(outputs, labels, device) total_segment_coefs += segment_coefs scaler.scale(loss).backward() From e6bc66fb0d3f32cfa98abf7dd13f40aea1cc0aee Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:34:01 +1000 Subject: [PATCH 089/102] removing deprecated + redundant import --- recognition/47049358/predict.py | 1 - recognition/47049358/train.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 76a2e0876..7c3586190 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -6,7 +6,6 @@ import torch import numpy as np import matplotlib.pyplot as plt -from torch.utils.data import DataLoader from time import time from monai.losses import DiceLoss from monai.data import DataLoader, Dataset diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 770b4283d..ab5a1280a 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -7,7 +7,7 @@ import numpy as np from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss from monai.data import DataLoader, Dataset -from torch.cuda.amp import autocast, GradScaler +from torch.amp import autocast, GradScaler NUM_EPOCHS = 300 BATCH_SIZE = 2 @@ -66,7 +66,7 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): batch_data["label"].to(device), ) - with autocast(): + with autocast(device_type=DEVICE.type): optimiser.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) From 500937834db33f9c0d7fad8ef39ff754f89f06db Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Thu, 24 Oct 2024 05:17:53 +1000 Subject: [PATCH 090/102] docstrings and updated readme --- recognition/47049358/README.md | 66 +++++++++++++---- recognition/47049358/dataset.py | 51 +++++++++++-- recognition/47049358/modules.py | 109 +++++++++++++++++++++++++--- recognition/47049358/predict.py | 79 +++++++++++++++----- recognition/47049358/references.bib | 26 +++++++ recognition/47049358/train.py | 66 +++++++++++++++-- 6 files changed, 341 insertions(+), 56 deletions(-) create mode 100644 recognition/47049358/references.bib diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index a3b47c6e9..257bde1e4 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -1,3 +1,10 @@ +--- +title: COMP3710 Report +author: "Ryuto Hisamoto" +date: "2024-10-24" +bibliography: references.bib +--- + # Improved 3D Improved UNet ## The Model @@ -5,8 +12,12 @@

Improved 3D UNet Architecture

+ +- Negative Slop: $10 ^ {-2}$ +- Dropout Probability: 0.3 + - UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network.\ + UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network. On top of it, the improvement on UNet proposed by authors of "Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge" [@IsenseeFabian2018BTSa]involves the integration of segmentation layers at different levels of the architecture. |Labels|Segment| @@ -18,13 +29,49 @@ |4| Rectum | |5| Prostate | - ### Training +### Loading Data -The model takes in an raw image as its input, and its goal is to learn the best feature map which ends up being a smulti-channel segmentation of the original image. +The authors of "Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge" seem to have used the following augmentation methods: - ### Testing +- Random rotation +- Random scaling +- Elastic transformation +- Gamma correction +- Mirroring (assumably horizontal flip given their problem space) + +However, some augmentations methods are altered to limit the complexity of solution. For instance, use of elastic transformation was avoided as it could alter the image significantly, causing it to deviate from the actual images the model may find. Moreover, the tuning of such complex method could decrease the maintainability of solutin. Therefore, the project preserved basic augmentation techniques to process the training data. More precisely, techniques used are limited to: + +- Random Rotation ($[-0.5, 0.5]$ for all x, y, and z coordinates) +- Random Vertical Flip +- Gaussian Noise ($\mu = 0, \sigma = 0.5$) + +In addition, all images are normalised as they are loaded to eliminate difference in intensity scales if there are any. Moreover, all voxel values are loaded as `torch.float32` but `torch.uint8` is used for labels to save memory consumption. + +### Training + +- Batch Size: 2 +- Number of Epochs: 300 +- Learning Rate: $5e ^ {-4}$ +- Initial Learning Rate (for lr_scheduler): 0.985 +- Weight Decay: $1e ^ {-5}$ +The model takes in an raw image as its input, and its goal is to learn the best feature map which ends up being a multi-channel segmentation of the original image. +### Loss Function + +The model utilises dice loss as its loss function. Moreover, it is capable of using deviations of dice loss such as a sum of dice loss and cross-entropy loss, or focal loss. A vanilla dice loss has formula: $$D(y_{true}, y_{pred}) = 2 \times \frac{\Sigma(y_{true} \cdot y_{pred})}{\Sigma y_{true} + \Sigma y_{pred}}$$ + +in which $y_{true}$ is the ground truth probability and $y_{pred}$ is the predicted probability. The loss function mitigates the problem with other loss functions such as a cross-entropy loss which tend to be biased toward a dominant class. The design of dice loss provides more accurate representation of the model's performance in segmentation. In addition `monai` provides an option to exclude background from the calculation of loss, and the model makes use of this option when calculating the loss (background is included when testing). + +### Optimiser + +**Adam (Adaptive Moment Estimation)** is an optimisation algorithm that boosts the speed of convergence of gradient descent. The optimiser utilises an exponential average of gradients, which allows its efficient and fast pace of convergence. Moreover, the optimiser applies a $L_2$ regularisation to penalise for the complexity of model. +In addition, the model utilises a learning rate scheduler based on the number of epochs, which dynamically changes the learning rate over epochs. This allows the model to start from a large learning rate which evntually settles to a small learning rate for easier convergence. +It is to be noted that mixed precision and gradient accumulation are used to reduce the memory consumption during the training. + + ### Testing + +The model is tested by measuring its dice scores on the segmentations it produces for unseen images. Although the model outputs softmax values for its predicted segmentations, they are one-hot encoded during the test to maximise the contribution of correct predictions. Moreover, unlike tranin ## The Problem @@ -34,14 +81,5 @@ The model takes in an raw image as its input, and its goal is to learn the best (Dice Coefficient)[https://en.wikipedia.org/wiki/Dice-Sørensen_coefficient] -Updates: - -**Data Augmentation** - -- Random Rotation -- Random Scaling -- Normalisation -- Gamma Correction -- Vertical Flip +(Loss Function)[https://www.sciencedirect.com/science/article/pii/S1746809422007030] -(Loss Function)[https://www.sciencedirect.com/science/article/pii/S1746809422007030] \ No newline at end of file diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 459d995bf..7bdf3cd37 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -1,21 +1,39 @@ +#!/usr/bin/env python +""" Initialises monai transformations and loads paths to image and label nifti files. + +dataset.py loads the files to perform image segmentation. It loads the paths to images and corresponding +labels, but none of them are processed in the file. Moreover, transformation on training set and test set +are defined in the file, but they are to be exported with corresponding dictionary files and used with +monai.data.Dataset and Dataloader. + +""" + # ========================== # Imports # ========================== import os from sklearn.model_selection import train_test_split -from monai.transforms import (LoadImaged, EnsureChannelFirstd, RandScaleIntensityd, +from monai.transforms import (LoadImaged, EnsureChannelFirstd, NormalizeIntensityd, SpatialCropd, RandFlipd, RandRotated, AsDiscreted, RandGaussianNoised, Compose, CastToTyped) import torch +__author__ = "Ryuto Hisamoto" + +__license__ = "Apache" +__version__ = "1.0.0" +__maintainer__ = "Ryuto Hisamoto" +__email__ = "s4704935@student.uq.edu.au" +__status__ = "Committed" + # ========================== # Constants # ========================== -IMAGE_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_MRs' -LABEL_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_labels_only' +IMAGE_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_MRs' # on rangpur +LABEL_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_labels_only' # on rangpur -# IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') +# IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') # assuming folders are in the cwd # LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') rawImageNames = sorted(os.listdir(IMAGE_FILE_NAME)) @@ -24,29 +42,46 @@ # Split the set into train, validation, and test set (80 : 20 for train:test) train_images, test_images, train_labels, test_labels = train_test_split(rawImageNames, rawLabelNames, train_size=0.8) # Split the data in training and test set +""" +A transformation is performed in for consistent dimensions in each images and labels, and random augmentation +of files to prevent the model's overfitting to the training set. They are performed in the order of: loading, cropping (to remove extra dimensions), +normalisation of voxel values, random vertical flip (spatial_axis = 2), random rotation (of small degrees), and +addition of random noise. For labels, an extra step to change encodings is applied. +""" + train_transforms = Compose( [ LoadImaged(keys=["image", "label"]), EnsureChannelFirstd(keys=["image", "label"]), SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), # Crop to depth 128 - RandFlipd(keys=["image", "label"], spatial_axis=0, prob=0.5), + NormalizeIntensityd(keys=["image"]), + RandFlipd(keys=["image", "label"], spatial_axis=2, prob=0.5), RandRotated(keys=["image", "label"], range_x=0.5, range_y=0.5, range_z=0.5, mode='nearest', prob=0.5), - RandScaleIntensityd(keys=["image"], factors=0.5, prob=0.5), RandGaussianNoised(keys=["image"], prob=0.5, mean=0, std=0.5), AsDiscreted(keys=["label"], to_onehot=6), CastToTyped(keys=["label"], dtype=torch.uint8), ] ) +""" +A transformation on test set involved the loading on images and labels, cropping for consistent dimensions, +normalisation of voxel values and encoding of labels. +""" + test_transforms = Compose( [ LoadImaged(keys=["image", "label"]), EnsureChannelFirstd(keys=["image", "label"]), SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), + NormalizeIntensityd(keys=["image"]), AsDiscreted(keys=["label"], to_onehot=6), CastToTyped(keys=["label"], dtype=torch.uint8), ] ) -train_dict = [{"image": os.path.join(IMAGE_FILE_NAME, image), "label": os.path.join(LABEL_FILE_NAME, label)} for image, label in zip(train_images, train_labels)] -test_dict = [{"image": os.path.join(IMAGE_FILE_NAME, image), "label": os.path.join(LABEL_FILE_NAME, label)} for image, label in zip(test_images, test_labels)] \ No newline at end of file +# Loads paths to images and labels, but do not process them yet + +train_dict = [{"image": os.path.join(IMAGE_FILE_NAME, image), "label": os.path.join(LABEL_FILE_NAME, label)} + for image, label in zip(train_images, train_labels)] +test_dict = [{"image": os.path.join(IMAGE_FILE_NAME, image), "label": os.path.join(LABEL_FILE_NAME, label)} + for image, label in zip(test_images, test_labels)] \ No newline at end of file diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 947033a73..29de34348 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -1,10 +1,33 @@ +#!/usr/bin/env python +""" +The model and its building blocks of 3d Improved UNet +""" import torch import torch.nn as nn +__author__ = "Ryuto Hisamoto" + +__license__ = "Apache" +__version__ = "1.0.0" +__maintainer__ = "Ryuto Hisamoto" +__email__ = "s4704935@student.uq.edu.au" +__status__ = "Committed" + NEGATIVE_SLOPE = 10 ** -2 DROP_PROB = 0.3 NUM_SEGMENTS = 6 +""" The most standard module which contains the 3 x 3 x 3 convolutional operation as with the normalisation + of the values and activations with Leaky ReLU. Instance normalisation is affine-enabled. + + Parameters: + - in_channels (int): Number of input channels. + - out_channels (int): Number of output channels. + - kernel_size (int, optional): Size of the convolutional kernel (default is 3). + - stride (int, optional): Stride of the convolution operation (default is 1). + - padding (int, optional): Padding size for the convolution (default is 1). + - inplace (bool, optional): Whether to perform operations in place. +""" class StandardModule(nn.Module): def __init__(self, in_channels, out_channels, kernel_size = 3, stride = 1, padding = 1, inplace = False): @@ -19,7 +42,13 @@ def forward(self, x): x = self.instance_norm(x) x = self.l_relu(x) return x - + +""" Context module which functions as a pre-activation residual block with 2 StandardModules + + Parameters: + - in_channels (int): Number of input channels. + - out_channels (int): Number of output channels. +""" class ContextModule(nn.Module): def __init__(self, in_channels, out_channels): super(ContextModule, self).__init__() @@ -33,6 +62,17 @@ def forward(self, x): x = self.block2(x) return x +""" A module that applies 3 x 3 x 3 convolution and following operations excpet with the stride of 2. All encoding layers +utilise this after the first one. + + Parameters: + - in_channels (int): Number of input channels. + - out_channels (int): Number of output channels. + - kernel_size (int, optional): Size of the convolutional kernel (default is 3). + - stride (int, optional): Stride of the convolution operation (default is 2). + - padding (int, optional): Padding size for the convolution (default is 1). + - inplace (bool, optional): Whether to perform operations in place. +""" class Stride2Module(nn.Module): def __init__(self, in_channels, out_channels, kernel_size=3, stride=2, padding=1, inplace = False): @@ -47,7 +87,19 @@ def forward(self, x): x = self.instance_norm(x) x = self.l_relu(x) return x - + +""" A module that upsamples (decodes) from the bottom-most layer using a convolutional transpose. +The module is used throughout the localisation pathway to take featres from lower levels of the network that encode +contextual information at low spatial resolution and transfer that information to a higher spatial resolution. + + Parameters: + - in_channels (int): Number of input channels. + - out_channels (int): Number of output channels. + - kernel_size (int, optional): Size of the convolutional kernel (default is 4). + - stride (int, optional): Stride of the convolution operation (default is 2). + - padding (int, optional): Padding size for the convolution (default is 1). + - inplace (bool, optional): Whether to perform operations in place. +""" class UpsamplingModule(nn.Module): def __init__(self, in_channels, out_channels): super(UpsamplingModule, self).__init__() @@ -60,7 +112,13 @@ def forward(self, x): x = self.block(x) return x +""" A mlocalisation modules that consists of a 3 x 3 x 3 convolution followed by a 1 x 1 x 1 convolution that halves the +number of feature maps. It acccepts the concatenated features from the skip connection and recombines them together. + Parameters: + - in_channels (int): Number of input channels. + - out_channels (int): Number of output channels. +""" class LocalisationModule(nn.Module): def __init__(self, in_channels, out_channels): super(LocalisationModule, self).__init__() @@ -73,7 +131,14 @@ def forward(self, x): x = self.block1(x) x = self.block2(x) return x - + +""" A segmentation layer that is integrated at different levels of the network, which are combined via elementwise summation +to form the final network output. + + Parameters: + - in_channels (int): Number of input channels. + - out_channels (int): Number of output channels. +""" class SegmentationLayer(nn.Module): def __init__(self, in_channels, out_channels): super(SegmentationLayer, self).__init__() @@ -83,6 +148,14 @@ def __init__(self, in_channels, out_channels): def forward(self, x): return self.seg(x) +""" A module that upscales the input for 2 times. The module is to be used to match the scale of feature maps +of segmentation layers from different levels of the network. + + Parameters: + - in_channels (int): Number of input channels. + - out_channels (int): Number of output channels. +""" + class UpScaleModule(nn.Module): def __init__(self, in_channels, out_channels): super(UpScaleModule, self).__init__() @@ -92,6 +165,9 @@ def __init__(self, in_channels, out_channels): def forward(self, x): return self.upscale(x) +""" 3D imporoved UNet that produces segmentations by first aggregating high level information by +context pathway and localising precisely in the localisation pathway. +""" class ImprovedUnet(nn.Module): def __init__(self): super(ImprovedUnet, self).__init__() @@ -138,51 +214,64 @@ def __init__(self): def forward(self, x): + + # Level 1 context pathway conv_out_1 = self.block1(x) context_out_1 = self.context1(conv_out_1) element_sum_1 = conv_out_1 + context_out_1 - # second term + + # Level 2 context pathway conv_out_2 = self.block2(element_sum_1) context_out_2 = self.context2(conv_out_2) element_sum_2 = conv_out_2 + context_out_2 - # third downsample + # Level 3 context pathway conv_out_3 = self.block3(element_sum_2) context_out_3 = self.context3(conv_out_3) element_sum_3 = conv_out_3 + context_out_3 + # Level 4 context pathway conv_out_4 = self.block4(element_sum_3) context_out_4 = self.context4(conv_out_4) element_sum_4 = conv_out_4 + context_out_4 + # Level 5 context pathway conv_out_5 = self.block5(element_sum_4) context_out_5 = self.context5(conv_out_5) element_sum_5 = conv_out_5 + context_out_5 - # First upsampling module. + # Level 0 localisation pathway upsample_out_1 = self.upsample1(element_sum_5) - concat_1 = torch.cat((element_sum_4, upsample_out_1), dim = 1) + # Level 1 localisation pathway + concat_1 = torch.cat((element_sum_4, upsample_out_1), dim = 1) localisation_out_1 = self.localise1(concat_1) upsample_out_2 = self.upsample2(localisation_out_1) - concat_2 = torch.cat((element_sum_3, upsample_out_2), dim = 1) + # Level 2 localisation pathway + concat_2 = torch.cat((element_sum_3, upsample_out_2), dim = 1) localisation_out_2 = self.localise2(concat_2) upsample_out_3 = self.upsample3(localisation_out_2) - concat_3 = torch.cat((element_sum_2, upsample_out_3), dim = 1) + # Level 3 localisation pathway + concat_3 = torch.cat((element_sum_2, upsample_out_3), dim = 1) localisation_out_3 = self.localise3(concat_3) upsample_out_4 = self.upsample4(localisation_out_3) + + # Level 4 localisation pathway concat_4 = torch.cat((element_sum_1, upsample_out_4), dim = 1) + convoutput_out = self.conv_output(concat_4) + # 1st Segmentation Layer segment_out_1 = self.segmentation1(localisation_out_2) upscale_out_1 = self.upscale_1(segment_out_1) + # 2nd Segmentation Layer segment_out_2 = self.segmentation2(localisation_out_3) seg_sum_1 = upscale_out_1 + segment_out_2 + # 3rd Segmentation Layer upscale_out_2 = self.upscale_2(seg_sum_1) - convoutput_out = self.conv_output(concat_4) segment_out_3 = self.segmentation3(convoutput_out) final_sum = upscale_out_2 + segment_out_3 diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 7c3586190..cecd14cf4 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -1,9 +1,10 @@ """ -showing example usage of your trained model. Print out any results and / or provide visualisations -where applicable +The file contains a method to visualise and/or measure the performance of the trained model +on unseen data. """ # libraries import torch +import torch.nn as nn import numpy as np import matplotlib.pyplot as plt from time import time @@ -15,7 +16,25 @@ from train import trained_model, CRITERION, compute_dice_segments, DEVICE from dataset import test_dict, test_transforms -def visualise_ground_truths(images, ground_truths, criterion): +__author__ = "Ryuto Hisamoto" + +__license__ = "Apache" +__version__ = "1.0.0" +__maintainer__ = "Ryuto Hisamoto" +__email__ = "s4704935@student.uq.edu.au" +__status__ = "Committed" + +def visualise_ground_truths(images: list, ground_truths: list, criterion): + """ Visualises the ground truths and their images by overlaying them on the same 3 x 3 plot. + + Args: + images (list): Images to overlay labels on. + ground_truths (list): Labels to overlay on top of images. + criterion (callable): Loss function used during the training to name the plot. + + Returns: + None: The function only plots, so it does not return any value. + """ # Create a 3x3 grid of subplots fig, axes = plt.subplots(3, 3, figsize=(15, 15)) @@ -49,10 +68,18 @@ def visualise_ground_truths(images, ground_truths, criterion): plt.tight_layout() plt.savefig(f'ground_truths_{criterion}.png') plt.close() - - return fig, axes -def visualise_predictions(images, predictions, criterion): +def visualise_predictions(images: list, predictions: list, criterion): + """Visualises the predictions and their images by overlaying them on the same 3 x 3 plot. + + Args: + images (list): A list of images to lay predicted labels on + predictions (list): A list of predicted labels proeuced by the model + criterion (callable): Loss function used during the training to name the plot. + + Returns: + None: The function only plots, so it does not return any value. + """ # Create a 3x3 grid of subplots fig, axes = plt.subplots(3, 3, figsize=(15, 15)) @@ -79,10 +106,27 @@ def visualise_predictions(images, predictions, criterion): plt.tight_layout() plt.savefig(f'predictions_{criterion}.png') plt.close() - - return fig, axes -def test(model, test_loader, device): +def test(model: nn.Module, test_loader: DataLoader, device: torch.device | str): + """The function which tests the model on unseen data stored in a DataLoader + + Args: + model (nn.Module): A trained model that is to be tested. + test_loader (DataLoader): DataLoader instance which contains image data and their labels for the model + to compare its performance against. + device (torch.device | str): A device the training is based on. + + Returns: + tuple: A tuple containing: + - np.array: An array of overall dice score for each test image and labels + - np.array: An array of segment 0 dice score for each test image and labels + - np.array: An array of segment 1 dice score for each test image and labels + - np.array: An array of segment 2 dice score for each test image and labels + - np.array: An array of segment 3 dice score for each test image and labels + - np.array: An array of segment 4 dice score for each test image and labels + - np.array: An array of segment 5 dice score for each test image and labels + """ + model.to(device) model.eval() # Set the model to evaluation mode @@ -145,12 +189,15 @@ def test(model, test_loader, device): return test_dice_coefs, seg_0_dice_coef, seg_1_dice_coef, seg_2_dice_coef, seg_3_dice_coef, seg_4_dice_coef, seg_5_dice_coef -""" - Plots dice coefficients of the whole test dataset. - Takes an array of dice scores as input. -""" +def plot_dice(criterion, segment_coefs: np.array): + """ A method that plots a bar chart to visualise the performance of model on unseen data + for each label. It is meant to demonstrated how accurately the model produces segmentations + for each lebel. -def plot_dice(criterion, segment_coefs): + Args: + criterion (callable): Loss function used during the training to name the plot. + segment_coefs (np.array): an array containing dice scores for each segment at corresponding indices. + """ x_values = np.arange(len(segment_coefs)) # Generate x-values as indices @@ -211,6 +258,4 @@ def plot_dice(criterion, segment_coefs): average_s4, average_s5]) # plot dice scores across the dataset. - plot_dice(CRITERION, segment_coefs) - - + plot_dice(CRITERION, segment_coefs) \ No newline at end of file diff --git a/recognition/47049358/references.bib b/recognition/47049358/references.bib new file mode 100644 index 000000000..7a55a38c0 --- /dev/null +++ b/recognition/47049358/references.bib @@ -0,0 +1,26 @@ +@inproceedings{IsenseeFabian2018BTSa, +issn = {0302-9743}, +abstract = {Quantitative analysis of brain tumors is critical for clinical decision making. While manual segmentation is tedious, time consuming and subjective, this task is at the same time very challenging to solve for automatic segmentation methods. In this paper we present our most recent effort on developing a robust segmentation algorithm in the form of a convolutional neural network. Our network architecture was inspired by the popular U-Net and has been carefully modified to maximize brain tumor segmentation performance. We use a dice loss function to cope with class imbalances and use extensive data augmentation to successfully prevent overfitting. Our method beats the current state of the art on BraTS 2015, is one of the leading methods on the BraTS 2017 validation set (dice scores of 0.896, 0.797 and 0.732 for whole tumor, tumor core and enhancing tumor, respectively) and achieves very good Dice scores on the test set (0.858 for whole, 0.775 for core and 0.647 for enhancing tumor). We furthermore take part in the survival prediction subchallenge by training an ensemble of a random forest regressor and multilayer perceptrons on shape features describing the tumor subregions. Our approach achieves 52.6% accuracy, a Spearman correlation coefficient of 0.496 and a mean square error of 209607 on the test set.}, +pages = {287--297}, +volume = {10670}, +publisher = {Springer International Publishing}, +booktitle = {BRAINLESION: GLIOMA, MULTIPLE SCLEROSIS, STROKE AND TRAUMATIC BRAIN INJURIES, BRAINLES 2017}, +isbn = {3319752375}, +year = {2018}, +title = {Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge}, +copyright = {Springer International Publishing AG, part of Springer Nature 2018}, +language = {eng}, +address = {Cham}, +author = {Isensee, Fabian and Kickingereder, Philipp and Wick, Wolfgang and Bendszus, Martin and Maier-Hein, Klaus H.}, +keywords = {Brain tumor ; Clinical Neurology ; CNN ; Computer Science ; Computer Science Theory & Methods ; Deep learning ; Glioblastoma ; Life Sciences & Biomedicine ; Neuroimaging ; Neurosciences ; Neurosciences & Neurology ; Science & Technology ; Technology}, +} + +@online{author2023, + author = {Armaanjeet Singh Sandhu}, + title = {Calculating the Sørensen-Dice Coefficient: A Simplified Guide}, + year = {2023}, + url = {https://medium.com/the-research-nest/calculating-the-sørensen-dice-coefficient-a-simplified-guide-3b59a1829a82}, + note = {Accessed: 2024-10-24} +} + + diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index ab5a1280a..c15a11ab0 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -1,14 +1,32 @@ +#!/usr/bin/env python +""" A collection of methods and tools to train the model. + +train.py has methods and tools which are related to the training of model, +some sections are commented out, and are to be enabled to change the training method. +For example, there are a few CRITERIONs, and one of preference is to be enabled to utilise +the loss function of preference. +""" + from dataset import train_dict, train_transforms from modules import ImprovedUnet import matplotlib.pyplot as plt import torch from torch.utils.data import DataLoader +import torch.nn as nn from time import time import numpy as np from monai.losses import DiceLoss, DiceCELoss, DiceFocalLoss from monai.data import DataLoader, Dataset from torch.amp import autocast, GradScaler +__author__ = "Ryuto Hisamoto" + +__license__ = "Apache" +__version__ = "1.0.0" +__maintainer__ = "Ryuto Hisamoto" +__email__ = "s4704935@student.uq.edu.au" +__status__ = "Committed" + NUM_EPOCHS = 300 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 @@ -19,7 +37,21 @@ # CRITERION = DiceCELoss(include_background=False, batch = True, lambda_ce = 0.2).to(DEVICE) # Based on Thyroid Tumor Segmentation Report # CRITERION = DiceFocalLoss(include_background=False, batch = True).to(DEVICE) # Default gamma = 2 -def compute_dice_segments(predictions, ground_truths, device): +def compute_dice_segments(predictions: torch.Tensor, ground_truths: torch.Tensor, device: torch.device | str): + """The method calculates the dice scores for each segment. The score computed + inside of the method is independent from the loss used to train the model, hence + its scores are purely dice coefficients for different segments. Both predictions and + ground_truths are required to have the same shape. + + Args: + predictions (torch.Tensor): Softmax/one-hot encoded predictions from the model. + ground_truths (torch.Tensor): One-hot encoded labels for an image. + device (torch.device | str): A device the process is based on, 'cuda' or 'cpu' + + Returns: + torch.Tensor: _A 0 dimensional tensor in which dice coefficient of a corresponding + label is stored in its index. + """ criterion = DiceLoss(reduction='none', batch=True).to(device) @@ -35,9 +67,30 @@ def compute_dice_segments(predictions, ground_truths, device): return segment_coefs -def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): - - # set up criterion, optimiser, and scheduler for learning rate. +def train(model: nn.Module, train_loader: DataLoader, criterion, num_epochs: int, device: torch.device | str): + """The training method that trains the model with given resources and parameters. + + Args: + model (nn.Module): A model to train. + train_loader (DataLoader): DataLoader instance which contains image data and their labels for the model + to compare its performance against. + criterion (callable): A loss function the model uses to optimise its performance + num_epochs (int): The number of epochs to train the model on. + device (torch.device | str): A device the training is based on. It is highly recommended to use 'cuda' for training. + + Returns: + tuple: A tuple containing: + - nn.Module: A trained model + - np.array: An array of overall dice score for each epoch + - np.array: An array of segment 0 dice score for each epoch + - np.array: An array of segment 1 dice score for each epoch + - np.array: An array of segment 2 dice score for each epoch + - np.array: An array of segment 3 dice score for each epoch + - np.array: An array of segment 4 dice score for each epoch + - np.array: An array of segment 5 dice score for each epoch + """ + + # Adam is used as an optimiser optimiser = torch.optim.Adam(model.parameters(), lr = LEARNING_RATE, weight_decay = WEIGHT_DECAY) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimiser, gamma = LR_INITIAL) @@ -71,13 +124,11 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): outputs = model(inputs) loss = criterion(outputs, labels) - torch.cuda.empty_cache() - segment_coefs = compute_dice_segments(outputs, labels, device) total_segment_coefs += segment_coefs scaler.scale(loss).backward() - if (i + 1) % accumuldation_steps == 0: # Gradient Accumulation + if (i + 1) % accumuldation_steps == 0 or i + 1 == len(train_loader): # Gradient Accumulation scaler.step(optimiser) scaler.update() @@ -125,6 +176,7 @@ def train(model, train_loader, criterion, num_epochs=NUM_EPOCHS, device="cuda"): epochs = range(1, NUM_EPOCHS + 1) +# Plots the model's performance during the training. plt.plot(epochs, training_dice_coefs, label='Training Dice Coefficient') plt.plot(epochs, seg0, label='Segment 0 Dice Coefficient') plt.plot(epochs, seg1, label='Segment 1 Dice Coefficient') From de3756bc68bce22796558621e5485bf9be7cd3f8 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:11:15 +1000 Subject: [PATCH 091/102] replaced all deprecated --- recognition/47049358/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index c15a11ab0..8b09e8c53 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -105,7 +105,7 @@ def train(model: nn.Module, train_loader: DataLoader, criterion, num_epochs: int seg_4_dice_coefs = np.zeros(NUM_EPOCHS) seg_5_dice_coefs = np.zeros(NUM_EPOCHS) - scaler = GradScaler() + scaler = GradScaler(device=DEVICE.type) accumuldation_steps = 2 From 8151765e595f2e653fa2db498f6e0b9d7ca66ed5 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Thu, 24 Oct 2024 19:36:54 +1000 Subject: [PATCH 092/102] yml added --- recognition/47049358/environment.yml | 70 ++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 recognition/47049358/environment.yml diff --git a/recognition/47049358/environment.yml b/recognition/47049358/environment.yml new file mode 100644 index 000000000..964f5a00f --- /dev/null +++ b/recognition/47049358/environment.yml @@ -0,0 +1,70 @@ +name: comp3710 +channels: + - defaults +dependencies: + - _libgcc_mutex=0.1=main + - _openmp_mutex=5.1=1_gnu + - ca-certificates=2024.9.24=h06a4308_0 + - ld_impl_linux-64=2.40=h12ee557_0 + - libffi=3.4.4=h6a678d5_1 + - libgcc-ng=11.2.0=h1234567_1 + - libgomp=11.2.0=h1234567_1 + - libstdcxx-ng=11.2.0=h1234567_1 + - ncurses=6.4=h6a678d5_0 + - openssl=3.0.15=h5eee18b_0 + - pip=24.2=py39h06a4308_0 + - python=3.9.20=he870216_1 + - readline=8.2=h5eee18b_0 + - setuptools=75.1.0=py39h06a4308_0 + - sqlite=3.45.3=h5eee18b_0 + - tk=8.6.14=h39e8969_0 + - tzdata=2024b=h04d1e81_0 + - wheel=0.44.0=py39h06a4308_0 + - xz=5.4.6=h5eee18b_1 + - zlib=1.2.13=h5eee18b_1 + - pip: + - contourpy==1.3.0 + - cycler==0.12.1 + - filelock==3.13.1 + - fonttools==4.54.1 + - fsspec==2024.2.0 + - importlib-resources==6.4.5 + - jinja2==3.1.3 + - joblib==1.4.2 + - kiwisolver==1.4.7 + - markupsafe==2.1.5 + - matplotlib==3.9.2 + - monai==1.4.0 + - mpmath==1.3.0 + - networkx==3.2.1 + - nibabel==5.3.1 + - numpy==1.26.3 + - nvidia-cublas-cu11==11.11.3.6 + - nvidia-cuda-cupti-cu11==11.8.87 + - nvidia-cuda-nvrtc-cu11==11.8.89 + - nvidia-cuda-runtime-cu11==11.8.89 + - nvidia-cudnn-cu11==9.1.0.70 + - nvidia-cufft-cu11==10.9.0.58 + - nvidia-curand-cu11==10.3.0.86 + - nvidia-cusolver-cu11==11.4.1.48 + - nvidia-cusparse-cu11==11.7.5.86 + - nvidia-nccl-cu11==2.21.5 + - nvidia-nvtx-cu11==11.8.86 + - opencv-python==4.10.0.84 + - packaging==24.1 + - pillow==10.2.0 + - pyparsing==3.2.0 + - python-dateutil==2.9.0.post0 + - scikit-learn==1.5.2 + - scipy==1.13.1 + - simpleitk==2.4.0 + - six==1.16.0 + - sympy==1.13.1 + - threadpoolctl==3.5.0 + - torch==2.5.0+cu118 + - torchaudio==2.5.0+cu118 + - torchvision==0.20.0+cu118 + - triton==3.1.0 + - typing-extensions==4.9.0 + - zipp==3.20.2 +prefix: /home/Student/s4704935/miniconda3/envs/comp3710 From 71cb1cb09b0b81fadc87e3fb68350035212e4b82 Mon Sep 17 00:00:00 2001 From: Ryuto Hisamoto Date: Thu, 24 Oct 2024 20:33:35 +1000 Subject: [PATCH 093/102] resized to reduce memory consumption --- recognition/47049358/dataset.py | 12 +++-- recognition/47049358/environment.yml | 70 ---------------------------- 2 files changed, 7 insertions(+), 75 deletions(-) delete mode 100644 recognition/47049358/environment.yml diff --git a/recognition/47049358/dataset.py b/recognition/47049358/dataset.py index 7bdf3cd37..3475d6846 100644 --- a/recognition/47049358/dataset.py +++ b/recognition/47049358/dataset.py @@ -15,7 +15,7 @@ from sklearn.model_selection import train_test_split from monai.transforms import (LoadImaged, EnsureChannelFirstd, NormalizeIntensityd, SpatialCropd, RandFlipd, RandRotated, AsDiscreted, - RandGaussianNoised, Compose, CastToTyped) + RandGaussianNoised, Compose, CastToTyped, Resized) import torch __author__ = "Ryuto Hisamoto" @@ -30,11 +30,11 @@ # Constants # ========================== -IMAGE_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_MRs' # on rangpur -LABEL_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_labels_only' # on rangpur +# IMAGE_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_MRs' # on rangpur +# LABEL_FILE_NAME = '/home/groups/comp3710/HipMRI_Study_open/semantic_labels_only' # on rangpur -# IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') # assuming folders are in the cwd -# LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') +IMAGE_FILE_NAME = os.path.join(os.getcwd(), 'semantic_MRs_anon') # assuming folders are in the cwd +LABEL_FILE_NAME = os.path.join(os.getcwd(), 'semantic_labels_anon') rawImageNames = sorted(os.listdir(IMAGE_FILE_NAME)) rawLabelNames = sorted(os.listdir(LABEL_FILE_NAME)) @@ -55,6 +55,7 @@ EnsureChannelFirstd(keys=["image", "label"]), SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), # Crop to depth 128 NormalizeIntensityd(keys=["image"]), + Resized(keys=["image", "label"], spatial_size=(128, 128, 64)), RandFlipd(keys=["image", "label"], spatial_axis=2, prob=0.5), RandRotated(keys=["image", "label"], range_x=0.5, range_y=0.5, range_z=0.5, mode='nearest', prob=0.5), RandGaussianNoised(keys=["image"], prob=0.5, mean=0, std=0.5), @@ -74,6 +75,7 @@ EnsureChannelFirstd(keys=["image", "label"]), SpatialCropd(keys=["image", "label"], roi_slices=[slice(None), slice(None), slice(0, 128)]), NormalizeIntensityd(keys=["image"]), + Resized(keys=["image", "label"], spatial_size=(128, 128, 64)), AsDiscreted(keys=["label"], to_onehot=6), CastToTyped(keys=["label"], dtype=torch.uint8), ] diff --git a/recognition/47049358/environment.yml b/recognition/47049358/environment.yml deleted file mode 100644 index 964f5a00f..000000000 --- a/recognition/47049358/environment.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: comp3710 -channels: - - defaults -dependencies: - - _libgcc_mutex=0.1=main - - _openmp_mutex=5.1=1_gnu - - ca-certificates=2024.9.24=h06a4308_0 - - ld_impl_linux-64=2.40=h12ee557_0 - - libffi=3.4.4=h6a678d5_1 - - libgcc-ng=11.2.0=h1234567_1 - - libgomp=11.2.0=h1234567_1 - - libstdcxx-ng=11.2.0=h1234567_1 - - ncurses=6.4=h6a678d5_0 - - openssl=3.0.15=h5eee18b_0 - - pip=24.2=py39h06a4308_0 - - python=3.9.20=he870216_1 - - readline=8.2=h5eee18b_0 - - setuptools=75.1.0=py39h06a4308_0 - - sqlite=3.45.3=h5eee18b_0 - - tk=8.6.14=h39e8969_0 - - tzdata=2024b=h04d1e81_0 - - wheel=0.44.0=py39h06a4308_0 - - xz=5.4.6=h5eee18b_1 - - zlib=1.2.13=h5eee18b_1 - - pip: - - contourpy==1.3.0 - - cycler==0.12.1 - - filelock==3.13.1 - - fonttools==4.54.1 - - fsspec==2024.2.0 - - importlib-resources==6.4.5 - - jinja2==3.1.3 - - joblib==1.4.2 - - kiwisolver==1.4.7 - - markupsafe==2.1.5 - - matplotlib==3.9.2 - - monai==1.4.0 - - mpmath==1.3.0 - - networkx==3.2.1 - - nibabel==5.3.1 - - numpy==1.26.3 - - nvidia-cublas-cu11==11.11.3.6 - - nvidia-cuda-cupti-cu11==11.8.87 - - nvidia-cuda-nvrtc-cu11==11.8.89 - - nvidia-cuda-runtime-cu11==11.8.89 - - nvidia-cudnn-cu11==9.1.0.70 - - nvidia-cufft-cu11==10.9.0.58 - - nvidia-curand-cu11==10.3.0.86 - - nvidia-cusolver-cu11==11.4.1.48 - - nvidia-cusparse-cu11==11.7.5.86 - - nvidia-nccl-cu11==2.21.5 - - nvidia-nvtx-cu11==11.8.86 - - opencv-python==4.10.0.84 - - packaging==24.1 - - pillow==10.2.0 - - pyparsing==3.2.0 - - python-dateutil==2.9.0.post0 - - scikit-learn==1.5.2 - - scipy==1.13.1 - - simpleitk==2.4.0 - - six==1.16.0 - - sympy==1.13.1 - - threadpoolctl==3.5.0 - - torch==2.5.0+cu118 - - torchaudio==2.5.0+cu118 - - torchvision==0.20.0+cu118 - - triton==3.1.0 - - typing-extensions==4.9.0 - - zipp==3.20.2 -prefix: /home/Student/s4704935/miniconda3/envs/comp3710 From 0a420acde09f53f67282116dbaaf8f863d7c8409 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Fri, 25 Oct 2024 02:33:24 +1000 Subject: [PATCH 094/102] some progress on report for later revisit --- recognition/47049358/README.md | 105 ++++++++++++++++++++-------- recognition/47049358/modules.py | 4 +- recognition/47049358/references.bib | 26 ------- requirements.txt | Bin 14052 -> 0 bytes 4 files changed, 76 insertions(+), 59 deletions(-) delete mode 100644 recognition/47049358/references.bib delete mode 100644 requirements.txt diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index 257bde1e4..14ae4477a 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -1,33 +1,32 @@ --- title: COMP3710 Report author: "Ryuto Hisamoto" -date: "2024-10-24" -bibliography: references.bib +date: "2024-10-25" --- -# Improved 3D Improved UNet +# Improved 3D UNet + +Improved 3D UNet is capable of producing segmentations for medical images. The report covers the architecture of model, its parameters and relevant components, and its performance on 3D prostate data. + + ## The Problem + + Segmentation is a task that requires a machine learning models to divide image components into meaningful parts. In other words, the model is required to classify components of an image correctly into corresponding labels. ## The Model

- Improved 3D UNet Architecture + Improved 3D UNet Architecture +
+ Figure 1: Improved 3D UNet Architecture

+ + UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network(Gupta, 2021). The authors of "Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge" proposes the improvement on the architecture by the integration of segmentation layers at different levels. The resulting architecture is improved 3D UNet which is capable of performing complex segmentation tasks with appropriate parameters and components. -- Negative Slop: $10 ^ {-2}$ -- Dropout Probability: 0.3 + In the context pathway (encoding part), 3 x 3 x 3 convolution with a stride and padding of 1 is applied in each convolutional layer. Then, instance normalisation is applied and its output groes through leaky ReLU with a negative slope of $10 ^ {-2}$ as an activation function. We refer to this module as a 'standard module', and 3 x 3 x 3 stride 2 convolution is the same as a standard module except its stride being 2 to reduce the resolution of input.Context modules are composed of two standard modules with a drop out layer in-between with a dropout probability of 30%. This helps in reducing computational cost and memory requirements. Lastly, output from context modules are combined with its input passed from a standard module with element-wise sum. From the 2nd level, the depth of layers is doubled, and the process is repeated throughout each level of the context pathway. - - UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network. On top of it, the improvement on UNet proposed by authors of "Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge" [@IsenseeFabian2018BTSa]involves the integration of segmentation layers at different levels of the architecture. - + The localisation pathway (decoding part) utilises a 4 x 4 x 4 transposed convolution with a stride of 2 and padding of 1 to increase the resolution while reducing the feature maps. As the input goes up layers, they are concatenated with the output from a context module on the same layer to preserve features which are potentially lost as they go through the network. Then, localisation modules combines the features together while reducing the number of feature maps to reduce memory consumption. Its output is handed over to the following upsampling module, and the process is repeated until it reaches back to the original level of the architecture. When the input reaches to the original level, it goes through another standard module before handed over to a segmentation layer and is summed with the previsous outputs of segmentation layers. - |Labels|Segment| -| --------------- | ---------------------------------------- | -|0| Background | -|1| Body | -|2| Bones | -|3| Bladder | -|4| Rectum | -|5| Prostate | +From the third localisation layer, segmentation layers which apply 1 x 1 x 1 convolution with a stride of 1 take outputs from localisation modules and map them to the corresponding segmentation labels and are summed element-wise after upscaled to match the size. Finally the output is applied a softmax to turn its predictions of labels into probabilities for later calculation of loss. It is to be noted that, argmax has to be applied to produce proper masks from the output of the model. Otherwise, the model produces its predictions from the architecture and processed discussed. ### Loading Data @@ -44,8 +43,25 @@ However, some augmentations methods are altered to limit the complexity of solut - Random Rotation ($[-0.5, 0.5]$ for all x, y, and z coordinates) - Random Vertical Flip - Gaussian Noise ($\mu = 0, \sigma = 0.5$) +- Resizing (down to (128 x 128 x 64)) + +Resizing is an optional transformation as it is meant to save the memory consumption and increase the speed of training. However, with a limit in memory, this transformation must be applied for the training to happen. The past attempts have shown that the implementation cannot process image size of (256 x 256 x 128) regardless of batch size. In addition, all images are normalised as they are loaded to eliminate difference in intensity scales if there are any. Finally, all voxel values are loaded as `torch.float32` but `torch.uint8` is used for labels to save memory consumption. The labels in the dataset are indexed according to the table below, and are assigned to corresponding layers as binary masks as they are on-hot encoded. For example, segments corresponding to the first type of label appears as 1s in the 0th layer while other parts appear as 0s, and so on. -In addition, all images are normalised as they are loaded to eliminate difference in intensity scales if there are any. Moreover, all voxel values are loaded as `torch.float32` but `torch.uint8` is used for labels to save memory consumption. + |Labels|Segment| +| - | - | +|0| Background | +|1| Body | +|2| Bones | +|3| Bladder | +|4| Rectum | +|5| Prostate | + + +

+ Example of labels layered on top of images +
+ Figure 2: Example of labels layered on top of images. +

### Training @@ -57,29 +73,56 @@ In addition, all images are normalised as they are loaded to eliminate differenc The model takes in an raw image as its input, and its goal is to learn the best feature map which ends up being a multi-channel segmentation of the original image. -### Loss Function +#### Loss Function + +The model utilises dice loss as its loss function. Moreover, it is capable of using deviations of dice loss such as a sum of dice loss and cross-entropy loss, or focal loss. A vanilla dice score has formula: $$D(y_{true}, y_{pred}) = 2 \times \frac{\Sigma(y_{true} \cdot y_{pred})}{\Sigma y_{true} + \Sigma y_{pred}}$$ + +in which $y_{true}$ is the ground truth probability and $y_{pred}$ is the predicted probability. Hence dice loss is provided by: + +$$L_{Dice} = 1 - D(y_{true}, y_{pred})$$ + +The loss function mitigates the problem with other loss functions such as a cross-entropy loss which tend to be biased toward a dominant class. The design of dice loss provides more accurate representation of the model's performance in segmentation. In addition `monai` provides an option to exclude background from the calculation of loss, and the model makes use of this option when calculating the loss (background is included when testing). + +The author recommends the sum of dice loss and a weighted cross-entropy loss (Yang et al., 2022) for the problem as it seems to produces the most optimal performance. Cross-entropy loss is calculating by: + +$$L_{CE} = \frac{1}{N} \Sigma_i - [y_i \times \ln (p_i) + (1 - y_i) \times \ln (1 - p_i)]$$ -The model utilises dice loss as its loss function. Moreover, it is capable of using deviations of dice loss such as a sum of dice loss and cross-entropy loss, or focal loss. A vanilla dice loss has formula: $$D(y_{true}, y_{pred}) = 2 \times \frac{\Sigma(y_{true} \cdot y_{pred})}{\Sigma y_{true} + \Sigma y_{pred}}$$ +where $y_i$ is the lebel of sample $i$ and $p_i$ represents the probability of sample $i$ predicted to be positive, and $N$ represents the number of samples. Hence the its wegithed sum with a dice loss can be shown as -in which $y_{true}$ is the ground truth probability and $y_{pred}$ is the predicted probability. The loss function mitigates the problem with other loss functions such as a cross-entropy loss which tend to be biased toward a dominant class. The design of dice loss provides more accurate representation of the model's performance in segmentation. In addition `monai` provides an option to exclude background from the calculation of loss, and the model makes use of this option when calculating the loss (background is included when testing). +$$L_{loss} = L_{Dice} + \alpha L_{CE}$$ -### Optimiser +"Multi-task thyroid tumor segmentation based on the joint loss function" recommends to set $\alpha = 0.2$, so the report strictly follows it to calculate the weighted loss. -**Adam (Adaptive Moment Estimation)** is an optimisation algorithm that boosts the speed of convergence of gradient descent. The optimiser utilises an exponential average of gradients, which allows its efficient and fast pace of convergence. Moreover, the optimiser applies a $L_2$ regularisation to penalise for the complexity of model. -In addition, the model utilises a learning rate scheduler based on the number of epochs, which dynamically changes the learning rate over epochs. This allows the model to start from a large learning rate which evntually settles to a small learning rate for easier convergence. -It is to be noted that mixed precision and gradient accumulation are used to reduce the memory consumption during the training. +#### Optimiser + +**Adam (Adaptive Moment Estimation)** is an optimisation algorithm that boosts the speed of convergence of gradient descent. The optimiser utilises an exponential average of gradients, which allows its efficient and fast pace of convergence. Moreover, the optimiser applies a **$L_2$ regularisation** (aka Tikhonov regularisation) to penalise for the complexity of model. Complexity can be defined as the number of parameters learned from the data, and high complexity is likely to be an indication of overfitting to the training samples. Hence, regularisation is necessary to prevent the model from learning high values of parameters by penalising the model for its complexity, and $L_2$ regularisation is one of the explicit regularisation methods which adds an extra penalty term to the cost function. The parameters learned with such technique can be denoted as + +$$\hat{\theta} = \arg \min_\theta \frac{1}{n} ||X\theta - y||^ 2_ 2 + \lambda ||\theta|| ^ 2 _ 2$$ + +In addition, the model utilises a learning rate scheduler based on the number of epochs, which dynamically changes the learning rate over epochs. This allows the model to start from a large learning rate which evntually settles to a small learning rate for easier convergence. In the implementation, the learnign rate is reduced by $1e ^ {-5}$ over each epoch. + +It is to be noted that mixed precision and gradient accumulation are used to reduce the memory consumption during the training. **Mixed precision** reduces the memory consumption by replaceing value types with `torch.float16` where it can to reduce the space required to perform necessary operations including loss and gradient calculations necessary to train the model. **Gradient accumulation** accumulates the gradients and updates the weights after some training loop. ### Testing -The model is tested by measuring its dice scores on the segmentations it produces for unseen images. Although the model outputs softmax values for its predicted segmentations, they are one-hot encoded during the test to maximise the contribution of correct predictions. Moreover, unlike tranin +The model is tested by measuring its dice scores on the segmentations it produces for unseen images. Although the model outputs softmax values for its predicted segmentations, they are one-hot encoded during the test to maximise the contribution of correct predictions. Dice scores for each label is calculated independently to obtain the accurate performance to analyse the model's weakness and strengths in predicting particular segments for all labels. Then, their averages are taken and are summarised in the bar chart. Moreover, the visualisation of first 9 labels are produces with the actual segmentations for comparison. + +## Result + +## Discussion + +Firstly, there had to be a compromise in maintaining the original resolution of the image given the limiation in resources. The model seem to perform well on downsized images, but without testing it on images with original resolution, its performance on original images can only be estimated. Moreover, the optimality of architecture remain as a question as the model could be potentially simplified to perform the same task without facing issues in its large consumption of computer memory. + +Secondly, the project did not incorporate the idea of pateient-level predictions. Despite the model's strong performance, its true robustness to scans taken from new patients must be explored to test its true ability to produce segmentations. In future, the model has to be tested for its capability by training it based on patient-level images. + - ## The Problem - Segmentation is a task that requires a machine learning models to divide image components into meaningful parts. In other words, the model is required to classify components of an image correctly into given labels. +## Conclusion - +## References -(Dice Coefficient)[https://en.wikipedia.org/wiki/Dice-Sørensen_coefficient] +1. Gupta, P. (2021, December 17). Understanding Skip Connections in Convolutional Neural Networks using U-Net Architecture. Medium. https://medium.com/@preeti.gupta02.pg/understanding-skip-connections-in-convolutional-neural-networks-using-u-net-architecture-b31d90f9670a -(Loss Function)[https://www.sciencedirect.com/science/article/pii/S1746809422007030] +2. Isensee, F., Kickingereder, P., Wick, W., Bendszus, M., & Maier-Hein, K. (2018). Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge. In arXiv. https://arxiv.org/pdf/1802.10508v1 +3. Yang, D., Li, Y., & Yu, J. (2022). Multi-task thyroid tumor segmentation based on the joint loss function. Biomedical Signal Processing and Control, 79(2). https://doi.org/10.1016/j.bspc.2022.104249 diff --git a/recognition/47049358/modules.py b/recognition/47049358/modules.py index 29de34348..0edacf759 100644 --- a/recognition/47049358/modules.py +++ b/recognition/47049358/modules.py @@ -53,7 +53,7 @@ class ContextModule(nn.Module): def __init__(self, in_channels, out_channels): super(ContextModule, self).__init__() self.block1 = StandardModule(in_channels = in_channels, out_channels = out_channels, inplace = True) - self.dropout = nn.Dropout(DROP_PROB) # Drop description uncertain, replace it with Dropout3d when poor performance + self.dropout = nn.Dropout(DROP_PROB) self.block2 = StandardModule(in_channels = in_channels, out_channels = out_channels, inplace = True) def forward(self, x): @@ -112,7 +112,7 @@ def forward(self, x): x = self.block(x) return x -""" A mlocalisation modules that consists of a 3 x 3 x 3 convolution followed by a 1 x 1 x 1 convolution that halves the +""" Localisation modules that consists of a 3 x 3 x 3 convolution followed by a 1 x 1 x 1 convolution that halves the number of feature maps. It acccepts the concatenated features from the skip connection and recombines them together. Parameters: diff --git a/recognition/47049358/references.bib b/recognition/47049358/references.bib deleted file mode 100644 index 7a55a38c0..000000000 --- a/recognition/47049358/references.bib +++ /dev/null @@ -1,26 +0,0 @@ -@inproceedings{IsenseeFabian2018BTSa, -issn = {0302-9743}, -abstract = {Quantitative analysis of brain tumors is critical for clinical decision making. While manual segmentation is tedious, time consuming and subjective, this task is at the same time very challenging to solve for automatic segmentation methods. In this paper we present our most recent effort on developing a robust segmentation algorithm in the form of a convolutional neural network. Our network architecture was inspired by the popular U-Net and has been carefully modified to maximize brain tumor segmentation performance. We use a dice loss function to cope with class imbalances and use extensive data augmentation to successfully prevent overfitting. Our method beats the current state of the art on BraTS 2015, is one of the leading methods on the BraTS 2017 validation set (dice scores of 0.896, 0.797 and 0.732 for whole tumor, tumor core and enhancing tumor, respectively) and achieves very good Dice scores on the test set (0.858 for whole, 0.775 for core and 0.647 for enhancing tumor). We furthermore take part in the survival prediction subchallenge by training an ensemble of a random forest regressor and multilayer perceptrons on shape features describing the tumor subregions. Our approach achieves 52.6% accuracy, a Spearman correlation coefficient of 0.496 and a mean square error of 209607 on the test set.}, -pages = {287--297}, -volume = {10670}, -publisher = {Springer International Publishing}, -booktitle = {BRAINLESION: GLIOMA, MULTIPLE SCLEROSIS, STROKE AND TRAUMATIC BRAIN INJURIES, BRAINLES 2017}, -isbn = {3319752375}, -year = {2018}, -title = {Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge}, -copyright = {Springer International Publishing AG, part of Springer Nature 2018}, -language = {eng}, -address = {Cham}, -author = {Isensee, Fabian and Kickingereder, Philipp and Wick, Wolfgang and Bendszus, Martin and Maier-Hein, Klaus H.}, -keywords = {Brain tumor ; Clinical Neurology ; CNN ; Computer Science ; Computer Science Theory & Methods ; Deep learning ; Glioblastoma ; Life Sciences & Biomedicine ; Neuroimaging ; Neurosciences ; Neurosciences & Neurology ; Science & Technology ; Technology}, -} - -@online{author2023, - author = {Armaanjeet Singh Sandhu}, - title = {Calculating the Sørensen-Dice Coefficient: A Simplified Guide}, - year = {2023}, - url = {https://medium.com/the-research-nest/calculating-the-sørensen-dice-coefficient-a-simplified-guide-3b59a1829a82}, - note = {Accessed: 2024-10-24} -} - - diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index f5aa83199de7cafe2ce807e11235ec14b5df4d1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14052 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⪚=~G==w4v|?B@D|2KmOs8I9FE716nI7dcTT`JEARwxpp8 zDnB#*dmoeY0Dfg25JCH%hz!WG@U|UY#a1`3M+$EYd6DbU}!<;t;dt*aCRu8{d28ofScCBLoW?(ooi%mIgQDM9-s z%Ae_6=jkDBbB_KL+Obc}(+nQQKWxF+5p?A_Z^691Bcpj6gy|#ZZR3LXH1udpZ}jl= zlzhg!&<*w|%S`570KYBA&M?161C@7l#5r4NBatn%Z`o$A!T}4}C+9~4NY8A{-)w*b zIk69sacJS@^P&GK8+#f6gNO~P4&TqwU?VwrGmSsjvY=}Zh?w7wLY{KAI-Z-sk<7s- z$2gv)o8k&@mfY=Q2C!cxS0fv0q#&Bki#l>B@~VQv;nplucE+O;5jz z%elVSbX?c*vWHHp|>^j+*fMPR6M@*N*cJx!o(UU#vw{P^!yxBfe zO!~$S`LWe`*||+qJW)(!#CuKNII~COmL%#YaZBd0l|f%9noyJ4%bP)1l{*qw->tB2 zF7J4s&O6ZgwznUZjT4Lq!eIZ+)eVgyJ z*h9p*Xd9h-jqk$w;dTBm~`k0*dXBnV(t8j^(GxSGyKP-9=AT=D_w#20zAoc zyldrmFWD1O(+iow?E^l6H!~S1&@>A*qwc%3 zVAmCMEB$khhqmmr1$eiV%w#Wmm=pP}0AlvIZbnvj%VX)n{(UQdxnf4eN3-v6ioP2Q zN7Q+0|44Yoy{V)5Ly`EpvmH Date: Fri, 25 Oct 2024 16:14:52 +1000 Subject: [PATCH 095/102] fixed corrupted image names --- recognition/47049358/.gitignore | 4 +- recognition/47049358/README.md | 146 ++++++++++++++++++++++++++++++-- recognition/47049358/predict.py | 6 +- recognition/47049358/train.py | 4 +- 4 files changed, 145 insertions(+), 15 deletions(-) diff --git a/recognition/47049358/.gitignore b/recognition/47049358/.gitignore index 0fafdc99a..db8326159 100644 --- a/recognition/47049358/.gitignore +++ b/recognition/47049358/.gitignore @@ -13,4 +13,6 @@ semantic_MRs_anon *.sh -*.out \ No newline at end of file +*.out + +*.pdf \ No newline at end of file diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index 14ae4477a..5b8f10b83 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -6,11 +6,12 @@ date: "2024-10-25" # Improved 3D UNet -Improved 3D UNet is capable of producing segmentations for medical images. The report covers the architecture of model, its parameters and relevant components, and its performance on 3D prostate data. +Improved 3D UNet is capable of producing segmentations for medical images. The report covers the architecture of model,its parameters and relevant components, and its performance on 3D prostate data. - ## The Problem +## The Problem - Segmentation is a task that requires a machine learning models to divide image components into meaningful parts. In other words, the model is required to classify components of an image correctly into corresponding labels. +Segmentation is a task that requires a machine learning models to divide image components into meaningful parts. +In other words, the model is required to classify components of an image correctly into corresponding labels. ## The Model @@ -20,11 +21,15 @@ Improved 3D UNet is capable of producing segmentations for medical images. The r Figure 1: Improved 3D UNet Architecture

- UNet is an architecture for convolutional neural networks specifically for segmentation tasks. The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network(Gupta, 2021). The authors of "Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge" proposes the improvement on the architecture by the integration of segmentation layers at different levels. The resulting architecture is improved 3D UNet which is capable of performing complex segmentation tasks with appropriate parameters and components. +UNet is an architecture for convolutional neural networks specifically for segmentation tasks (Gupta, 2021). +The model takes advantage of skip connections and tensor concatenations to preserve input details and its structure while learning appropriate segmentations. +The basic structure of UNet involves the downsampling and upsampling of original images with skip connections in between corresponding pair of downsampling and upsampling layers. +Skip connection is a technique used to (1) preserve features of the image and (2) prevent diminishing gradients over deep layers of network preventing the learning of parameters (PATHAK, 2024). +The authors of "Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge" proposes the improvement on the architecture by the integration of segmentation layers at different levels. The resulting architecture is improved 3D UNet which is capable of performing complex segmentation tasks with appropriate parameters and components. - In the context pathway (encoding part), 3 x 3 x 3 convolution with a stride and padding of 1 is applied in each convolutional layer. Then, instance normalisation is applied and its output groes through leaky ReLU with a negative slope of $10 ^ {-2}$ as an activation function. We refer to this module as a 'standard module', and 3 x 3 x 3 stride 2 convolution is the same as a standard module except its stride being 2 to reduce the resolution of input.Context modules are composed of two standard modules with a drop out layer in-between with a dropout probability of 30%. This helps in reducing computational cost and memory requirements. Lastly, output from context modules are combined with its input passed from a standard module with element-wise sum. From the 2nd level, the depth of layers is doubled, and the process is repeated throughout each level of the context pathway. +In the context pathway (encoding part), 3 x 3 x 3 convolution with a stride and padding of 1 is applied in each convolutional layer. Then, instance normalisation is applied and its output groes through leaky ReLU with a negative slope of $10 ^ {-2}$ as an activation function. We refer to this module as a 'standard module', and 3 x 3 x 3 stride 2 convolution is the same as a standard module except its stride being 2 to reduce the resolution of input.Context modules are composed of two standard modules with a drop out layer in-between with a dropout probability of 30%. This helps in reducing computational cost and memory requirements. Lastly, output from context modules are combined with its input passed from a standard module with element-wise sum. From the 2nd level, the depth of layers is doubled, and the process is repeated throughout each level of the context pathway. - The localisation pathway (decoding part) utilises a 4 x 4 x 4 transposed convolution with a stride of 2 and padding of 1 to increase the resolution while reducing the feature maps. As the input goes up layers, they are concatenated with the output from a context module on the same layer to preserve features which are potentially lost as they go through the network. Then, localisation modules combines the features together while reducing the number of feature maps to reduce memory consumption. Its output is handed over to the following upsampling module, and the process is repeated until it reaches back to the original level of the architecture. When the input reaches to the original level, it goes through another standard module before handed over to a segmentation layer and is summed with the previsous outputs of segmentation layers. +The localisation pathway (decoding part) utilises a 4 x 4 x 4 transposed convolution with a stride of 2 and padding of 1 to increase the resolution while reducing the feature maps. As the input goes up layers, they are concatenated with the output from a context module on the same layer to preserve features which are potentially lost as they go through the network. Then, localisation modules combines the features together while reducing the number of feature maps to reduce memory consumption. Its output is handed over to the following upsampling module, and the process is repeated until it reaches back to the original level of the architecture. When the input reaches to the original level, it goes through another standard module before handed over to a segmentation layer and is summed with the previsous outputs of segmentation layers. From the third localisation layer, segmentation layers which apply 1 x 1 x 1 convolution with a stride of 1 take outputs from localisation modules and map them to the corresponding segmentation labels and are summed element-wise after upscaled to match the size. Finally the output is applied a softmax to turn its predictions of labels into probabilities for later calculation of loss. It is to be noted that, argmax has to be applied to produce proper masks from the output of the model. Otherwise, the model produces its predictions from the architecture and processed discussed. @@ -83,7 +88,7 @@ $$L_{Dice} = 1 - D(y_{true}, y_{pred})$$ The loss function mitigates the problem with other loss functions such as a cross-entropy loss which tend to be biased toward a dominant class. The design of dice loss provides more accurate representation of the model's performance in segmentation. In addition `monai` provides an option to exclude background from the calculation of loss, and the model makes use of this option when calculating the loss (background is included when testing). -The author recommends the sum of dice loss and a weighted cross-entropy loss (Yang et al., 2022) for the problem as it seems to produces the most optimal performance. Cross-entropy loss is calculating by: +It is recommended to use the sum of dice loss and a weighted cross-entropy loss (Yang et al., 2022) for the problem as it seems to optimise the performance the most. Cross-entropy loss is calculating by: $$L_{CE} = \frac{1}{N} \Sigma_i - [y_i \times \ln (p_i) + (1 - y_i) \times \ln (1 - p_i)]$$ @@ -109,20 +114,143 @@ The model is tested by measuring its dice scores on the segmentations it produce ## Result +The outcome shows the significant impact of the choice of loss function in the performance of model. It was found that with other loss functions, the model performs poorly on assigning correct labels to small segments. Specifically, segment label 4 (rectum) often suffered from poor performance as it was often ignored by the model in optimising the segmentaion of corresponding label. However, the addition of weighted cross-entropy loss seem to enforce the model to classify segments correctly, which might have led to an improvement in performance. + ## Discussion Firstly, there had to be a compromise in maintaining the original resolution of the image given the limiation in resources. The model seem to perform well on downsized images, but without testing it on images with original resolution, its performance on original images can only be estimated. Moreover, the optimality of architecture remain as a question as the model could be potentially simplified to perform the same task without facing issues in its large consumption of computer memory. Secondly, the project did not incorporate the idea of pateient-level predictions. Despite the model's strong performance, its true robustness to scans taken from new patients must be explored to test its true ability to produce segmentations. In future, the model has to be tested for its capability by training it based on patient-level images. - +Finally, although the report strictly followed the implementation of the architectures and loss functions from the published papers with different problem space, there could be more optimal or efficient adjustments that could improve the model's performance in terms of accuracy and time and/or memory savings. Therefore, future research +could focus on the improvement of current model with differentiations from the architectures and components already mentioned by researchers for new discoveries. ## Conclusion +Improved 3D UNet is a powerful architecture which makes complex image-processing tasks possible. However, its performance is truly maximised through the observation of its behaviour and performance under different settings, tunings, and/or parameter selections. In the given problem of segmenting 3D prostate images, adjusting the loss function from a vanilla dice loss to the sum of dice loss and weighted cross-entropy loss improved the performance dramatically. The model could be explored in depth in regards to its relationship with its components for improved performance, which could potentially lead to a discovery of new and more generalised architectures that could function in wider + ## References 1. Gupta, P. (2021, December 17). Understanding Skip Connections in Convolutional Neural Networks using U-Net Architecture. Medium. https://medium.com/@preeti.gupta02.pg/understanding-skip-connections-in-convolutional-neural-networks-using-u-net-architecture-b31d90f9670a 2. Isensee, F., Kickingereder, P., Wick, W., Bendszus, M., & Maier-Hein, K. (2018). Brain Tumor Segmentation and Radiomics Survival Prediction: Contribution to the BRATS 2017 Challenge. In arXiv. https://arxiv.org/pdf/1802.10508v1 -3. Yang, D., Li, Y., & Yu, J. (2022). Multi-task thyroid tumor segmentation based on the joint loss function. Biomedical Signal Processing and Control, 79(2). https://doi.org/10.1016/j.bspc.2022.104249 +3. PATHAK, H. (2024, July 21). How do skip connections impact the training process of neural networks? Medium. https://medium.com/@harshnpathak/how-do-skip-connections-impact-the-training-process-of-neural-networks-bccca6efb2eb + +4. Yang, D., Li, Y., & Yu, J. (2022). Multi-task thyroid tumor segmentation based on the joint loss function. Biomedical Signal Processing and Control, 79(2). https://doi.org/10.1016/j.bspc.2022.104249 + +## Dependencies + +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: linux-64 +_libgcc_mutex=0.1=main +_openmp_mutex=5.1=1_gnu +blas=1.0=mkl +brotli-python=1.0.9=py312h6a678d5_8 +bzip2=1.0.8=h5eee18b_6 +ca-certificates=2024.9.24=h06a4308_0 +certifi=2024.8.30=py312h06a4308_0 +charset-normalizer=3.3.2=pyhd3eb1b0_0 +contourpy=1.3.0=pypi_0 +cuda-cudart=11.8.89=0 +cuda-cupti=11.8.87=0 +cuda-libraries=11.8.0=0 +cuda-nvrtc=11.8.89=0 +cuda-nvtx=11.8.86=0 +cuda-runtime=11.8.0=0 +cuda-version=12.6=3 +cycler=0.12.1=pypi_0 +expat=2.6.3=h6a678d5_0 +ffmpeg=4.3=hf484d3e_0 +filelock=3.13.1=py312h06a4308_0 +fonttools=4.54.1=pypi_0 +freetype=2.12.1=h4a9f257_0 +fsspec=2024.10.0=pypi_0 +giflib=5.2.2=h5eee18b_0 +gmp=6.2.1=h295c915_3 +gnutls=3.6.15=he1e5248_0 +idna=3.7=py312h06a4308_0 +intel-openmp=2023.1.0=hdb19cb5_46306 +jinja2=3.1.4=py312h06a4308_0 +joblib=1.4.2=pypi_0 +jpeg=9e=h5eee18b_3 +kiwisolver=1.4.7=pypi_0 +lame=3.100=h7b6447c_0 +lcms2=2.12=h3be6417_0 +ld_impl_linux-64=2.40=h12ee557_0 +lerc=3.0=h295c915_0 +libcublas=11.11.3.6=0 +libcufft=10.9.0.58=0 +libcufile=1.11.1.6=0 +libcurand=10.3.7.77=0 +libcusolver=11.4.1.48=0 +libcusparse=11.7.5.86=0 +libdeflate=1.17=h5eee18b_1 +libffi=3.4.4=h6a678d5_1 +libgcc-ng=11.2.0=h1234567_1 +libgomp=11.2.0=h1234567_1 +libiconv=1.16=h5eee18b_3 +libidn2=2.3.4=h5eee18b_0 +libjpeg-turbo=2.0.0=h9bf148f_0 +libnpp=11.8.0.86=0 +libnvjpeg=11.9.0.86=0 +libpng=1.6.39=h5eee18b_0 +libstdcxx-ng=11.2.0=h1234567_1 +libtasn1=4.19.0=h5eee18b_0 +libtiff=4.5.1=h6a678d5_0 +libunistring=0.9.10=h27cfd23_0 +libuuid=1.41.5=h5eee18b_0 +libwebp=1.3.2=h11a3e52_0 +libwebp-base=1.3.2=h5eee18b_1 +llvm-openmp=14.0.6=h9e868ea_0 +lz4-c=1.9.4=h6a678d5_1 +markupsafe=2.1.3=py312h5eee18b_0 +matplotlib=3.9.2=pypi_0 +mkl=2023.1.0=h213fc3f_46344 +mkl-service=2.4.0=py312h5eee18b_1 +mkl_fft=1.3.10=py312h5eee18b_0 +mkl_random=1.2.7=py312h526ad5a_0 +monai=1.4.0=pypi_0 +mpmath=1.3.0=py312h06a4308_0 +ncurses=6.4=h6a678d5_0 +nettle=3.7.3=hbbd107a_1 +networkx=3.2.1=py312h06a4308_0 +nibabel=5.3.2=pypi_0 +numpy=1.26.4=pypi_0 +openh264=2.1.1=h4ff587b_0 +openjpeg=2.5.2=he7f1fd0_0 +openssl=3.0.15=h5eee18b_0 +packaging=24.1=pypi_0 +pillow=10.4.0=py312h5eee18b_0 +pip=24.2=py312h06a4308_0 +pyparsing=3.2.0=pypi_0 +pysocks=1.7.1=py312h06a4308_0 +python=3.12.7=h5148396_0 +python-dateutil=2.9.0.post0=pypi_0 +pytorch=2.5.0=py3.12_cuda11.8_cudnn9.1.0_0 +pytorch-cuda=11.8=h7e8668a_6 +pytorch-mutex=1.0=cuda +pyyaml=6.0.2=py312h5eee18b_0 +readline=8.2=h5eee18b_0 +requests=2.32.3=py312h06a4308_0 +scikit-learn=1.5.2=pypi_0 +scipy=1.14.1=pypi_0 +setuptools=75.1.0=py312h06a4308_0 +six=1.16.0=pypi_0 +sqlite=3.45.3=h5eee18b_0 +sympy=1.13.1=pypi_0 +tbb=2021.8.0=hdb19cb5_0 +threadpoolctl=3.5.0=pypi_0 +tk=8.6.14=h39e8969_0 +torchaudio=2.5.0=py312_cu118 +torchtriton=3.1.0=py312 +torchvision=0.20.0=py312_cu118 +typing_extensions=4.11.0=py312h06a4308_0 +tzdata=2024b=h04d1e81_0 +urllib3=2.2.3=py312h06a4308_0 +wheel=0.44.0=py312h06a4308_0 +xz=5.4.6=h5eee18b_1 +yaml=0.2.5=h7b6447c_0 +zlib=1.2.13=h5eee18b_1 +zstd=1.5.6=hc292b87_0 diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index cecd14cf4..3203e1d2f 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -66,7 +66,7 @@ def visualise_ground_truths(images: list, ground_truths: list, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'ground_truths_{criterion}.png') + plt.savefig(f'ground_truths_{str(criterion)}.png') plt.close() def visualise_predictions(images: list, predictions: list, criterion): @@ -104,7 +104,7 @@ def visualise_predictions(images: list, predictions: list, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'predictions_{criterion}.png') + plt.savefig(f'predictions_{str(criterion)}.png') plt.close() def test(model: nn.Module, test_loader: DataLoader, device: torch.device | str): @@ -209,7 +209,7 @@ def plot_dice(criterion, segment_coefs: np.array): plt.title("Dice Score for Each Segment") plt.legend() plt.grid(True) - plt.savefig(f'dice_coefs_test_{criterion}.png') + plt.savefig(f'dice_coefs_test_{str(criterion)}.png') plt.close() diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 8b09e8c53..31ee36610 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -184,10 +184,10 @@ def train(model: nn.Module, train_loader: DataLoader, criterion, num_epochs: int plt.plot(epochs, seg3, label='Segment 3 Dice Coefficient') plt.plot(epochs, seg4, label='Segment 4 Dice Coefficient') plt.plot(epochs, seg5, label='Segment 5 Dice Coefficient') -plt.title(f'Dice Coefficient Over Epochs for {CRITERION}') +plt.title(f'Dice Coefficient Over Epochs for {str(CRITERION)}') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig(f'unet_dice_coefs_over_epochs_{CRITERION}.png') +plt.savefig(f'unet_dice_coefs_over_epochs_{str(CRITERION)}.png') plt.close() \ No newline at end of file From 34d0a31fce21c7257a756ab8b52e4c00fa801ffd Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Fri, 25 Oct 2024 21:35:12 +1000 Subject: [PATCH 096/102] broken image names corrected for sure --- recognition/47049358/predict.py | 26 +++++++++++++------------- recognition/47049358/train.py | 14 +++++++++----- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/recognition/47049358/predict.py b/recognition/47049358/predict.py index 3203e1d2f..d39a71bae 100644 --- a/recognition/47049358/predict.py +++ b/recognition/47049358/predict.py @@ -13,7 +13,7 @@ from monai.transforms import (AsDiscrete, Compose, CastToType) # import from local files -from train import trained_model, CRITERION, compute_dice_segments, DEVICE +from train import trained_model, CRITERION, compute_dice_segments, DEVICE, CRITERION_NAME from dataset import test_dict, test_transforms __author__ = "Ryuto Hisamoto" @@ -24,13 +24,13 @@ __email__ = "s4704935@student.uq.edu.au" __status__ = "Committed" -def visualise_ground_truths(images: list, ground_truths: list, criterion): +def visualise_ground_truths(images: list, ground_truths: list, criterion_name: str): """ Visualises the ground truths and their images by overlaying them on the same 3 x 3 plot. Args: images (list): Images to overlay labels on. ground_truths (list): Labels to overlay on top of images. - criterion (callable): Loss function used during the training to name the plot. + criterion_name (str): Name of the loss function used during the training to name the plot. Returns: None: The function only plots, so it does not return any value. @@ -66,16 +66,16 @@ def visualise_ground_truths(images: list, ground_truths: list, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'ground_truths_{str(criterion)}.png') + plt.savefig(f'ground_truths_{str(CRITERION_NAME)}.png') plt.close() -def visualise_predictions(images: list, predictions: list, criterion): +def visualise_predictions(images: list, predictions: list, criterion_name : str): """Visualises the predictions and their images by overlaying them on the same 3 x 3 plot. Args: images (list): A list of images to lay predicted labels on predictions (list): A list of predicted labels proeuced by the model - criterion (callable): Loss function used during the training to name the plot. + criterion (str): The name of loss function used during the training to name the plot. Returns: None: The function only plots, so it does not return any value. @@ -104,7 +104,7 @@ def visualise_predictions(images: list, predictions: list, criterion): # Show the plot plt.tight_layout() - plt.savefig(f'predictions_{str(criterion)}.png') + plt.savefig(f'predictions_{str(CRITERION_NAME)}.png') plt.close() def test(model: nn.Module, test_loader: DataLoader, device: torch.device | str): @@ -184,18 +184,18 @@ def test(model: nn.Module, test_loader: DataLoader, device: torch.device | str): test_dice_coefs = np.append(test_dice_coefs, test_dice) - visualise_ground_truths(images, ground_truths, CRITERION) - visualise_predictions(images, predictions, CRITERION) + visualise_ground_truths(images, ground_truths, CRITERION_NAME) + visualise_predictions(images, predictions, CRITERION_NAME) return test_dice_coefs, seg_0_dice_coef, seg_1_dice_coef, seg_2_dice_coef, seg_3_dice_coef, seg_4_dice_coef, seg_5_dice_coef -def plot_dice(criterion, segment_coefs: np.array): +def plot_dice(criterion_name : str, segment_coefs: np.array): """ A method that plots a bar chart to visualise the performance of model on unseen data for each label. It is meant to demonstrated how accurately the model produces segmentations for each lebel. Args: - criterion (callable): Loss function used during the training to name the plot. + criterion (str): The name of loss function used during the training to name the plot. segment_coefs (np.array): an array containing dice scores for each segment at corresponding indices. """ @@ -209,7 +209,7 @@ def plot_dice(criterion, segment_coefs: np.array): plt.title("Dice Score for Each Segment") plt.legend() plt.grid(True) - plt.savefig(f'dice_coefs_test_{str(criterion)}.png') + plt.savefig(f'dice_coefs_test_{str(criterion_name)}.png') plt.close() @@ -258,4 +258,4 @@ def plot_dice(criterion, segment_coefs: np.array): average_s4, average_s5]) # plot dice scores across the dataset. - plot_dice(CRITERION, segment_coefs) \ No newline at end of file + plot_dice(CRITERION_NAME, segment_coefs) \ No newline at end of file diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 31ee36610..5292e3f06 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -27,15 +27,19 @@ __email__ = "s4704935@student.uq.edu.au" __status__ = "Committed" -NUM_EPOCHS = 300 +NUM_EPOCHS = 1 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 LR_INITIAL = 0.985 DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") -CRITERION = DiceLoss(include_background=False, batch=True).to(DEVICE) -# CRITERION = DiceCELoss(include_background=False, batch = True, lambda_ce = 0.2).to(DEVICE) # Based on Thyroid Tumor Segmentation Report +# CRITERION = DiceLoss(include_background=False, batch=True).to(DEVICE) +# CRITERION_NAME = 'dice_loss' +CRITERION = DiceCELoss(include_background=False, batch = True, lambda_ce = 0.2).to(DEVICE) # Based on Thyroid Tumor Segmentation Report +CRITERION_NAME = 'dice_ce_loss' # CRITERION = DiceFocalLoss(include_background=False, batch = True).to(DEVICE) # Default gamma = 2 +# CRITERION_NAME = 'dice_focal_loss' + def compute_dice_segments(predictions: torch.Tensor, ground_truths: torch.Tensor, device: torch.device | str): """The method calculates the dice scores for each segment. The score computed @@ -184,10 +188,10 @@ def train(model: nn.Module, train_loader: DataLoader, criterion, num_epochs: int plt.plot(epochs, seg3, label='Segment 3 Dice Coefficient') plt.plot(epochs, seg4, label='Segment 4 Dice Coefficient') plt.plot(epochs, seg5, label='Segment 5 Dice Coefficient') -plt.title(f'Dice Coefficient Over Epochs for {str(CRITERION)}') +plt.title(f'Dice Coefficient Over Epochs for {str(CRITERION_NAME)}') plt.xlabel('Epochs') plt.ylabel('Loss') plt.legend() plt.grid(True) -plt.savefig(f'unet_dice_coefs_over_epochs_{str(CRITERION)}.png') +plt.savefig(f'unet_dice_coefs_over_epochs_{str(CRITERION_NAME)}.png') plt.close() \ No newline at end of file From b6cdc4c2e921ef6d3896442272835128f4991e53 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sun, 27 Oct 2024 22:51:57 +1000 Subject: [PATCH 097/102] proper loss recorded during the training --- recognition/47049358/README.md | 150 ++++++++------------------------- recognition/47049358/train.py | 7 +- 2 files changed, 40 insertions(+), 117 deletions(-) diff --git a/recognition/47049358/README.md b/recognition/47049358/README.md index 5b8f10b83..a38824c8c 100644 --- a/recognition/47049358/README.md +++ b/recognition/47049358/README.md @@ -50,7 +50,7 @@ However, some augmentations methods are altered to limit the complexity of solut - Gaussian Noise ($\mu = 0, \sigma = 0.5$) - Resizing (down to (128 x 128 x 64)) -Resizing is an optional transformation as it is meant to save the memory consumption and increase the speed of training. However, with a limit in memory, this transformation must be applied for the training to happen. The past attempts have shown that the implementation cannot process image size of (256 x 256 x 128) regardless of batch size. In addition, all images are normalised as they are loaded to eliminate difference in intensity scales if there are any. Finally, all voxel values are loaded as `torch.float32` but `torch.uint8` is used for labels to save memory consumption. The labels in the dataset are indexed according to the table below, and are assigned to corresponding layers as binary masks as they are on-hot encoded. For example, segments corresponding to the first type of label appears as 1s in the 0th layer while other parts appear as 0s, and so on. +Resizing is an optional transformation as it is meant to be done to save the memory consumption and increase the speed of training. **However, resizing must be applied with limited memory resources to run the model**. The past attempts have shown that the implementation cannot process image size of (256 x 256 x 128) regardless of batch size. In addition, all images are normalised as they are loaded to eliminate difference in intensity scales if there are any. Finally, all voxel values are loaded as `torch.float32` but `torch.uint8` is used for labels to save memory consumption. The labels in the dataset are indexed according to the table below, and are assigned to corresponding layers as binary masks as they are on-hot encoded. For example, segments corresponding to the first type of label appears as 1s in the 0th layer while other parts appear as 0s, and so on. |Labels|Segment| | - | - | @@ -108,13 +108,37 @@ In addition, the model utilises a learning rate scheduler based on the number of It is to be noted that mixed precision and gradient accumulation are used to reduce the memory consumption during the training. **Mixed precision** reduces the memory consumption by replaceing value types with `torch.float16` where it can to reduce the space required to perform necessary operations including loss and gradient calculations necessary to train the model. **Gradient accumulation** accumulates the gradients and updates the weights after some training loop. - ### Testing +### Testing -The model is tested by measuring its dice scores on the segmentations it produces for unseen images. Although the model outputs softmax values for its predicted segmentations, they are one-hot encoded during the test to maximise the contribution of correct predictions. Dice scores for each label is calculated independently to obtain the accurate performance to analyse the model's weakness and strengths in predicting particular segments for all labels. Then, their averages are taken and are summarised in the bar chart. Moreover, the visualisation of first 9 labels are produces with the actual segmentations for comparison. +The model is tested by measuring its dice scores on the segmentations it produces for unseen images. Although the model outputs softmax values for its predicted segmentations, they are one-hot encoded during the test to maximise the contribution of correct predictions. Dice scores for each label is calculated independently to obtain the accurate performance to analyse the model's weakness and strengths in predicting particular segments for all labels. Then, their averages are taken and are summarised in the bar chart. Moreover, the visualisation of first 9 labels are produced with the actual segmentations for comparison. ## Result -The outcome shows the significant impact of the choice of loss function in the performance of model. It was found that with other loss functions, the model performs poorly on assigning correct labels to small segments. Specifically, segment label 4 (rectum) often suffered from poor performance as it was often ignored by the model in optimising the segmentaion of corresponding label. However, the addition of weighted cross-entropy loss seem to enforce the model to classify segments correctly, which might have led to an improvement in performance. +

+ The Training Progress with Dice Loss + CE +
+ Figure 3: The Training Progress with Dice Loss + 0.2CE +

+ +

+ Example of Predicted Labels produced by the Model +
+ Figure 4: Example of Ground Truth Labels used for Testing +

+ +

+ Example of Predicted Labels produced by the Model +
+ Figure 5: Example of Predicted Labels produced by the model +

+ +

+ The Final Dice Scores achieved by the Model for Each Label +
+ Figure 6: The Final Dice Scores achieved by the Model for Each Label +

+ +The outcome shows the significant impact of the choice of loss function in the performance of model. It was found that with other loss functions, the model performs poorly on assigning correct labels to small segments. Specifically, segment label 4 (rectum) often suffered from poor performance as it was often ignored by the model in optimising the segmentaion of corresponding label. However, the addition of weighted cross-entropy loss seem to enforce the model to classify segments correctly, which might seem to cause a tremendous improvement in performance. The final model produces segment predictions with dice scores greater than 0.8 each, which is an astonishing performance from where it started off. ## Discussion @@ -141,116 +165,12 @@ Improved 3D UNet is a powerful architecture which makes complex image-processing ## Dependencies -# This file may be used to create an environment using: -# $ conda create --name --file -# platform: linux-64 -_libgcc_mutex=0.1=main -_openmp_mutex=5.1=1_gnu -blas=1.0=mkl -brotli-python=1.0.9=py312h6a678d5_8 -bzip2=1.0.8=h5eee18b_6 -ca-certificates=2024.9.24=h06a4308_0 -certifi=2024.8.30=py312h06a4308_0 -charset-normalizer=3.3.2=pyhd3eb1b0_0 -contourpy=1.3.0=pypi_0 -cuda-cudart=11.8.89=0 -cuda-cupti=11.8.87=0 -cuda-libraries=11.8.0=0 -cuda-nvrtc=11.8.89=0 -cuda-nvtx=11.8.86=0 -cuda-runtime=11.8.0=0 -cuda-version=12.6=3 -cycler=0.12.1=pypi_0 -expat=2.6.3=h6a678d5_0 -ffmpeg=4.3=hf484d3e_0 -filelock=3.13.1=py312h06a4308_0 -fonttools=4.54.1=pypi_0 -freetype=2.12.1=h4a9f257_0 -fsspec=2024.10.0=pypi_0 -giflib=5.2.2=h5eee18b_0 -gmp=6.2.1=h295c915_3 -gnutls=3.6.15=he1e5248_0 -idna=3.7=py312h06a4308_0 -intel-openmp=2023.1.0=hdb19cb5_46306 -jinja2=3.1.4=py312h06a4308_0 -joblib=1.4.2=pypi_0 -jpeg=9e=h5eee18b_3 -kiwisolver=1.4.7=pypi_0 -lame=3.100=h7b6447c_0 -lcms2=2.12=h3be6417_0 -ld_impl_linux-64=2.40=h12ee557_0 -lerc=3.0=h295c915_0 -libcublas=11.11.3.6=0 -libcufft=10.9.0.58=0 -libcufile=1.11.1.6=0 -libcurand=10.3.7.77=0 -libcusolver=11.4.1.48=0 -libcusparse=11.7.5.86=0 -libdeflate=1.17=h5eee18b_1 -libffi=3.4.4=h6a678d5_1 -libgcc-ng=11.2.0=h1234567_1 -libgomp=11.2.0=h1234567_1 -libiconv=1.16=h5eee18b_3 -libidn2=2.3.4=h5eee18b_0 -libjpeg-turbo=2.0.0=h9bf148f_0 -libnpp=11.8.0.86=0 -libnvjpeg=11.9.0.86=0 -libpng=1.6.39=h5eee18b_0 -libstdcxx-ng=11.2.0=h1234567_1 -libtasn1=4.19.0=h5eee18b_0 -libtiff=4.5.1=h6a678d5_0 -libunistring=0.9.10=h27cfd23_0 -libuuid=1.41.5=h5eee18b_0 -libwebp=1.3.2=h11a3e52_0 -libwebp-base=1.3.2=h5eee18b_1 -llvm-openmp=14.0.6=h9e868ea_0 -lz4-c=1.9.4=h6a678d5_1 -markupsafe=2.1.3=py312h5eee18b_0 -matplotlib=3.9.2=pypi_0 -mkl=2023.1.0=h213fc3f_46344 -mkl-service=2.4.0=py312h5eee18b_1 -mkl_fft=1.3.10=py312h5eee18b_0 -mkl_random=1.2.7=py312h526ad5a_0 -monai=1.4.0=pypi_0 -mpmath=1.3.0=py312h06a4308_0 -ncurses=6.4=h6a678d5_0 -nettle=3.7.3=hbbd107a_1 -networkx=3.2.1=py312h06a4308_0 +matplotlib=3.9.2 +monai=1.4.0 nibabel=5.3.2=pypi_0 -numpy=1.26.4=pypi_0 -openh264=2.1.1=h4ff587b_0 -openjpeg=2.5.2=he7f1fd0_0 -openssl=3.0.15=h5eee18b_0 -packaging=24.1=pypi_0 -pillow=10.4.0=py312h5eee18b_0 -pip=24.2=py312h06a4308_0 -pyparsing=3.2.0=pypi_0 -pysocks=1.7.1=py312h06a4308_0 -python=3.12.7=h5148396_0 -python-dateutil=2.9.0.post0=pypi_0 -pytorch=2.5.0=py3.12_cuda11.8_cudnn9.1.0_0 -pytorch-cuda=11.8=h7e8668a_6 -pytorch-mutex=1.0=cuda -pyyaml=6.0.2=py312h5eee18b_0 -readline=8.2=h5eee18b_0 -requests=2.32.3=py312h06a4308_0 +pytorch=2.5.0 scikit-learn=1.5.2=pypi_0 -scipy=1.14.1=pypi_0 -setuptools=75.1.0=py312h06a4308_0 -six=1.16.0=pypi_0 -sqlite=3.45.3=h5eee18b_0 -sympy=1.13.1=pypi_0 -tbb=2021.8.0=hdb19cb5_0 -threadpoolctl=3.5.0=pypi_0 -tk=8.6.14=h39e8969_0 -torchaudio=2.5.0=py312_cu118 -torchtriton=3.1.0=py312 -torchvision=0.20.0=py312_cu118 -typing_extensions=4.11.0=py312h06a4308_0 -tzdata=2024b=h04d1e81_0 -urllib3=2.2.3=py312h06a4308_0 -wheel=0.44.0=py312h06a4308_0 -xz=5.4.6=h5eee18b_1 -yaml=0.2.5=h7b6447c_0 -zlib=1.2.13=h5eee18b_1 -zstd=1.5.6=hc292b87_0 +torchaudio=2.5.0 +torchvision=0.20.0 + +For more details, refer to `requirements.txt` diff --git a/recognition/47049358/train.py b/recognition/47049358/train.py index 5292e3f06..28e293b8e 100644 --- a/recognition/47049358/train.py +++ b/recognition/47049358/train.py @@ -27,7 +27,7 @@ __email__ = "s4704935@student.uq.edu.au" __status__ = "Committed" -NUM_EPOCHS = 1 +NUM_EPOCHS = 300 BATCH_SIZE = 2 LEARNING_RATE = 5e-4 WEIGHT_DECAY = 1e-5 @@ -101,6 +101,8 @@ def train(model: nn.Module, train_loader: DataLoader, criterion, num_epochs: int model.to(device) model.train() + dice = DiceLoss(batch=True).to(device) + training_dice_coefs = np.zeros(NUM_EPOCHS) seg_0_dice_coefs = np.zeros(NUM_EPOCHS) seg_1_dice_coefs = np.zeros(NUM_EPOCHS) @@ -136,7 +138,8 @@ def train(model: nn.Module, train_loader: DataLoader, criterion, num_epochs: int scaler.step(optimiser) scaler.update() - running_dice += 1 - loss.item() + dice_batch = dice(outputs, labels) + running_dice += 1 - dice_batch.item() scheduler.step() From 7a335525653005b01a738c1fe5612ae9c6863c01 Mon Sep 17 00:00:00 2001 From: Selinuntius02 <120080805+Selinuntius02@users.noreply.github.com> Date: Sun, 27 Oct 2024 22:52:51 +1000 Subject: [PATCH 098/102] images for documentation --- recognition/47049358/.gitignore | 7 +++++-- .../dice_coefs_test_dice_ce_loss.png | Bin 0 -> 16351 bytes .../example_labels_and_images.png | Bin 0 -> 1451232 bytes .../ground_truths_dice_ce_loss.png | Bin 0 -> 229298 bytes .../documentation/model_architecture.png | Bin 0 -> 343183 bytes .../predictions_dice_ce_loss.png | Bin 0 -> 228744 bytes ...et_dice_coefs_over_epochs_dice_ce_loss.png | Bin 0 -> 77302 bytes 7 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 recognition/47049358/documentation/dice_coefs_test_dice_ce_loss.png create mode 100644 recognition/47049358/documentation/example_labels_and_images.png create mode 100644 recognition/47049358/documentation/ground_truths_dice_ce_loss.png create mode 100644 recognition/47049358/documentation/model_architecture.png create mode 100644 recognition/47049358/documentation/predictions_dice_ce_loss.png create mode 100644 recognition/47049358/documentation/unet_dice_coefs_over_epochs_dice_ce_loss.png diff --git a/recognition/47049358/.gitignore b/recognition/47049358/.gitignore index db8326159..89f90e6ac 100644 --- a/recognition/47049358/.gitignore +++ b/recognition/47049358/.gitignore @@ -9,10 +9,13 @@ semantic_MRs_anon *.txt -*.png +Images + +rangpur_outputs *.sh *.out -*.pdf \ No newline at end of file +*.pdf + diff --git a/recognition/47049358/documentation/dice_coefs_test_dice_ce_loss.png b/recognition/47049358/documentation/dice_coefs_test_dice_ce_loss.png new file mode 100644 index 0000000000000000000000000000000000000000..98c4671d52e26ac29f4b50acd5fdd44f720fab26 GIT binary patch literal 16351 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 G_kRGre`weM literal 0 HcmV?d00001 diff --git a/recognition/47049358/documentation/example_labels_and_images.png b/recognition/47049358/documentation/example_labels_and_images.png new file mode 100644 index 0000000000000000000000000000000000000000..7fc154c95cacfaa203b0aebaa205e945946b5145 GIT binary patch literal 1451232 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

7;9Gn2 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 z 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

fK#odp`8axU`P{u#(Sy0f zBlNC<=3h4ura(d&)rdBHr24z?460oiQndqaPtAlYwDa`OAI`!!%=C6<<~Yp96U>tj z1stj8yRi9`{0zyG6`6LTOu*d?0qrzMUm{*rXNu>n#dT+|xzSA0X1)Kb^SsUDT2YcU z%jg)zQhjfCclp)^$dkTBN>(h}f)%jma@`-DFvKv1v2)Cwq6k28lssb=ZA4$LHn}1L zd1_$DY9AxwPP%lIMeSU&Vj)a5*1H`Qx)wQ_{k<~K>5f1IV#aStC33F3f1c&hs^mRO ztj$-@XFN{C@EtjJo?aD$E_4I*2Wi7AzlYQM0aVP`AOo�hoD;klA%XGBnLTXSyDv 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

5vr|V`#C$Vh?=bM1>L^r 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 z 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

G#=Y%HKds$YIV4x=DJ|qa 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