{"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":"gpu","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":30698,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# README\n1. Code is writing in the simplest form possible, to make learning easy. \n2. In just `5 Code Cells`, you will have done your Kaggle Submission for \"Digit Recognizer\" competition \n2. Dataset is downloaded from `Huggingface Datasets`, Model is written in Pytorch, Training Loop is written in pytorch","metadata":{}},{"cell_type":"code","source":"!pip install datasets torch lightning gradio torchinfo","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-07-15T10:15:14.211047Z","iopub.execute_input":"2024-07-15T10:15:14.211394Z","iopub.status.idle":"2024-07-15T10:15:37.461014Z","shell.execute_reply.started":"2024-07-15T10:15:14.211346Z","shell.execute_reply":"2024-07-15T10:15:37.460054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. Simple Dataset downloading Pipeline","metadata":{}},{"cell_type":"code","source":"import torch, torchvision, torchinfo\nimport datasets as huggingface_datasets\n\ntraining_dataset    = huggingface_datasets.load_dataset(\"mnist\", split=\"train\")\n\nclass Custom_Dataset(torch.utils.data.Dataset):\n    def __init__(self, dataset):\n        self.dataset = dataset\n        self.data_transformations = torchvision.transforms.Compose(\n            [\n                torchvision.transforms.ToTensor(),\n            ]\n        )\n\n    def __getitem__(self, index):\n        image , label  = self.dataset[index]['image'], self.dataset[index]['label']\n        image_tensor   = self.data_transformations(image)\n        single_example = (image_tensor, label)\n        return single_example\n    \n    def __len__(self):\n        return len(self.dataset)\n\ncustom_training_dataset   = Custom_Dataset(training_dataset) # __init__ method called automatically to initalize\ntraining_dataloader       = torch.utils.data.DataLoader(custom_training_dataset, batch_size = 32, shuffle= True)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T10:17:06.817744Z","iopub.execute_input":"2024-07-15T10:17:06.818669Z","iopub.status.idle":"2024-07-15T10:17:31.525528Z","shell.execute_reply.started":"2024-07-15T10:17:06.818613Z","shell.execute_reply":"2024-07-15T10:17:31.524732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_dataset        = huggingface_datasets.load_dataset(\"mnist\", split=\"test\" )\ncustom_validation_dataset = Custom_Dataset(validation_dataset)\nvalidation_dataloader     = torch.utils.data.DataLoader(custom_validation_dataset, batch_size = 32, shuffle= True)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T10:17:31.526997Z","iopub.execute_input":"2024-07-15T10:17:31.527272Z","iopub.status.idle":"2024-07-15T10:17:33.732823Z","shell.execute_reply.started":"2024-07-15T10:17:31.527248Z","shell.execute_reply":"2024-07-15T10:17:33.731778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Simple Model Architecture","metadata":{}},{"cell_type":"code","source":"model_random_parameters = torch.nn.Sequential(\n    \n    torch.nn.Flatten(start_dim=1),         # Dim:BCHW -> (0:B , 1:C, 2:H, 3:W)\n\n    torch.nn.Linear(in_features = 28*28*1  , out_features   = 40   ), torch.nn.ReLU(),                 # LAYER 1: 1st Hidden Layer\n    torch.nn.Linear(in_features = 40       , out_features = 30     ), torch.nn.ReLU(),                 # LAYER 2: 2nd Hidden Layer\n\n    torch.nn.Linear(in_features = 30       , out_features = 10   ),                                  # OUTPUT LAYER\n)\n\nmodel = model_random_parameters\n\ntorchinfo.summary(model, input_size= (1,1*28*28), verbose=2);","metadata":{"execution":{"iopub.status.busy":"2024-07-15T10:17:33.734018Z","iopub.execute_input":"2024-07-15T10:17:33.734300Z","iopub.status.idle":"2024-07-15T10:17:34.085703Z","shell.execute_reply.started":"2024-07-15T10:17:33.734275Z","shell.execute_reply":"2024-07-15T10:17:34.084794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Simple Model Training Pipeline","metadata":{}},{"cell_type":"code","source":"import lightning\nimport torchmetrics\n\nclass Lightning_Module(lightning.LightningModule):\n    def __init__(self, model):\n        super().__init__()\n        \n        self.model = model\n        self.automatic_optimization = False\n        self.training_accuracy   = torchmetrics.Accuracy(task=\"multiclass\", num_classes=10)\n        self.validation_accuracy = torchmetrics.Accuracy(task=\"multiclass\", num_classes=10)\n  \n    def training_step (self, batch, batch_idx):\n        images_actual, labels_actual        = batch\n        predicted_logits  = self.model(images_actual)\n        labels_predicted  = torch.argmax(predicted_logits, dim = 1)\n\n        loss             = torch.nn.functional.cross_entropy(predicted_logits, labels_actual)\n        \n        optimizer        = self.optimizers()\n        optimizer.zero_grad()\n        self.manual_backward(loss)\n        optimizer.step()\n        \"\"\"\n        for individual_parameter in self.parameters():\n            individual_parameter = individual_parameter - individual_parameter.grad * learning_rate\n        \"\"\"\n        self.training_accuracy(labels_predicted, labels_actual)\n        self.log(\"train_loss\"     , loss                   , prog_bar = True)\n        self.log(\"train_accuracy\" , self.training_accuracy , prog_bar = True)\n        \n        return loss\n\n    def validation_step (self, batch, batch_idx):\n        images_actual, labels_actual        = batch\n        predicted_logits  = self.model(images_actual)\n        labels_predicted  = torch.argmax(predicted_logits, dim = 1)\n\n        loss = torch.nn.functional.cross_entropy(predicted_logits, labels_actual)\n        self.validation_accuracy(labels_predicted, labels_actual)\n        self.log(\"validation_loss\"     , loss                     , prog_bar= False)\n        self.log(\"validation_accuracy\" , self.validation_accuracy , prog_bar= True)\n    \n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)\n        return optimizer\n\n# for batch_number, data_batch in enumerate(training_dataloader):\n# \tx, y = data_batch\n# \tloss = lightning_model.training_step(x)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T10:17:34.087924Z","iopub.execute_input":"2024-07-15T10:17:34.088213Z","iopub.status.idle":"2024-07-15T10:17:36.675497Z","shell.execute_reply.started":"2024-07-15T10:17:34.088187Z","shell.execute_reply":"2024-07-15T10:17:36.674722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs  = 10\nlightning_model   = Lightning_Module(model)\nlightning_trainer = lightning.Trainer( max_epochs= epochs)\n\nlightning_trainer.fit(model=lightning_model, train_dataloaders= training_dataloader, val_dataloaders= validation_dataloader)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T10:17:36.676493Z","iopub.execute_input":"2024-07-15T10:17:36.676753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Details of Problem Complexity\n- 0.00784 Mega Pixel Image\n- 60,000 of such images\n- They are black and white\n- They contain only numbers 0 to 9\n- Even this SIMPLE PROBLEM, requires a MODEL of MINIMUM 10,000 parameters","metadata":{}},{"cell_type":"markdown","source":"# 4. Kaggle Competition Submission","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport torch, torchvision\n\ndf      = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")\ntensors = torch.tensor(df.to_numpy()).reshape(-1,1,28,28)\n\ny_prediction_logits = model(x)\ny_labels_predicted  = torch.argmax(y_prediction_logits, dim = 1)\n\nsubmission          = pd.DataFrame({'ImageId' : torch.arange(1, len(y_labels_predicted) + 1).cpu(), \n                                    'Label'   : y_labels_predicted.cpu()})\nsubmission.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}