{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.7.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":5048,"databundleVersionId":868335,"sourceType":"competition"},{"sourceId":2877433,"sourceType":"datasetVersion","datasetId":1743523},{"sourceId":153186277,"sourceType":"kernelVersion"}],"dockerImageVersionId":30146,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Title: Distracted Driver Detection","metadata":{}},{"cell_type":"markdown","source":"## Project Members:\n\n```\nName: Muhammad Maiz     Reg. ID: SP21-BCS-052\nName: Rehan Ahmed       Reg. ID: SP21-BCS-104\nName: Hassan Arslan     Reg. ID: SP21-BCS-048\n```\n","metadata":{}},{"cell_type":"markdown","source":"### Objective: \nEnhancing road safety by identifying instances of driver distraction such as drowsiness, engagement in activities like texting, making calls, makeup and settling hairs, talking to passengers, operating the radio and drinking etc.","metadata":{}},{"cell_type":"markdown","source":"### Motivation\nIn today's fast-paced world, distracted driving has emerged as a critical concern, posing serious threats to road safety. The National Highway Traffic Safety Administration (NHTSA) reported that 36,750 people died in motor vehicle crashes in 2018, and 12% of it was due to distracted driving.","metadata":{}},{"cell_type":"markdown","source":"## Dataset\n\nhttps://www.kaggle.com/competitions/state-farm-distracted-driver-detection/data","metadata":{}},{"cell_type":"code","source":"# Import the module to use\nimport os.path as osp\nfrom glob import glob\nimport random\nimport time\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport plotly.express as px\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import accuracy_score\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.utils.data as data\nimport torch.optim as optim\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2024-05-24T18:59:37.999127Z","iopub.execute_input":"2024-05-24T18:59:37.999452Z","iopub.status.idle":"2024-05-24T18:59:38.007096Z","shell.execute_reply.started":"2024-05-24T18:59:37.999419Z","shell.execute_reply":"2024-05-24T18:59:38.006287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def fix_seed(seed):\n    # random\n    random.seed(seed)\n    # Numpy\n    np.random.seed(seed)\n    # Pytorch\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    torch.backends.cudnn.deterministic = True","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.008541Z","iopub.execute_input":"2024-05-24T18:59:38.008890Z","iopub.status.idle":"2024-05-24T18:59:38.019995Z","shell.execute_reply.started":"2024-05-24T18:59:38.008855Z","shell.execute_reply":"2024-05-24T18:59:38.019322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fix Seed value\nSEED = 42\nfix_seed(SEED)\n\n# Defining the description of each class\nactivity_map = {\n    'c0': 'Safe driving', \n    'c1': 'Texting - right', \n    'c2': 'Talking on the phone - right', \n    'c3': 'Texting - left', \n    'c4': 'Talking on the phone - left', \n    'c5': 'Operating the radio', \n    'c6': 'Drinking', \n    'c7': 'Reaching behind', \n    'c8': 'Hair and makeup', \n    'c9': 'Talking to passenger'\n}\n\n# path definition\ndata_dir = '/kaggle/input/state-farm-distracted-driver-detection'\ncsv_file_path = osp.join(data_dir, 'driver_imgs_list.csv')","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.020972Z","iopub.execute_input":"2024-05-24T18:59:38.021211Z","iopub.status.idle":"2024-05-24T18:59:38.030556Z","shell.execute_reply.started":"2024-05-24T18:59:38.021174Z","shell.execute_reply":"2024-05-24T18:59:38.029846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(csv_file_path) # Read csv file\ndf.head(5) # show first 5 rows","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.032078Z","iopub.execute_input":"2024-05-24T18:59:38.032610Z","iopub.status.idle":"2024-05-24T18:59:38.066054Z","shell.execute_reply.started":"2024-05-24T18:59:38.032554Z","shell.execute_reply":"2024-05-24T18:59:38.065318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"code","source":"by_drivers = df.groupby('subject') # Group by driver\nunique_drivers = by_drivers.groups.keys() # List of driver names\n\n# Number of drivers included in the dataset\nprint('unique drivers: ',len(unique_drivers)) \n# Average number of images per driver\nprint('mean of images: ', round(df.groupby('subject').count()['classname'].mean()))","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.067477Z","iopub.execute_input":"2024-05-24T18:59:38.068005Z","iopub.status.idle":"2024-05-24T18:59:38.086935Z","shell.execute_reply.started":"2024-05-24T18:59:38.067968Z","shell.execute_reply":"2024-05-24T18:59:38.086152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_file_num = len(glob(osp.join(data_dir, 'imgs/train/*/*.jpg'))) # Number of training data\ntest_file_num = len(glob(osp.join(data_dir, 'imgs/test/*.jpg'))) # Number of test data\ncategory_num = len(df['classname'].unique()) # number of categories\nprint('train_file_num: ', train_file_num)\nprint('test_file_num: ', test_file_num)\nprint('category_num: ', category_num)","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.087888Z","iopub.execute_input":"2024-05-24T18:59:38.088090Z","iopub.status.idle":"2024-05-24T18:59:38.501391Z","shell.execute_reply.started":"2024-05-24T18:59:38.088065Z","shell.execute_reply":"2024-05-24T18:59:38.500608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Number of data per class\npx.histogram(df, x=\"classname\", color=\"classname\", title=\"Number of images by categories \")","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.503390Z","iopub.execute_input":"2024-05-24T18:59:38.503628Z","iopub.status.idle":"2024-05-24T18:59:38.802695Z","shell.execute_reply.started":"2024-05-24T18:59:38.503598Z","shell.execute_reply":"2024-05-24T18:59:38.801964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"drivers_id = pd.DataFrame((df['subject'].value_counts()).reset_index())\ndrivers_id.columns = ['driver_id', 'Counts']\npx.histogram(drivers_id, x=\"driver_id\",y=\"Counts\" ,color=\"driver_id\", title=\"Number of images by subjects \")","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.803885Z","iopub.execute_input":"2024-05-24T18:59:38.804146Z","iopub.status.idle":"2024-05-24T18:59:38.987141Z","shell.execute_reply.started":"2024-05-24T18:59:38.804111Z","shell.execute_reply":"2024-05-24T18:59:38.986440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Histogram of number of images per driver\npx.histogram(df, x='subject', color='subject', title='Number of images by subjects')","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:38.988393Z","iopub.execute_input":"2024-05-24T18:59:38.989012Z","iopub.status.idle":"2024-05-24T18:59:39.571805Z","shell.execute_reply.started":"2024-05-24T18:59:38.988972Z","shell.execute_reply":"2024-05-24T18:59:39.571050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Draw data for each class\nplt.figure(figsize=(12, 20))\nfor i, (key, value) in enumerate(activity_map.items()):\n    image_dir = osp.join(data_dir, 'imgs/train', key, '*.jpg')\n    image_path = glob(image_dir)[0]\n    image = cv2.imread(image_path)[:, :, (2, 1, 0)]\n    plt.subplot(5, 2, i+1)\n    plt.imshow(image)\n    plt.title(value)","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:39.572825Z","iopub.execute_input":"2024-05-24T18:59:39.573033Z","iopub.status.idle":"2024-05-24T18:59:41.851669Z","shell.execute_reply.started":"2024-05-24T18:59:39.573007Z","shell.execute_reply":"2024-05-24T18:59:41.850667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocessing","metadata":{}},{"cell_type":"code","source":"# Add file path column\ndf['file_path'] = df.apply(lambda x: osp.join(data_dir, 'imgs/train', x.classname, x.img), axis=1)\n\n# Convert the correct answer labels to numbers and add a column\ndf['class_num'] = df['classname'].map(lambda x: int(x[1]))\ndf.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:41.852975Z","iopub.execute_input":"2024-05-24T18:59:41.853232Z","iopub.status.idle":"2024-05-24T18:59:42.619624Z","shell.execute_reply.started":"2024-05-24T18:59:41.853201Z","shell.execute_reply":"2024-05-24T18:59:42.618806Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset Class","metadata":{}},{"cell_type":"code","source":"class DataTransform():\n    \"\"\"\n    Image and annotation preprocessing class. It behaves differently during training and verification.\n    Set the image size to input_size x input_size.\n    Data augmentation is performed during training.\n\n\n    Attributes\n    ----------\n    input_size : int\n        The size of the image to resize.\n    color_mean : (R, G, B)\n        Average value for each color channel.\n    color_std : (R, G, B)\n        Standard deviation for each color channel.\n    \"\"\"\n\n    def __init__(self, input_size, color_mean, color_std):\n        self.data_transform = {\n            'train': A.Compose([\n                A.HorizontalFlip(p=0.5),\n                A.Rotate(-10, 10),\n                A.Resize(input_size, input_size),  # Resize (input_size)\n                A.Normalize(color_mean, color_std),  # Standardization\n                ToTensorV2() # Tensorization\n            ]),\n            'val': A.Compose([\n                A.Resize(input_size, input_size),  # Resize (input_size)\n                A.Normalize(color_mean, color_std),  # Standardization\n                ToTensorV2() # Tensorization\n            ])\n        }\n\n    def __call__(self, phase, image):\n        \"\"\"\n        Parameters\n        ----------\n        phase : 'train' or 'val'\n            Specify the preprocessing mode.\n        \"\"\"\n        transformed = self.data_transform[phase](image=image)\n        return transformed['image']","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:42.620783Z","iopub.execute_input":"2024-05-24T18:59:42.621029Z","iopub.status.idle":"2024-05-24T18:59:42.629372Z","shell.execute_reply.started":"2024-05-24T18:59:42.621000Z","shell.execute_reply":"2024-05-24T18:59:42.628500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset(data.Dataset):\n    \"\"\"\n    Attributes\n    ----------\n    df: DataFrame\n        Data frame with columns class_num, file_path\n    phase : 'train' or 'val'\n        Set learning or training.\n    transform: object\n        Instance of preprocessing class\n    \"\"\"\n    def __init__(self, df, phase, transform):\n        self.df = df\n        self.phase = phase\n        self.transform = transform\n\n    def __len__(self):\n        '''Returns the number of images'''\n        return len(self.df)\n\n    def __getitem__(self, index):\n        '''Get Tensor format data of preprocessed image'''\n        image = self.pull_item(index)\n        return image, self.df.iloc[index]['class_num']\n\n    def pull_item(self, index):\n        '''Get image Tensor format data'''\n        \n        # 1. Load image\n        image_path = self.df.iloc[index]['file_path']\n        image = cv2.imread(image_path)[:, :, (2, 1, 0)]\n\n        # 2. Perform pretreatment\n        return self.transform(self.phase, image)","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:42.631555Z","iopub.execute_input":"2024-05-24T18:59:42.631815Z","iopub.status.idle":"2024-05-24T18:59:42.644487Z","shell.execute_reply.started":"2024-05-24T18:59:42.631788Z","shell.execute_reply":"2024-05-24T18:59:42.643764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"##### Normalized pixel value = (Original pixel value - Mean) / Standard deviation","metadata":{}},{"cell_type":"code","source":"# Operation confirmation\n\n# ImageNet Dataset Values\n# Average value and standard deviation of (RGB) colors\ncolor_mean = (0.485, 0.456, 0.406)\ncolor_std = (0.229, 0.224, 0.225)\ninput_size = 256\n\n# data split\ndf_train, df_val = train_test_split(df, stratify=df['subject'], random_state=SEED)\n\n# Create dataset\ntrain_dataset = Dataset(df_train, phase=\"train\", transform=DataTransform(\n    input_size=input_size, color_mean=color_mean, color_std=color_std))\n\nval_dataset = Dataset(df_val, phase=\"val\", transform=DataTransform(\n    input_size=input_size, color_mean=color_mean, color_std=color_std))\n\n# Data retrieval example\nimage, label = train_dataset[0]\nplt.imshow(image.permute(1, 2, 0)) # From tensor (C, H, W) to (H, W, C)\nplt.title(activity_map['c' + f'{label}'])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:42.645674Z","iopub.execute_input":"2024-05-24T18:59:42.645991Z","iopub.status.idle":"2024-05-24T18:59:42.930917Z","shell.execute_reply.started":"2024-05-24T18:59:42.645957Z","shell.execute_reply":"2024-05-24T18:59:42.930178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataLoader","metadata":{}},{"cell_type":"code","source":"# Create data loader\nbatch_size = 64\n\ntrain_dataloader = data.DataLoader(\n    train_dataset, batch_size=batch_size, shuffle=True)\n\nval_dataloader = data.DataLoader(\n    val_dataset, batch_size=batch_size, shuffle=False)\n\n# Combine into dictionary object\ndataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader}\n\n# Check operation\nbatch_iterator = iter(dataloaders_dict[\"val\"])  # convert to iterator\nimages, labels = next(batch_iterator)  # get the first element\nprint(images.size())  # torch.Size([8, 3, 256, 256])\nprint(labels.size())  # torch.Size([8])","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:42.931994Z","iopub.execute_input":"2024-05-24T18:59:42.932219Z","iopub.status.idle":"2024-05-24T18:59:43.528159Z","shell.execute_reply.started":"2024-05-24T18:59:42.932191Z","shell.execute_reply":"2024-05-24T18:59:43.527355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create model","metadata":{}},{"cell_type":"code","source":"%pip install efficientnet_pytorch\nfrom efficientnet_pytorch import EfficientNet\nmodel = EfficientNet.from_pretrained('efficientnet-b0', num_classes=10)\n\n# class Model(nn.Module):\n#     def __init__(self, num_classes=10):\n#         super(Model, self).__init__()\n#         self.net = nn.Sequential(\n#             nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=2, padding=1),\n#             nn.BatchNorm2d(num_features=64),\n#             nn.ReLU(),\n#             nn.Conv2d(in_channels=64, out_channels=16, kernel_size=3, stride=2, padding=1),\n#             nn.BatchNorm2d(num_features=16),\n#             nn.ReLU(),\n#             nn.Flatten(),\n#             nn.Linear(in_features=65536, out_features=num_classes)\n#         )\n    \n#     def forward(self, x):\n#         output = self.net(x)\n#         return output\n# \n# model = Model(num_classes=10)","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:43.529383Z","iopub.execute_input":"2024-05-24T18:59:43.529621Z","iopub.status.idle":"2024-05-24T18:59:49.005841Z","shell.execute_reply.started":"2024-05-24T18:59:43.529590Z","shell.execute_reply":"2024-05-24T18:59:49.004956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save checkpoint\ndef save_checkpoint(model, optimizer, scheduler, epoch, path):\n    torch.save(\n        {'epoch': epoch,\n                'model': model.state_dict(),\n                'optimizer': optimizer.state_dict(),\n                'scheduler': scheduler.state_dict(), \n        }, path)\n\n# Read checkpoint\ndef load_checkpoint(model, optimizer, scheduler, path):\n    checkpoint = torch.load(path)\n    model.load_state_dict(checkpoint['model'])\n    optimizer.load_state_dict(checkpoint['optimizer'])\n    scheduler.load_state_dict(checkpoint['scheduler'])\n\n# Function to train the model\ndef train_model(model, dataloaders_dict, criterion, scheduler, optimizer, device, num_epochs, save_path):\n    # network to GPU\n    model.to(device)\n\n    best_val_loss = float('inf')\n    best_preds = None\n    \n    # epoch loop\n    for epoch in range(num_epochs):\n\n        # save start time\n        t_epoch_start = time.time()\n        epoch_train_loss = 0.0  # loss sum of epoch\n        epoch_val_loss = 0.0  # loss sum of epoch\n        preds = []\n        trues = []\n\n        print('-------------')\n        print(f'Epoch {epoch+1}/{num_epochs}')\n        print('-------------')\n\n        # Training and validation loop for each epoch\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()  # put the model in training mode\n            else:\n                model.eval()   # put the model in validation mode\n                print('-------------')\n                \n            # Forward calculation\n            for i, (images, labels) in enumerate(dataloaders_dict[phase]):\n\n                # Send data to GPU if GPU is available\n                images = images.to(device)\n                labels = labels.to(device)\n\n                # Forward calculation\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(images)\n                    loss = criterion(outputs, labels)\n                    \n                    # Backpropagation during training\n                    if phase == 'train':\n                        loss.backward()  # Calculate slope\n                        optimizer.step()\n                        optimizer.zero_grad() # Initialize gradient\n                        epoch_train_loss += loss.item()/len(dataloaders_dict[phase].dataset)\n                    # At verification time\n                    else:\n                        preds += [outputs.detach().cpu().softmax(dim=1).numpy()]\n                        trues += [labels.detach().cpu()]\n                        epoch_val_loss += loss.item()/len(dataloaders_dict[phase].dataset)\n                    \n                    # Show progress\n                    if i%10 == 0:\n                        print(f'[{phase}][{i+1}/{len(dataloaders_dict[phase])}] loss: {loss.item()/images.size(0): .4f}')\n        \n        if phase == 'train':\n            scheduler.step()  # Update optimization scheduler\n            \n        # Loss and correct answer rate for each phase of epoch\n        t_epoch_finish = time.time()\n        print('-------------')\n        print(f'epoch {epoch+1} epoch_train_Loss:{epoch_train_loss:.4f} epoch_val_loss:{epoch_val_loss:.4f} time: {t_epoch_finish - t_epoch_start:.4f} sec.')\n        print(f'epoch_val_acc: {accuracy_score(np.concatenate(trues), np.concatenate(preds).argmax(axis=1))}')\n        \n        # Save the model of the epoch with the lowest validation loss\n        if best_val_loss > epoch_val_loss:\n            best_preds = np.concatenate(preds)\n            best_val_loss = epoch_val_loss\n            save_checkpoint(model, optimizer, scheduler, epoch, save_path)\n            print(\"save model\")\n    return best_val_loss, best_preds\n\n# Function that performs 1fold learning\ndef run_one_fold(df_train, df_val, fold, device):\n    # Create dataset\n    train_dataset = Dataset(df_train, phase=\"train\", transform=DataTransform(\n        input_size=args.input_size, color_mean=args.color_mean, color_std=args.color_std))\n\n    val_dataset = Dataset(df_val, phase=\"val\", transform=DataTransform(\n        input_size=args.input_size, color_mean=args.color_mean, color_std=args.color_std))\n    \n    # Create data loader\n    train_dataloader = data.DataLoader(\n        train_dataset, batch_size=args.batch_size, shuffle=True)\n\n    val_dataloader = data.DataLoader(\n        val_dataset, batch_size=args.batch_size, shuffle=False)\n\n    # Combine into dictionary object\n    dataloaders_dict = {\"train\": train_dataloader, \"val\": val_dataloader}\n\n    # model definition\n    model = EfficientNet.from_pretrained(args.model_name, num_classes=args.num_classes)\n    optimizer = optim.Adam(model.parameters(), lr=args.lr) # Optimization method\n    criterion = nn.CrossEntropyLoss() # loss function\n    scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=args.gamma) # Scheduler\n    \n    save_path = f\"{args.model_name}_fold_{fold}.pth\"\n    best_val_loss, best_preds = train_model(model, dataloaders_dict, criterion, scheduler, optimizer, device, num_epochs=args.epochs, save_path=save_path)\n    return best_val_loss, best_preds\n\n# Function to learn kfold\ndef run_k_fold(df):\n    # Check if GPU can be used\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    print(\"Device used:\", device)\n    \n    # Stratified K-fold cross validation\n    skf = StratifiedKFold(n_splits=args.folds, shuffle=True, random_state=SEED)\n    oof = pd.DataFrame(index=df.index)\n    for fold, (train_index, val_index) in enumerate(skf.split(df, df['subject'])):\n        print(f'\\n\\nFOLD: {fold}')\n        print('-'*50)\n        df_train, df_val = df.loc[train_index], df.loc[val_index]\n        best_val_loss, best_preds = run_one_fold(df_train, df_val, fold, device)\n        oof.loc[val_index, activity_map.keys()] = best_preds\n    return oof","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:49.007802Z","iopub.execute_input":"2024-05-24T18:59:49.008044Z","iopub.status.idle":"2024-05-24T18:59:49.037081Z","shell.execute_reply.started":"2024-05-24T18:59:49.008013Z","shell.execute_reply":"2024-05-24T18:59:49.036319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# learning parameters\nclass args:\n    model_name = 'efficientnet-b3'\n    color_mean = (0.485, 0.456, 0.406)\n    color_std = (0.229, 0.224, 0.225)\n    input_size = 256\n    num_classes = 10\n    batch_size = 64\n    epochs = 10\n    folds = 5\n    lr = 1e-3\n    gamma = 0.98\n    debug = False\n    train = True","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:49.038063Z","iopub.execute_input":"2024-05-24T18:59:49.038289Z","iopub.status.idle":"2024-05-24T18:59:49.051345Z","shell.execute_reply.started":"2024-05-24T18:59:49.038260Z","shell.execute_reply":"2024-05-24T18:59:49.050618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if args.debug:\n    df_train = df.iloc[:1000]\nelse:\n    df_train = df.copy()\n\nif args.train:\n    oof = run_k_fold(df_train)\n    accuracy = accuracy_score(df_train['class_num'], oof.values.argmax(axis=1))\n    print(f'\\n\\naccuracy: {accuracy}')","metadata":{"execution":{"iopub.status.busy":"2024-05-24T18:59:49.052430Z","iopub.execute_input":"2024-05-24T18:59:49.052659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predicting test data","metadata":{}},{"cell_type":"code","source":"# Function to perform inference on test data\ndef inference(model, dataloader, device):\n    model.to(device)\n    model.eval()\n    preds = []\n    for i, (images, labels) in enumerate(dataloader):\n        images = images.to(device)\n        with torch.no_grad():\n            outputs = model(images)\n        preds += [outputs.detach().cpu().softmax(dim=1).numpy()]\n        \n        if i%10 == 0:\n            print(f'[test][{i+1}/{len(dataloader)}]')\n        \n    preds = np.concatenate(preds)\n    return preds\n\n# Perform inference on k models and create an ensemble\ndef inference_k_fold(df_test):\n    test_dataset = Dataset(df_test, phase=\"val\", transform=DataTransform(\n        input_size=args.input_size, color_mean=args.color_mean, color_std=args.color_std))\n    test_dataloader = data.DataLoader(\n        test_dataset, batch_size=args.batch_size, shuffle=False)\n\n    model = EfficientNet.from_pretrained(args.model_name, num_classes=args.num_classes)\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n    for fold in range(args.folds):\n        print(f'\\n\\nFOLD: {fold}')\n        print('-'*50)\n        model.load_state_dict(torch.load(f\"/kaggle/input/statefarmdistracteddriverdetectionpretrain/{args.model_name}_fold_{fold}.pth\", map_location=torch.device('cpu'))['model'])\n        df_test.loc[:, activity_map.keys()] += (inference(model, test_dataloader, device) / args.folds)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if args.debug:\n    results = pd.read_csv('result.csv')\n    results.to_csv('result.csv', index=False)\nelse:\n    # Load test data\n    df_test = pd.read_csv(osp.join(data_dir, 'sample_submission.csv'))\n\n    # Preprocessing\n    df_test['file_path'] = df_test.apply(lambda row: osp.join(data_dir, f'imgs/test/{row.img}'), axis=1)\n    df_test['class_num'] = 0\n    df_test.loc[:, activity_map.keys()] = 0\n    \n    # Average k inference results and store in results\n    inference_k_fold(df_test)\n    results = df_test.drop(['file_path', 'class_num'], axis=1)\n    results.iloc[:, 1:] = results.iloc[:, 1:].clip(0, 1)\n    results.to_csv('result.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}