{"metadata":{"colab":{"provenance":[]},"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.7.12","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":30461,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# IMPORTS\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt \nimport cv2\nimport torch\nimport torch.nn.functional as F\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision.datasets as datasets\nimport torchvision.transforms as transforms\nfrom sklearn.metrics import confusion_matrix, classification_report\nfrom tqdm.notebook import tqdm\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import TensorDataset, DataLoader","metadata":{"id":"imUeKBfJseSM","execution":{"iopub.status.busy":"2024-05-14T12:46:52.727789Z","iopub.execute_input":"2024-05-14T12:46:52.728675Z","iopub.status.idle":"2024-05-14T12:46:52.735461Z","shell.execute_reply.started":"2024-05-14T12:46:52.728632Z","shell.execute_reply":"2024-05-14T12:46:52.734597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# defining the device to run the model on GPU \ndevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\nBATCH_SIZE = 32\ndata_dir_Train = \"/kaggle/input/digit-recognizer/train.csv\"","metadata":{"id":"HxXD4Rr8chLk","execution":{"iopub.status.busy":"2024-05-14T12:46:52.737432Z","iopub.execute_input":"2024-05-14T12:46:52.737744Z","iopub.status.idle":"2024-05-14T12:46:52.749275Z","shell.execute_reply.started":"2024-05-14T12:46:52.737717Z","shell.execute_reply":"2024-05-14T12:46:52.748241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def ACC_Plot(epochs, acc):\n    \"\"\"\n    epochs: list contains the number of epochs\n    acc: Accuracy of each epoch\n    \"\"\"\n    plt.xlabel('Epochs') \n    plt.ylabel('accuracy')\n    plt.plot(epochs, acc)","metadata":{"id":"y-smRcIcYtMZ","execution":{"iopub.status.busy":"2024-05-14T12:46:52.750330Z","iopub.execute_input":"2024-05-14T12:46:52.750657Z","iopub.status.idle":"2024-05-14T12:46:52.762104Z","shell.execute_reply.started":"2024-05-14T12:46:52.750628Z","shell.execute_reply":"2024-05-14T12:46:52.761311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_classification(model, data_loader, class_names):\n    \"\"\"\n    *Plot the classification results of a PyTorch model*\n    model: A trained PyTorch model.\n    data_loader: A PyTorch DataLoader that contains the input images.\n    class_names: A list of class names corresponding to the output classes of the model.\n    \"\"\"\n\n    # Setting the model to evaluation mode\n    model.eval()\n\n    # Create empty lists to store the true labels and predicted labels\n    true_labels = []\n    predicted_labels = []\n\n    # Iterate over the input data and generate predictions\n    with torch.no_grad():\n        for images, labels in data_loader:\n            # Forward pass through the model\n            images, labels = images.to(device), labels.to(device)\n            outputs = model(images)\n\n            # Convert the outputs to class predictions\n            _, predicted = torch.max(outputs, 1)\n\n            # Append the true and predicted labels to the lists\n            true_labels.extend(labels.cpu().numpy())\n            predicted_labels.extend(predicted.cpu().numpy())\n\n    # Generate the confusion matrix\n    cm = confusion_matrix(true_labels, predicted_labels)\n\n    # Normalize the confusion matrix\n    cm_norm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n\n    # Generate the classification report\n    cr = classification_report(true_labels, predicted_labels, target_names=class_names)\n\n    # Plot the confusion matrix\n    fig, ax = plt.subplots(figsize=(10, 10))\n    im = ax.imshow(cm_norm, interpolation='nearest', cmap=plt.cm.Blues)\n    ax.figure.colorbar(im, ax=ax)\n    ax.set(xticks=np.arange(cm.shape[1]),\n           yticks=np.arange(cm.shape[0]),\n           xticklabels=class_names, yticklabels=class_names,\n           xlabel='Predicted label',\n           ylabel='True label',\n           title='Confusion matrix')\n    plt.setp(ax.get_xticklabels(), rotation=45, ha=\"right\",\n             rotation_mode=\"anchor\")\n\n    # Loop over data dimensions and create text annotations.\n    fmt = '.2f'\n    thresh = cm_norm.max() / 2.\n    for i in range(cm_norm.shape[0]):\n        for j in range(cm_norm.shape[1]):\n            ax.text(j, i, format(cm_norm[i, j], fmt),\n                    ha=\"center\", va=\"center\",\n                    color=\"white\" if cm_norm[i, j] > thresh else \"black\")\n    fig.tight_layout()\n\n    # Print the classification report\n    print(cr)\n","metadata":{"id":"vc5GKA8xY2Zn","execution":{"iopub.status.busy":"2024-05-14T12:46:52.764154Z","iopub.execute_input":"2024-05-14T12:46:52.764456Z","iopub.status.idle":"2024-05-14T12:46:52.781020Z","shell.execute_reply.started":"2024-05-14T12:46:52.764416Z","shell.execute_reply":"2024-05-14T12:46:52.780213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(network, train_loader, optimizer, loss_function):\n    # creating list to hold loss and accuracy per batch\n    loss_per_batch = []\n    acc_per_batch = []\n\n    # iterating through batches\n    print('training...')\n    for images, labels in tqdm(train_loader):\n        # sending images to device\n        images, labels = images.to(device), labels.to(device)\n\n        # zeroing optimizer gradients\n        optimizer.zero_grad()\n\n        # classifying instances\n        classifications = network(images)\n\n        # computing loss/how wrong our classifications are\n        loss = loss_function(classifications, labels)\n        loss_per_batch.append(loss.item())\n\n        # computing gradients/the direction that fits our objective\n        loss.backward()\n\n        # optimizing weights/slightly adjusting parameters\n        optimizer.step()\n\n        # computing accuracy for the batch\n        preds = torch.argmax(classifications, dim=1)\n        acc = (preds == labels).sum().item() / len(labels)\n        acc_per_batch.append(acc)\n\n    # computing the overall accuracy for the training set\n    train_acc = sum(acc_per_batch) / len(acc_per_batch)\n#   returning the acc_per_batch to use it in the acc_per_batch plot\n    return acc_per_batch, train_acc","metadata":{"id":"h2DZZunHYjCF","execution":{"iopub.status.busy":"2024-05-14T12:46:52.782132Z","iopub.execute_input":"2024-05-14T12:46:52.782391Z","iopub.status.idle":"2024-05-14T12:46:52.799219Z","shell.execute_reply.started":"2024-05-14T12:46:52.782366Z","shell.execute_reply":"2024-05-14T12:46:52.798346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the nn architecture\nclass Classifier(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)\n        self.relu = nn.ReLU()\n        self.maxpool = nn.MaxPool2d(kernel_size=2)\n        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)\n        self.flatten = nn.Flatten()\n        self.fc1 = nn.Linear(64 * 7 * 7, 128)\n        self.fc2 = nn.Linear(128, 10)\n        self.softmax = nn.Softmax(dim=1)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n        x = self.flatten(x)\n        x = self.fc1(x)\n        x = self.relu(x)\n        x = self.fc2(x)\n        x = self.softmax(x)\n        return x","metadata":{"id":"lHh57tTQBUMI","outputId":"f54ad35d-1524-40f2-851b-8455b44790a3","execution":{"iopub.status.busy":"2024-05-14T12:46:52.800387Z","iopub.execute_input":"2024-05-14T12:46:52.800721Z","iopub.status.idle":"2024-05-14T12:46:52.819048Z","shell.execute_reply.started":"2024-05-14T12:46:52.800691Z","shell.execute_reply":"2024-05-14T12:46:52.818214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Reading the training CSV file\nTRAIN_df= pd.read_csv(data_dir_Train)","metadata":{"id":"Fs5gqlBQwc31","outputId":"0831a810-c416-47ab-cfb9-8b675a8249a7","execution":{"iopub.status.busy":"2024-05-14T12:46:52.834730Z","iopub.execute_input":"2024-05-14T12:46:52.835533Z","iopub.status.idle":"2024-05-14T12:46:55.740905Z","shell.execute_reply.started":"2024-05-14T12:46:52.835494Z","shell.execute_reply":"2024-05-14T12:46:55.740010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# splitting the training file into Train, Validation\ntrain_df, val_df = train_test_split(TRAIN_df, test_size=0.2, shuffle= False)\n# splitting the X, Y\ntrain_df_Y = train_df[\"label\"]\ntrain_df_X = train_df.drop(columns = \"label\")\n# splitting the X, Y\nval_df_Y = val_df[\"label\"]\nval_df_X = val_df.drop(columns = \"label\")","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:46:55.743181Z","iopub.execute_input":"2024-05-14T12:46:55.743556Z","iopub.status.idle":"2024-05-14T12:46:55.966327Z","shell.execute_reply.started":"2024-05-14T12:46:55.743522Z","shell.execute_reply":"2024-05-14T12:46:55.965443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plotting number of pics to see the labels with images\nfig,ax = plt.subplots(5,5,figsize = (15,15))\nax = ax.ravel()\nfor i in range(25):\n    image = train_df_X.iloc[i]\n    ax[i].imshow(image.to_numpy().reshape(28,28),cmap = 'gray')\n    ax[i].set_title(train_df_Y[i])\n    ax[i].axis(\"off\")\nplt.show()","metadata":{"id":"B9geZdTEJoI3","execution":{"iopub.status.busy":"2024-05-14T12:46:55.967563Z","iopub.execute_input":"2024-05-14T12:46:55.967875Z","iopub.status.idle":"2024-05-14T12:46:56.796616Z","shell.execute_reply.started":"2024-05-14T12:46:55.967845Z","shell.execute_reply":"2024-05-14T12:46:56.795607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# coverting the dataframe to numpy array and reshaping it\ntrain_mnist_X = train_df_X.to_numpy().reshape(-1,1, 28, 28)\n# normalizing the pixels\ntrain_mnist_X = np.divide(train_mnist_X, 255)\n# converting the numpy array to tensor\ntrain_mnist_X = torch.tensor(train_mnist_X, dtype=torch.float32)\n# converting the Y Df to numpy array then to tensor\ntrain_mnist_Y = torch.tensor(np.array(train_df_Y), dtype=torch.long)\n# ------------------------------\n# coverting the dataframe to numpy array and reshaping it\ntest_mnist_X = val_df_X.to_numpy().reshape(-1,1, 28, 28)\n# normalizing the pixels\ntest_mnist_X = np.divide(test_mnist_X, 255)\n# converting the numpy array to tensor\ntest_mnist_X = torch.tensor(test_mnist_X, dtype=torch.float32)\n# converting the Y Df to numpy array then to tensor\ntest_mnist_Y = torch.tensor(np.array(val_df_Y), dtype=torch.long)","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:46:56.798013Z","iopub.execute_input":"2024-05-14T12:46:56.798328Z","iopub.status.idle":"2024-05-14T12:46:56.964447Z","shell.execute_reply.started":"2024-05-14T12:46:56.798298Z","shell.execute_reply":"2024-05-14T12:46:56.963391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# showing the shape of X tensor \ntest_mnist_X.shape","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:46:56.968440Z","iopub.execute_input":"2024-05-14T12:46:56.968919Z","iopub.status.idle":"2024-05-14T12:46:56.975879Z","shell.execute_reply.started":"2024-05-14T12:46:56.968870Z","shell.execute_reply":"2024-05-14T12:46:56.974720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# making a DataSets for train, test\ntrain_dataset = TensorDataset(train_mnist_X, train_mnist_Y)\nval_dataset = TensorDataset(test_mnist_X, test_mnist_Y)","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:46:56.977448Z","iopub.execute_input":"2024-05-14T12:46:56.977837Z","iopub.status.idle":"2024-05-14T12:46:56.988379Z","shell.execute_reply.started":"2024-05-14T12:46:56.977798Z","shell.execute_reply":"2024-05-14T12:46:56.987608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# making 2 Dataloaders fo the train, validation\ntrain_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\ntest_loader = DataLoader(val_dataset, batch_size=BATCH_SIZE, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:46:56.989785Z","iopub.execute_input":"2024-05-14T12:46:56.990095Z","iopub.status.idle":"2024-05-14T12:46:57.010406Z","shell.execute_reply.started":"2024-05-14T12:46:56.990066Z","shell.execute_reply":"2024-05-14T12:46:57.009522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# showing the shape of the single batch in the train loader\nimage, label= next(iter(train_loader))\nimage.shape","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:46:57.011954Z","iopub.execute_input":"2024-05-14T12:46:57.012254Z","iopub.status.idle":"2024-05-14T12:46:57.027721Z","shell.execute_reply.started":"2024-05-14T12:46:57.012226Z","shell.execute_reply":"2024-05-14T12:46:57.026675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Defining the model, loss function and optimizer\nmodel = Classifier()\nmodel = model.cuda() if device else model\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters())","metadata":{"id":"gLo9KfQcjBi5","execution":{"iopub.status.busy":"2024-05-14T12:46:57.029083Z","iopub.execute_input":"2024-05-14T12:46:57.029370Z","iopub.status.idle":"2024-05-14T12:46:57.039535Z","shell.execute_reply.started":"2024-05-14T12:46:57.029342Z","shell.execute_reply":"2024-05-14T12:46:57.038726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training the model\nnum_epochs = 5\nAcc = []\nfor epoch in range(num_epochs):\n    Train_acc_per_batch, acc = train(model, train_loader, optimizer, criterion)\n    Acc.append(acc)\n    print(\"Epoch accuracy: \",acc)\nprint(\"Train accuracy:\",acc)\nprint(\"All Done!\")","metadata":{"id":"9_CfX9w3FmhX","execution":{"iopub.status.busy":"2024-05-14T12:46:57.040876Z","iopub.execute_input":"2024-05-14T12:46:57.041167Z","iopub.status.idle":"2024-05-14T12:47:18.904152Z","shell.execute_reply.started":"2024-05-14T12:46:57.041139Z","shell.execute_reply":"2024-05-14T12:47:18.902957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# accuracy per batch graph\nACC_Plot([1,2,3,4,5],Acc)","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:47:18.905776Z","iopub.execute_input":"2024-05-14T12:47:18.906128Z","iopub.status.idle":"2024-05-14T12:47:19.109618Z","shell.execute_reply.started":"2024-05-14T12:47:18.906095Z","shell.execute_reply":"2024-05-14T12:47:19.108640Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluating the model\nmodel.eval()\nwith torch.no_grad():\n    correct = 0\n    total = 0\n    for images, labels in test_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        _, predicted = torch.max(outputs.data, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n\n    print(f\"Validation accuracy: {correct/total:.4f}\")","metadata":{"id":"WpjJqRvXjSIN","execution":{"iopub.status.busy":"2024-05-14T12:47:19.110734Z","iopub.execute_input":"2024-05-14T12:47:19.111022Z","iopub.status.idle":"2024-05-14T12:47:19.555154Z","shell.execute_reply.started":"2024-05-14T12:47:19.110992Z","shell.execute_reply":"2024-05-14T12:47:19.553768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ploting the confusion matrix \nlabels = np.arange(10)\nlabels=labels.astype(str)\nplot_classification(model, test_loader,labels)","metadata":{"id":"zKvRSibqFJS0","outputId":"198216f2-cf73-4062-d540-dd2a95ba4f1b","execution":{"iopub.status.busy":"2024-05-14T12:47:19.557292Z","iopub.execute_input":"2024-05-14T12:47:19.557674Z","iopub.status.idle":"2024-05-14T12:47:21.102665Z","shell.execute_reply.started":"2024-05-14T12:47:19.557631Z","shell.execute_reply":"2024-05-14T12:47:21.101397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# saving the model\ntorch.save({\n            'epoch': num_epochs,\n            'model_state_dict': model.state_dict(),\n            'optimizer_state_dict': optimizer.state_dict(),\n            }, \"/kaggle/working/state.pth\")","metadata":{"execution":{"iopub.status.busy":"2024-05-14T12:47:21.106426Z","iopub.execute_input":"2024-05-14T12:47:21.106811Z","iopub.status.idle":"2024-05-14T12:47:21.128599Z","shell.execute_reply.started":"2024-05-14T12:47:21.106776Z","shell.execute_reply":"2024-05-14T12:47:21.127336Z"},"trusted":true},"execution_count":null,"outputs":[]}]}