{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom tqdm import tqdm\n\n%matplotlib inline","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-08-25T06:48:02.949540Z","iopub.execute_input":"2023-08-25T06:48:02.949908Z","iopub.status.idle":"2023-08-25T06:48:07.093745Z","shell.execute_reply.started":"2023-08-25T06:48:02.949876Z","shell.execute_reply":"2023-08-25T06:48:07.092761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load and analyze data","metadata":{}},{"cell_type":"code","source":"# Load data\n\ndata_train = pd.read_csv(\"/kaggle/input/digit-recognizer/train.csv\")\ndata_test = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")\nsample_submission = pd.read_csv(\"/kaggle/input/digit-recognizer/sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:07.096073Z","iopub.execute_input":"2023-08-25T06:48:07.096826Z","iopub.status.idle":"2023-08-25T06:48:12.958465Z","shell.execute_reply.started":"2023-08-25T06:48:07.096790Z","shell.execute_reply":"2023-08-25T06:48:12.957457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_train.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:12.959812Z","iopub.execute_input":"2023-08-25T06:48:12.961318Z","iopub.status.idle":"2023-08-25T06:48:12.987879Z","shell.execute_reply.started":"2023-08-25T06:48:12.961280Z","shell.execute_reply":"2023-08-25T06:48:12.986697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(data_train.shape)\ndata_train.describe()","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:12.989433Z","iopub.execute_input":"2023-08-25T06:48:12.990986Z","iopub.status.idle":"2023-08-25T06:48:15.686712Z","shell.execute_reply.started":"2023-08-25T06:48:12.990947Z","shell.execute_reply":"2023-08-25T06:48:15.685631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_train['label'].value_counts()\n\nplt.figure(figsize=(5,3))\nplt.hist(data_train['label'], bins=10, density=False, rwidth=0.9, color='#172582');\nplt.ylabel('Frequency')\nplt.xlabel('Digits')\nplt.xticks([0, 1,2,3,4,5,6,7,8,9])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:15.690987Z","iopub.execute_input":"2023-08-25T06:48:15.691371Z","iopub.status.idle":"2023-08-25T06:48:15.982516Z","shell.execute_reply.started":"2023-08-25T06:48:15.691340Z","shell.execute_reply":"2023-08-25T06:48:15.981593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Missing values","metadata":{}},{"cell_type":"code","source":"print(f'train - {data_train.isnull().sum().sum()}')\nprint(f'test - {data_test.isnull().sum().sum()}')","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:15.983868Z","iopub.execute_input":"2023-08-25T06:48:15.984821Z","iopub.status.idle":"2023-08-25T06:48:16.031459Z","shell.execute_reply.started":"2023-08-25T06:48:15.984788Z","shell.execute_reply":"2023-08-25T06:48:16.030372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Great! There are no missing values in the dataset.","metadata":{}},{"cell_type":"markdown","source":"## Display digits","metadata":{}},{"cell_type":"code","source":"def plot_img(index, data=data_train):\n    data = data.copy()\n    if data.shape[1] == 785:\n        data.drop('label', axis=1, inplace=True)\n    img = data.iloc[index].to_numpy()\n    img = img.reshape((28,28))\n\n    plt.imshow(img, cmap='binary')\n    plt.axis(\"off\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:16.032979Z","iopub.execute_input":"2023-08-25T06:48:16.033444Z","iopub.status.idle":"2023-08-25T06:48:16.041689Z","shell.execute_reply.started":"2023-08-25T06:48:16.033408Z","shell.execute_reply":"2023-08-25T06:48:16.040409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_img(42, data_train)","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:16.043621Z","iopub.execute_input":"2023-08-25T06:48:16.044060Z","iopub.status.idle":"2023-08-25T06:48:16.294064Z","shell.execute_reply.started":"2023-08-25T06:48:16.044026Z","shell.execute_reply":"2023-08-25T06:48:16.292779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Split train and test data","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nimport torch.nn.functional as F\n\nX = data_train.drop('label', axis=1)\ny = data_train['label']\n\nX = torch.FloatTensor(np.array(X))\ny = torch.tensor(np.array(y))\ny = F.one_hot(y, 10).type_as(torch.FloatTensor())\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:16.295721Z","iopub.execute_input":"2023-08-25T06:48:16.296060Z","iopub.status.idle":"2023-08-25T06:48:17.660533Z","shell.execute_reply.started":"2023-08-25T06:48:16.296028Z","shell.execute_reply":"2023-08-25T06:48:17.659454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset & DataLoader","metadata":{}},{"cell_type":"code","source":"class MnistDataset(Dataset):\n    def __init__(self, data, labels, transform=None):\n        self.data = data\n        self.labels = labels\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.data)   \n    \n    def __getitem__(self, idx):\n        sample = self.data[idx].reshape((1, 28, 28))\n        label = self.labels[idx]\n        \n        \n        if self.transform:\n            sample = np.array(sample)\n            sample = sample.reshape((28, 28, 1))\n            sample = self.transform(image=sample)['image']\n        \n        return sample, label","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:17.665856Z","iopub.execute_input":"2023-08-25T06:48:17.668603Z","iopub.status.idle":"2023-08-25T06:48:17.680639Z","shell.execute_reply.started":"2023-08-25T06:48:17.668557Z","shell.execute_reply":"2023-08-25T06:48:17.679533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\ntransform_train = A.Compose([\n    A.RandomScale(scale_limit=0.1, p=0.3),\n    A.Rotate(limit=0.1, p=0.2),\n    A.Resize(height=28, width=28, p=1.0),\n    A.Normalize(mean=(0.1307,), std=(0.3081,), p=1.0),\n    ToTensorV2(p=1.0)\n])\n\ntransform_test = A.Compose([\n    A.Normalize(mean=(0.1307,), std=(0.3081,)),\n    ToTensorV2()\n])","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:17.682139Z","iopub.execute_input":"2023-08-25T06:48:17.682748Z","iopub.status.idle":"2023-08-25T06:48:19.054700Z","shell.execute_reply.started":"2023-08-25T06:48:17.682700Z","shell.execute_reply":"2023-08-25T06:48:19.053758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 32\n\n# Creating datasets\ntrain_dataset = MnistDataset(X_train, y_train, transform=transform_train)\ntest_dataset = MnistDataset(X_test, y_test, transform=transform_test)\n\n# Creating data loaders\ntrain_dataloader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True, drop_last=True)\ntest_dataloader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True, drop_last=True)","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:19.056015Z","iopub.execute_input":"2023-08-25T06:48:19.056476Z","iopub.status.idle":"2023-08-25T06:48:19.066827Z","shell.execute_reply.started":"2023-08-25T06:48:19.056435Z","shell.execute_reply":"2023-08-25T06:48:19.065763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class NN(nn.Module):\n    def __init__(self):\n        super(NN, self).__init__()\n        self.conv1 = nn.Conv2d(1, 32, kernel_size=5)\n        self.conv2 = nn.Conv2d(32, 32, kernel_size=5)\n        self.conv3 = nn.Conv2d(32,64, kernel_size=5)\n        \n        self.flatten = nn.Flatten()\n        self.fc1 = nn.Linear(3*3*64, 256)\n        self.fc2 = nn.Linear(256, 10)\n    \n    def forward(self, x):\n        x = F.relu(self.conv1(x))\n        x = F.relu(F.max_pool2d(self.conv2(x), 2))\n        x = F.dropout(x, p=0.5, training=model.training)\n        x = F.relu(F.max_pool2d(self.conv3(x),2))\n        x = F.dropout(x, p=0.5, training=model.training)\n        \n        x = self.flatten(x)\n        x = F.relu(self.fc1(x))\n        x = F.dropout(x, training=self.training)\n        x = self.fc2(x)\n        return x ","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:19.068911Z","iopub.execute_input":"2023-08-25T06:48:19.069392Z","iopub.status.idle":"2023-08-25T06:48:19.079711Z","shell.execute_reply.started":"2023-08-25T06:48:19.069359Z","shell.execute_reply":"2023-08-25T06:48:19.078659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\n\nmodel = NN().to(DEVICE)\nloss_fn = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:19.084702Z","iopub.execute_input":"2023-08-25T06:48:19.085031Z","iopub.status.idle":"2023-08-25T06:48:22.219867Z","shell.execute_reply.started":"2023-08-25T06:48:19.085006Z","shell.execute_reply":"2023-08-25T06:48:22.218755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 20\nbatch_losses = []\nbatch_accuracy = [] \n\nfor epoch in tqdm(range(EPOCHS)):\n    for iteration, (X_batch, y_batch) in enumerate(train_dataloader):\n        model.train()\n        optimizer.zero_grad()\n\n        output = model(X_batch.to(DEVICE))\n        loss = loss_fn(output, y_batch.to(DEVICE))\n        batch_losses.append(loss.item())\n\n        loss.backward()\n        optimizer.step()\n   \n    for iteration, (X_batch, y_batch) in enumerate(test_dataloader):\n        model.eval()\n        \n        with torch.no_grad():\n            output = model(X_batch.to(DEVICE))\n            \n        correct = 0\n        correct += (torch.max(output, 1)[1] == torch.max(y_batch, 1)[1].to(DEVICE)).sum().item()\n        accuracy = correct / (len(X_batch))\n        batch_accuracy.append(accuracy)\n    \n\ntrain_losses = np.array(batch_losses).reshape(EPOCHS, -1).mean(axis=1)\nval_accuracy = np.array(batch_accuracy).reshape(EPOCHS, -1).mean(axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:48:22.221775Z","iopub.execute_input":"2023-08-25T06:48:22.222170Z","iopub.status.idle":"2023-08-25T06:52:09.811464Z","shell.execute_reply.started":"2023-08-25T06:48:22.222131Z","shell.execute_reply":"2023-08-25T06:52:09.809686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 2, figsize=(10, 4))\n\nplt.subplot(1, 2, 1)\nplt.plot(range(EPOCHS), val_accuracy, c='g')\nplt.xlabel('Epoch Number')\nplt.title('Val Accuracy')\n\nplt.subplot(1, 2, 2)\nplt.plot(range(EPOCHS), train_losses, c='r')\nplt.xlabel('Epoch Number')\nplt.title('Cross Entropy')\n\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:52:09.812881Z","iopub.execute_input":"2023-08-25T06:52:09.813752Z","iopub.status.idle":"2023-08-25T06:52:10.265751Z","shell.execute_reply.started":"2023-08-25T06:52:09.813702Z","shell.execute_reply":"2023-08-25T06:52:10.264699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predictions on  the test dataset","metadata":{}},{"cell_type":"code","source":"rows = 4\ncolumns = 6\n\nfig, ax = plt.subplots(rows, columns,figsize=(10, 8))\n\nfor i in range(rows*columns):\n    x, y = test_dataset[i]\n    with torch.no_grad():\n        y_pred = model(x.unsqueeze(0).to(DEVICE)).argmax(axis=1)\n    plt.subplot(rows, columns,i+1)\n    plt.imshow(x.squeeze(0))\n    plt.title(f'Predict: {y_pred[0]}')\n    \nfig.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:52:10.267674Z","iopub.execute_input":"2023-08-25T06:52:10.268445Z","iopub.status.idle":"2023-08-25T06:52:14.340491Z","shell.execute_reply.started":"2023-08-25T06:52:10.268406Z","shell.execute_reply":"2023-08-25T06:52:14.339571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Make submission","metadata":{}},{"cell_type":"code","source":"sample_submission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:52:14.342033Z","iopub.execute_input":"2023-08-25T06:52:14.342680Z","iopub.status.idle":"2023-08-25T06:52:14.354882Z","shell.execute_reply.started":"2023-08-25T06:52:14.342644Z","shell.execute_reply":"2023-08-25T06:52:14.353825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_data = torch.FloatTensor(np.array(data_test)).view(28000, 1, 28, 28).to(DEVICE)\n\npredicts = model(submission_data)\nlabels = np.array(torch.max(predicts, 1)[1].cpu())","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:52:14.356640Z","iopub.execute_input":"2023-08-25T06:52:14.357032Z","iopub.status.idle":"2023-08-25T06:52:14.798641Z","shell.execute_reply.started":"2023-08-25T06:52:14.356997Z","shell.execute_reply":"2023-08-25T06:52:14.797746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = sample_submission.copy()\nsubmission['Label'] = labels\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:52:14.800020Z","iopub.execute_input":"2023-08-25T06:52:14.801093Z","iopub.status.idle":"2023-08-25T06:52:14.813252Z","shell.execute_reply.started":"2023-08-25T06:52:14.801048Z","shell.execute_reply":"2023-08-25T06:52:14.812055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save submission file\nsubmission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-08-25T06:52:14.815041Z","iopub.execute_input":"2023-08-25T06:52:14.815475Z","iopub.status.idle":"2023-08-25T06:52:14.885774Z","shell.execute_reply.started":"2023-08-25T06:52:14.815432Z","shell.execute_reply":"2023-08-25T06:52:14.884761Z"},"trusted":true},"execution_count":null,"outputs":[]}]}