{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","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":30664,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from torch.utils.data import DataLoader, TensorDataset\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nimport pandas as pd\nimport numpy as np\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:42:52.744782Z","iopub.execute_input":"2024-03-09T20:42:52.745626Z","iopub.status.idle":"2024-03-09T20:42:57.094181Z","shell.execute_reply.started":"2024-03-09T20:42:52.745595Z","shell.execute_reply":"2024-03-09T20:42:57.093061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\ntrain_labels = train_data['label'].values\ntrain_data = train_data.drop('label', axis=1).values","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:42:57.096716Z","iopub.execute_input":"2024-03-09T20:42:57.097293Z","iopub.status.idle":"2024-03-09T20:43:01.055458Z","shell.execute_reply.started":"2024-03-09T20:42:57.097255Z","shell.execute_reply":"2024-03-09T20:43:01.054248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data = train_data / 255.","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:43:01.059165Z","iopub.execute_input":"2024-03-09T20:43:01.060126Z","iopub.status.idle":"2024-03-09T20:43:01.179939Z","shell.execute_reply.started":"2024-03-09T20:43:01.060083Z","shell.execute_reply":"2024-03-09T20:43:01.178841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_val, y_train, y_val = train_test_split(train_data, train_labels, test_size=0.1, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:43:01.181171Z","iopub.execute_input":"2024-03-09T20:43:01.181459Z","iopub.status.idle":"2024-03-09T20:43:01.574834Z","shell.execute_reply.started":"2024-03-09T20:43:01.181432Z","shell.execute_reply":"2024-03-09T20:43:01.573906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train = torch.tensor(X_train, dtype=torch.float32)\nX_train = X_train.view(-1, 1, 28, 28)\ny_train = torch.tensor(y_train, dtype=torch.long)\nX_val = torch.tensor(X_val, dtype=torch.float32)\nX_val = X_val.view(-1, 1, 28, 28)\ny_val = torch.tensor(y_val, dtype=torch.long)\nprint(X_train.shape, y_train.shape, X_val.shape, y_val.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:43:02.216334Z","iopub.execute_input":"2024-03-09T20:43:02.217207Z","iopub.status.idle":"2024-03-09T20:43:02.331767Z","shell.execute_reply.started":"2024-03-09T20:43:02.217165Z","shell.execute_reply":"2024-03-09T20:43:02.330774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")\ntest_data = torch.tensor(test_data.values, dtype=torch.float32)\ntest_data = test_data / 255.\ntest_data = test_data.view(-1, 1, 28, 28)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T21:15:28.702664Z","iopub.execute_input":"2024-03-09T21:15:28.703495Z","iopub.status.idle":"2024-03-09T21:15:30.587513Z","shell.execute_reply.started":"2024-03-09T21:15:28.703464Z","shell.execute_reply":"2024-03-09T21:15:30.586677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = TensorDataset(X_train, y_train)\nval_dataset = TensorDataset(X_val, y_val)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:43:08.815911Z","iopub.execute_input":"2024-03-09T20:43:08.816801Z","iopub.status.idle":"2024-03-09T20:43:08.821815Z","shell.execute_reply.started":"2024-03-09T20:43:08.816761Z","shell.execute_reply":"2024-03-09T20:43:08.820794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del train_data\ndel train_labels\ndel test_data\ndel X_train\ndel y_train\ndel X_val\ndel y_val","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:43:14.481028Z","iopub.execute_input":"2024-03-09T20:43:14.481391Z","iopub.status.idle":"2024-03-09T20:43:14.488285Z","shell.execute_reply.started":"2024-03-09T20:43:14.481360Z","shell.execute_reply":"2024-03-09T20:43:14.487195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 256\ntrain_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)\nval_loader = DataLoader(dataset=val_dataset, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T20:43:21.339152Z","iopub.execute_input":"2024-03-09T20:43:21.339766Z","iopub.status.idle":"2024-03-09T20:43:21.344689Z","shell.execute_reply.started":"2024-03-09T20:43:21.339733Z","shell.execute_reply":"2024-03-09T20:43:21.343695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CNN(nn.Module):\n    def __init__(self, num_outputs):\n        super(CNN, self).__init__()\n\n        self.model = nn.Sequential(\n            nn.Conv2d(in_channels=1, out_channels=32, kernel_size=5, padding=2),\n            nn.BatchNorm2d(32),\n            nn.ReLU(),\n            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),\n            nn.BatchNorm2d(64),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2),\n            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=5, padding=2),\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            nn.Conv2d(in_channels=128, out_channels=256, kernel_size=5, padding=2),\n            nn.BatchNorm2d(256),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2),\n            nn.Conv2d(in_channels=256, out_channels=512, kernel_size=5, padding=2),\n            nn.BatchNorm2d(512),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2),\n            nn.Flatten(),\n            nn.Dropout(0.1),\n            nn.Linear(512 * 3 * 3, 128),\n            nn.ReLU(),\n            nn.Dropout(0.1),\n            nn.Linear(128, num_outputs)\n        )\n\n    def forward(self, x):\n        return self.model(x)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T21:44:59.034671Z","iopub.execute_input":"2024-03-09T21:44:59.035316Z","iopub.status.idle":"2024-03-09T21:44:59.045419Z","shell.execute_reply.started":"2024-03-09T21:44:59.035283Z","shell.execute_reply":"2024-03-09T21:44:59.044525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = CNN(10)\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001, amsgrad=True)\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nmodel = model.to(device)\nmodel","metadata":{"execution":{"iopub.status.busy":"2024-03-09T21:45:01.677674Z","iopub.execute_input":"2024-03-09T21:45:01.678102Z","iopub.status.idle":"2024-03-09T21:45:01.743814Z","shell.execute_reply.started":"2024-03-09T21:45:01.678055Z","shell.execute_reply":"2024-03-09T21:45:01.742895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs = 50\nearly_stop = 5\nno_progress = 0\nbest_model = None\nbest_loss = float('inf')\n\ntrain_losses = []\nval_losses = []\ntrain_accuracies = []\nval_accuracies = []\n\nfor i in range(num_epochs):\n    model.train()\n    correct_train = 0\n    total_train = 0\n    running_loss_train = 0.0\n    \n    \n    for inputs, targets in train_loader:\n        inputs = inputs.to(device)\n        targets = targets.to(device)\n\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, targets)\n        loss.backward()\n        optimizer.step()\n        \n        _, predicted = torch.max(outputs.data, 1)\n        total_train += targets.size(0)\n        correct_train += (predicted == targets).sum().item()\n        \n        running_loss_train += loss.item()\n        \n    train_accuracy = correct_train / total_train\n    train_accuracies.append(train_accuracy)\n    train_losses.append(running_loss_train / len(train_loader))\n        \n    model.eval()\n    val_loss = 0.0\n    correct_val = 0.0\n    total_val = 0\n    \n    with torch.no_grad():\n        for val_inputs, val_targets in val_loader:\n            val_inputs, val_targets = val_inputs.to(device), val_targets.to(device)\n            val_outputs = model(val_inputs)\n            val_loss += criterion(val_outputs, val_targets).item()\n            \n            _, predicted_val = torch.max(val_outputs.data, 1)\n            total_val += val_targets.size(0)\n            correct_val += (predicted_val == val_targets).sum().item()\n        \n    \n    val_accuracy = correct_val / total_val\n    val_accuracies.append(val_accuracy)\n    val_loss /= len(val_loader)\n    val_losses.append(val_loss)\n    \n    print(f'Epoch {i+1}/{num_epochs}: Validation loss = {val_loss}, Validation accuracy = {val_accuracy}')\n    \n    if val_loss < best_loss:\n        best_loss = val_loss\n        best_model = model.state_dict()\n        no_progress = 0\n    else:\n        no_progress += 1\n        \n    if no_progress >= early_stop:\n        print('Early stopping')\n        break\n\nmodel.load_state_dict(best_model)\n\nplt.figure(figsize=(12, 4))\n\nplt.subplot(1, 2, 1)\nplt.plot(train_losses, label='Train Loss')\nplt.plot(val_losses, label='Validation Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\nplt.grid()\n\nplt.subplot(1, 2, 2)\nplt.plot(train_accuracies, label='Train Accuracy')\nplt.plot(val_accuracies, label='Validation Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.grid()\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-09T21:45:04.359532Z","iopub.execute_input":"2024-03-09T21:45:04.360267Z","iopub.status.idle":"2024-03-09T21:48:56.359638Z","shell.execute_reply.started":"2024-03-09T21:45:04.360233Z","shell.execute_reply":"2024-03-09T21:48:56.358663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\nwith torch.no_grad():\n    predictions = model(test_data.to(device))\n    predicted_labels = torch.argmax(predictions, axis=1).cpu().numpy()","metadata":{"execution":{"iopub.status.busy":"2024-03-09T21:49:10.874075Z","iopub.execute_input":"2024-03-09T21:49:10.874655Z","iopub.status.idle":"2024-03-09T21:49:17.130436Z","shell.execute_reply.started":"2024-03-09T21:49:10.874622Z","shell.execute_reply":"2024-03-09T21:49:17.129601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = pd.DataFrame({\n    'ImageId': range(1, len(predicted_labels) + 1),\n    'Label': predicted_labels\n})","metadata":{"execution":{"iopub.status.busy":"2024-03-09T21:49:20.472255Z","iopub.execute_input":"2024-03-09T21:49:20.472926Z","iopub.status.idle":"2024-03-09T21:49:20.477892Z","shell.execute_reply.started":"2024-03-09T21:49:20.472885Z","shell.execute_reply":"2024-03-09T21:49:20.476894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T21:49:23.524964Z","iopub.execute_input":"2024-03-09T21:49:23.525662Z","iopub.status.idle":"2024-03-09T21:49:23.565444Z","shell.execute_reply.started":"2024-03-09T21:49:23.525628Z","shell.execute_reply":"2024-03-09T21:49:23.564521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}