{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":14774,"databundleVersionId":875431},{"sourceType":"modelInstanceVersion","sourceId":821749,"databundleVersionId":16502414,"modelInstanceId":624502,"modelId":636345}],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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\n# import numpy as np # linear algebra\n# import 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\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\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","trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:33:57.367847Z","iopub.execute_input":"2026-04-07T16:33:57.368624Z","iopub.status.idle":"2026-04-07T16:33:57.372797Z","shell.execute_reply.started":"2026-04-07T16:33:57.368589Z","shell.execute_reply":"2026-04-07T16:33:57.371885Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Imports here\nfrom __future__ import print_function, division\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom torch.utils import data\nimport torch\nfrom torch import nn\nfrom torch import optim\nimport torchvision\nimport torch.nn.functional as F\nfrom torchvision import datasets, transforms, models\nimport torchvision.models as models\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torch.utils.data import Dataset, DataLoader\nfrom skimage import io, transform\nimport torch.utils.data as data_utils\nfrom PIL import Image, ImageFile\nimport json\nfrom torch.optim import lr_scheduler\nimport time\nimport os\nimport argparse\nimport copy\nimport pandas as pd\nImageFile.LOAD_TRUNCATED_IMAGES = True\nimport cv2\n# Import useful sklearn functions\nimport sklearn\nfrom sklearn.metrics import cohen_kappa_score, accuracy_score\n\nimport time\nfrom tqdm import tqdm_notebook\n\nimport os\nprint(os.listdir(\"/kaggle/input/competitions\"))\nbase_dir = \"/kaggle/input/competitions/aptos2019-blindness-detection/\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:33:57.374341Z","iopub.execute_input":"2026-04-07T16:33:57.375026Z","iopub.status.idle":"2026-04-07T16:34:03.335952Z","shell.execute_reply.started":"2026-04-07T16:33:57.374999Z","shell.execute_reply":"2026-04-07T16:34:03.335278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import seaborn as sns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:03.337040Z","iopub.execute_input":"2026-04-07T16:34:03.337564Z","iopub.status.idle":"2026-04-07T16:34:03.762001Z","shell.execute_reply.started":"2026-04-07T16:34:03.337535Z","shell.execute_reply":"2026-04-07T16:34:03.761049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_csv = pd.read_csv('/kaggle/input/competitions/aptos2019-blindness-detection/train.csv')\ntest_csv = pd.read_csv('/kaggle/input/competitions/aptos2019-blindness-detection/test.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:03.763165Z","iopub.execute_input":"2026-04-07T16:34:03.763526Z","iopub.status.idle":"2026-04-07T16:34:03.785224Z","shell.execute_reply.started":"2026-04-07T16:34:03.763485Z","shell.execute_reply":"2026-04-07T16:34:03.784577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Train Size = {}'.format(len(train_csv)))\nprint('Public Test Size = {}'.format(len(test_csv)))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:03.787587Z","iopub.execute_input":"2026-04-07T16:34:03.787919Z","iopub.status.idle":"2026-04-07T16:34:03.792738Z","shell.execute_reply.started":"2026-04-07T16:34:03.787892Z","shell.execute_reply":"2026-04-07T16:34:03.791876Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_csv.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:03.793877Z","iopub.execute_input":"2026-04-07T16:34:03.794195Z","iopub.status.idle":"2026-04-07T16:34:03.829019Z","shell.execute_reply.started":"2026-04-07T16:34:03.794171Z","shell.execute_reply":"2026-04-07T16:34:03.828252Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"counts = train_csv['diagnosis'].value_counts()\nclass_list = ['No DR', 'Mild', 'Moderate', 'Severe', 'Proliferate']\nfor i,x in enumerate(class_list):\n    counts[x] = counts.pop(i)\n\nplt.figure(figsize=(10,5))\nsns.barplot(\n    x=counts.index,\n    y=counts.values,\n    hue=counts.index,\n    palette='bright',\n    legend=False\n)\nplt.title('Distribution of Output Classes')\nplt.ylabel('Number of Occurrences', fontsize=12)\nplt.xlabel('Target Classes', fontsize=12)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:03.830008Z","iopub.execute_input":"2026-04-07T16:34:03.830417Z","iopub.status.idle":"2026-04-07T16:34:04.200888Z","shell.execute_reply.started":"2026-04-07T16:34:03.830353Z","shell.execute_reply":"2026-04-07T16:34:04.200155Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig = plt.figure(figsize=(30, 6))\n# display 20 images\ntrain_imgs = os.listdir(base_dir+\"/train_images\")\nfor idx, img in enumerate(np.random.choice(train_imgs, 16)):\n    ax = fig.add_subplot(2, 16//2, idx+1, xticks=[], yticks=[])\n    im = Image.open(base_dir+\"/train_images/\" + img)\n    plt.imshow(im)\n    lab = train_csv.loc[train_csv['id_code'] == img.split('.')[0], 'diagnosis'].values[0]\n    ax.set_title('Severity: %s'%lab)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:04.201899Z","iopub.execute_input":"2026-04-07T16:34:04.202282Z","iopub.status.idle":"2026-04-07T16:34:13.530146Z","shell.execute_reply.started":"2026-04-07T16:34:04.202254Z","shell.execute_reply":"2026-04-07T16:34:13.528925Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig = plt.figure(figsize=(30, 6))\n# display 20 images\ntest_imgs = os.listdir(base_dir+\"/test_images\")\nfor idx, img in enumerate(np.random.choice(test_imgs, 16)):\n    ax = fig.add_subplot(2, 16//2, idx+1, xticks=[], yticks=[])\n    im = Image.open(base_dir+\"/test_images/\" + img)\n    plt.imshow(im)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:13.531546Z","iopub.execute_input":"2026-04-07T16:34:13.531917Z","iopub.status.idle":"2026-04-07T16:34:18.423122Z","shell.execute_reply.started":"2026-04-07T16:34:13.531888Z","shell.execute_reply":"2026-04-07T16:34:18.421757Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Our own custom class for datasets\nclass CreateDataset(Dataset):\n    def __init__(self, df_data, data_dir = '../input/', transform=None):\n        super().__init__()\n        self.df = df_data.values\n        self.data_dir = data_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, index):\n        img_name,label = self.df[index]\n        img_path = os.path.join(self.data_dir, img_name+'.png')\n        image = cv2.imread(img_path)\n        if self.transform is not None:\n            image = self.transform(image)\n        return image, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.424712Z","iopub.execute_input":"2026-04-07T16:34:18.425151Z","iopub.status.idle":"2026-04-07T16:34:18.434754Z","shell.execute_reply.started":"2026-04-07T16:34:18.425099Z","shell.execute_reply":"2026-04-07T16:34:18.433658Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_transforms = transforms.Compose([\n    transforms.ToPILImage(),\n    transforms.Resize((224, 224)),\n    transforms.RandomHorizontalFlip(p=0.4),\n    #transforms.ColorJitter(brightness=2, contrast=2),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.436127Z","iopub.execute_input":"2026-04-07T16:34:18.436704Z","iopub.status.idle":"2026-04-07T16:34:18.447259Z","shell.execute_reply.started":"2026-04-07T16:34:18.436652Z","shell.execute_reply":"2026-04-07T16:34:18.446356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_transforms = transforms.Compose([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])])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.448766Z","iopub.execute_input":"2026-04-07T16:34:18.449721Z","iopub.status.idle":"2026-04-07T16:34:18.461781Z","shell.execute_reply.started":"2026-04-07T16:34:18.449690Z","shell.execute_reply":"2026-04-07T16:34:18.460732Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_path = \"/kaggle/input/competitions/aptos2019-blindness-detection/train_images/\"\ntest_path = \"/kaggle/input/competitions/aptos2019-blindness-detection/test_images/\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.462860Z","iopub.execute_input":"2026-04-07T16:34:18.463212Z","iopub.status.idle":"2026-04-07T16:34:18.474849Z","shell.execute_reply.started":"2026-04-07T16:34:18.463168Z","shell.execute_reply":"2026-04-07T16:34:18.473982Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data = CreateDataset(df_data=train_csv, data_dir=train_path, transform=train_transforms)\ntest_data = CreateDataset(df_data=test_csv, data_dir=test_path, transform=test_transforms)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.478886Z","iopub.execute_input":"2026-04-07T16:34:18.479434Z","iopub.status.idle":"2026-04-07T16:34:18.491477Z","shell.execute_reply.started":"2026-04-07T16:34:18.479368Z","shell.execute_reply":"2026-04-07T16:34:18.490642Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"valid_size = 0.2\nnum_train = len(train_data)\nindices = list(range(num_train))\nnp.random.shuffle(indices)\nsplit = int(np.floor(valid_size * num_train))\ntrain_idx, valid_idx = indices[split:], indices[:split]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.492416Z","iopub.execute_input":"2026-04-07T16:34:18.492712Z","iopub.status.idle":"2026-04-07T16:34:18.500087Z","shell.execute_reply.started":"2026-04-07T16:34:18.492668Z","shell.execute_reply":"2026-04-07T16:34:18.499297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_sampler = SubsetRandomSampler(train_idx)\nvalid_sampler = SubsetRandomSampler(valid_idx)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.501358Z","iopub.execute_input":"2026-04-07T16:34:18.501831Z","iopub.status.idle":"2026-04-07T16:34:18.512624Z","shell.execute_reply.started":"2026-04-07T16:34:18.501802Z","shell.execute_reply":"2026-04-07T16:34:18.511649Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"trainloader = torch.utils.data.DataLoader(train_data, batch_size=64,sampler=train_sampler)\nvalidloader = torch.utils.data.DataLoader(train_data, batch_size=64, sampler=valid_sampler)\ntestloader = torch.utils.data.DataLoader(test_data, batch_size=64)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.513795Z","iopub.execute_input":"2026-04-07T16:34:18.514137Z","iopub.status.idle":"2026-04-07T16:34:18.526769Z","shell.execute_reply.started":"2026-04-07T16:34:18.514085Z","shell.execute_reply":"2026-04-07T16:34:18.526038Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"training examples contain : {len(train_data)}\")\nprint(f\"testing examples contain : {len(test_data)}\")\n\nprint(len(trainloader))\nprint(len(validloader))\nprint(len(testloader))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.527729Z","iopub.execute_input":"2026-04-07T16:34:18.528348Z","iopub.status.idle":"2026-04-07T16:34:18.543025Z","shell.execute_reply.started":"2026-04-07T16:34:18.528317Z","shell.execute_reply":"2026-04-07T16:34:18.542267Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# LOAD ONE BATCH OF TESTING SET TO CHECK THE IMAGES AND THEIR LABELS\nimages, labels = next(iter(trainloader))\n\n# Checking shape of image\nprint(f\"Image shape : {images.shape}\")\nprint(f\"Label shape : {labels.shape}\")\n\n# denormalizing images\ndef imshow(inp, title=None):\n    \"\"\"Imshow for Tensor.\"\"\"\n    inp = inp.numpy().transpose((1, 2, 0))\n    mean = np.array([0.485, 0.456, 0.406])\n    std = np.array([0.229, 0.224, 0.225])\n    inp = std * inp + mean\n    inp = np.clip(inp, 0, 1)\n    plt.imshow(inp)\n    if title is not None:\n        plt.title(title)\n    plt.pause(0.001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:18.544152Z","iopub.execute_input":"2026-04-07T16:34:18.544511Z","iopub.status.idle":"2026-04-07T16:34:25.560640Z","shell.execute_reply.started":"2026-04-07T16:34:18.544473Z","shell.execute_reply":"2026-04-07T16:34:25.559798Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# plotting the images of loaded batch with given fig size and frame data    \nimport torchvision\nimport matplotlib.pyplot as plt\nimport numpy as np\ngrid = torchvision.utils.make_grid(images, nrow = 20, padding = 2)\nplt.figure(figsize = (20, 20))  \nplt.imshow(np.transpose(grid, (1, 2, 0)))   \nprint('labels:', labels)    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:25.561783Z","iopub.execute_input":"2026-04-07T16:34:25.562176Z","iopub.status.idle":"2026-04-07T16:34:27.009856Z","shell.execute_reply.started":"2026-04-07T16:34:25.562142Z","shell.execute_reply":"2026-04-07T16:34:27.008868Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_names = ['No DR', 'Mild', 'Moderate', 'Severe', 'Proliferative DR']\n\nimages, labels = next(iter(trainloader))\nout = torchvision.utils.make_grid(images)\nimshow(out, title=[class_names[x] for x in labels])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:27.010992Z","iopub.execute_input":"2026-04-07T16:34:27.011298Z","iopub.status.idle":"2026-04-07T16:34:38.210414Z","shell.execute_reply.started":"2026-04-07T16:34:27.011271Z","shell.execute_reply":"2026-04-07T16:34:38.209559Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_on_gpu = torch.cuda.is_available()\n\nif not train_on_gpu:\n    print('CUDA is not available.  Training on CPU ...')\nelse:\n    print('CUDA is available!  Training on GPU ...')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:38.211582Z","iopub.execute_input":"2026-04-07T16:34:38.211966Z","iopub.status.idle":"2026-04-07T16:34:38.467888Z","shell.execute_reply.started":"2026-04-07T16:34:38.211925Z","shell.execute_reply":"2026-04-07T16:34:38.466853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nmodel = models.resnet152(pretrained=True) \n\nnum_ftrs = model.fc.in_features \nout_ftrs = 5 \n  \nmodel.fc = nn.Sequential(nn.Linear(num_ftrs, 512),nn.ReLU(),nn.Linear(512,out_ftrs),nn.LogSoftmax(dim=1))\n\ncriterion = nn.NLLLoss()\noptimizer = torch.optim.Adam(filter(lambda p:p.requires_grad,model.parameters()) , lr = 0.00001) \n\nscheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)\nmodel.to(device);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:38.469121Z","iopub.execute_input":"2026-04-07T16:34:38.469533Z","iopub.status.idle":"2026-04-07T16:34:41.436882Z","shell.execute_reply.started":"2026-04-07T16:34:38.469492Z","shell.execute_reply":"2026-04-07T16:34:41.436085Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_save_name = 'classifier.pt'\npath = F\"/kaggle/working/{model_save_name}\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:41.438161Z","iopub.execute_input":"2026-04-07T16:34:41.438566Z","iopub.status.idle":"2026-04-07T16:34:41.442595Z","shell.execute_reply.started":"2026-04-07T16:34:41.438521Z","shell.execute_reply":"2026-04-07T16:34:41.441685Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# to unfreeze more layers \nfor name,child in model.named_children():\n  if name in ['layer2','layer3','layer4','fc']:\n    print(name + 'is unfrozen')\n    for param in child.parameters():\n      param.requires_grad = True\n  else:\n    print(name + 'is frozen')\n    for param in child.parameters():\n      param.requires_grad = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:41.443599Z","iopub.execute_input":"2026-04-07T16:34:41.444052Z","iopub.status.idle":"2026-04-07T16:34:41.461200Z","shell.execute_reply.started":"2026-04-07T16:34:41.444024Z","shell.execute_reply":"2026-04-07T16:34:41.460443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = torch.optim.Adam(filter(lambda p:p.requires_grad,model.parameters()) , lr = 0.000001) \nscheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:41.462149Z","iopub.execute_input":"2026-04-07T16:34:41.462625Z","iopub.status.idle":"2026-04-07T16:34:41.478681Z","shell.execute_reply.started":"2026-04-07T16:34:41.462583Z","shell.execute_reply":"2026-04-07T16:34:41.477631Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# def load_model(path):\n#   checkpoint = torch.load(path)\n#   model.load_state_dict(checkpoint['model_state_dict'])\n#   optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n#   return model\ndef load_model(path):\n    checkpoint = torch.load(path, weights_only=False)  \n    model.load_state_dict(checkpoint['model_state_dict'])\n    optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:41.479826Z","iopub.execute_input":"2026-04-07T16:34:41.480447Z","iopub.status.idle":"2026-04-07T16:34:41.493519Z","shell.execute_reply.started":"2026-04-07T16:34:41.480403Z","shell.execute_reply":"2026-04-07T16:34:41.492423Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = load_model(\"/kaggle/input/models/longvu1611/kernel4f121f3247/pytorch/default/1/classifier.pt\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:41.494730Z","iopub.execute_input":"2026-04-07T16:34:41.495147Z","iopub.status.idle":"2026-04-07T16:34:47.420602Z","shell.execute_reply.started":"2026-04-07T16:34:41.495091Z","shell.execute_reply":"2026-04-07T16:34:47.419849Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:47.421668Z","iopub.execute_input":"2026-04-07T16:34:47.422032Z","iopub.status.idle":"2026-04-07T16:34:47.431649Z","shell.execute_reply.started":"2026-04-07T16:34:47.422002Z","shell.execute_reply":"2026-04-07T16:34:47.430935Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pytorch_total_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\nprint(\"Number of trainable parameters: \\n{}\".format(pytorch_total_params))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:47.432733Z","iopub.execute_input":"2026-04-07T16:34:47.433097Z","iopub.status.idle":"2026-04-07T16:34:47.478606Z","shell.execute_reply.started":"2026-04-07T16:34:47.433055Z","shell.execute_reply":"2026-04-07T16:34:47.477678Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# def train_and_test(e):\n#     epochs = e\n#     train_losses , test_losses, acc = [] , [], []\n#     valid_loss_min = np.Inf \n#     model.train()\n#     print(\"Model Training started.....\")\n#     for epoch in range(epochs):\n#       running_loss = 0\n#       batch = 0\n#       for images , labels in trainloader:\n#         images, labels = images.to(device), labels.to(device)\n#         optimizer.zero_grad()\n#         outputs = model(images)\n#         loss = criterion(outputs,labels)\n#         loss.backward()\n#         optimizer.step()\n#         running_loss += loss.item()\n#         batch += 1\n#         if batch % 10 == 0:\n#             print(f\" epoch {epoch + 1} batch {batch} completed\") \n#       test_loss = 0\n#       accuracy = 0\n#       with torch.no_grad():\n#         print(f\"validation started for {epoch + 1}\")\n#         model.eval() \n#         for images , labels in validloader:\n#           images, labels = images.to(device), labels.to(device)\n#           logps = model(images) \n#           test_loss += criterion(logps,labels) \n#           ps = torch.exp(logps)\n#           top_p , top_class = ps.topk(1,dim=1)\n#           equals = top_class == labels.view(*top_class.shape)\n#           accuracy += torch.mean(equals.type(torch.FloatTensor))\n#       train_losses.append(running_loss/len(trainloader))\n#       test_losses.append(test_loss/len(validloader))\n#       acc.append(accuracy)\n#       scheduler.step()\n#       print(\"Epoch: {}/{}.. \".format(epoch+1, epochs),\"Training Loss: {:.3f}.. \".format(running_loss/len(trainloader)),\"Valid Loss: {:.3f}.. \".format(test_loss/len(validloader)),\n#         \"Valid Accuracy: {:.3f}\".format(accuracy/len(validloader)))\n#       model.train() \n#       if test_loss/len(validloader) <= valid_loss_min:\n#         print('Validation loss decreased ({:.6f} --> {:.6f}).  Saving model ...'.format(valid_loss_min,test_loss/len(validloader))) \n#         torch.save({\n#             'epoch': epoch,\n#             'model': model,\n#             'model_state_dict': model.state_dict(),\n#             'optimizer_state_dict': optimizer.state_dict(),\n#             'loss': valid_loss_min\n#             }, path)\n#         valid_loss_min = test_loss/len(validloader)    \n#     print('Training Completed Succesfully !')    \n#     return train_losses, test_losses, acc ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:47.480698Z","iopub.execute_input":"2026-04-07T16:34:47.481027Z","iopub.status.idle":"2026-04-07T16:34:47.495616Z","shell.execute_reply.started":"2026-04-07T16:34:47.480999Z","shell.execute_reply":"2026-04-07T16:34:47.494664Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_and_test(e):\n    epochs = e\n    train_losses, test_losses, acc = [], [], []\n    \n    valid_loss_min = np.inf   #  FIX NumPy 2.0\n    \n    print(\"Model Training started.....\")\n    \n    for epoch in range(epochs):\n        running_loss = 0\n        batch = 0\n        \n        ###################\n        # TRAIN\n        ###################\n        model.train()\n        \n        for images, labels in trainloader:\n            images, labels = images.to(device), labels.to(device)\n            \n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n            \n            running_loss += loss.item()\n            batch += 1\n            \n            if batch % 10 == 0:\n                print(f\"epoch {epoch+1} batch {batch} completed\")\n        \n        ###################\n        # VALIDATION\n        ###################\n        test_loss = 0\n        accuracy = 0\n        \n        model.eval()\n        with torch.no_grad():\n            print(f\"validation started for epoch {epoch+1}\")\n            \n            for images, labels in validloader:\n                images, labels = images.to(device), labels.to(device)\n                \n                logps = model(images)\n                loss = criterion(logps, labels)\n                test_loss += loss.item()   # FIX (phải dùng .item())\n                \n                ps = torch.exp(logps)\n                top_class = ps.argmax(dim=1)\n                accuracy += (top_class == labels).float().mean().item()  # FIX\n        \n        ###################\n        # METRICS\n        ###################\n        train_loss_epoch = running_loss / len(trainloader)\n        valid_loss_epoch = test_loss / len(validloader)\n        accuracy_epoch = accuracy / len(validloader)\n        \n        train_losses.append(train_loss_epoch)\n        test_losses.append(valid_loss_epoch)\n        acc.append(accuracy_epoch)\n        \n        scheduler.step()\n        \n        print(f\"Epoch {epoch+1}/{epochs}.. \"\n              f\"Train Loss: {train_loss_epoch:.3f}.. \"\n              f\"Valid Loss: {valid_loss_epoch:.3f}.. \"\n              f\"Valid Acc: {accuracy_epoch:.3f}\")\n        \n        ###################\n        # SAVE BEST MODEL\n        ###################\n        if valid_loss_epoch <= valid_loss_min:\n            print(f\"Validation loss decreased ({valid_loss_min:.6f} --> {valid_loss_epoch:.6f}). Saving model...\")\n            \n            torch.save({\n                'epoch': epoch,\n                'model_state_dict': model.state_dict(),   # bỏ lưu cả model (nhẹ hơn)\n                'optimizer_state_dict': optimizer.state_dict(),\n                'loss': valid_loss_epoch\n            }, path)\n            \n            valid_loss_min = valid_loss_epoch\n    \n    print('Training Completed Successfully!')\n    \n    return train_losses, test_losses, acc","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:47.496704Z","iopub.execute_input":"2026-04-07T16:34:47.497318Z","iopub.status.idle":"2026-04-07T16:34:47.514172Z","shell.execute_reply.started":"2026-04-07T16:34:47.497291Z","shell.execute_reply":"2026-04-07T16:34:47.513300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_losses, valid_losses, acc = train_and_test(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T16:34:47.515465Z","iopub.execute_input":"2026-04-07T16:34:47.515827Z","iopub.status.idle":"2026-04-07T17:14:02.800829Z","shell.execute_reply.started":"2026-04-07T16:34:47.515780Z","shell.execute_reply":"2026-04-07T17:14:02.800034Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(os.listdir(\"/kaggle/working\"))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T17:14:02.801847Z","iopub.execute_input":"2026-04-07T17:14:02.802195Z","iopub.status.idle":"2026-04-07T17:14:02.807116Z","shell.execute_reply.started":"2026-04-07T17:14:02.802149Z","shell.execute_reply":"2026-04-07T17:14:02.806443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\n\ntorch.save({\n    'model_state_dict': model.state_dict(),\n    'optimizer_state_dict': optimizer.state_dict()\n}, \"/kaggle/working/classifier.pt\")\n\nprint(\"Model saved!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T17:14:02.808032Z","iopub.execute_input":"2026-04-07T17:14:02.808569Z","iopub.status.idle":"2026-04-07T17:14:04.232961Z","shell.execute_reply.started":"2026-04-07T17:14:02.808543Z","shell.execute_reply":"2026-04-07T17:14:04.232074Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n%matplotlib inline\n%config InlineBackend.figure_format = 'retina'\n\nplt.plot(train_losses, label='train_')\nplt.plot(valid_losses, label='Validation loss')\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Loss\")\nplt.legend(frameon=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T17:14:04.234037Z","iopub.execute_input":"2026-04-07T17:14:04.234357Z","iopub.status.idle":"2026-04-07T17:14:04.434007Z","shell.execute_reply.started":"2026-04-07T17:14:04.234324Z","shell.execute_reply":"2026-04-07T17:14:04.433453Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%matplotlib inline\n%config InlineBackend.figure_format = 'retina'\n\nplt.plot(acc, label='accuracy')\nplt.legend(\"\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"accuracy\")\nplt.legend(frameon=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-07T17:14:04.434980Z","iopub.execute_input":"2026-04-07T17:14:04.435331Z","iopub.status.idle":"2026-04-07T17:14:04.627972Z","shell.execute_reply.started":"2026-04-07T17:14:04.435305Z","shell.execute_reply":"2026-04-07T17:14:04.627407Z"}},"outputs":[],"execution_count":null}]}