{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"sourceType":"competition"}],"dockerImageVersionId":30474,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/working/train_classes'):\n    print(dirname)\n    for filename in filenames: \n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-16T17:42:22.403902Z","iopub.execute_input":"2023-05-16T17:42:22.404619Z","iopub.status.idle":"2023-05-16T17:42:22.412122Z","shell.execute_reply.started":"2023-05-16T17:42:22.404583Z","shell.execute_reply":"2023-05-16T17:42:22.410614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd \nimport cv2\nimport matplotlib.pyplot as plt\nimport os\nfrom torch.utils.data import DataLoader, Dataset, WeightedRandomSampler\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nfrom torchvision import datasets, models, transforms\nimport time\nimport shutil\nimport random\nimport copy\nfrom PIL import Image","metadata":{"execution":{"iopub.status.busy":"2023-05-16T17:24:55.327168Z","iopub.execute_input":"2023-05-16T17:24:55.329122Z","iopub.status.idle":"2023-05-16T17:24:55.334741Z","shell.execute_reply.started":"2023-05-16T17:24:55.329095Z","shell.execute_reply":"2023-05-16T17:24:55.333814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# training images directory\nDATA_DIR = '/kaggle/input/aptos2019-blindness-detection'\nTRAIN_DIR = '/kaggle/working/train_classes'\nVALID_DIR = '/kaggle/working/valid_classes'\n# test images directory\nTEST_DIR = '/kaggle/input/aptos2019-blindness-detection/test_images'\n# classes\nCLASSES = {0: 'No DR', 1: 'Mild', 2: 'Moderate', 3: 'Severe', 4: 'Proliferative DR'}\nNUM_CLASSES = len(CLASSES)\nOUT_DIR = '/kaggle/working/'","metadata":{"execution":{"iopub.status.busy":"2023-05-07T19:31:08.361515Z","iopub.execute_input":"2023-05-07T19:31:08.362019Z","iopub.status.idle":"2023-05-07T19:31:08.368983Z","shell.execute_reply.started":"2023-05-07T19:31:08.36198Z","shell.execute_reply":"2023-05-07T19:31:08.367787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create train and validation folders containing classes' folders\nos.makedirs(TRAIN_DIR)\nos.makedirs(VALID_DIR)","metadata":{"execution":{"iopub.status.busy":"2023-05-06T16:44:33.608305Z","iopub.execute_input":"2023-05-06T16:44:33.608777Z","iopub.status.idle":"2023-05-06T16:44:33.662516Z","shell.execute_reply.started":"2023-05-06T16:44:33.608732Z","shell.execute_reply":"2023-05-06T16:44:33.660859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set the percentage of data to use for validation\nvalid_pct = 0.2\n# Get a list of all image files in the data folder\nimage_files = glob.glob(f\"{DATA_DIR}/train_images/*.png\")\n# Shuffle the image files randomly\nrandom.shuffle(image_files)\n\n# Split the image files into train and validation sets\nsplit_idx = int(len(image_files) * valid_pct)\nvalid_files = image_files[:split_idx]\ntrain_files = image_files[split_idx:]","metadata":{"execution":{"iopub.status.busy":"2023-05-06T16:44:33.663813Z","iopub.status.idle":"2023-05-06T16:44:33.664564Z","shell.execute_reply.started":"2023-05-06T16:44:33.664364Z","shell.execute_reply":"2023-05-06T16:44:33.664388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize a few transformed images\nfig, axs = plt.subplots(nrows=3, ncols=3, figsize=(8, 8))\nfor i, ax in enumerate(axs.flat):\n    idx = random.randint(0, dataset_sizes['train'])\n    img = cv2.imread(train_files[idx])\n    ax.imshow(img[:,:,::-1])\n    ax.set_title(f\"Image {idx}\")\n    ax.axis('off')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-07T19:59:50.920658Z","iopub.execute_input":"2023-05-07T19:59:50.921078Z","iopub.status.idle":"2023-05-07T19:59:56.39623Z","shell.execute_reply.started":"2023-05-07T19:59:50.921045Z","shell.execute_reply":"2023-05-07T19:59:56.395028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def crop_image_from_gray(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n    #         print(img1.shape,img2.shape,img3.shape)\n            img = np.stack([img1,img2,img3],axis=-1)\n    #         print(img.shape)\n        return img\n\ndef preprocess_image(image, sigmaX=10):\n#     image = cv2.imread(path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (512, 512))\n    image=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , sigmaX) ,-4 ,128)\n        \n    return image","metadata":{"execution":{"iopub.status.busy":"2023-05-16T17:29:38.076847Z","iopub.execute_input":"2023-05-16T17:29:38.078061Z","iopub.status.idle":"2023-05-16T17:29:38.089082Z","shell.execute_reply.started":"2023-05-16T17:29:38.078013Z","shell.execute_reply":"2023-05-16T17:29:38.088159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Read the CSV file containing the classe for each image\ncsv_path = '/kaggle/input/aptos2019-blindness-detection/train.csv'\ndf = pd.read_csv(csv_path)\n\n# Create a folder for each class in the train and validation folders \nfor folder_path in [TRAIN_DIR, VALID_DIR]:\n    for class_id, class_name in CLASSES.items():\n        class_dir = os.path.join(folder_path, class_name)\n        if not os.path.exists(class_dir):\n            os.makedirs(class_dir)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T17:40:33.936582Z","iopub.execute_input":"2023-05-16T17:40:33.936974Z","iopub.status.idle":"2023-05-16T17:40:33.971465Z","shell.execute_reply.started":"2023-05-16T17:40:33.936923Z","shell.execute_reply":"2023-05-16T17:40:33.970616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Move the images to their corresponding class folders in the train and validation paths\nfor images_paths, folder_path in [(train_files, TRAIN_DIR), (valid_files, VALID_DIR)]:\n    for image_path in images_paths:\n        image_id = os.path.basename(image_path)[:-4]\n        class_id = df[df['id_code'] == image_id].iloc[0]['diagnosis']\n        class_name = CLASSES[class_id]\n        dst_path = os.path.join(folder_path, class_name, image_id+'.png')\n#         shutil.copy(image_path, dst_path)\n        # Load the image\n        img = cv2.imread(image_path)\n        \n        # Apply pre-processing function to the image\n        preprocessed_img = preprocess_image(img)\n        \n        # Save the pre-processed image to the destination path\n        cv2.imwrite(dst_path, preprocessed_img)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T17:42:36.662141Z","iopub.execute_input":"2023-05-16T17:42:36.663864Z","iopub.status.idle":"2023-05-16T17:55:52.259364Z","shell.execute_reply.started":"2023-05-16T17:42:36.663818Z","shell.execute_reply":"2023-05-16T17:55:52.258296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define class weights\ntrain_class_weights = []\nvalid_class_weights = []\nfor (class_weights, img_dir, phase) in [(train_class_weights, TRAIN_DIR, 'Training'), (valid_class_weights, VALID_DIR, 'Validation')]:\n    print('\\nCounting {} images :'.format(phase))\n    for _, class_name in CLASSES.items():\n        class_dir = os.path.join(img_dir, class_name)\n        num_images = len(os.listdir(class_dir))\n        class_weights.append(1/num_images)\n        print('Class {}: {} images'.format(class_name, num_images))\n    \ntrain_class_weights = torch.FloatTensor(train_class_weights)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T17:56:11.492899Z","iopub.execute_input":"2023-05-16T17:56:11.493515Z","iopub.status.idle":"2023-05-16T17:56:11.505597Z","shell.execute_reply.started":"2023-05-16T17:56:11.493479Z","shell.execute_reply":"2023-05-16T17:56:11.504385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_images_per_class = 2\n# Create subplots to display the images\nfig, axs = plt.subplots(NUM_CLASSES, num_images_per_class, figsize=(6, 10))\nfor class_id, class_name in CLASSES.items():\n    class_dir = os.path.join(TRAIN_DIR, class_name)\n    # Get the list of image filenames in the class directory\n    image_files = os.listdir(class_dir)\n\n    # Randomly select a few images from the class directory\n    random_images = random.sample(image_files, num_images_per_class)\n\n    # Loop through each randomly selected image\n    for i, image_file in enumerate(random_images):\n        # Get the path to the current image\n        image_path = os.path.join(class_dir, image_file)\n        img = cv2.imread(image_path)\n        axs[class_id,i].imshow(img)\n        axs[class_id,i].axis('off')\n        axs[class_id,i].set_title(f\"Class = {CLASSES[class_id]}\")\n#     # Set the title of the subplots to the class name\n#     fig.suptitle(class_name)\n#     # Show the plot\n#     plt.show()\n    \nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-16T18:36:53.393688Z","iopub.execute_input":"2023-05-16T18:36:53.39411Z","iopub.status.idle":"2023-05-16T18:36:54.525895Z","shell.execute_reply.started":"2023-05-16T18:36:53.394075Z","shell.execute_reply":"2023-05-16T18:36:54.524837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2023-05-16T18:35:12.609982Z","iopub.execute_input":"2023-05-16T18:35:12.610719Z","iopub.status.idle":"2023-05-16T18:35:12.616415Z","shell.execute_reply.started":"2023-05-16T18:35:12.610679Z","shell.execute_reply":"2023-05-16T18:35:12.615467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Calculate the mean and standard deviation of the dataset\n# channels_sum = np.zeros(3)\n# channels_squared_sum = np.zeros(3)\n# for filepath in train_files:\n#     img = cv2.imread(filepath)[:,:,::-1]\n#     img = np.array(img)\n#     channels_sum += np.sum(img, axis=(0, 1))\n#     channels_squared_sum += np.sum(np.square(img), axis=(0, 1))\n# pixel_count = len(train_files) * img.shape[0] * img.shape[1]\n# mean = channels_sum / pixel_count\n# std = np.sqrt((channels_squared_sum / pixel_count) - np.square(mean))\n# print(\"Mean: \", mean)\n# print(\"Std: \", std)","metadata":{"execution":{"iopub.status.busy":"2023-05-07T21:21:13.999847Z","iopub.execute_input":"2023-05-07T21:21:14.000365Z","iopub.status.idle":"2023-05-07T21:38:08.070116Z","shell.execute_reply.started":"2023-05-07T21:21:14.000317Z","shell.execute_reply":"2023-05-07T21:38:08.068131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# channels_sum = np.zeros(3)\n# channels_squared_sum = np.zeros(3)\n# for filepath in valid_files:\n#     img = cv2.imread(filepath)[:,:,::-1]\n#     img = np.array(img)\n#     channels_sum += np.sum(img, axis=(0, 1))\n#     channels_squared_sum += np.sum(np.square(img), axis=(0, 1))\n# pixel_count = len(valid_files) * img.shape[0] * img.shape[1]\n# val_mean = channels_sum / pixel_count\n# val_std = np.sqrt((channels_squared_sum / pixel_count) - np.square(mean))\n# print(\"Val mean: \", val_mean)\n# print(\"Val std: \", val_std)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_transforms = {\n    'train': transforms.Compose([\n        transforms.RandomResizedCrop(size=232,scale=(0.8, 1.0)),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ]),\n    'val': transforms.Compose([\n        transforms.Resize(232),\n        transforms.CenterCrop(224),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ]),\n}","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:59:03.107038Z","iopub.execute_input":"2023-05-16T19:59:03.107422Z","iopub.status.idle":"2023-05-16T19:59:03.114682Z","shell.execute_reply.started":"2023-05-16T19:59:03.107389Z","shell.execute_reply":"2023-05-16T19:59:03.113729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_datasets = {\n    'train': datasets.ImageFolder(root=TRAIN_DIR, transform=data_transforms['train']),\n    'val': datasets.ImageFolder(root=VALID_DIR, transform=data_transforms['val'])}","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:59:09.934974Z","iopub.execute_input":"2023-05-16T19:59:09.935792Z","iopub.status.idle":"2023-05-16T19:59:09.960218Z","shell.execute_reply.started":"2023-05-16T19:59:09.935756Z","shell.execute_reply":"2023-05-16T19:59:09.959288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_sample_weights = [train_class_weights[label] for label in image_datasets['train'].targets]\nval_sample_weights = [valid_class_weights[label] for label in image_datasets['val'].targets]","metadata":{"execution":{"iopub.status.busy":"2023-05-16T18:38:46.418787Z","iopub.execute_input":"2023-05-16T18:38:46.419156Z","iopub.status.idle":"2023-05-16T18:38:46.43237Z","shell.execute_reply.started":"2023-05-16T18:38:46.419125Z","shell.execute_reply":"2023-05-16T18:38:46.43129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a sampler for each class\nsampler = {\n    'train' : WeightedRandomSampler(weights=train_sample_weights, num_samples=len(image_datasets['train']), replacement=True),\n    'val' : WeightedRandomSampler(weights=val_sample_weights, num_samples=len(image_datasets['val']), replacement=True),\n}","metadata":{"execution":{"iopub.status.busy":"2023-05-16T18:37:42.107694Z","iopub.execute_input":"2023-05-16T18:37:42.108083Z","iopub.status.idle":"2023-05-16T18:37:42.118608Z","shell.execute_reply.started":"2023-05-16T18:37:42.108049Z","shell.execute_reply":"2023-05-16T18:37:42.1175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a DataLoaders\ndataloaders = {\n    'train': torch.utils.data.DataLoader(image_datasets['train'], batch_size=BATCH_SIZE,\n                                             shuffle=False, num_workers=NUM_WORKERS, sampler=sampler['train']),\n    'val': torch.utils.data.DataLoader(image_datasets['val'], batch_size=BATCH_SIZE,\n                                             shuffle=False, num_workers=NUM_WORKERS, sampler=sampler['val'])\n              }\ndataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:59:17.861816Z","iopub.execute_input":"2023-05-16T19:59:17.862535Z","iopub.status.idle":"2023-05-16T19:59:17.869632Z","shell.execute_reply.started":"2023-05-16T19:59:17.862499Z","shell.execute_reply":"2023-05-16T19:59:17.86848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize a few transformed images\nfig, axs = plt.subplots(nrows=3, ncols=3, figsize=(8, 8))\nfor i, ax in enumerate(axs.flat):\n    img, label = image_datasets['train'][random.randint(0,dataset_sizes['train'])]\n    img = img.permute(1, 2, 0)\n#     ax.imshow(cv2.cvtColor(img.numpy(), cv2.COLOR_BGR2RGB))\n    ax.imshow(img)\n    ax.set_title(f\"Class {label}\")\n    ax.axis('off')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:59:24.044692Z","iopub.execute_input":"2023-05-16T19:59:24.045088Z","iopub.status.idle":"2023-05-16T19:59:25.131601Z","shell.execute_reply.started":"2023-05-16T19:59:24.045054Z","shell.execute_reply":"2023-05-16T19:59:25.130763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Load & train the model","metadata":{"execution":{"iopub.status.busy":"2023-05-06T11:22:50.218398Z","iopub.execute_input":"2023-05-06T11:22:50.218854Z","iopub.status.idle":"2023-05-06T11:22:50.226558Z","shell.execute_reply.started":"2023-05-06T11:22:50.218821Z","shell.execute_reply":"2023-05-06T11:22:50.225282Z"}}},{"cell_type":"code","source":"BATCH_SIZE = 8 # increase / decrease according to GPU memeory\nNUM_EPOCHS = 20 # number of epochs to train for\nNUM_WORKERS = 2\nLEARNING_RATE = 1e-3\nDEVICE = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')","metadata":{"execution":{"iopub.status.busy":"2023-05-16T18:43:07.216103Z","iopub.execute_input":"2023-05-16T18:43:07.216504Z","iopub.status.idle":"2023-05-16T18:43:07.222387Z","shell.execute_reply.started":"2023-05-16T18:43:07.216475Z","shell.execute_reply":"2023-05-16T18:43:07.221333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, criterion, optimizer, num_epochs=25 ):\n    train_loss = []\n    train_acc = []\n    valid_loss = []\n    valid_acc = []\n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_acc = 0.0\n    since = time.time()\n    \n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch+1, num_epochs))\n        print('-' * 10)\n\n        model.train()  # Set model to training mode\n\n        running_loss = 0.0\n        running_corrects = 0\n\n        # Iterate over data.\n        for batch_idx, (inputs, labels) in enumerate(dataloaders['train']):\n            inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)\n            # zero the parameter gradients\n            optimizer.zero_grad()\n            # forward\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n\n            # backward + optimize \n            loss.backward()\n            optimizer.step()\n\n            # statistics\n            _, preds = torch.max(outputs, 1)\n            running_loss += loss.item() * inputs.size(0)\n            running_corrects += torch.sum(preds == labels.data)\n                \n        epoch_loss = running_loss / dataset_sizes['train']\n        epoch_acc = running_corrects.double() / dataset_sizes['train']\n        \n        train_loss.append(epoch_loss)\n        train_acc.append(epoch_acc)\n\n        print('Train loss: {:.4f}, acc: {:.4f}'.format(epoch_loss,\n                                                    epoch_acc))\n        running_loss = 0.0\n        running_corrects = 0\n\n        with torch.no_grad():\n            # Set to evaluation mode\n            model.eval()\n            for batch_idx, (inputs, labels) in enumerate(dataloaders['val']):\n                inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)\n            \n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n        \n                _, preds = torch.max(outputs.data, 1)\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data)\n            \n        epoch_loss = running_loss / dataset_sizes['val']\n        epoch_acc = running_corrects.double() / dataset_sizes['val']\n        \n        valid_loss.append(epoch_loss)\n        valid_acc.append(epoch_acc)\n        \n        print('Val loss: {:.4f}, acc: {:.4f}'.format(epoch_loss,\n                                                    epoch_acc))\n        # deep copy the model\n        if epoch_acc > best_acc:\n            best_acc = epoch_acc\n            best_model_wts = copy.deepcopy(model.state_dict())\n        \n    time_elapsed = time.time() - since\n    print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s')\n    print(f'Best val Acc: {best_acc:4f}')\n\n    # load best model weights\n    model.load_state_dict(best_model_wts)\n    return model, train_loss, train_acc, valid_loss, valid_acc","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:20:16.425157Z","iopub.execute_input":"2023-05-09T06:20:16.42551Z","iopub.status.idle":"2023-05-09T06:20:16.437115Z","shell.execute_reply.started":"2023-05-09T06:20:16.425481Z","shell.execute_reply":"2023-05-09T06:20:16.436193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load pre-trained ResNet model and modify last layer\nmodel = torchvision.models.resnet50(weights='DEFAULT')\n\nfor param in model.parameters():\n    param.requires_grad = False\n\nnum_features = model.fc.in_features\nmodel.fc = nn.Sequential(\n#                 nn.AdaptiveAvgPool2d(num_features),\n#                 nn.Dropout(0.5),\n                nn.Linear(num_features, 2048),\n                nn.Dropout(0.2),\n                nn.Linear(2048, 2048),\n                nn.Dropout(0.2),\n                nn.ReLU(inplace=True),\n                nn.Linear(2048, NUM_CLASSES)\n            )\n\n# Set loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\n# optimizer = optim.SGD(model.parameters(), lr=LEARNING_RATE, momentum=0.9)\noptimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)\nmodel.to(DEVICE)\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:59:58.613Z","iopub.execute_input":"2023-05-16T19:59:58.613382Z","iopub.status.idle":"2023-05-16T19:59:59.200022Z","shell.execute_reply.started":"2023-05-16T19:59:58.613351Z","shell.execute_reply":"2023-05-16T19:59:59.199007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the model\nmodel_trained, train_loss, train_acc, valid_loss, valid_acc = train_model(model, criterion, optimizer, num_epochs=NUM_EPOCHS)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T20:00:12.508484Z","iopub.execute_input":"2023-05-16T20:00:12.508872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = None","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:16:41.664592Z","iopub.execute_input":"2023-05-16T19:16:41.665172Z","iopub.status.idle":"2023-05-16T19:16:41.670053Z","shell.execute_reply.started":"2023-05-16T19:16:41.665141Z","shell.execute_reply":"2023-05-16T19:16:41.669088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_transform = transforms.Compose([\n        transforms.Resize(256),\n        transforms.CenterCrop(232),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])\ndef predict(model, test_img_path):\n    transform = test_transform\n    test_img = Image.open(test_img_path)\n    test_img_tensor = transform(test_img).unsqueeze(0).to(DEVICE)\n    with torch.no_grad():\n        # Model outputs log probabilities\n        output = model(test_img_tensor)\n        _, pred = torch.max(output, 1)\n#         loss = criterion(output, labels)\n        \n        _, preds = torch.max(outputs.data, 1)\n#         running_loss = loss.item() * inputs.size(0)\n        running_corrects = torch.sum(preds == labels.data)\n    return output","metadata":{"execution":{"iopub.status.busy":"2023-05-08T20:12:53.182584Z","iopub.execute_input":"2023-05-08T20:12:53.182938Z","iopub.status.idle":"2023-05-08T20:12:53.190968Z","shell.execute_reply.started":"2023-05-08T20:12:53.182909Z","shell.execute_reply":"2023-05-08T20:12:53.189227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"row = []\nimage_id = os.path.basename('/kaggle/input/aptos2019-blindness-detection/train_images/001639a390f0.png')[:-4]\nrow.append(image_id)\npath = \"/kaggle/input/aptos2019-blindness-detection/train_images/000c1434d8d7.png\"\npred = predict(model, path)\nrow.append(pred)\nprint(\"Output class :  \", pred)","metadata":{"execution":{"iopub.status.busy":"2023-05-08T20:14:14.55168Z","iopub.execute_input":"2023-05-08T20:14:14.552139Z","iopub.status.idle":"2023-05-08T20:14:14.862177Z","shell.execute_reply.started":"2023-05-08T20:14:14.552102Z","shell.execute_reply":"2023-05-08T20:14:14.861126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cpt = 0\nfor _, (inputs, labels) in enumerate(dataloaders['val']):\n    print(labels)\n    cpt += 1\n    if cpt == 10:\n        break","metadata":{"execution":{"iopub.status.busy":"2023-05-08T21:56:20.814991Z","iopub.execute_input":"2023-05-08T21:56:20.815385Z","iopub.status.idle":"2023-05-08T21:56:31.556523Z","shell.execute_reply.started":"2023-05-08T21:56:20.815354Z","shell.execute_reply":"2023-05-08T21:56:31.555057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save the model\npath =  os.path.join(OUT_DIR, \"Resnet50.pth\")\ntorch.save(model.state_dict(), path)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T18:13:08.601918Z","iopub.execute_input":"2023-05-09T18:13:08.602264Z","iopub.status.idle":"2023-05-09T18:13:08.766505Z","shell.execute_reply.started":"2023-05-09T18:13:08.602236Z","shell.execute_reply":"2023-05-09T18:13:08.765549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot loss\nplt.title(\"Loss\")\nplt.plot(train_loss, label='training loss')\nplt.plot(valid_loss, label='validation loss')\nplt.xlabel('num_epochs', fontsize=12)\nplt.ylabel('loss', fontsize=12)\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:01:55.65637Z","iopub.execute_input":"2023-05-16T19:01:55.656793Z","iopub.status.idle":"2023-05-16T19:01:55.952812Z","shell.execute_reply.started":"2023-05-16T19:01:55.656758Z","shell.execute_reply":"2023-05-16T19:01:55.951869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot accuracy\nplt.title(\"Accuracy\")\nplt.plot([acc.item() for acc in train_acc], label='training accuracy')\nplt.plot([acc.item() for acc in valid_acc], label='validation accuracy')\nplt.xlabel('num_epochs', fontsize=12)\nplt.ylabel('accuracy', fontsize=12)\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-16T19:02:10.958997Z","iopub.execute_input":"2023-05-16T19:02:10.95973Z","iopub.status.idle":"2023-05-16T19:02:11.255925Z","shell.execute_reply.started":"2023-05-16T19:02:10.959693Z","shell.execute_reply":"2023-05-16T19:02:11.254889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_transforms['test'] = transforms.Compose([\n        transforms.Resize(256),\n        transforms.CenterCrop(232),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])","metadata":{"execution":{"iopub.status.busy":"2023-05-08T07:39:43.664101Z","iopub.execute_input":"2023-05-08T07:39:43.664539Z","iopub.status.idle":"2023-05-08T07:39:43.669919Z","shell.execute_reply.started":"2023-05-08T07:39:43.664505Z","shell.execute_reply":"2023-05-08T07:39:43.668972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(model, test_img_path):\n    transform = data_transforms['test']\n    test_img = cv2.imread(test_img_path)[:,:,::-1]\n    test_image_tensor = transform(test_img).unsqueeze(0).to(device)\n    with torch.no_grad():\n        model.eval()\n        # Model outputs log probabilities\n        output = model(image)\n        _, preds = torch.max(output, 1)\n        print(\"Output class :  \", preds)","metadata":{"execution":{"iopub.status.busy":"2023-05-08T20:12:39.250592Z","iopub.execute_input":"2023-05-08T20:12:39.250948Z","iopub.status.idle":"2023-05-08T20:12:39.25626Z","shell.execute_reply.started":"2023-05-08T20:12:39.250919Z","shell.execute_reply":"2023-05-08T20:12:39.255338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = []\ntest_files = glob.glob(f\"{TEST_DIR}/*.png\")\n","metadata":{"execution":{"iopub.status.busy":"2023-05-08T07:56:23.960996Z","iopub.execute_input":"2023-05-08T07:56:23.961416Z","iopub.status.idle":"2023-05-08T07:56:23.973229Z","shell.execute_reply.started":"2023-05-08T07:56:23.961383Z","shell.execute_reply":"2023-05-08T07:56:23.972229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!kaggle kernels output -p /kaggle/working/ResNet50.pth","metadata":{"execution":{"iopub.status.busy":"2023-05-08T08:15:00.598008Z","iopub.execute_input":"2023-05-08T08:15:00.59843Z","iopub.status.idle":"2023-05-08T08:15:01.978299Z","shell.execute_reply.started":"2023-05-08T08:15:00.598386Z","shell.execute_reply":"2023-05-08T08:15:01.977036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Delete folders\n# for _, class_name in CLASSES.items():\n#     class_dir = os.path.join(VALID_DIR, class_name)\n#     shutil.rmtree(class_dir)","metadata":{"execution":{"iopub.status.busy":"2023-05-16T17:39:38.701056Z","iopub.execute_input":"2023-05-16T17:39:38.701406Z","iopub.status.idle":"2023-05-16T17:39:39.013803Z","shell.execute_reply.started":"2023-05-16T17:39:38.701378Z","shell.execute_reply":"2023-05-16T17:39:39.012413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define data directory and data transforms\ndata_dir = '/path/to/data'\ndata_transforms = {\n    'train': transforms.Compose([\n        transforms.RandomResizedCrop(224),\n        transforms.RandomHorizontalFlip(),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ]),\n    'val': transforms.Compose([\n        transforms.Resize(256),\n        transforms.CenterCrop(224),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ]),\n    'test': transforms.Compose([\n        transforms.Resize(256),\n        transforms.CenterCrop(224),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])\n}\n\n# Load data\nimage_datasets = {x: ImageFolder(root=data_dir + '/' + x, transform=data_transforms[x])\n                  for x in ['train', 'val', 'test']}\ndataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=32, shuffle=True, num_workers=4)\n               for x in ['train', 'val', 'test']}\ndataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val', 'test']}\nclass_names = image_datasets['train'].classes\n\n# Load pre-trained ResNet model and modify last layer\nmodel = torchvision.models.resnet18(pretrained=True)\nnum_features = model.fc.in_features\nmodel.fc = nn.Linear(num_features, len(class_names))\n\n# Set loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n\n# Train the model\nmodel.to(device)\nnum_epochs = 10\nfor epoch in range(num_epochs):\n    for phase in ['train', 'val']:\n        if phase == 'train':\n            model.train()\n        else:\n            model.eval()\n        running_loss = 0.0\n        running_corrects = 0\n        for inputs, labels in dataloaders[phase]:\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            optimizer.zero_grad()\n            with torch.set_grad_enabled(phase == 'train'):\n                outputs = model(inputs)\n                _, preds = torch.max(outputs, 1)\n                loss = criterion(outputs, labels)\n                if phase == 'train':\n                    loss.backward()\n                    optimizer.step()\n            running_loss += loss.item() * inputs.size(0)\n            running_corrects += torch.sum(preds == labels.data)\n        epoch_loss = running_loss / dataset_sizes[phase]\n        epoch_acc = running_corrects.double() / dataset_sizes[phase]\n        print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))\n","metadata":{"execution":{"iopub.status.busy":"2023-05-06T16:44:36.407758Z","iopub.execute_input":"2023-05-06T16:44:36.408206Z","iopub.status.idle":"2023-05-06T16:44:36.570929Z"},"trusted":true},"execution_count":null,"outputs":[]}]}