{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":31011,"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)\nimport pandas as pd\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import models, transforms\nimport numpy as np\nfrom PIL import Image\nimport torch.nn as nn\nimport torch.optim as optim\nfrom sklearn.model_selection import train_test_split\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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-03T18:35:36.139556Z","iopub.execute_input":"2025-05-03T18:35:36.139843Z","iopub.status.idle":"2025-05-03T18:35:46.567545Z","shell.execute_reply.started":"2025-05-03T18:35:36.139817Z","shell.execute_reply":"2025-05-03T18:35:46.566689Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-03T18:35:46.569234Z","iopub.execute_input":"2025-05-03T18:35:46.570099Z","iopub.status.idle":"2025-05-03T18:35:49.567367Z","shell.execute_reply.started":"2025-05-03T18:35:46.570080Z","shell.execute_reply":"2025-05-03T18:35:49.566634Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class MNISTFromCSV(Dataset):\n    def __init__(self, df, transform=None):\n        self.images = df[[f\"pixel{i}\" for i in range(784)]].values.reshape(-1, 28, 28).astype(np.uint8)\n        self.labels = df[\"label\"].values\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.labels)\n\n    def __getitem__(self, idx):\n        image = Image.fromarray(self.images[idx], mode='L')  # 'L' = grayscale\n        if self.transform:\n            image = self.transform(image)\n        label = torch.tensor(self.labels[idx], dtype=torch.long)\n        return image, label\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-03T18:35:49.568149Z","iopub.execute_input":"2025-05-03T18:35:49.568384Z","iopub.status.idle":"2025-05-03T18:35:49.573748Z","shell.execute_reply.started":"2025-05-03T18:35:49.568357Z","shell.execute_reply":"2025-05-03T18:35:49.573122Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")  # adjust path\ntrain_df, val_df = train_test_split(df, test_size=0.2, random_state=42)\n\n# Convert 1-channel (grayscale) to 3-channel by duplication\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),  # Required for ResNet\n    transforms.Grayscale(num_output_channels=3),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)  # Normalized to [-1, 1]\n])\n\ntrain_dataset = MNISTFromCSV(train_df, transform)\nval_dataset = MNISTFromCSV(val_df, transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=64)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-03T18:35:49.574490Z","iopub.execute_input":"2025-05-03T18:35:49.574708Z","iopub.status.idle":"2025-05-03T18:35:51.690494Z","shell.execute_reply.started":"2025-05-03T18:35:49.574694Z","shell.execute_reply":"2025-05-03T18:35:51.689889Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nmodel = models.resnet18(pretrained=True)\nfor param in model.parameters():\n    param.requires_grad = False  # freeze all layers\n\n# Replace last layer for 10 MNIST classes\nmodel.fc = nn.Linear(model.fc.in_features, 10)\nmodel = model.to(device)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-03T18:35:51.691261Z","iopub.execute_input":"2025-05-03T18:35:51.691552Z","iopub.status.idle":"2025-05-03T18:35:52.593666Z","shell.execute_reply.started":"2025-05-03T18:35:51.691527Z","shell.execute_reply":"2025-05-03T18:35:52.592923Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.fc.parameters(), lr=0.001)\n\nfor epoch in range(5):  # small number of epochs\n    model.train()\n    total_loss = 0\n    for images, labels in train_loader:\n        images, labels = images.to(device), labels.to(device)\n\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        total_loss += loss.item()\n\n    print(f\"Epoch {epoch+1}, Loss: {total_loss:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-03T18:35:52.594585Z","iopub.execute_input":"2025-05-03T18:35:52.594838Z","iopub.status.idle":"2025-05-03T18:43:57.755926Z","shell.execute_reply.started":"2025-05-03T18:35:52.594820Z","shell.execute_reply":"2025-05-03T18:43:57.755023Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\ncorrect = 0\ntotal = 0\n\nwith torch.no_grad():\n    for images, labels in val_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        predicted = torch.argmax(outputs, dim=1)\n        correct += (predicted == labels).sum().item()\n        total += labels.size(0)\n\nprint(f\"Validation Accuracy: {correct / total:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-03T18:43:57.757855Z","iopub.execute_input":"2025-05-03T18:43:57.758490Z","iopub.status.idle":"2025-05-03T18:44:21.469814Z","shell.execute_reply.started":"2025-05-03T18:43:57.758470Z","shell.execute_reply":"2025-05-03T18:44:21.469094Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}