{"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":6799,"databundleVersionId":4225553},{"sourceType":"datasetVersion","sourceId":2409323,"datasetId":1457432,"databundleVersionId":2451409}],"dockerImageVersionId":31328,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<div style=\"background-color:#fff; padding:40px; display:flex; justify-content:center; align-items:center; font-family:Arial, sans-serif;\">\n  <div style=\"background-color:#ffffff; padding:30px; border-radius:12px; max-width:600px; width:100%; text-align:center; box-shadow:0 10px 25px rgba(0,0,0,0.15);margin:0 auto;\">\n      <img src=\"https://holosen.net/public/src/img/logo/holosen-logo.png\" width=\"50\"/>\n    <p style=\"font-size:18px; font-weight:bold; color:#222222; line-height:1.8; margin-bottom:25px;text-align:justify\">\n     I prepared this code for the Holosen Artificial Intelligence 0-100 training course.\n        <br/>\n        For more detailed Persian training resources, you can visit:\n    </p>\n    <a href=\"https://holosen.net/artificial-intelligence/?src=kaggle\" target=\"_blank\" \n       style=\"display:inline-block; background-color:#525fe1; color:#ffffff; text-decoration:none; padding:14px 28px; border-radius:8px; font-size:16px; font-weight:bold;\">\n       Holosen Artificial Intelligence 0-100 Training Course\n    </a>\n  </div>\n</div>","metadata":{}},{"cell_type":"code","source":"import os\nimport torch\nimport random\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.init as init\nimport matplotlib.pyplot as plt\nfrom torchvision import transforms, datasets\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import random_split, DataLoader","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:17.469649Z","iopub.execute_input":"2026-03-23T17:11:17.47021Z","iopub.status.idle":"2026-03-23T17:11:29.923314Z","shell.execute_reply.started":"2026-03-23T17:11:17.47016Z","shell.execute_reply":"2026-03-23T17:11:29.922425Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Configuration","metadata":{}},{"cell_type":"code","source":"# DATA_PATH = '/kaggle/input/competitions/imagenet-object-localization-challenge/ILSVRC/Data/CLS-LOC/train'\nDATA_PATH = '/kaggle/input/datasets/arjunashok33/miniimagenet'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:29.925297Z","iopub.execute_input":"2026-03-23T17:11:29.925844Z","iopub.status.idle":"2026-03-23T17:11:29.929282Z","shell.execute_reply.started":"2026-03-23T17:11:29.925812Z","shell.execute_reply":"2026-03-23T17:11:29.928677Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BATCH_SIZE = 128\nEPOCHS = 10\nIMAGE_SIZE = 227\nWORKERS = 4","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:29.930275Z","iopub.execute_input":"2026-03-23T17:11:29.930614Z","iopub.status.idle":"2026-03-23T17:11:29.950039Z","shell.execute_reply.started":"2026-03-23T17:11:29.930556Z","shell.execute_reply":"2026-03-23T17:11:29.949439Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"NUM_CLASSESS_TO_USE = -1 # all => -1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:29.950966Z","iopub.execute_input":"2026-03-23T17:11:29.95126Z","iopub.status.idle":"2026-03-23T17:11:29.964236Z","shell.execute_reply.started":"2026-03-23T17:11:29.951237Z","shell.execute_reply":"2026-03-23T17:11:29.963665Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ndevice","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:29.965151Z","iopub.execute_input":"2026-03-23T17:11:29.965498Z","iopub.status.idle":"2026-03-23T17:11:30.236822Z","shell.execute_reply.started":"2026-03-23T17:11:29.965462Z","shell.execute_reply":"2026-03-23T17:11:30.235984Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# ETL","metadata":{}},{"cell_type":"markdown","source":"## Tranform","metadata":{}},{"cell_type":"code","source":"train_transform = transforms.Compose([\n    transforms.Resize(256),\n    transforms.RandomCrop(IMAGE_SIZE),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\n\nval_transform = transforms.Compose([\n    transforms.Resize(256),\n    transforms.CenterCrop(IMAGE_SIZE),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:30.237592Z","iopub.execute_input":"2026-03-23T17:11:30.237858Z","iopub.status.idle":"2026-03-23T17:11:30.252572Z","shell.execute_reply.started":"2026-03-23T17:11:30.23782Z","shell.execute_reply":"2026-03-23T17:11:30.25178Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Limited Edition Configuration","metadata":{}},{"cell_type":"code","source":"all_classes = sorted(os.listdir(DATA_PATH))\nprint(\"All classes count:\", len(all_classes))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:30.255268Z","iopub.execute_input":"2026-03-23T17:11:30.255728Z","iopub.status.idle":"2026-03-23T17:11:30.27735Z","shell.execute_reply.started":"2026-03-23T17:11:30.255681Z","shell.execute_reply":"2026-03-23T17:11:30.276693Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if NUM_CLASSESS_TO_USE != -1:\n    selected_classes = random.sample(all_classes, NUM_CLASSESS_TO_USE)\nelse:\n    selected_classes = all_classes\n\nprint(\"selected classes count:\",len(selected_classes))\nselected_classes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:30.278301Z","iopub.execute_input":"2026-03-23T17:11:30.278825Z","iopub.status.idle":"2026-03-23T17:11:30.285028Z","shell.execute_reply.started":"2026-03-23T17:11:30.278796Z","shell.execute_reply":"2026-03-23T17:11:30.284312Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"subset_path = '/kaggle/working/subset_data'\n\nif not os.path.exists(subset_path):\n    os.makedirs(subset_path)\n    \n    for cls in selected_classes:\n        src = os.path.join(DATA_PATH, cls)\n        dst = os.path.join(subset_path, cls)\n        os.symlink(src, dst)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:30.285796Z","iopub.execute_input":"2026-03-23T17:11:30.286064Z","iopub.status.idle":"2026-03-23T17:11:30.300404Z","shell.execute_reply.started":"2026-03-23T17:11:30.286032Z","shell.execute_reply":"2026-03-23T17:11:30.299756Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Dataset","metadata":{}},{"cell_type":"code","source":"dataset = datasets.ImageFolder(subset_path, transform=train_transform)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:30.301266Z","iopub.execute_input":"2026-03-23T17:11:30.30153Z","iopub.status.idle":"2026-03-23T17:11:50.72123Z","shell.execute_reply.started":"2026-03-23T17:11:30.301506Z","shell.execute_reply":"2026-03-23T17:11:50.720462Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Count of classes:\",len(dataset.classes))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:50.722283Z","iopub.execute_input":"2026-03-23T17:11:50.722601Z","iopub.status.idle":"2026-03-23T17:11:50.727013Z","shell.execute_reply.started":"2026-03-23T17:11:50.722576Z","shell.execute_reply":"2026-03-23T17:11:50.726307Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train / Validation","metadata":{}},{"cell_type":"code","source":"train_size = int(0.9 * len(dataset))\nval_size = len(dataset) - train_size\n\nprint(\"train size:\",train_size,\", validation size:\",val_size)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:50.727937Z","iopub.execute_input":"2026-03-23T17:11:50.728237Z","iopub.status.idle":"2026-03-23T17:11:50.749269Z","shell.execute_reply.started":"2026-03-23T17:11:50.728199Z","shell.execute_reply":"2026-03-23T17:11:50.748637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data, val_data = random_split(dataset, [train_size, val_size])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:50.750107Z","iopub.execute_input":"2026-03-23T17:11:50.75036Z","iopub.status.idle":"2026-03-23T17:11:50.798167Z","shell.execute_reply.started":"2026-03-23T17:11:50.750337Z","shell.execute_reply":"2026-03-23T17:11:50.797525Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_data.dataset.transform = val_transform","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:50.799Z","iopub.execute_input":"2026-03-23T17:11:50.799204Z","iopub.status.idle":"2026-03-23T17:11:50.803057Z","shell.execute_reply.started":"2026-03-23T17:11:50.799183Z","shell.execute_reply":"2026-03-23T17:11:50.802401Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Mini Batch","metadata":{}},{"cell_type":"code","source":"train_loader = DataLoader(\n    train_data,\n    batch_size=BATCH_SIZE,\n    shuffle=True,\n    num_workers=WORKERS,\n    pin_memory=True,\n    persistent_workers=True,\n    prefetch_factor=2\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:50.804106Z","iopub.execute_input":"2026-03-23T17:11:50.8045Z","iopub.status.idle":"2026-03-23T17:11:50.818411Z","shell.execute_reply.started":"2026-03-23T17:11:50.804461Z","shell.execute_reply":"2026-03-23T17:11:50.817842Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_loader = DataLoader(\n    val_data,\n    batch_size=BATCH_SIZE,\n    num_workers=WORKERS,\n    pin_memory=True,\n    persistent_workers=True,\n    prefetch_factor=2\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:50.819245Z","iopub.execute_input":"2026-03-23T17:11:50.819535Z","iopub.status.idle":"2026-03-23T17:11:50.833418Z","shell.execute_reply.started":"2026-03-23T17:11:50.819496Z","shell.execute_reply":"2026-03-23T17:11:50.832697Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Model (AlexNet)","metadata":{}},{"cell_type":"code","source":"model = nn.Sequential(\n\n    # Layer1 => Conv\n    nn.Conv2d(3, 96, kernel_size=11, stride=4),\n    nn.ReLU(),\n    nn.LocalResponseNorm(5),\n    nn.MaxPool2d(3, stride=2),\n\n    # Layer2 => Conv\n    nn.Conv2d(96, 256, kernel_size=5, padding=2, groups=2),\n    nn.ReLU(),\n    nn.LocalResponseNorm(5),\n    nn.MaxPool2d(3, stride=2),\n\n    # Layer3 => Conv\n    nn.Conv2d(256, 384, kernel_size=3, padding=1),\n    nn.ReLU(),\n\n    # Layer4 => Conv\n    nn.Conv2d(384, 384, kernel_size=3, padding=1, groups=2),\n    nn.ReLU(),\n\n    # Layer5 => Conv\n    nn.Conv2d(384, 256, kernel_size=3, padding=1, groups=2),\n    nn.ReLU(),\n    nn.MaxPool2d(3, stride=2),\n\n    nn.Flatten(),\n\n    # FC1 => Linear\n    nn.Linear(256 * 6 * 6, 4096),\n    nn.ReLU(),\n    nn.Dropout(0.5),\n\n    # FC2 => Linear\n    nn.Linear(4096,4096),\n    nn.ReLU(),\n    nn.Dropout(0.5),\n\n    nn.Linear(4096, len(dataset.classes))\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:50.83442Z","iopub.execute_input":"2026-03-23T17:11:50.834755Z","iopub.status.idle":"2026-03-23T17:11:51.284834Z","shell.execute_reply.started":"2026-03-23T17:11:50.834698Z","shell.execute_reply":"2026-03-23T17:11:51.284011Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## MultiGPU Support","metadata":{}},{"cell_type":"code","source":"if torch.cuda.device_count() > 1:\n    model = nn.DataParallel(model)\n\nmodel = model.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:51.285867Z","iopub.execute_input":"2026-03-23T17:11:51.286164Z","iopub.status.idle":"2026-03-23T17:11:51.693982Z","shell.execute_reply.started":"2026-03-23T17:11:51.286133Z","shell.execute_reply":"2026-03-23T17:11:51.693291Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Weight Initialization","metadata":{}},{"cell_type":"code","source":"for layer in model.modules():\n    if isinstance(layer, (nn.Linear, nn.Conv2d)):\n        init.normal_(layer.weight, 0, 0.01)\n        if layer.bias is not None:\n            nn.init.zeros_(layer.bias)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:51.694779Z","iopub.execute_input":"2026-03-23T17:11:51.694995Z","iopub.status.idle":"2026-03-23T17:11:51.761244Z","shell.execute_reply.started":"2026-03-23T17:11:51.694974Z","shell.execute_reply":"2026-03-23T17:11:51.760376Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Training Setup","metadata":{}},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\n\noptimizer = optim.SGD(\n    model.parameters(),\n    lr=0.01,\n    momentum=0.9,\n    weight_decay=5e-4\n)\n\nscheduler = optim.lr_scheduler.StepLR(optimizer,step_size=10,gamma=0.1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:51.762196Z","iopub.execute_input":"2026-03-23T17:11:51.762504Z","iopub.status.idle":"2026-03-23T17:11:51.767125Z","shell.execute_reply.started":"2026-03-23T17:11:51.762464Z","shell.execute_reply":"2026-03-23T17:11:51.766517Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Tracking","metadata":{}},{"cell_type":"code","source":"train_losses = []\nval_losses = []\nlrs = []","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:51.767969Z","iopub.execute_input":"2026-03-23T17:11:51.768194Z","iopub.status.idle":"2026-03-23T17:11:51.7845Z","shell.execute_reply.started":"2026-03-23T17:11:51.768175Z","shell.execute_reply":"2026-03-23T17:11:51.783801Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for epoch in range(EPOCHS):\n\n    # Train\n    model.train()\n    train_loss = 0\n\n    for images, labels in train_loader:\n\n        images = images.to(device) # GPU/CPU\n        labels = labels.to(device) # GPU/CPU\n        \n        outputs = model(images)\n        loss = criterion(outputs, labels)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        train_loss += loss.item()\n\n    train_loss /= len(train_loader)\n\n    # Validation\n    model.eval()\n    val_loss = 0\n\n    with torch.no_grad():\n        for images, labels in val_loader:\n\n            images = images.to(device) # GPU/CPU\n            labels = labels.to(device) # GPU/CPU\n            \n            outputs = model(images)\n            loss = criterion(outputs, labels)\n\n            val_loss += loss.item()\n\n        val_loss /= len(val_loader)\n\n    current_lr = optimizer.param_groups[0]['lr']\n\n    # saving metrics\n    train_losses.append(train_loss)\n    val_losses.append(val_loss)\n    lrs.append(current_lr)\n    \n    print(f\"Epoch {epoch} => train loss = {train_loss:.4f}, val loss = {val_loss:.4f}, lr = {current_lr:.6f}\")\n\n    # Scheduler Step\n    scheduler.step()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:11:51.787371Z","iopub.execute_input":"2026-03-23T17:11:51.787613Z","iopub.status.idle":"2026-03-23T17:15:25.208009Z","shell.execute_reply.started":"2026-03-23T17:11:51.787574Z","shell.execute_reply":"2026-03-23T17:15:25.207005Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Plot\n## Learning Curve","metadata":{}},{"cell_type":"code","source":"plt.figure()\nplt.plot(train_losses, label=\"Train Loss\")\nplt.plot(val_losses, label = \"Validation Loss\")\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"Loss\")\nplt.title(\"Learning Curve\")\nplt.legend()\nplt.grid()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:15:25.209934Z","iopub.execute_input":"2026-03-23T17:15:25.21027Z","iopub.status.idle":"2026-03-23T17:15:25.413056Z","shell.execute_reply.started":"2026-03-23T17:15:25.210226Z","shell.execute_reply":"2026-03-23T17:15:25.412287Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Learning Rate","metadata":{}},{"cell_type":"code","source":"plt.figure()\nplt.plot(lrs, label=\"Learning Rate\")\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"LR\")\nplt.title(\"Learning Schedule\")\nplt.legend()\nplt.grid()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:15:25.414087Z","iopub.execute_input":"2026-03-23T17:15:25.414404Z","iopub.status.idle":"2026-03-23T17:15:25.543571Z","shell.execute_reply.started":"2026-03-23T17:15:25.414376Z","shell.execute_reply":"2026-03-23T17:15:25.542929Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Saving Model","metadata":{}},{"cell_type":"code","source":"torch.save(\n    model.module.state_dict() if hasattr(model, \"module\") else model.state_dict(),\n    \"/kaggle/working/alexnet.pth\"\n)\nprint(\"Model Saved\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-23T17:15:25.54461Z","iopub.execute_input":"2026-03-23T17:15:25.544991Z","iopub.status.idle":"2026-03-23T17:15:25.972655Z","shell.execute_reply.started":"2026-03-23T17:15:25.544957Z","shell.execute_reply":"2026-03-23T17:15:25.972017Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Publishing Model","metadata":{}},{"cell_type":"code","source":"import json\n\nwith open(\"/kaggle/working/classes.json\", \"w\") as f:\n    json.dump(dataset.classes, f)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}