{"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":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":4117,"databundleVersionId":46665}],"dockerImageVersionId":31329,"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/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\n\n# Use the kagglehub client library to attach Kaggle resources like competitions, datasets, and models to your session\n# Learn more about kagglehub: https://github.com/Kaggle/kagglehub/blob/main/README.md\n\nimport kagglehub\n# kagglehub.dataset_download('<owner>/<dataset-slug>')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.042295Z","iopub.execute_input":"2026-05-24T19:08:09.042709Z","iopub.status.idle":"2026-05-24T19:08:09.052733Z","shell.execute_reply.started":"2026-05-24T19:08:09.042668Z","shell.execute_reply":"2026-05-24T19:08:09.051901Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **IMPORTS**","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport torch\nimport random\nimport numpy as np\n\nfrom tqdm import tqdm \n\nimport torch.nn as nn\nimport torch.optim as optim\n\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom sklearn.neighbors import NearestNeighbors","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.054259Z","iopub.execute_input":"2026-05-24T19:08:09.054624Z","iopub.status.idle":"2026-05-24T19:08:09.062385Z","shell.execute_reply.started":"2026-05-24T19:08:09.054569Z","shell.execute_reply":"2026-05-24T19:08:09.061707Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **CONFIG**","metadata":{}},{"cell_type":"code","source":"CONFIG = {\n\n    \"image_size\": 64,\n    \"batch_size\": 32,\n\n    \"latent_dim\": 256,\n\n    \"epochs\": 100,\n\n    \"lr\": 0.0002,\n\n    \"num_classes\": 9,   # BIG2015 classes\n\n    \"device\": \"cuda\"\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.063287Z","iopub.execute_input":"2026-05-24T19:08:09.063573Z","iopub.status.idle":"2026-05-24T19:08:09.076289Z","shell.execute_reply.started":"2026-05-24T19:08:09.063550Z","shell.execute_reply":"2026-05-24T19:08:09.075688Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **DATASET**","metadata":{}},{"cell_type":"code","source":"DATASET_PATH = \"/kaggle/input/competitions/malware-classification\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.077467Z","iopub.execute_input":"2026-05-24T19:08:09.077743Z","iopub.status.idle":"2026-05-24T19:08:09.089182Z","shell.execute_reply.started":"2026-05-24T19:08:09.077721Z","shell.execute_reply":"2026-05-24T19:08:09.088499Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_df = pd.read_csv(\n    os.path.join(DATASET_PATH, \"trainLabels.csv\")\n)\n\nprint(labels_df.head())\n\ntransform = transforms.Compose([\n\n    transforms.ToTensor(),\n\n    transforms.Normalize((0.5,), (0.5,))\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.228153Z","iopub.execute_input":"2026-05-24T19:08:09.228434Z","iopub.status.idle":"2026-05-24T19:08:09.246381Z","shell.execute_reply.started":"2026-05-24T19:08:09.228412Z","shell.execute_reply":"2026-05-24T19:08:09.245530Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"os.makedirs(\n    \"/kaggle/working/malware_images\",\n    exist_ok=True\n)\n\ntrain_folder = \"/kaggle/input/competitions/malware-classification/train\"\n\nimage_output_dir = \"/kaggle/working/malware_images\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:11:05.468600Z","iopub.execute_input":"2026-05-24T19:11:05.469324Z","iopub.status.idle":"2026-05-24T19:11:05.473323Z","shell.execute_reply.started":"2026-05-24T19:11:05.469292Z","shell.execute_reply":"2026-05-24T19:11:05.472711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def bytes_to_image(byte_file, output_path):\n\n    with open(byte_file, 'r') as f:\n\n        lines = f.readlines()\n\n    hex_values = []\n\n    for line in lines:\n\n        parts = line.strip().split()[1:]\n\n        for p in parts:\n\n            if p == '??':\n\n                hex_values.append(0)\n\n            else:\n\n                hex_values.append(int(p, 16))\n\n    arr = np.array(hex_values, dtype=np.uint8)\n\n    width = 256\n\n    height = int(np.ceil(len(arr) / width))\n\n    padded = np.pad(\n        arr,\n        (0, width * height - len(arr)),\n        mode='constant'\n    )\n\n    image = padded.reshape(height, width)\n\n    image = cv2.resize(image, (64,64))\n\n    cv2.imwrite(output_path, image)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:11:08.922522Z","iopub.execute_input":"2026-05-24T19:11:08.922810Z","iopub.status.idle":"2026-05-24T19:11:08.928742Z","shell.execute_reply.started":"2026-05-24T19:11:08.922785Z","shell.execute_reply":"2026-05-24T19:11:08.927852Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels_df = pd.read_csv(\n    \"/kaggle/input/competitions/malware-classification/trainLabels.csv\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:11:14.329344Z","iopub.execute_input":"2026-05-24T19:11:14.330068Z","iopub.status.idle":"2026-05-24T19:11:14.341615Z","shell.execute_reply.started":"2026-05-24T19:11:14.330037Z","shell.execute_reply":"2026-05-24T19:11:14.340980Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for idx, row in tqdm(\n    labels_df.iterrows(),\n    total=len(labels_df)\n):\n\n    file_id = row[\"Id\"]\n\n    byte_path = os.path.join(\n        train_folder,\n        file_id + \".bytes\"\n    )\n\n    output_path = os.path.join(\n        image_output_dir,\n        file_id + \".png\"\n    )\n\n    if os.path.exists(byte_path):\n\n        try:\n\n            bytes_to_image(\n                byte_path,\n                output_path\n            )\n\n        except:\n\n            pass","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:11:18.071101Z","iopub.execute_input":"2026-05-24T19:11:18.071403Z","iopub.status.idle":"2026-05-24T19:11:18.565942Z","shell.execute_reply.started":"2026-05-24T19:11:18.071375Z","shell.execute_reply":"2026-05-24T19:11:18.565336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_paths = []\nlabels = []\n\nimage_dir = \"/kaggle/working/malware_images\"\n\nfor idx, row in labels_df.iterrows():\n\n    file_id = row[\"Id\"]\n\n    label = row[\"Class\"] - 1\n\n    img_path = os.path.join(\n        image_dir,\n        file_id + \".png\"\n    )\n\n    if os.path.exists(img_path):\n\n        image_paths.append(img_path)\n\n        labels.append(label)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:11:34.974356Z","iopub.execute_input":"2026-05-24T19:11:34.975077Z","iopub.status.idle":"2026-05-24T19:11:35.453232Z","shell.execute_reply.started":"2026-05-24T19:11:34.975044Z","shell.execute_reply":"2026-05-24T19:11:35.452651Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(len(image_paths))\nprint(len(labels))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:11:39.627884Z","iopub.execute_input":"2026-05-24T19:11:39.628707Z","iopub.status.idle":"2026-05-24T19:11:39.633012Z","shell.execute_reply.started":"2026-05-24T19:11:39.628661Z","shell.execute_reply":"2026-05-24T19:11:39.632122Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain_paths, val_paths, train_labels, val_labels = train_test_split(\n\n    image_paths,\n    labels,\n\n    test_size=0.2,\n\n    stratify=labels,\n\n    random_state=42\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.260911Z","iopub.status.idle":"2026-05-24T19:08:09.261197Z","shell.execute_reply.started":"2026-05-24T19:08:09.261078Z","shell.execute_reply":"2026-05-24T19:08:09.261094Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Malware Image Dataset**","metadata":{}},{"cell_type":"code","source":"class MalwareDataset(Dataset):\n\n    def __init__(self, image_paths, labels, transform=None):\n\n        self.image_paths = image_paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n\n        img = cv2.imread(self.image_paths[idx], 0)\n\n        img = cv2.resize(img, (64,64))\n\n        if self.transform:\n            img = self.transform(img)\n\n        label = self.labels[idx]\n\n        return img, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.262371Z","iopub.status.idle":"2026-05-24T19:08:09.262692Z","shell.execute_reply.started":"2026-05-24T19:08:09.262531Z","shell.execute_reply":"2026-05-24T19:08:09.262545Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = MalwareDataset(\n\n    train_paths,\n    train_labels,\n\n    transform=transform\n)\n\nval_dataset = MalwareDataset(\n\n    val_paths,\n    val_labels,\n\n    transform=transform\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.263368Z","iopub.status.idle":"2026-05-24T19:08:09.263586Z","shell.execute_reply.started":"2026-05-24T19:08:09.263480Z","shell.execute_reply":"2026-05-24T19:08:09.263493Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loader = DataLoader(\n\n    train_dataset,\n\n    batch_size=32,\n\n    shuffle=True\n)\n\nval_loader = DataLoader(\n\n    val_dataset,\n\n    batch_size=32,\n\n    shuffle=False\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.264750Z","iopub.status.idle":"2026-05-24T19:08:09.265144Z","shell.execute_reply.started":"2026-05-24T19:08:09.264938Z","shell.execute_reply":"2026-05-24T19:08:09.264972Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **CBAM Attention**","metadata":{}},{"cell_type":"code","source":"class ChannelAttention(nn.Module):\n\n    def __init__(self, in_planes, ratio=8):\n\n        super().__init__()\n\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n\n        self.max_pool = nn.AdaptiveMaxPool2d(1)\n\n        self.fc = nn.Sequential(\n            nn.Conv2d(in_planes, in_planes // ratio, 1),\n            nn.ReLU(),\n            nn.Conv2d(in_planes // ratio, in_planes, 1)\n        )\n\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n\n        avg_out = self.fc(self.avg_pool(x))\n\n        max_out = self.fc(self.max_pool(x))\n\n        out = avg_out + max_out\n\n        return self.sigmoid(out)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.266272Z","iopub.status.idle":"2026-05-24T19:08:09.266612Z","shell.execute_reply.started":"2026-05-24T19:08:09.266492Z","shell.execute_reply":"2026-05-24T19:08:09.266508Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Spatial Attention**","metadata":{}},{"cell_type":"code","source":"class SpatialAttention(nn.Module):\n\n    def __init__(self):\n\n        super().__init__()\n\n        self.conv = nn.Conv2d(2,1,7,padding=3)\n\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n\n        avg_out = torch.mean(x, dim=1, keepdim=True)\n\n        max_out,_ = torch.max(x, dim=1, keepdim=True)\n\n        x = torch.cat([avg_out, max_out], dim=1)\n\n        x = self.conv(x)\n\n        return self.sigmoid(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.269277Z","iopub.status.idle":"2026-05-24T19:08:09.269813Z","shell.execute_reply.started":"2026-05-24T19:08:09.269627Z","shell.execute_reply":"2026-05-24T19:08:09.269685Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **ATTENTION CNN ENCODER**","metadata":{}},{"cell_type":"code","source":"class AttentionEncoder(nn.Module):\n\n    def __init__(self):\n\n        super().__init__()\n\n        self.features = nn.Sequential(\n\n            nn.Conv2d(1,64,3,padding=1),\n            nn.BatchNorm2d(64),\n            nn.LeakyReLU(0.2),\n\n            nn.MaxPool2d(2),\n\n            nn.Conv2d(64,128,3,padding=1),\n            nn.BatchNorm2d(128),\n            nn.LeakyReLU(0.2),\n\n            nn.MaxPool2d(2),\n\n            nn.Conv2d(128,256,3,padding=1),\n            nn.BatchNorm2d(256),\n            nn.LeakyReLU(0.2),\n\n            nn.MaxPool2d(2)\n        )\n\n        self.ca = ChannelAttention(256)\n\n        self.sa = SpatialAttention()\n\n        self.fc = nn.Linear(256*8*8, CONFIG[\"latent_dim\"])\n\n    def forward(self, x):\n\n        x = self.features(x)\n\n        x = self.ca(x) * x\n\n        x = self.sa(x) * x\n\n        x = x.view(x.size(0), -1)\n\n        latent = self.fc(x)\n\n        return latent","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.271091Z","iopub.status.idle":"2026-05-24T19:08:09.271426Z","shell.execute_reply.started":"2026-05-24T19:08:09.271294Z","shell.execute_reply":"2026-05-24T19:08:09.271316Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **DEEPSMOTE LATENT INTERPOLATION**","metadata":{}},{"cell_type":"code","source":"def deepsmote_interpolation(latent_vectors, labels):\n\n    synthetic = []\n\n    synthetic_labels = []\n\n    unique_classes = np.unique(labels)\n\n    for cls in unique_classes:\n\n        idx = np.where(labels == cls)[0]\n\n        minority = latent_vectors[idx]\n\n        if len(minority) < 2:\n            continue\n\n        nbrs = NearestNeighbors(\n            n_neighbors=2\n        ).fit(minority)\n\n        distances, indices = nbrs.kneighbors(minority)\n\n        for i in range(len(minority)):\n\n            neighbor = minority[indices[i][1]]\n\n            alpha = np.random.rand()\n\n            new_sample = (\n                minority[i]\n                +\n                alpha * (neighbor - minority[i])\n            )\n\n            synthetic.append(new_sample)\n\n            synthetic_labels.append(cls)\n\n    return np.array(synthetic), np.array(synthetic_labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.273011Z","iopub.status.idle":"2026-05-24T19:08:09.273387Z","shell.execute_reply.started":"2026-05-24T19:08:09.273205Z","shell.execute_reply":"2026-05-24T19:08:09.273229Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **ATTENTION GAN GENERATOR**","metadata":{}},{"cell_type":"code","source":"class Generator(nn.Module):\n\n    def __init__(self):\n\n        super().__init__()\n\n        self.fc = nn.Linear(\n            CONFIG[\"latent_dim\"],\n            256*8*8\n        )\n\n        self.net = nn.Sequential(\n\n            nn.ConvTranspose2d(\n                256,128,4,2,1\n            ),\n\n            nn.BatchNorm2d(128),\n\n            nn.ReLU(),\n\n            nn.ConvTranspose2d(\n                128,64,4,2,1\n            ),\n\n            nn.BatchNorm2d(64),\n\n            nn.ReLU(),\n\n            nn.ConvTranspose2d(\n                64,1,4,2,1\n            ),\n\n            nn.Tanh()\n        )\n\n    def forward(self, z):\n\n        x = self.fc(z)\n\n        x = x.view(-1,256,8,8)\n\n        img = self.net(x)\n\n        return img","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.274688Z","iopub.status.idle":"2026-05-24T19:08:09.275169Z","shell.execute_reply.started":"2026-05-24T19:08:09.274965Z","shell.execute_reply":"2026-05-24T19:08:09.274990Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **DISCRIMINATOR**","metadata":{}},{"cell_type":"code","source":"class Discriminator(nn.Module):\n\n    def __init__(self):\n\n        super().__init__()\n\n        self.net = nn.Sequential(\n\n            nn.Conv2d(1,64,4,2,1),\n            nn.LeakyReLU(0.2),\n\n            nn.Conv2d(64,128,4,2,1),\n            nn.BatchNorm2d(128),\n            nn.LeakyReLU(0.2),\n\n            nn.Flatten(),\n\n            nn.Linear(128*16*16,1),\n\n            nn.Sigmoid()\n        )\n\n    def forward(self, x):\n\n        return self.net(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.276153Z","iopub.status.idle":"2026-05-24T19:08:09.276492Z","shell.execute_reply.started":"2026-05-24T19:08:09.276360Z","shell.execute_reply":"2026-05-24T19:08:09.276385Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **FINAL CNN CLASSIFIER**","metadata":{}},{"cell_type":"code","source":"class MalwareClassifier(nn.Module):\n\n    def __init__(self):\n\n        super().__init__()\n\n        self.encoder = AttentionEncoder()\n\n        self.classifier = nn.Linear(\n            CONFIG[\"latent_dim\"],\n            CONFIG[\"num_classes\"]\n        )\n\n    def forward(self, x):\n\n        z = self.encoder(x)\n\n        out = self.classifier(z)\n\n        return out","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.277917Z","iopub.status.idle":"2026-05-24T19:08:09.278343Z","shell.execute_reply.started":"2026-05-24T19:08:09.278134Z","shell.execute_reply":"2026-05-24T19:08:09.278159Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **TRAINING LOOP**","metadata":{}},{"cell_type":"code","source":"device = torch.device(\n    \"cuda\" if torch.cuda.is_available() else \"cpu\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.413740Z","iopub.execute_input":"2026-05-24T19:08:09.414113Z","iopub.status.idle":"2026-05-24T19:08:09.417597Z","shell.execute_reply.started":"2026-05-24T19:08:09.414091Z","shell.execute_reply":"2026-05-24T19:08:09.416864Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = MalwareClassifier().to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.419104Z","iopub.execute_input":"2026-05-24T19:08:09.419372Z","iopub.status.idle":"2026-05-24T19:08:09.470121Z","shell.execute_reply.started":"2026-05-24T19:08:09.419352Z","shell.execute_reply":"2026-05-24T19:08:09.469347Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\n\noptimizer = torch.optim.Adam(\n    model.parameters(),\n    lr=0.0002\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.471021Z","iopub.execute_input":"2026-05-24T19:08:09.471280Z","iopub.status.idle":"2026-05-24T19:08:09.475244Z","shell.execute_reply.started":"2026-05-24T19:08:09.471250Z","shell.execute_reply":"2026-05-24T19:08:09.474664Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"EPOCHS = 5","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.475990Z","iopub.execute_input":"2026-05-24T19:08:09.476296Z","iopub.status.idle":"2026-05-24T19:08:09.487130Z","shell.execute_reply.started":"2026-05-24T19:08:09.476273Z","shell.execute_reply":"2026-05-24T19:08:09.486382Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_losses = []\nval_losses = []\n\ntrain_accs = []\nval_accs = []\n\nfor epoch in range(EPOCHS):\n\n    model.train()\n\n    running_loss = 0\n    correct = 0\n    total = 0\n\n    for images, labels in train_loader:\n\n        images = images.to(device)\n        labels = labels.to(device)\n\n        optimizer.zero_grad()\n\n        outputs = model(images)\n\n        loss = criterion(outputs, labels)\n\n        loss.backward()\n\n        optimizer.step()\n\n        running_loss += loss.item()\n\n        _, predicted = torch.max(outputs, 1)\n\n        total += labels.size(0)\n\n        correct += (predicted == labels).sum().item()\n\n    train_acc = 100 * correct / total\n    train_loss = running_loss / len(train_loader)\n\n    train_accs.append(train_acc)\n    train_losses.append(train_loss)\n\n    # VALIDATION\n\n    model.eval()\n\n    val_correct = 0\n    val_total = 0\n    val_running_loss = 0\n\n    with torch.no_grad():\n\n        for images, labels in val_loader:\n\n            images = images.to(device)\n            labels = labels.to(device)\n\n            outputs = model(images)\n\n            loss = criterion(outputs, labels)\n\n            val_running_loss += loss.item()\n\n            _, predicted = torch.max(outputs, 1)\n\n            val_total += labels.size(0)\n\n            val_correct += (predicted == labels).sum().item()\n\n    val_acc = 100 * val_correct / val_total\n    val_loss = val_running_loss / len(val_loader)\n\n    val_accs.append(val_acc)\n    val_losses.append(val_loss)\n\n    print(f\"Epoch [{epoch+1}/{EPOCHS}]\")\n    print(f\"Train Loss: {train_loss:.4f} | Train Acc: {train_acc:.2f}\")\n    print(f\"Val Loss: {val_loss:.4f} | Val Acc: {val_acc:.2f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.488594Z","iopub.execute_input":"2026-05-24T19:08:09.488976Z","iopub.status.idle":"2026-05-24T19:08:09.502558Z","shell.execute_reply.started":"2026-05-24T19:08:09.488939Z","shell.execute_reply":"2026-05-24T19:08:09.501538Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **ACCURACY + LOSS GRAPH**","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.figure(figsize=(10,5))\n\nplt.plot(train_accs, label='Train Accuracy')\nplt.plot(val_accs, label='Validation Accuracy')\n\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"Accuracy\")\n\nplt.legend()\n\nplt.title(\"Training vs Validation Accuracy\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.503229Z","iopub.status.idle":"2026-05-24T19:08:09.503505Z","shell.execute_reply.started":"2026-05-24T19:08:09.503390Z","shell.execute_reply":"2026-05-24T19:08:09.503405Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(10,5))\n\nplt.plot(train_losses, label='Train Loss')\nplt.plot(val_losses, label='Validation Loss')\n\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"Loss\")\n\nplt.legend()\n\nplt.title(\"Training vs Validation Loss\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-24T19:08:09.505046Z","iopub.status.idle":"2026-05-24T19:08:09.505324Z","shell.execute_reply.started":"2026-05-24T19:08:09.505169Z","shell.execute_reply":"2026-05-24T19:08:09.505183Z"}},"outputs":[],"execution_count":null}]}