{"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":"!pip install --quiet timm split-folders\n","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:29:55.836639Z","iopub.execute_input":"2023-04-06T16:29:55.837346Z","iopub.status.idle":"2023-04-06T16:30:05.807930Z","shell.execute_reply.started":"2023-04-06T16:29:55.837307Z","shell.execute_reply":"2023-04-06T16:30:05.806672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport splitfolders\nimport cv2, glob\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:34:24.968029Z","iopub.execute_input":"2023-04-06T16:34:24.968712Z","iopub.status.idle":"2023-04-06T16:34:24.975503Z","shell.execute_reply.started":"2023-04-06T16:34:24.968669Z","shell.execute_reply":"2023-04-06T16:34:24.974142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/state-farm-distracted-driver-detection/driver_imgs_list.csv\")\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:30:05.962393Z","iopub.execute_input":"2023-04-06T16:30:05.962834Z","iopub.status.idle":"2023-04-06T16:30:06.009092Z","shell.execute_reply.started":"2023-04-06T16:30:05.962797Z","shell.execute_reply":"2023-04-06T16:30:06.008019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Split train data to train & Validation","metadata":{}},{"cell_type":"code","source":"data_dir = '/kaggle/input/state-farm-distracted-driver-detection/imgs/train'\nsplitfolders.ratio(data_dir, output=\"dataa\",\n    seed=1337, ratio=(.8, .2), group_prefix=None, move=False)","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:30:06.011971Z","iopub.execute_input":"2023-04-06T16:30:06.012420Z","iopub.status.idle":"2023-04-06T16:32:58.646365Z","shell.execute_reply.started":"2023-04-06T16:30:06.012384Z","shell.execute_reply":"2023-04-06T16:32:58.645147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Display Images","metadata":{}},{"cell_type":"code","source":"state = ['safe driving', 'texting - right', 'talking on the phone - right', 'texting - left', 'talking on the phone - left',\n         'operating the radio', 'drinking', 'reaching behind', 'hair and makeup', 'talking to passenger', 'UNKNOWN']\n\ndef Display(path, Class=None):\n    img = cv2.imread(path)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    if Class == None:\n        plt.figure()\n        plt.title(state[10])\n        plt.imshow(img)\n        plt.axis(\"off\")\n        # print(img.shape)\n    else:\n        plt.subplot(2, 5, Class+1)\n        plt.title(state[Class])\n        plt.imshow(img)\n        plt.axis(\"off\")\n\nplt.figure(figsize=(20, 5))\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c0/img_100026.jpg\", 0)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c1/img_100021.jpg\", 1)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c2/img_100029.jpg\", 2)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c3/img_100006.jpg\", 3)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c4/img_100225.jpg\", 4)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c5/img_10000.jpg\", 5)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c6/img_100036.jpg\", 6)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c7/img_100057.jpg\", 7)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c8/img_100015.jpg\", 8)\nDisplay(\"/kaggle/input/state-farm-distracted-driver-detection/imgs/train/c9/img_100090.jpg\", 9)","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:34:34.013394Z","iopub.execute_input":"2023-04-06T16:34:34.014291Z","iopub.status.idle":"2023-04-06T16:34:35.273958Z","shell.execute_reply.started":"2023-04-06T16:34:34.014240Z","shell.execute_reply":"2023-04-06T16:34:35.273052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model define\nfrom typing import Any, Dict, Optional, Tuple, List\n\nimport os\nimport subprocess\nimport torch\nimport timm\nimport json\n\nimport torchvision\nimport pytorch_lightning as pl\nimport torchvision.transforms as T\nimport torch.nn.functional as F\n\n\nfrom torchmetrics import F1Score, Precision, Recall, ConfusionMatrix, MaxMetric, MeanMetric\nfrom torchmetrics.classification.accuracy import Accuracy\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport seaborn as sn\nimport io\nfrom PIL import Image\n\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n\nclass IntHandler:\n    def legend_artist(self, legend, orig_handle, fontsize, handlebox):\n        x0, y0 = handlebox.xdescent, handlebox.ydescent\n        text = plt.matplotlib.text.Text(x0, y0, str(orig_handle))\n        handlebox.add_artist(text)\n        return text\n\n\nclass LitResnet(pl.LightningModule):\n    def __init__(self, num_classes=6, model_name='resnet18', optim_name=\"SGD\", lr=0.05):\n        super().__init__()\n\n        self.num_classes = num_classes\n        self.save_hyperparameters()\n        self.model = timm.create_model(model_name, pretrained=True, num_classes=num_classes)\n\n        self.lr = lr\n        # configure optimizer\n        if optim_name == \"ADAM\":\n            self.optim_name = torch.optim.Adam\n        if optim_name == \"SGD\":\n            self.optim_name = torch.optim.SGD\n        if optim_name == \"RMS\":\n            self.optim_name = torch.optim.RMSprop\n\n        # loss function\n        self.criterion = torch.nn.CrossEntropyLoss()\n        \n        self.normalize = T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n        # for averaging loss across batches\n        self.train_loss = MeanMetric()\n        self.val_loss = MeanMetric()\n        self.test_loss = MeanMetric()\n\n        # metric objects for calculating and averaging accuracy across batches\n        self.train_acc = Accuracy(task='multiclass', num_classes=self.num_classes)\n        self.val_acc = Accuracy(task='multiclass', num_classes=self.num_classes)\n        self.test_acc = Accuracy(task='multiclass', num_classes=self.num_classes)\n\n        # some other metrics to be logged\n        self.f1_score = F1Score(task=\"multiclass\", num_classes=self.num_classes)\n        self.precision_score = Precision(task=\"multiclass\", average='macro', num_classes=self.num_classes)\n        self.recall_score = Recall(task=\"multiclass\", average='macro', num_classes=self.num_classes)\n\n    def forward(self, x):\n        return self.model(x)\n    \n    \n    def step(self, batch: Any):\n        x, y = batch\n        logits = self.forward(x)\n        loss = self.criterion(logits, y)\n        preds = torch.argmax(logits, dim=1)\n        return loss, preds, y\n\n    def training_step(self, batch: Any, batch_idx: int):\n        loss, preds, targets = self.step(batch)\n\n        # update and log metrics\n        self.train_loss(loss)\n        self.train_acc(preds, targets)\n        self.log(\"train/loss\", self.train_loss, on_step=True, on_epoch=True, prog_bar=True)\n        self.log(\"train/acc\", self.train_acc, on_step=True, on_epoch=True, prog_bar=True)\n\n        # we can return here dict with any tensors\n        # and then read it in some callback or in `training_epoch_end()` below\n        # remember to always return loss from `training_step()` or backpropagation will fail!\n        return {\"loss\": loss, \"preds\": preds, \"targets\": targets}\n\n    def training_epoch_end(self, outputs: List[Any]):\n        # `outputs` is a list of dicts returned from `training_step()`\n        pass\n\n    def validation_step(self, batch: Any, batch_idx: int):\n        loss, preds, targets = self.step(batch)\n\n        # update and log metrics\n        self.val_loss(loss)\n        self.val_acc(preds, targets)\n        self.f1_score(preds, targets)\n        self.precision_score(preds, targets)\n        self.recall_score(preds, targets)\n        self.log(\"val/loss\", self.val_loss, on_step=True, on_epoch=True, prog_bar=True)\n        self.log(\"val/acc\", self.val_acc, on_step=True, on_epoch=True, prog_bar=False)\n        self.log(\"val/f1\", self.val_acc, on_step=False, on_epoch=True, prog_bar=False)\n        self.log(\"val/precision\", self.precision_score, on_step=False, on_epoch=True, prog_bar=False)\n        self.log(\"val/recall\", self.recall_score, on_step=False, on_epoch=True, prog_bar=False)\n        return {\"loss\": loss, \"preds\": preds, \"targets\": targets}\n\n    def validation_epoch_end(self, outs: List[Any]):\n        tb = self.logger.experiment  # noqa\n\n        outputs = torch.cat([tmp['preds'] for tmp in outs])\n        labels = torch.cat([tmp['targets'] for tmp in outs])\n\n        confusion = ConfusionMatrix(task=\"multiclass\", num_classes=self.num_classes).to(device)\n        confusion(outputs, labels)\n        computed_confusion = confusion.compute().detach().cpu().numpy().astype(int)\n\n        # confusion matrix\n        df_cm = pd.DataFrame(\n            computed_confusion,\n            index=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n            columns= ['safe driving', 'texting - right', 'talking on the phone - right', 'texting - left', 'talking on the phone - left',\n         'operating the radio', 'drinking', 'reaching behind', 'hair and makeup', 'talking to passenger']\n        )\n\n        fig, ax = plt.subplots(figsize=(10, 5))\n        fig.subplots_adjust(left=0.05, right=.65)\n        sn.set(font_scale=1.2)\n        sn.heatmap(df_cm, annot=True, annot_kws={\"size\": 16}, fmt='d', ax=ax)\n        ax.legend(\n            [0, 1, 2, 3, 4, 5],\n            ['buildings', 'forest', 'glacier', 'mountain', 'sea', 'street'],\n            handler_map={int: IntHandler()},\n            loc='upper left',\n            bbox_to_anchor=(1.2, 1)\n        )\n        buf = io.BytesIO()\n\n        plt.savefig(buf, format='jpeg', bbox_inches='tight')\n        buf.seek(0)\n        im = Image.open(buf)\n        im = torchvision.transforms.ToTensor()(im)\n        tb.add_image(\"val_confusion_matrix\", im, global_step=self.current_epoch)\n\n    def test_step(self, batch: Any, batch_idx: int):\n        loss, preds, targets = self.step(batch)\n\n        # update and log metrics\n        self.test_loss(loss)\n        self.test_acc(preds, targets)\n        self.log(\"test/loss\", self.test_loss, on_step=False, on_epoch=True, prog_bar=True)\n        self.log(\"test/acc\", self.test_acc, on_step=False, on_epoch=True, prog_bar=True)\n\n        return {\"loss\": loss, \"preds\": preds, \"targets\": targets}\n\n    def test_epoch_end(self, outputs: List[Any]):\n        pass\n\n    def configure_optimizers(self):\n        optimizer = self.optim_name(\n            self.parameters(),\n            lr=self.lr,\n        )\n        sch = torch.optim.lr_scheduler.StepLR(optimizer, step_size  = 10 , gamma = 0.5)\n        return {\n            \"optimizer\":optimizer,\n            \"lr_scheduler\" : {\n                \"scheduler\" : sch,\n                \"monitor\" : \"train/loss\",\n                \n            }\n          }","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:35:46.672675Z","iopub.execute_input":"2023-04-06T16:35:46.673163Z","iopub.status.idle":"2023-04-06T16:35:47.315930Z","shell.execute_reply.started":"2023-04-06T16:35:46.673121Z","shell.execute_reply":"2023-04-06T16:35:47.314818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from typing import Any, Dict, Optional\n\nimport pytorch_lightning as pl\nimport torchvision.transforms as T\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import DataLoader, Dataset\n\n\nclass IntelClassificationDataModule(pl.LightningDataModule):\n    def __init__(\n        self,\n        train_data_dir: str = \"data/\",\n        test_data_dir: str = \"data/\",\n        batch_size: int = 256,\n        num_workers: int = 0,\n        pin_memory: bool = False,\n    ):\n        super().__init__()\n\n        # this line allows to access init params with 'self.hparams' attribute\n        # also ensures init params will be stored in ckpt\n        self.save_hyperparameters(logger=False)\n        \n        self.train_data_dir = train_data_dir\n        self.test_data_dir = test_data_dir\n\n        ######################\n        # data transformations\n        ######################\n        # References: https://pytorch.org/vision/stable/auto_examples/plot_transforms.html\n        \n\n        self.transforms1 = T.RandomApply(\n            [\n                T.RandomRotation(degrees=(0, 70)),\n                T.RandomHorizontalFlip(p=0.5),\n                T.ColorJitter(brightness=(0.1, 0.6), contrast=1, saturation=0, hue=0.3),\n                T.GaussianBlur(kernel_size=(5, 9), sigma=(0.1, 5)),\n                T.RandomHorizontalFlip(p=0.3),\n            ], \n            p=0.3\n        )\n        self.transforms = T.Compose([\n                self.transforms1,\n                T.Resize((224, 224)),\n                T.ToTensor(),\n                T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ])\n        self.data_train: Optional[Dataset] = None\n        self.data_test: Optional[Dataset] = None\n\n    @property\n    def num_classes(self):\n        return len(self.data_train.classes)\n    \n    @property\n    def classes(self):\n        return self.data_train.classes\n\n    def prepare_data(self):\n        \"\"\"Download data if needed.\n        Do not use it to assign state (self.x = y).\n        \"\"\"\n        pass\n\n    def setup(self, stage: Optional[str] = None):\n        \"\"\"Load data. Set variables: `self.data_train`, `self.data_val`, `self.data_test`.\n        This method is called by lightning with both `trainer.fit()` and `trainer.test()`, so be\n        careful not to execute things like random split twice!\n        \"\"\"\n        # load and split datasets only if not loaded already\n        if not self.data_train and not self.data_test:\n            trainset = ImageFolder(self.train_data_dir, transform=self.transforms)\n            testset = ImageFolder(self.test_data_dir, transform=self.transforms)\n            \n            self.data_train, self.data_test = trainset, testset\n\n    def train_dataloader(self):\n        return DataLoader(\n            dataset=self.data_train,\n            batch_size=self.hparams.batch_size,\n            num_workers=self.hparams.num_workers,\n            pin_memory=self.hparams.pin_memory,\n            shuffle=True,\n        )\n\n    def val_dataloader(self):\n        return DataLoader(\n            dataset=self.data_test,\n            batch_size=self.hparams.batch_size,\n            num_workers=self.hparams.num_workers,\n            pin_memory=self.hparams.pin_memory,\n            shuffle=False,\n        )\n\n    def test_dataloader(self):\n        return DataLoader(\n            dataset=self.data_test,\n            batch_size=self.hparams.batch_size,\n            num_workers=self.hparams.num_workers,\n            pin_memory=self.hparams.pin_memory,\n            shuffle=False,\n        )\n\n    def teardown(self, stage: Optional[str] = None):\n        \"\"\"Clean up after fit or test.\"\"\"\n        pass\n\n    def state_dict(self):\n        \"\"\"Extra things to save to checkpoint.\"\"\"\n        return {}\n\n    def load_state_dict(self, state_dict: Dict[str, Any]):\n        \"\"\"Things to do when loading checkpoint.\"\"\"\n        pass\n\n","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:35:48.572765Z","iopub.execute_input":"2023-04-06T16:35:48.573314Z","iopub.status.idle":"2023-04-06T16:35:48.591141Z","shell.execute_reply.started":"2023-04-06T16:35:48.573275Z","shell.execute_reply":"2023-04-06T16:35:48.589789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_DATA_PATH = '/kaggle/working/dataa/train'\nTEST_DATA_PATH = '/kaggle/working/dataa/val'\n\nbatch_size = 128\n\n","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:35:49.621863Z","iopub.execute_input":"2023-04-06T16:35:49.622566Z","iopub.status.idle":"2023-04-06T16:35:49.627446Z","shell.execute_reply.started":"2023-04-06T16:35:49.622529Z","shell.execute_reply":"2023-04-06T16:35:49.626333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from typing import Any, Dict, Optional, Tuple\n\nimport os\nimport subprocess\nimport torch\nimport timm\nimport json\n\nimport pytorch_lightning as pl\nfrom pathlib import Path\nfrom torchvision.datasets import ImageFolder\nfrom pytorch_lightning import loggers as pl_loggers\nfrom pytorch_lightning.callbacks.early_stopping import EarlyStopping\n\n\nmodel_name = \"regnetz_c16\"\noptimizer_name = \"ADAM\"\nlearning_rate = 0.000012\nbatch_size = 64\n\n\n \n\ndef train(model, datamodule):\n    tb_logger = pl_loggers.TensorBoardLogger(save_dir=\"output\")\n    early_stop_callback = EarlyStopping(monitor=\"val/acc\", min_delta=0.00, patience=3, verbose=False, mode=\"max\")\n    trainer = pl.Trainer(\n        max_epochs=10,\n        accelerator=\"auto\",\n        callbacks=[early_stop_callback],\n        logger=[tb_logger]\n    )\n    hyperparameters = dict(model_name=model_name, optimizer_name=optimizer_name, learning_rate=learning_rate)\n    trainer.logger.log_hyperparams(hyperparameters)\n    trainer.fit(model, datamodule)\n    \n    return trainer\n\n\ndef save_scripted_model(model):\n    script = model.to_torchscript()\n\n    # save for use in production environment\n    torch.jit.save(script,\"model.scripted.pt\")\n    \n    \ndef save_model(model):\n    torch.save(model.state_dict(), \"model.pt\")\n\n\ndef save_last_ckpt(trainer):\n    trainer.save_checkpoint(\"last.ckpt\")\n\n\nif __name__ == '__main__':\n    test_dir = \"/kaggle/working/dataa/val\"\n    train_dir = \"/kaggle/working/dataa/train\"\n    \n    # Reading dataset\n    print(\":: Reading dataset ..\")\n    img_dset = ImageFolder(train_dir)\n    \n    print(\":: Classnames: \", img_dset.classes)\n    \n    \n    datamodule = IntelClassificationDataModule(train_data_dir=train_dir, test_data_dir=test_dir,\n                                               batch_size=batch_size,num_workers=4)\n    datamodule.setup()\n    \n    print(\":: Datamodule setup completed ..\")\n    model = LitResnet(num_classes=datamodule.num_classes, model_name=model_name, optim_name=optimizer_name,\n                      lr=learning_rate)\n        \n    print(\":: Training ...\")\n    trainer = train(model, datamodule)\n\n    print(\":: Saving Model Ckpt\")\n    save_last_ckpt(trainer)\n    \n    # set to evaluation model before scripting\n    print(\":: Saving Scripted Model\")\n    save_model(model)\n","metadata":{"execution":{"iopub.status.busy":"2023-04-06T16:35:50.292878Z","iopub.execute_input":"2023-04-06T16:35:50.293564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}