{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":125281,"databundleVersionId":14781158,"sourceType":"competition"}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nimport random\nimport os\n\n\nrandom_seed = 2025\nBATCH_SIZE = 64\nLR = 0.001\nEPOCHS = 5\nNUM_WORKERS = 2\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n#print(f\"Using device: {DEVICE}\")\n\n\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False\n\n\n\ndef seed_worker(worker_id):\n    worker_seed = torch.initial_seed() % 2 ** 32\n    np.random.seed(worker_seed)\n    random.seed(worker_seed)\n\n\nclass SatelliteDataset(Dataset):\n    def __init__(self, x_data, y_data=None, transform=None):\n        self.x = torch.FloatTensor(x_data).permute(0, 3, 1, 2) / 255.0\n        self.y = torch.LongTensor(y_data) if y_data is not None else None\n\n    def __len__(self):\n        return len(self.x)\n\n    def __getitem__(self, idx):\n        if self.y is not None:\n            return self.x[idx], self.y[idx]\n        else:\n            return self.x[idx]\n\n\nclass SimpleCNN(nn.Module):\n    def __init__(self, num_classes=10):\n        super(SimpleCNN, self).__init__()\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 32, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2),  # 64->32\n            nn.Conv2d(32, 64, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2),  # 32->16\n            nn.Conv2d(64, 128, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2)  # 16->8\n        )\n        self.classifier = nn.Sequential(\n            nn.Flatten(),\n            nn.Linear(128 * 8 * 8, 256),\n            nn.ReLU(),\n            nn.Linear(256, num_classes)\n        )\n\n    def forward(self, x):\n        x = self.features(x)\n        x = self.classifier(x)\n        return x\n\n\ndef run_topic5_baseline():\n    seed_everything(random_seed)\n\n    g = torch.Generator()\n    g.manual_seed(random_seed)\n\n    print(\"Loading data...\")\n\n    train_data = np.load('/kaggle/input/cugb-ml-2025-cnn/train.npz')\n    test_data = np.load('/kaggle/input/cugb-ml-2025-cnn/test.npz')\n\n    X_all = train_data['x']\n    y_all = train_data['y']\n    X_test_np = test_data['x']\n\n    X_train, X_val, y_train, y_val = train_test_split(\n        X_all, y_all, test_size=0.2, random_state=random_seed\n    )\n\n\n    train_loader = DataLoader(\n        SatelliteDataset(X_train, y_train),\n        batch_size=BATCH_SIZE,\n        shuffle=True,\n        num_workers=NUM_WORKERS,\n        worker_init_fn=seed_worker,\n        generator=g\n    )\n\n    val_loader = DataLoader(\n        SatelliteDataset(X_val, y_val),\n        batch_size=BATCH_SIZE,\n        shuffle=False,\n        num_workers=NUM_WORKERS,\n        worker_init_fn=seed_worker,\n        generator=g\n    )\n\n    test_loader = DataLoader(\n        SatelliteDataset(X_test_np),\n        batch_size=BATCH_SIZE,\n        shuffle=False,\n        num_workers=NUM_WORKERS,\n        worker_init_fn=seed_worker,\n        generator=g\n    )\n\n    model = SimpleCNN().to(DEVICE)\n    criterion = nn.CrossEntropyLoss()\n    optimizer = optim.Adam(model.parameters(), lr=LR)\n\n    print(\"Starting Training...\")\n    for epoch in range(EPOCHS):\n        model.train()\n        running_loss = 0.0\n        for inputs, labels in train_loader:\n            inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)\n            optimizer.zero_grad()\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n            running_loss += loss.item()\n\n        # Validation\n        model.eval()\n        correct = 0\n        total = 0\n        with torch.no_grad():\n            for inputs, labels in val_loader:\n                inputs, labels = inputs.to(DEVICE), labels.to(DEVICE)\n                outputs = model(inputs)\n                _, predicted = torch.max(outputs.data, 1)\n                total += labels.size(0)\n                correct += (predicted == labels).sum().item()\n\n        val_acc = 100 * correct / total\n        print(f\"Epoch {epoch + 1}/{EPOCHS}, Loss: {running_loss / len(train_loader):.4f}, Val Acc: {val_acc:.2f}%\")\n\n    print(\"Predicting Test Set...\")\n    model.eval()\n    all_preds = []\n    with torch.no_grad():\n        for inputs in test_loader:\n            inputs = inputs.to(DEVICE)\n            outputs = model(inputs)\n            _, predicted = torch.max(outputs.data, 1)\n            all_preds.extend(predicted.cpu().numpy())\n\n    ids = np.arange(len(all_preds))\n    submission = pd.DataFrame({'Id': ids, 'Category': all_preds})\n    submission.to_csv('MySubmission_topic5.csv', index=False)\n    print(\"Done! Saved to MySubmission_topic5.csv\")\n\n\nif __name__ == '__main__':\n    run_topic5_baseline()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-05T08:00:53.214833Z","iopub.execute_input":"2025-12-05T08:00:53.215230Z","iopub.status.idle":"2025-12-05T08:07:01.297913Z","shell.execute_reply.started":"2025-12-05T08:00:53.215193Z","shell.execute_reply":"2025-12-05T08:07:01.296180Z"}},"outputs":[],"execution_count":null}]}