ASomeoneWhoInterestedWithAI commited on
Commit
dfc3e16
Β·
verified Β·
1 Parent(s): be06ab3

Upload LookThemV5ContinueTrain.ipynb

Browse files
Files changed (1) hide show
  1. LookThemV5ContinueTrain.ipynb +1 -1
LookThemV5ContinueTrain.ipynb CHANGED
@@ -1 +1 @@
1
- {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"authorship_tag":"ABX9TyNy5K3TFR7NSBjaIHLUl4Gf"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"code","execution_count":null,"metadata":{"id":"o2qDQ51KeH1s"},"outputs":[],"source":[]},{"cell_type":"code","source":["import os\n","import zipfile\n","import urllib.request\n","import math\n","import torch\n","import torch.nn as nn\n","import torch.nn.functional as F\n","import torch.optim as optim\n","from torch.utils.data import DataLoader\n","from torchvision import datasets, transforms\n","\n","# ==========================================\n","# 1. DOWNLOAD & PREPROCESS DATASET (TINY-IMAGENET)\n","# ==========================================\n","def prepare_tiny_imagenet():\n"," dataset_url = \"http://cs231n.stanford.edu/tiny-imagenet-200.zip\"\n"," zip_path = \"./tiny-imagenet-200.zip\"\n"," extract_path = \"./tiny-imagenet-200\"\n","\n"," if not os.path.exists(zip_path):\n"," print(\"πŸ“₯ Mengunduh Tiny-ImageNet (~230MB)... Mohon tunggu...\")\n"," urllib.request.urlretrieve(dataset_url, zip_path)\n"," print(\"βœ… Download Selesai!\")\n","\n"," if not os.path.exists(extract_path):\n"," print(\"πŸ“¦ Mengekstrak dataset...\")\n"," with zipfile.ZipFile(zip_path, 'r') as zip_ref:\n"," zip_ref.extractall(\"./\")\n"," print(\"βœ… Ekstrak Selesai!\")\n","\n"," return os.path.join(extract_path, \"train\"), os.path.join(extract_path, \"val\")\n","\n","train_dir, val_dir = prepare_tiny_imagenet()\n","\n","# Merapikan folder validasi bawaan Tiny-ImageNet\n","val_img_dir = \"./tiny-imagenet-200/val/images\"\n","val_annotations = \"./tiny-imagenet-200/val/val_annotations.txt\"\n","\n","if os.path.exists(val_img_dir):\n"," print(\"🧹 Merapikan struktur folder Validation asli Tiny-ImageNet...\")\n"," with open(val_annotations, \"r\") as f:\n"," lines = f.readlines()\n","\n"," for line in lines:\n"," parts = line.strip().split(\"\\t\")\n"," img_name, class_name = parts[0], parts[1]\n"," class_dir = os.path.join(\"./tiny-imagenet-200/val\", class_name)\n"," os.makedirs(class_dir, exist_ok=True)\n"," src_path = os.path.join(val_img_dir, img_name)\n"," dst_path = os.path.join(class_dir, img_name)\n"," if os.path.exists(src_path):\n"," os.rename(src_path, dst_path)\n"," os.rmdir(val_img_dir)\n"," print(\"βœ… Folder Validation sekarang sudah rapi!\")\n","\n","transform_train = transforms.Compose([\n"," transforms.RandomHorizontalFlip(),\n"," transforms.RandomRotation(15),\n"," transforms.ToTensor(),\n"," transforms.Normalize((0.4802, 0.4481, 0.3975), (0.2302, 0.2265, 0.2262))\n","])\n","\n","transform_val = transforms.Compose([\n"," transforms.ToTensor(),\n"," transforms.Normalize((0.4802, 0.4481, 0.3975), (0.2302, 0.2265, 0.2262))\n","])\n","\n","train_dataset = datasets.ImageFolder(root=train_dir, transform=transform_train)\n","val_dataset = datasets.ImageFolder(root=val_dir, transform=transform_val)\n","\n","train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=2, pin_memory=True)\n","val_loader = DataLoader(val_dataset, batch_size=256, shuffle=False, num_workers=2, pin_memory=True)\n","\n","# ==========================================\n","# 2. CORE LAYER: LOOKTHEM CORE LAYER\n","# ==========================================\n","class LookThemLayer(nn.Module):\n"," def __init__(self, num_tokens, in_features, hidden_dim):\n"," super(LookThemLayer, self).__init__()\n"," self.num_tokens = num_tokens\n"," self.in_features = in_features\n","\n"," self.mod1_w1 = nn.Parameter(torch.randn(num_tokens, in_features, hidden_dim))\n"," self.mod1_b1 = nn.Parameter(torch.zeros(num_tokens, hidden_dim))\n"," self.mod1_w2 = nn.Parameter(torch.randn(num_tokens, hidden_dim, 1))\n"," self.mod1_b2 = nn.Parameter(torch.zeros(num_tokens, 1))\n","\n"," self.mod2_w1 = nn.Parameter(torch.randn(num_tokens, in_features, hidden_dim))\n"," self.mod2_b1 = nn.Parameter(torch.zeros(num_tokens, hidden_dim))\n"," self.mod2_w2 = nn.Parameter(torch.randn(num_tokens, hidden_dim, 1))\n"," self.mod2_b2 = nn.Parameter(torch.zeros(num_tokens, 1))\n","\n"," self.trans_w = nn.Parameter(torch.randn(num_tokens, 1, 1))\n"," self.trans_b = nn.Parameter(torch.zeros(num_tokens, 1))\n"," self._init_weights()\n","\n"," def _init_weights(self):\n"," for w in [self.mod1_w1, self.mod2_w1, self.mod1_w2, self.mod2_w2, self.trans_w]:\n"," nn.init.kaiming_uniform_(w, a=math.sqrt(5))\n","\n"," def forward(self, x):\n"," N = self.num_tokens\n"," h1 = torch.einsum('bti,tij->btj', x, self.mod1_w1) + self.mod1_b1\n"," out_m1 = torch.einsum('btj,tjk->btk', F.gelu(h1), self.mod1_w2) + self.mod1_b2\n","\n"," h2 = torch.einsum('bti,tij->btj', x, self.mod2_w1) + self.mod2_b1\n"," out_m2 = torch.einsum('btj,tjk->btk', F.gelu(h2), self.mod2_w2) + self.mod2_b2\n","\n"," out_m2_safe = out_m2 + 1e-5\n"," compare = torch.tanh(out_m1.unsqueeze(2) / out_m2_safe.unsqueeze(1))\n"," compare2 = torch.tanh(out_m1.unsqueeze(1) / out_m2_safe.unsqueeze(2))\n","\n"," bias_reshaped = self.trans_b.view(1, 1, N, 1)\n"," trans_compare = torch.einsum('bije,jef->bijf', compare, self.trans_w) + bias_reshaped\n"," trans_compare2 = torch.einsum('bije,jef->bijf', compare2, self.trans_w) + bias_reshaped\n","\n"," interaksi = (trans_compare * x.unsqueeze(2) + trans_compare2 * x.unsqueeze(1)) / 2\n"," mask = 1.0 - torch.eye(N, device=x.device)\n"," interaksi_masked = interaksi * mask.view(1, N, N, 1)\n","\n"," return interaksi_masked.sum(dim=2) / (N - 1.0)\n","\n","# ==========================================\n","# 3. INDUK ARSITEKTUR: LOOKTHEM V5 (STANDARD CONV STREAM B)\n","# ==========================================\n","class LookThemV5(nn.Module):\n"," def __init__(self):\n"," super(LookThemV5, self).__init__()\n","\n"," self.register_buffer('grayscale_weights', torch.tensor([0.299, 0.587, 0.114]).view(1, 3, 1, 1))\n","\n"," # --- STREAM A: BENTUK MAKRO (Ditahan di 16x16 - Resolusi Tinggi) ---\n"," self.stream_a = nn.Sequential(\n"," nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1), # [B, 16, 32, 32]\n"," nn.BatchNorm2d(16), nn.GELU(),\n"," nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 16, 16] (256 Luas Spasial)\n"," nn.BatchNorm2d(32), nn.GELU()\n"," )\n","\n"," # Jembatan Progresif Token: Mengompres spasial 256 -> 64 token secara cerdas\n"," self.token_bridge = nn.Linear(256, 64)\n","\n"," # --- STREAM B: ESENSI WARNA (Mengecil ke 8x8 Mengikuti Pola V2 - Standard Conv) ---\n"," self.stream_b = nn.Sequential(\n"," nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1), # [B, 16, 32, 32]\n"," nn.BatchNorm2d(16), nn.GELU(),\n"," nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 16, 16]\n"," nn.BatchNorm2d(32), nn.GELU(),\n","\n"," # UPDATE V5: Menggunakan Standard Conv Stride murni gaya V2 agar kombinasi warna langsung padat\n"," nn.Conv2d(32, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 8, 8] (64 Luas Spasial)\n"," nn.BatchNorm2d(32), nn.GELU()\n"," )\n","\n"," # --- CORE COGNITION LAYER (64 Token, Gabungan Features 32 + 32 = 64) ---\n"," self.lookthem = LookThemLayer(num_tokens=64, in_features=64, hidden_dim=32)\n","\n"," # --- CLASSIFIER RAMPING ANTI-OVERFIT ---\n"," self.classifier = nn.Sequential(\n"," nn.Flatten(),\n"," nn.Linear(64 * 64, 256),\n"," nn.ReLU(),\n"," nn.Dropout(0.4),\n"," nn.Linear(256, 200)\n"," )\n","\n"," def forward(self, x):\n"," batch_size = x.size(0)\n","\n"," # 1. Ekstrak Stream A (Grayscale 16x16)\n"," x_gray = torch.sum(x * self.grayscale_weights, dim=1, keepdim=True)\n"," feat_a = self.stream_a(x_gray) # [B, 32, 16, 16]\n"," feat_a_flat = feat_a.view(batch_size, 32, 256)\n"," feat_a_compressed = self.token_bridge(feat_a_flat) # [B, 32, 64]\n"," feat_a_tokens = feat_a_compressed.transpose(1, 2) # [B, 64 Token, 32 Features]\n","\n"," # 2. Ekstrak Stream B (RGB 8x8 via Standard Conv)\n"," feat_b = self.stream_b(x) # [B, 32, 8, 8]\n"," feat_b_tokens = feat_b.view(batch_size, 32, 64).transpose(1, 2) # [B, 64 Token, 32 Features]\n","\n"," # 3. Penggabungan Asimetris Tingkat Features (Total tetap 64 Token)\n"," tokens_combined = torch.cat([feat_a_tokens, feat_b_tokens], dim=2) # [B, 64 Token, 64 Features]\n","\n"," # 4. Kognisi Relasional & Klasifikasi\n"," out_lookthem = self.lookthem(tokens_combined)\n"," return self.classifier(out_lookthem)\n","\n","# ==========================================\n","# 4. RUNTIME TRAINING + CHECKPOINT SYSTEM\n","# ==========================================\n","device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n","model = LookThemV5().to(device)\n","model.load_state_dict(torch.load(\"LookThem_V5_Final.pth\"))\n","\n","criterion = nn.CrossEntropyLoss()\n","optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)\n","scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=20)\n","\n","start_epoch = 20\n","checkpoint_path = \"lookthem_v5_checkpoint.pth\"\n","\n","if os.path.exists(checkpoint_path):\n"," print(\"πŸ’Ύ Checkpoint V5 ditemukan! Melanjutkan progres eksperimen...\")\n"," checkpoint = torch.load(checkpoint_path)\n"," model.load_state_dict(checkpoint['model_state_dict'])\n"," optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n"," scheduler.load_state_dict(checkpoint['scheduler_state_dict'])\n"," start_epoch = checkpoint['epoch']\n"," print(f\"▢️ Berhasil resume dari Epoch ke-{start_epoch+1}\")\n","\n","print(f\"πŸš€ Memulai pengujian LookThem V5 (Asymmetric Fusion) menggunakan {device}...\")\n","\n","for epoch in range(start_epoch, 40):\n"," model.train()\n"," total_loss, correct, total = 0, 0, 0\n","\n"," for data, target in train_loader:\n"," data, target = data.to(device), target.to(device)\n","\n"," optimizer.zero_grad()\n"," output = model(data)\n"," loss = criterion(output, target)\n"," loss.backward()\n"," optimizer.step()\n","\n"," total_loss += loss.item()\n"," _, predicted = output.max(1)\n"," total += target.size(0)\n"," correct += predicted.eq(target).sum().item()\n","\n"," scheduler.step()\n"," acc = 100. * correct / total\n"," current_lr = optimizer.param_groups[0]['lr']\n"," print(f\"Epoch {epoch+1:02d}/45 -> Train Loss: {total_loss/len(train_loader):.4f} | Train Acc: {acc:.2f}% | LR: {current_lr:.6f}\")\n","\n"," if (epoch + 1) % 5 == 0:\n"," torch.save({\n"," 'epoch': epoch + 1,\n"," 'model_state_dict': model.state_dict(),\n"," 'optimizer_state_dict': optimizer.state_dict(),\n"," 'scheduler_state_dict': scheduler.state_dict(),\n"," }, checkpoint_path)\n"," print(f\"πŸ”’ [SYSTEM-SAVER] Progres Epoch {epoch+1} berhasil dikunci ke disk!\")\n","\n","# ==========================================\n","# 5. VALIDASI AKHIR\n","# ==========================================\n","model.eval()\n","test_loss, test_correct, test_total = 0, 0, 0\n","\n","print(\"\\nπŸ”’ Memulai Pengujian Validasi Akhir...\")\n","with torch.no_grad():\n"," for data, target in val_loader:\n"," data, target = data.to(device), target.to(device)\n"," output = model(data)\n"," loss = criterion(output, target)\n","\n"," test_loss += loss.item()\n"," _, predicted = output.max(1)\n"," test_total += target.size(0)\n"," test_correct += predicted.eq(target).sum().item()\n","\n","final_test_acc = 100. * test_correct / test_total\n","print(\"=== HASIL EVALUASI AKHIR LOOKTHEM V5 ===\")\n","print(f\"Test Loss: {test_loss/len(val_loader):.4f} | Test Accuracy: {final_test_acc:.2f}%\")\n","\n","torch.save(model.state_dict(), \"LookThem_V5_Final.pth\")\n","print(f\"🏁 Selesai! Ukuran berkas final: {os.path.getsize('LookThem_V5_Final.pth') / (1024*1024):.2f} MB\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"tFR4mJB3Aavo","executionInfo":{"status":"ok","timestamp":1779015771684,"user_tz":-420,"elapsed":1299707,"user":{"displayName":"Cici rizky plk","userId":"03714270658772765776"}},"outputId":"2000bd37-8ac3-4e71-c254-593aa76b8bba"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["πŸ“₯ Mengunduh Tiny-ImageNet (~230MB)... Mohon tunggu...\n","βœ… Download Selesai!\n","πŸ“¦ Mengekstrak dataset...\n","βœ… Ekstrak Selesai!\n","🧹 Merapikan struktur folder Validation asli Tiny-ImageNet...\n","βœ… Folder Validation sekarang sudah rapi!\n","πŸš€ Memulai pengujian LookThem V5 (Asymmetric Fusion) menggunakan cuda...\n","Epoch 21/45 -> Train Loss: 2.9485 | Train Acc: 31.26% | LR: 0.000994\n","Epoch 22/45 -> Train Loss: 2.9226 | Train Acc: 31.82% | LR: 0.000976\n","Epoch 23/45 -> Train Loss: 2.8892 | Train Acc: 32.31% | LR: 0.000946\n","Epoch 24/45 -> Train Loss: 2.8511 | Train Acc: 32.96% | LR: 0.000905\n","Epoch 25/45 -> Train Loss: 2.7994 | Train Acc: 33.99% | LR: 0.000854\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 25 berhasil dikunci ke disk!\n","Epoch 26/45 -> Train Loss: 2.7520 | Train Acc: 34.68% | LR: 0.000794\n","Epoch 27/45 -> Train Loss: 2.7019 | Train Acc: 35.62% | LR: 0.000727\n","Epoch 28/45 -> Train Loss: 2.6495 | Train Acc: 36.73% | LR: 0.000655\n","Epoch 29/45 -> Train Loss: 2.5908 | Train Acc: 37.85% | LR: 0.000578\n","Epoch 30/45 -> Train Loss: 2.5368 | Train Acc: 38.85% | LR: 0.000500\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 30 berhasil dikunci ke disk!\n","Epoch 31/45 -> Train Loss: 2.4757 | Train Acc: 39.98% | LR: 0.000422\n","Epoch 32/45 -> Train Loss: 2.4225 | Train Acc: 40.84% | LR: 0.000345\n","Epoch 33/45 -> Train Loss: 2.3618 | Train Acc: 42.08% | LR: 0.000273\n","Epoch 34/45 -> Train Loss: 2.3135 | Train Acc: 42.85% | LR: 0.000206\n","Epoch 35/45 -> Train Loss: 2.2597 | Train Acc: 43.90% | LR: 0.000146\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 35 berhasil dikunci ke disk!\n","Epoch 36/45 -> Train Loss: 2.2173 | Train Acc: 44.72% | LR: 0.000095\n","Epoch 37/45 -> Train Loss: 2.1843 | Train Acc: 45.51% | LR: 0.000054\n","Epoch 38/45 -> Train Loss: 2.1596 | Train Acc: 45.93% | LR: 0.000024\n","Epoch 39/45 -> Train Loss: 2.1380 | Train Acc: 46.32% | LR: 0.000006\n","Epoch 40/45 -> Train Loss: 2.1291 | Train Acc: 46.58% | LR: 0.000000\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 40 berhasil dikunci ke disk!\n","\n","πŸ”’ Memulai Pengujian Validasi Akhir...\n","=== HASIL EVALUASI AKHIR LOOKTHEM V5 ===\n","Test Loss: 2.8726 | Test Accuracy: 35.46%\n","🏁 Selesai! Ukuran berkas final: 5.38 MB\n"]}]},{"cell_type":"code","source":["im
 
1
+ {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"authorship_tag":"ABX9TyNy5K3TFR7NSBjaIHLUl4Gf"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"code","execution_count":null,"metadata":{"id":"o2qDQ51KeH1s"},"outputs":[],"source":[]},{"cell_type":"code","source":["import os\n","import zipfile\n","import urllib.request\n","import math\n","import torch\n","import torch.nn as nn\n","import torch.nn.functional as F\n","import torch.optim as optim\n","from torch.utils.data import DataLoader\n","from torchvision import datasets, transforms\n","\n","# ==========================================\n","# 1. DOWNLOAD & PREPROCESS DATASET (TINY-IMAGENET)\n","# ==========================================\n","def prepare_tiny_imagenet():\n"," dataset_url = \"http://cs231n.stanford.edu/tiny-imagenet-200.zip\"\n"," zip_path = \"./tiny-imagenet-200.zip\"\n"," extract_path = \"./tiny-imagenet-200\"\n","\n"," if not os.path.exists(zip_path):\n"," print(\"πŸ“₯ Mengunduh Tiny-ImageNet (~230MB)... Mohon tunggu...\")\n"," urllib.request.urlretrieve(dataset_url, zip_path)\n"," print(\"βœ… Download Selesai!\")\n","\n"," if not os.path.exists(extract_path):\n"," print(\"πŸ“¦ Mengekstrak dataset...\")\n"," with zipfile.ZipFile(zip_path, 'r') as zip_ref:\n"," zip_ref.extractall(\"./\")\n"," print(\"βœ… Ekstrak Selesai!\")\n","\n"," return os.path.join(extract_path, \"train\"), os.path.join(extract_path, \"val\")\n","\n","train_dir, val_dir = prepare_tiny_imagenet()\n","\n","# Merapikan folder validasi bawaan Tiny-ImageNet\n","val_img_dir = \"./tiny-imagenet-200/val/images\"\n","val_annotations = \"./tiny-imagenet-200/val/val_annotations.txt\"\n","\n","if os.path.exists(val_img_dir):\n"," print(\"🧹 Merapikan struktur folder Validation asli Tiny-ImageNet...\")\n"," with open(val_annotations, \"r\") as f:\n"," lines = f.readlines()\n","\n"," for line in lines:\n"," parts = line.strip().split(\"\\t\")\n"," img_name, class_name = parts[0], parts[1]\n"," class_dir = os.path.join(\"./tiny-imagenet-200/val\", class_name)\n"," os.makedirs(class_dir, exist_ok=True)\n"," src_path = os.path.join(val_img_dir, img_name)\n"," dst_path = os.path.join(class_dir, img_name)\n"," if os.path.exists(src_path):\n"," os.rename(src_path, dst_path)\n"," os.rmdir(val_img_dir)\n"," print(\"βœ… Folder Validation sekarang sudah rapi!\")\n","\n","transform_train = transforms.Compose([\n"," transforms.RandomHorizontalFlip(),\n"," transforms.RandomRotation(15),\n"," transforms.ToTensor(),\n"," transforms.Normalize((0.4802, 0.4481, 0.3975), (0.2302, 0.2265, 0.2262))\n","])\n","\n","transform_val = transforms.Compose([\n"," transforms.ToTensor(),\n"," transforms.Normalize((0.4802, 0.4481, 0.3975), (0.2302, 0.2265, 0.2262))\n","])\n","\n","train_dataset = datasets.ImageFolder(root=train_dir, transform=transform_train)\n","val_dataset = datasets.ImageFolder(root=val_dir, transform=transform_val)\n","\n","train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=2, pin_memory=True)\n","val_loader = DataLoader(val_dataset, batch_size=256, shuffle=False, num_workers=2, pin_memory=True)\n","\n","# ==========================================\n","# 2. CORE LAYER: LOOKTHEM CORE LAYER\n","# ==========================================\n","class LookThemLayer(nn.Module):\n"," def __init__(self, num_tokens, in_features, hidden_dim):\n"," super(LookThemLayer, self).__init__()\n"," self.num_tokens = num_tokens\n"," self.in_features = in_features\n","\n"," self.mod1_w1 = nn.Parameter(torch.randn(num_tokens, in_features, hidden_dim))\n"," self.mod1_b1 = nn.Parameter(torch.zeros(num_tokens, hidden_dim))\n"," self.mod1_w2 = nn.Parameter(torch.randn(num_tokens, hidden_dim, 1))\n"," self.mod1_b2 = nn.Parameter(torch.zeros(num_tokens, 1))\n","\n"," self.mod2_w1 = nn.Parameter(torch.randn(num_tokens, in_features, hidden_dim))\n"," self.mod2_b1 = nn.Parameter(torch.zeros(num_tokens, hidden_dim))\n"," self.mod2_w2 = nn.Parameter(torch.randn(num_tokens, hidden_dim, 1))\n"," self.mod2_b2 = nn.Parameter(torch.zeros(num_tokens, 1))\n","\n"," self.trans_w = nn.Parameter(torch.randn(num_tokens, 1, 1))\n"," self.trans_b = nn.Parameter(torch.zeros(num_tokens, 1))\n"," self._init_weights()\n","\n"," def _init_weights(self):\n"," for w in [self.mod1_w1, self.mod2_w1, self.mod1_w2, self.mod2_w2, self.trans_w]:\n"," nn.init.kaiming_uniform_(w, a=math.sqrt(5))\n","\n"," def forward(self, x):\n"," N = self.num_tokens\n"," h1 = torch.einsum('bti,tij->btj', x, self.mod1_w1) + self.mod1_b1\n"," out_m1 = torch.einsum('btj,tjk->btk', F.gelu(h1), self.mod1_w2) + self.mod1_b2\n","\n"," h2 = torch.einsum('bti,tij->btj', x, self.mod2_w1) + self.mod2_b1\n"," out_m2 = torch.einsum('btj,tjk->btk', F.gelu(h2), self.mod2_w2) + self.mod2_b2\n","\n"," out_m2_safe = out_m2 + 1e-5\n"," compare = torch.tanh(out_m1.unsqueeze(2) / out_m2_safe.unsqueeze(1))\n"," compare2 = torch.tanh(out_m1.unsqueeze(1) / out_m2_safe.unsqueeze(2))\n","\n"," bias_reshaped = self.trans_b.view(1, 1, N, 1)\n"," trans_compare = torch.einsum('bije,jef->bijf', compare, self.trans_w) + bias_reshaped\n"," trans_compare2 = torch.einsum('bije,jef->bijf', compare2, self.trans_w) + bias_reshaped\n","\n"," interaksi = (trans_compare * x.unsqueeze(2) + trans_compare2 * x.unsqueeze(1)) / 2\n"," mask = 1.0 - torch.eye(N, device=x.device)\n"," interaksi_masked = interaksi * mask.view(1, N, N, 1)\n","\n"," return interaksi_masked.sum(dim=2) / (N - 1.0)\n","\n","# ==========================================\n","# 3. INDUK ARSITEKTUR: LOOKTHEM V5 (STANDARD CONV STREAM B)\n","# ==========================================\n","class LookThemV5(nn.Module):\n"," def __init__(self):\n"," super(LookThemV5, self).__init__()\n","\n"," self.register_buffer('grayscale_weights', torch.tensor([0.299, 0.587, 0.114]).view(1, 3, 1, 1))\n","\n"," # --- STREAM A: BENTUK MAKRO (Ditahan di 16x16 - Resolusi Tinggi) ---\n"," self.stream_a = nn.Sequential(\n"," nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1), # [B, 16, 32, 32]\n"," nn.BatchNorm2d(16), nn.GELU(),\n"," nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 16, 16] (256 Luas Spasial)\n"," nn.BatchNorm2d(32), nn.GELU()\n"," )\n","\n"," # Jembatan Progresif Token: Mengompres spasial 256 -> 64 token secara cerdas\n"," self.token_bridge = nn.Linear(256, 64)\n","\n"," # --- STREAM B: ESENSI WARNA (Mengecil ke 8x8 Mengikuti Pola V2 - Standard Conv) ---\n"," self.stream_b = nn.Sequential(\n"," nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1), # [B, 16, 32, 32]\n"," nn.BatchNorm2d(16), nn.GELU(),\n"," nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 16, 16]\n"," nn.BatchNorm2d(32), nn.GELU(),\n","\n"," # UPDATE V5: Menggunakan Standard Conv Stride murni gaya V2 agar kombinasi warna langsung padat\n"," nn.Conv2d(32, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 8, 8] (64 Luas Spasial)\n"," nn.BatchNorm2d(32), nn.GELU()\n"," )\n","\n"," # --- CORE COGNITION LAYER (64 Token, Gabungan Features 32 + 32 = 64) ---\n"," self.lookthem = LookThemLayer(num_tokens=64, in_features=64, hidden_dim=32)\n","\n"," # --- CLASSIFIER RAMPING ANTI-OVERFIT ---\n"," self.classifier = nn.Sequential(\n"," nn.Flatten(),\n"," nn.Linear(64 * 64, 256),\n"," nn.ReLU(),\n"," nn.Dropout(0.4),\n"," nn.Linear(256, 200)\n"," )\n","\n"," def forward(self, x):\n"," batch_size = x.size(0)\n","\n"," # 1. Ekstrak Stream A (Grayscale 16x16)\n"," x_gray = torch.sum(x * self.grayscale_weights, dim=1, keepdim=True)\n"," feat_a = self.stream_a(x_gray) # [B, 32, 16, 16]\n"," feat_a_flat = feat_a.view(batch_size, 32, 256)\n"," feat_a_compressed = self.token_bridge(feat_a_flat) # [B, 32, 64]\n"," feat_a_tokens = feat_a_compressed.transpose(1, 2) # [B, 64 Token, 32 Features]\n","\n"," # 2. Ekstrak Stream B (RGB 8x8 via Standard Conv)\n"," feat_b = self.stream_b(x) # [B, 32, 8, 8]\n"," feat_b_tokens = feat_b.view(batch_size, 32, 64).transpose(1, 2) # [B, 64 Token, 32 Features]\n","\n"," # 3. Penggabungan Asimetris Tingkat Features (Total tetap 64 Token)\n"," tokens_combined = torch.cat([feat_a_tokens, feat_b_tokens], dim=2) # [B, 64 Token, 64 Features]\n","\n"," # 4. Kognisi Relasional & Klasifikasi\n"," out_lookthem = self.lookthem(tokens_combined)\n"," return self.classifier(out_lookthem)\n","\n","# ==========================================\n","# 4. RUNTIME TRAINING + CHECKPOINT SYSTEM\n","# ==========================================\n","device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n","model = LookThemV5().to(device)\n","model.load_state_dict(torch.load(\"LookThem_V5_Final.pth\"))\n","\n","criterion = nn.CrossEntropyLoss()\n","optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)\n","scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=20)\n","\n","start_epoch = 20\n","checkpoint_path = \"lookthem_v5_checkpoint.pth\"\n","\n","if os.path.exists(checkpoint_path):\n"," print(\"πŸ’Ύ Checkpoint V5 ditemukan! Melanjutkan progres eksperimen...\")\n"," checkpoint = torch.load(checkpoint_path)\n"," model.load_state_dict(checkpoint['model_state_dict'])\n"," optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n"," scheduler.load_state_dict(checkpoint['scheduler_state_dict'])\n"," start_epoch = checkpoint['epoch']\n"," print(f\"▢️ Berhasil resume dari Epoch ke-{start_epoch+1}\")\n","\n","print(f\"πŸš€ Memulai pengujian LookThem V5 (Asymmetric Fusion) menggunakan {device}...\")\n","\n","for epoch in range(start_epoch, 40):\n"," model.train()\n"," total_loss, correct, total = 0, 0, 0\n","\n"," for data, target in train_loader:\n"," data, target = data.to(device), target.to(device)\n","\n"," optimizer.zero_grad()\n"," output = model(data)\n"," loss = criterion(output, target)\n"," loss.backward()\n"," optimizer.step()\n","\n"," total_loss += loss.item()\n"," _, predicted = output.max(1)\n"," total += target.size(0)\n"," correct += predicted.eq(target).sum().item()\n","\n"," scheduler.step()\n"," acc = 100. * correct / total\n"," current_lr = optimizer.param_groups[0]['lr']\n"," print(f\"Epoch {epoch+1:02d}/45 -> Train Loss: {total_loss/len(train_loader):.4f} | Train Acc: {acc:.2f}% | LR: {current_lr:.6f}\")\n","\n"," if (epoch + 1) % 5 == 0:\n"," torch.save({\n"," 'epoch': epoch + 1,\n"," 'model_state_dict': model.state_dict(),\n"," 'optimizer_state_dict': optimizer.state_dict(),\n"," 'scheduler_state_dict': scheduler.state_dict(),\n"," }, checkpoint_path)\n"," print(f\"πŸ”’ [SYSTEM-SAVER] Progres Epoch {epoch+1} berhasil dikunci ke disk!\")\n","\n","# ==========================================\n","# 5. VALIDASI AKHIR\n","# ==========================================\n","model.eval()\n","test_loss, test_correct, test_total = 0, 0, 0\n","\n","print(\"\\nπŸ”’ Memulai Pengujian Validasi Akhir...\")\n","with torch.no_grad():\n"," for data, target in val_loader:\n"," data, target = data.to(device), target.to(device)\n"," output = model(data)\n"," loss = criterion(output, target)\n","\n"," test_loss += loss.item()\n"," _, predicted = output.max(1)\n"," test_total += target.size(0)\n"," test_correct += predicted.eq(target).sum().item()\n","\n","final_test_acc = 100. * test_correct / test_total\n","print(\"=== HASIL EVALUASI AKHIR LOOKTHEM V5 ===\")\n","print(f\"Test Loss: {test_loss/len(val_loader):.4f} | Test Accuracy: {final_test_acc:.2f}%\")\n","\n","torch.save(model.state_dict(), \"LookThem_V5_Final.pth\")\n","print(f\"🏁 Selesai! Ukuran berkas final: {os.path.getsize('LookThem_V5_Final.pth') / (1024*1024):.2f} MB\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"tFR4mJB3Aavo","executionInfo":{"status":"ok","timestamp":1779015771684,"user_tz":-420,"elapsed":1299707,"user":{"displayName":"Cici rizky plk","userId":"03714270658772765776"}},"outputId":"2000bd37-8ac3-4e71-c254-593aa76b8bba"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["πŸ“₯ Mengunduh Tiny-ImageNet (~230MB)... Mohon tunggu...\n","βœ… Download Selesai!\n","πŸ“¦ Mengekstrak dataset...\n","βœ… Ekstrak Selesai!\n","🧹 Merapikan struktur folder Validation asli Tiny-ImageNet...\n","βœ… Folder Validation sekarang sudah rapi!\n","πŸš€ Memulai pengujian LookThem V5 (Asymmetric Fusion) menggunakan cuda...\n","Epoch 21/45 -> Train Loss: 2.9485 | Train Acc: 31.26% | LR: 0.000994\n","Epoch 22/45 -> Train Loss: 2.9226 | Train Acc: 31.82% | LR: 0.000976\n","Epoch 23/45 -> Train Loss: 2.8892 | Train Acc: 32.31% | LR: 0.000946\n","Epoch 24/45 -> Train Loss: 2.8511 | Train Acc: 32.96% | LR: 0.000905\n","Epoch 25/45 -> Train Loss: 2.7994 | Train Acc: 33.99% | LR: 0.000854\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 25 berhasil dikunci ke disk!\n","Epoch 26/45 -> Train Loss: 2.7520 | Train Acc: 34.68% | LR: 0.000794\n","Epoch 27/45 -> Train Loss: 2.7019 | Train Acc: 35.62% | LR: 0.000727\n","Epoch 28/45 -> Train Loss: 2.6495 | Train Acc: 36.73% | LR: 0.000655\n","Epoch 29/45 -> Train Loss: 2.5908 | Train Acc: 37.85% | LR: 0.000578\n","Epoch 30/45 -> Train Loss: 2.5368 | Train Acc: 38.85% | LR: 0.000500\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 30 berhasil dikunci ke disk!\n","Epoch 31/45 -> Train Loss: 2.4757 | Train Acc: 39.98% | LR: 0.000422\n","Epoch 32/45 -> Train Loss: 2.4225 | Train Acc: 40.84% | LR: 0.000345\n","Epoch 33/45 -> Train Loss: 2.3618 | Train Acc: 42.08% | LR: 0.000273\n","Epoch 34/45 -> Train Loss: 2.3135 | Train Acc: 42.85% | LR: 0.000206\n","Epoch 35/45 -> Train Loss: 2.2597 | Train Acc: 43.90% | LR: 0.000146\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 35 berhasil dikunci ke disk!\n","Epoch 36/45 -> Train Loss: 2.2173 | Train Acc: 44.72% | LR: 0.000095\n","Epoch 37/45 -> Train Loss: 2.1843 | Train Acc: 45.51% | LR: 0.000054\n","Epoch 38/45 -> Train Loss: 2.1596 | Train Acc: 45.93% | LR: 0.000024\n","Epoch 39/45 -> Train Loss: 2.1380 | Train Acc: 46.32% | LR: 0.000006\n","Epoch 40/45 -> Train Loss: 2.1291 | Train Acc: 46.58% | LR: 0.000000\n","πŸ”’ [SYSTEM-SAVER] Progres Epoch 40 berhasil dikunci ke disk!\n","\n","πŸ”’ Memulai Pengujian Validasi Akhir...\n","=== HASIL EVALUASI AKHIR LOOKTHEM V5 ===\n","Test Loss: 2.8726 | Test Accuracy: 35.46%\n","🏁 Selesai! Ukuran berkas final: 5.38 MB\n"]}]},{"cell_type":"code","source":["import os\n","import zipfile\n","import urllib.request\n","import math\n","import torch\n","import torch.nn as nn\n","import torch.nn.functional as F\n","from torch.utils.data import DataLoader\n","from torchvision import datasets, transforms\n","\n","# ==========================================\n","# 1. DOWNLOAD & PREPROCESS DATASET (TINY-IMAGENET)\n","# (Minimal setup for data loaders)\n","# ==========================================\n","def prepare_tiny_imagenet():\n"," dataset_url = \"http://cs231n.stanford.edu/tiny-imagenet-200.zip\"\n"," zip_path = \"./tiny-imagenet-200.zip\"\n"," extract_path = \"./tiny-imagenet-200\"\n","\n"," if not os.path.exists(zip_path):\n"," print(\"πŸ“₯ Mengunduh Tiny-ImageNet (~230MB)... Mohon tunggu...\")\n"," urllib.request.urlretrieve(dataset_url, zip_path)\n"," print(\"βœ… Download Selesai!\")\n","\n"," if not os.path.exists(extract_path):\n"," print(\"πŸ“¦ Mengekstrak dataset...\")\n"," with zipfile.ZipFile(zip_path, 'r') as zip_ref:\n"," zip_ref.extractall(\"./\")\n"," print(\"βœ… Ekstrak Selesai!\")\n","\n"," return os.path.join(extract_path, \"train\"), os.path.join(extract_path, \"val\")\n","\n","train_dir, val_dir = prepare_tiny_imagenet()\n","\n","# Merapikan folder validasi bawaan Tiny-ImageNet\n","val_img_dir = \"./tiny-imagenet-200/val/images\"\n","val_annotations = \"./tiny-imagenet-200/val/val_annotations.txt\"\n","\n","# Only run if original structure detected to prevent errors on rerun\n","if os.path.exists(val_img_dir) and not os.path.exists(\"./tiny-imagenet-200/val/n01443537\") : # Check for a common class folder to see if it's already structured\n"," print(\"🧹 Merapikan struktur folder Validation asli Tiny-ImageNet...\")\n"," with open(val_annotations, \"r\") as f:\n"," lines = f.readlines()\n","\n"," for line in lines:\n"," parts = line.strip().split(\"\\t\")\n"," img_name, class_name = parts[0], parts[1]\n"," class_dir = os.path.join(\"./tiny-imagenet-200/val\", class_name)\n"," os.makedirs(class_dir, exist_ok=True)\n"," src_path = os.path.join(val_img_dir, img_name)\n"," dst_path = os.path.join(class_dir, img_name)\n"," if os.path.exists(src_path):\n"," os.rename(src_path, dst_path)\n"," os.rmdir(val_img_dir)\n"," print(\"βœ… Folder Validation sekarang sudah rapi!\")\n","\n","transform_train = transforms.Compose([\n"," transforms.RandomHorizontalFlip(),\n"," transforms.RandomRotation(15),\n"," transforms.ToTensor(),\n"," transforms.Normalize((0.4802, 0.4481, 0.3975), (0.2302, 0.2265, 0.2262))\n","])\n","\n","transform_val = transforms.Compose([\n"," transforms.ToTensor(),\n"," transforms.Normalize((0.4802, 0.4481, 0.3975), (0.2302, 0.2265, 0.2262))\n","])\n","\n","train_dataset = datasets.ImageFolder(root=train_dir, transform=transform_train)\n","val_dataset = datasets.ImageFolder(root=val_dir, transform=transform_val)\n","\n","train_loader = DataLoader(train_dataset, batch_size=128, shuffle=False, num_workers=2, pin_memory=True) # Shuffle=False for consistent accuracy calculation\n","val_loader = DataLoader(val_dataset, batch_size=256, shuffle=False, num_workers=2, pin_memory=True)\n","\n","# ==========================================\n","# 2. CORE LAYER: LOOKTHEM CORE LAYER\n","# (Copied from tFR4mJB3Aavo)\n","# ==========================================\n","class LookThemLayer(nn.Module):\n"," def __init__(self, num_tokens, in_features, hidden_dim):\n"," super(LookThemLayer, self).__init__()\n"," self.num_tokens = num_tokens\n"," self.in_features = in_features\n","\n"," self.mod1_w1 = nn.Parameter(torch.randn(num_tokens, in_features, hidden_dim))\n"," self.mod1_b1 = nn.Parameter(torch.zeros(num_tokens, hidden_dim))\n"," self.mod1_w2 = nn.Parameter(torch.randn(num_tokens, hidden_dim, 1))\n"," self.mod1_b2 = nn.Parameter(torch.zeros(num_tokens, 1))\n","\n"," self.mod2_w1 = nn.Parameter(torch.randn(num_tokens, in_features, hidden_dim))\n"," self.mod2_b1 = nn.Parameter(torch.zeros(num_tokens, hidden_dim))\n"," self.mod2_w2 = nn.Parameter(torch.randn(num_tokens, hidden_dim, 1))\n"," self.mod2_b2 = nn.Parameter(torch.zeros(num_tokens, 1))\n","\n"," self.trans_w = nn.Parameter(torch.randn(num_tokens, 1, 1))\n"," self.trans_b = nn.Parameter(torch.zeros(num_tokens, 1))\n"," self._init_weights()\n","\n"," def _init_weights(self):\n"," for w in [self.mod1_w1, self.mod2_w1, self.mod1_w2, self.mod2_w2, self.trans_w]:\n"," nn.init.kaiming_uniform_(w, a=math.sqrt(5))\n","\n"," def forward(self, x):\n"," N = self.num_tokens\n"," h1 = torch.einsum('bti,tij->btj', x, self.mod1_w1) + self.mod1_b1\n"," out_m1 = torch.einsum('btj,tjk->btk', F.gelu(h1), self.mod1_w2) + self.mod1_b2\n","\n"," h2 = torch.einsum('bti,tij->btj', x, self.mod2_w1) + self.mod2_b1\n"," out_m2 = torch.einsum('btj,tjk->btk', F.gelu(h2), self.mod2_w2) + self.mod2_b2\n","\n"," out_m2_safe = out_m2 + 1e-5\n"," compare = torch.tanh(out_m1.unsqueeze(2) / out_m2_safe.unsqueeze(1))\n"," compare2 = torch.tanh(out_m1.unsqueeze(1) / out_m2_safe.unsqueeze(2))\n","\n"," bias_reshaped = self.trans_b.view(1, 1, N, 1)\n"," trans_compare = torch.einsum('bije,jef->bijf', compare, self.trans_w) + bias_reshaped\n"," trans_compare2 = torch.einsum('bije,jef->bijf', compare2, self.trans_w) + bias_reshaped\n","\n"," interaksi = (trans_compare * x.unsqueeze(2) + trans_compare2 * x.unsqueeze(1)) / 2\n"," mask = 1.0 - torch.eye(N, device=x.device)\n"," interaksi_masked = interaksi * mask.view(1, N, N, 1)\n","\n"," return interaksi_masked.sum(dim=2) / (N - 1.0)\n","\n","# ==========================================\n","# 3. INDUK ARSITEKTUR: LOOKTHEM V5 (STANDARD CONV STREAM B)\n","# (Copied from tFR4mJB3Aavo)\n","# ==========================================\n","class LookThemV5(nn.Module):\n"," def __init__(self):\n"," super(LookThemV5, self).__init__()\n","\n"," self.register_buffer('grayscale_weights', torch.tensor([0.299, 0.587, 0.114]).view(1, 3, 1, 1))\n","\n"," # --- STREAM A: BENTUK MAKRO (Ditahan di 16x16 - Resolusi Tinggi) ---\n"," self.stream_a = nn.Sequential(\n"," nn.Conv2d(1, 16, kernel_size=3, stride=2, padding=1), # [B, 16, 32, 32]\n"," nn.BatchNorm2d(16), nn.GELU(),\n"," nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 16, 16] (256 Luas Spasial)\n"," nn.BatchNorm2d(32), nn.GELU()\n"," )\n","\n"," # Jembatan Progresif Token: Mengompres spasial 256 -> 64 token secara cerdas\n"," self.token_bridge = nn.Linear(256, 64)\n","\n"," # --- STREAM B: ESENSI WARNA (Mengecil ke 8x8 Mengikuti Pola V2 - Standard Conv) ---\n"," self.stream_b = nn.Sequential(\n"," nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1), # [B, 16, 32, 32]\n"," nn.BatchNorm2d(16), nn.GELU(),\n"," nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 16, 16]\n"," nn.BatchNorm2d(32), nn.GELU(),\n","\n"," # UPDATE V5: Menggunakan Standard Conv Stride murni gaya V2 agar kombinasi warna langsung padat\n"," nn.Conv2d(32, 32, kernel_size=3, stride=2, padding=1), # [B, 32, 8, 8] (64 Luas Spasial)\n"," nn.BatchNorm2d(32), nn.GELU()\n"," )\n","\n"," # --- CORE COGNITION LAYER (64 Token, Gabungan Features 32 + 32 = 64) ---\n"," self.lookthem = LookThemLayer(num_tokens=64, in_features=64, hidden_dim=32)\n","\n"," # --- CLASSIFIER RAMPING ANTI-OVERFIT ---\n"," self.classifier = nn.Sequential(\n"," nn.Flatten(),\n"," nn.Linear(64 * 64, 256),\n"," nn.ReLU(),\n"," nn.Dropout(0.4),\n"," nn.Linear(256, 200)\n"," )\n","\n"," def forward(self, x):\n"," batch_size = x.size(0)\n","\n"," # 1. Ekstrak Stream A (Grayscale 16x16)\n"," x_gray = torch.sum(x * self.grayscale_weights, dim=1, keepdim=True)\n"," feat_a = self.stream_a(x_gray) # [B, 32, 16, 16]\n"," feat_a_flat = feat_a.view(batch_size, 32, 256)\n"," feat_a_compressed = self.token_bridge(feat_a_flat) # [B, 32, 64]\n"," feat_a_tokens = feat_a_compressed.transpose(1, 2) # [B, 64 Token, 32 Features]\n","\n"," # 2. Ekstrak Stream B (RGB 8x8 via Standard Conv)\n"," feat_b = self.stream_b(x) # [B, 32, 8, 8]\n"," feat_b_tokens = feat_b.view(batch_size, 32, 64).transpose(1, 2) # [B, 64 Token, 32 Features]\n","\n"," # 3. Penggabungan Asimetris Tingkat Features (Total tetap 64 Token)\n"," tokens_combined = torch.cat([feat_a_tokens, feat_b_tokens], dim=2) # [B, 64 Token, 64 Features]\n","\n"," # 4. Kognisi Relasional & Klasifikasi\n"," out_lookthem = self.lookthem(tokens_combined)\n"," return self.classifier(out_lookthem)\n","\n","# ==========================================\n","# 4. MODEL AND DEVICE SETUP\n","# ==========================================\n","device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n","model = LookThemV5().to(device)\n","\n","# Ensure the model checkpoint exists. If not, you might need to run the training cell first.\n","if os.path.exists(\"LookThem_V5_Final.pth\"):\n"," model.load_state_dict(torch.load(\"LookThem_V5_Final.pth\", map_location=device))\n"," print(\"βœ… Model 'LookThem_V5_Final.pth' loaded successfully!\")\n","else:\n"," print(\"⚠️ Model checkpoint 'LookThem_V5_Final.pth' not found. Please train the model first or provide the correct path.\")\n","\n","# ==========================================\n","# 5. ACCURACY CALCULATION\n","# ==========================================\n","def calculate_accuracy(model, dataloader, device, topk=(1, 5)):\n"," model.eval()\n"," total_samples = 0\n"," correct_top1 = 0\n"," correct_top5 = 0\n","\n"," with torch.no_grad():\n"," for data, target in dataloader:\n"," data, target = data.to(device), target.to(device)\n"," output = model(data)\n","\n"," # Calculate top-1 accuracy\n"," _, predicted_top1 = output.max(1)\n"," correct_top1 += predicted_top1.eq(target).sum().item()\n","\n"," # Calculate top-5 accuracy\n"," _, predicted_top5 = output.topk(max(topk), 1, True, True)\n"," target_reshaped = target.view(target.size(0), -1).expand_as(predicted_top5)\n"," correct_top5 += predicted_top5.eq(target_reshaped).sum().item()\n","\n"," total_samples += target.size(0)\n","\n"," top1_acc = 100. * correct_top1 / total_samples\n"," top5_acc = 100. * correct_top5 / total_samples\n"," return top1_acc, top5_acc\n","\n","print(\"\\n=== Calculating Top-1 and Top-5 Accuracy ===\")\n","\n","# Calculate accuracy for training set\n","train_top1_acc, train_top5_acc = calculate_accuracy(model, train_loader, device)\n","print(f\"Train Top-1 Accuracy: {train_top1_acc:.2f}%\")\n","print(f\"Train Top-5 Accuracy: {train_top5_acc:.2f}%\")\n","\n","# Calculate accuracy for validation set\n","val_top1_acc, val_top5_acc = calculate_accuracy(model, val_loader, device)\n","print(f\"Validation Top-1 Accuracy: {val_top1_acc:.2f}%\")\n","print(f\"Validation Top-5 Accuracy: {val_top5_acc:.2f}%\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"PycAPwVwIjla","executionInfo":{"status":"ok","timestamp":1779025489199,"user_tz":-420,"elapsed":246498,"user":{"displayName":"Cici rizky plk","userId":"03714270658772765776"}},"outputId":"3fc71bdb-c1b0-4257-8ea6-2f448a513793"},"execution_count":null,"outputs":[{"metadata":{"tags":null},"name":"stdout","output_type":"stream","text":["πŸ“₯ Mengunduh Tiny-ImageNet (~230MB)... Mohon tunggu...\n","βœ… Download Selesai!\n","πŸ“¦ Mengekstrak dataset...\n","βœ… Ekstrak Selesai!\n","🧹 Merapikan struktur folder Validation asli Tiny-ImageNet...\n","βœ… Folder Validation sekarang sudah rapi!\n","βœ… Model 'LookThem_V5_Final.pth' loaded successfully!\n","\n","=== Calculating Top-1 and Top-5 Accuracy ===\n"]},{"metadata":{"tags":null},"name":"stderr","output_type":"stream","text":["/usr/local/lib/python3.12/dist-packages/torch/utils/data/dataloader.py:1118: UserWarning: 'pin_memory' argument is set as true but no accelerator is found, then device pinned memory won't be used.\n"," super().__init__(loader)\n"]},{"output_type":"stream","name":"stdout","text":["Train Top-1 Accuracy: 59.76%\n","Train Top-5 Accuracy: 83.41%\n","Validation Top-1 Accuracy: 35.46%\n","Validation Top-5 Accuracy: 61.87%\n"]}]}]}