{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":17947,"databundleVersionId":896432,"sourceType":"competition"}],"dockerImageVersionId":30699,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<a href=\"https://www.kaggle.com/code/ukaszniedwiadek/food101-exodia?scriptVersionId=182879136\" target=\"_blank\"><img align=\"left\" alt=\"Kaggle\" title=\"Open in Kaggle\" src=\"https://kaggle.com/static/images/open-in-kaggle.svg\"></a>","metadata":{}},{"cell_type":"markdown","source":"Importing libraries","metadata":{}},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np\nimport pandas as pd\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n\n\nimport torch\nimport os\nimport csv\nimport cv2\nfrom PIL import Image\nfrom torchvision import transforms\nimport torchvision.models as models\n#from albumentations.pytorch import ToTensorV2\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import Dataset, DataLoader\nimport timm\nfrom tqdm.notebook import tqdm\nfrom timeit import default_timer as timer\nimport torch.nn as nn\nimport time\nfrom torch.optim import lr_scheduler\nfrom tempfile import TemporaryDirectory\n","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:35.929619Z","iopub.execute_input":"2024-06-12T17:24:35.930424Z","iopub.status.idle":"2024-06-12T17:24:35.936919Z","shell.execute_reply.started":"2024-06-12T17:24:35.930391Z","shell.execute_reply":"2024-06-12T17:24:35.935883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import torch_xla\n# import torch_xla.core.xla_model as xm\n\n# device = xm.xla_device()\n# print(device)","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:35.938353Z","iopub.execute_input":"2024-06-12T17:24:35.938611Z","iopub.status.idle":"2024-06-12T17:24:35.950885Z","shell.execute_reply.started":"2024-06-12T17:24:35.938590Z","shell.execute_reply":"2024-06-12T17:24:35.950037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu') \nprint(f'Using {device} device')\n# device = xm.xla_device()\n# print(device)","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:35.953126Z","iopub.execute_input":"2024-06-12T17:24:35.953508Z","iopub.status.idle":"2024-06-12T17:24:35.963131Z","shell.execute_reply.started":"2024-06-12T17:24:35.953476Z","shell.execute_reply":"2024-06-12T17:24:35.962318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Defining Classes and functions","metadata":{}},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, df, data_root, transforms=None, give_label=True):\n        \"\"\"Performed only once when the Dataset object is instantiated.\n        give_label should be False for test data\n        \"\"\" \n        super().__init__()\n        self.df = df.reset_index(drop=True).copy()\n        self.data_root = data_root\n        self.transforms = transforms\n        self.give_label = give_label\n        \n        if give_label == True:\n            self.df['label'] = self.df['label'].astype(int)\n            self.labels = self.df['label'].values\n\n    def __len__(self):\n        \"\"\"Function to return the number of records in the dataset\n        \"\"\" \n        return self.df.shape[0]\n    \n    def __getitem__(self, index):\n        \"\"\"Function to return samples corresponding to a given index from a dataset\n        \"\"\" \n        # get labels\n        if self.give_label:\n            target = self.labels[index]\n            target = torch.tensor(target)\n\n        # Load images\n        img = Image.open(f'{self.data_root}/{self.df.loc[index][\"image_id\"]}.jpg').convert(\"RGB\")\n        #img  = load_img(f'{self.data_root}/{self.df.loc[index][\"image_id\"]}.jpg').astype(np.float32)\n        # img /= 255.0 # Normalization\n\n        # Transform images\n        if self.transforms:\n            img = self.transforms(img)\n\n        if self.give_label == True:\n            return img, target\n        else:\n            return img\n\n\ndef load_img(path):\n    img = Image.open(PATH_TRAINING + category + \"\\\\\" + imgPath).convert(\"RGB\")\n    img_bgr = cv2.imread(path)\n    img_rgb = img_bgr[:, :, ::-1]\n    return img_rgb\n\n\ndef get_labels(path, give_label):\n    list_id = []\n    list_label = []\n    with open(path, mode ='r')as file:\n        csvFile = csv.reader(file)\n        for lines in csvFile:\n            list_id.append(lines[0])\n            if give_label:\n                list_label.append(lines[1])\n    list_id.pop(0)\n    if give_label:\n        list_label.pop(0)\n        return list_id, list_label\n    return list_id","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:35.964027Z","iopub.execute_input":"2024-06-12T17:24:35.964268Z","iopub.status.idle":"2024-06-12T17:24:35.978479Z","shell.execute_reply.started":"2024-06-12T17:24:35.964242Z","shell.execute_reply":"2024-06-12T17:24:35.977719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Loading the dataset","metadata":{}},{"cell_type":"code","source":"main_dir = \"/kaggle/input/dat18seefood\"\nbatch_size = 32\nimage_size = 256\n\n\nitems = os.listdir(main_dir)\ntrain_id = []\ntrain_label = []\n\ntest_id = []\ntest_label = []\n\nfor item in items:\n    if item == \"train.csv\":\n        path = os.path.join(main_dir, item)\n        train_id, train_label = get_labels(path, give_label=True)\n    if item == \"test.csv\":\n        path = os.path.join(main_dir, item)\n        test_id = get_labels(path, give_label=False)\n\nX_train, X_val, y_train, y_val = train_test_split(train_id, train_label, stratify=train_label, test_size=0.20, random_state=42)\nprint(f\"[DEBUG] Number of samples in validation set is: {len(X_val)}\")\nprint(f\"[DEBUG] Number of samples in train set is: {len(X_train)}\")\ndf_train = pd.DataFrame({\n    'image_id': X_train,\n    'label': y_train\n})\n\ndf_val = pd.DataFrame({\n    'image_id': X_val,\n    'label': y_val\n})\n\ndf_test = pd.DataFrame({\n    'image_id': test_id,\n})\n\ndf_labels = pd.read_csv(main_dir + '/labelnames.csv')\nprint(f\"[INFO] Loaded dataframe of dataset with ID's and labels\\n {df_labels}\")\nprint(f\"[DEBUG] Number of samples for each class in train set {df_train['label'].value_counts()}\")\nprint(f\"[DEBUG] Number of samples for each class in validation set {df_val['label'].value_counts()}\")\nprint(f\"[DEBUG] Number of samples for each class in test set {df_test['image_id'].value_counts()}\")","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:35.979852Z","iopub.execute_input":"2024-06-12T17:24:35.980100Z","iopub.status.idle":"2024-06-12T17:24:36.207681Z","shell.execute_reply.started":"2024-06-12T17:24:35.980080Z","shell.execute_reply":"2024-06-12T17:24:36.206722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Augment the dataset","metadata":{}},{"cell_type":"code","source":"train_transform = transforms.Compose([\n    transforms.Resize((image_size, image_size)),\n    transforms.RandomRotation(45),\n    transforms.RandomResizedCrop(image_size, scale=(0.7, 1.0)),\n    transforms.RandomHorizontalFlip(0.2),\n    transforms.RandomVerticalFlip(0.2),\n    transforms.RandomAffine(degrees=0, shear=0.25),\n    transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\nval_transform = transforms.Compose([\n    transforms.Resize((image_size, image_size)),\n    transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\ntest_transform = transforms.Compose([\n    transforms.Resize((image_size, image_size)),\n    transforms.ToTensor(),\n])\n\ntrain_dataset = CustomDataset(df_train, main_dir+\"/train/\",transforms=train_transform,give_label=True)\nval_dataset = CustomDataset(df_val, main_dir+\"/train/\",transforms=val_transform,give_label=True)\ntest_dataset = CustomDataset(df_test, main_dir+\"/test/\",transforms=test_transform,give_label=False)\n\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=True)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)\n\ndataloaders = {\n    \"train\": train_loader,\n    \"val\": val_loader,\n    \"test\": test_loader\n}\n\ndataset_sizes = {\n    \"train\": len(train_loader),\n    \"val\": len(val_loader),\n    \"test\": len(test_loader)\n}\n# class_names = image_datasets['train'].classes\nprint(dataset_sizes)\n#it = iter(train_loader)\n#first = next(it)\n# second = next(it)\ni=0\nfor images, labels in train_loader:\n    print(f\"Image on idx {i} {images.shape}\")\n    print(f\"Label on idx {i} {labels.shape}\")\n    print(labels)\n    i+=1\n    if i==3:\n        break","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:36.209748Z","iopub.execute_input":"2024-06-12T17:24:36.210413Z","iopub.status.idle":"2024-06-12T17:24:37.153487Z","shell.execute_reply.started":"2024-06-12T17:24:36.210376Z","shell.execute_reply":"2024-06-12T17:24:37.152584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomClassifier(nn.Module):\n    def __init__(self, in_features, num_classes):\n        super(CustomClassifier, self).__init__()\n        self.classifier = nn.Sequential(\n            nn.Linear(in_features, 128),\n            nn.ReLU(),\n            nn.Linear(128, 128),\n            nn.ReLU(),\n            nn.Linear(128, num_classes),\n            nn.Softmax(dim=1)\n        )\n    \n    def forward(self, x):\n        return self.classifier(x)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:37.154848Z","iopub.execute_input":"2024-06-12T17:24:37.155564Z","iopub.status.idle":"2024-06-12T17:24:37.162004Z","shell.execute_reply.started":"2024-06-12T17:24:37.155532Z","shell.execute_reply":"2024-06-12T17:24:37.161146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = models.efficientnet_v2_s(pretrained=True)\nin_features = model.classifier[1].in_features\n# Replace the classifier with the custom classifier\nmodel.classifier = CustomClassifier(in_features, 101)\n# model.classifier[1] = nn.Linear(model.classifier[1].in_features, 101)\nmodel= nn.DataParallel(model)\nmodel_ft = model.to(device)","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:37.164393Z","iopub.execute_input":"2024-06-12T17:24:37.165051Z","iopub.status.idle":"2024-06-12T17:24:37.773795Z","shell.execute_reply.started":"2024-06-12T17:24:37.164987Z","shell.execute_reply":"2024-06-12T17:24:37.772840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, criterion, optimizer, scheduler, num_epochs=25):\n    since = time.time()\n    \n    # Create a temporary directory to save training checkpoints\n    with TemporaryDirectory() as tempdir:\n        best_model_params_path = os.path.join(tempdir, 'best_model_params.pt')\n\n        #torch.save(model.state_dict(), best_model_params_path)\n        best_acc = 0.0\n\n        for epoch in range(num_epochs):\n            print(f'Epoch {epoch}/{num_epochs - 1}')\n            print('-' * 10)\n\n            # Each epoch has a training and validation phase\n            for phase in ['train', 'val']:\n                if phase == 'train':\n                    model.train()  # Set model to training mode\n                else:\n                    model.eval()   # Set model to evaluate mode\n\n                running_loss = 0.0\n                running_corrects = 0\n\n                # Iterate over data.\n                i=0\n                for inputs, labels in dataloaders[phase]:\n                    inputs = inputs.to(device)\n                    labels = labels.to(device)\n\n                    # zero the parameter gradients\n                    optimizer.zero_grad()\n\n                    # forward\n                    # track history if only in train\n                    with torch.set_grad_enabled(phase == 'train'):\n                        outputs = model(inputs)\n                        _, preds = torch.max(outputs, 1)\n                        loss = criterion(outputs, labels)\n\n                        # backward + optimize only if in training phase\n                        if phase == 'train':\n                            loss.backward()\n                            optimizer.step()\n\n                    # statistics\n                    running_loss += loss.item() * inputs.size(0)\n                    running_corrects += torch.sum(preds == labels.data)\n                    #print(f\"{phase} iteration {i} finished.\")\n                    i+=1\n                if phase == 'train':\n                    scheduler.step()\n\n                epoch_loss = running_loss / dataset_sizes[phase]\n                epoch_acc = running_corrects.double() / dataset_sizes[phase]\n\n                print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')\n\n                # deep copy the model\n                if phase == 'val' and epoch_acc > best_acc:\n                    best_acc = epoch_acc\n                    torch.save(model.state_dict(), best_model_params_path)\n\n            print()\n\n        time_elapsed = time.time() - since\n        print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s')\n        print(f'Best val Acc: {best_acc:4f}')\n\n        # load best model weights\n        model.load_state_dict(torch.load(best_model_params_path))\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:37.775056Z","iopub.execute_input":"2024-06-12T17:24:37.775340Z","iopub.status.idle":"2024-06-12T17:24:37.788820Z","shell.execute_reply.started":"2024-06-12T17:24:37.775316Z","shell.execute_reply":"2024-06-12T17:24:37.787864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# criterion = nn.CrossEntropyLoss().to(device)\n\noptimizer_ft = torch.optim.Adam(model_ft.parameters(), lr=0.001)\n\nexp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)\n\nmodel_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,\n                       num_epochs=1)","metadata":{"execution":{"iopub.status.busy":"2024-06-12T17:24:37.790123Z","iopub.execute_input":"2024-06-12T17:24:37.790526Z","iopub.status.idle":"2024-06-12T17:47:00.918780Z","shell.execute_reply.started":"2024-06-12T17:24:37.790496Z","shell.execute_reply":"2024-06-12T17:47:00.917836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(type(df_test['image_id']))\nid_code = pd.Series(['id_001', 'id_002', 'id_003', 'id_004', 'id_005'])\nprint(type(id_code))\n\n# Example label list\nlabel = [1, 0, 1, 0, 1]\n\n# Create a DataFrame from the Series and list\ndf = pd.DataFrame({\n    'id_code': id_code,\n    'label': label\n})\n\n#directory = \"/kaggle/output\"\n#os.makedirs(directory, exist_ok=True)\n#df.to_csv('/kaggle/working/submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-12T19:16:47.772664Z","iopub.execute_input":"2024-06-12T19:16:47.772997Z","iopub.status.idle":"2024-06-12T19:16:47.779649Z","shell.execute_reply.started":"2024-06-12T19:16:47.772973Z","shell.execute_reply":"2024-06-12T19:16:47.778846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\nall_predictions = []\n\nwith torch.no_grad():  # Disable gradient computation for inference\n    i = 0\n    for data in test_loader:\n        print(\"iter: \" + str(i))\n        if i == 5:\n            break\n        data = data.to(device)\n\n        # Forward pass\n        outputs = model(data)\n        _, predictions = torch.max(outputs, 1)  # Get the index of the max log-probability\n\n        all_predictions.extend(predictions.cpu().numpy())\n        i += 1","metadata":{"execution":{"iopub.status.busy":"2024-06-12T19:20:32.848071Z","iopub.execute_input":"2024-06-12T19:20:32.848453Z","iopub.status.idle":"2024-06-12T19:20:34.982275Z","shell.execute_reply.started":"2024-06-12T19:20:32.848426Z","shell.execute_reply":"2024-06-12T19:20:34.981346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = pd.read_csv(os.path.join(main_dir, \"sample_submission.csv\"))\nprint(sample)\nsample.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-12T19:40:53.555548Z","iopub.execute_input":"2024-06-12T19:40:53.556365Z","iopub.status.idle":"2024-06-12T19:40:53.612534Z","shell.execute_reply.started":"2024-06-12T19:40:53.556331Z","shell.execute_reply":"2024-06-12T19:40:53.611710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print(all_predictions)\n# id_code = df_test['image_id'][:160]\n# all_predictions = all_predictions[:160]\n# print(len(all_predictions))\n# print(len(id_code))\n# df = pd.DataFrame({\n#     'id_code': id_code,\n#     'label': all_predictions\n# })\n# print(df)\n# df.to_csv('submission.csv', index=False)\n# !head 'submission.csv'","metadata":{"execution":{"iopub.status.busy":"2024-06-12T19:26:06.241960Z","iopub.execute_input":"2024-06-12T19:26:06.242553Z","iopub.status.idle":"2024-06-12T19:26:07.283523Z","shell.execute_reply.started":"2024-06-12T19:26:06.242515Z","shell.execute_reply":"2024-06-12T19:26:07.282590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# model = torch.hub.load('hankyul2/EfficientNetV2-pytorch', 'efficientnet_v2_s', pretrained=True, nclass=100)\n\n# epochs_no_improve = 0\n# valid_loss_min = np.Inf\n# max_epochs_stop = 3\n\n# valid_max_acc = 0\n# history = []\n# overall_start = timer()\n# learing_rate = 0.001\n\n# # Load model, loss function, and optimizing algorithm\n# model = model.to(device)\n# loss_fn = nn.CrossEntropyLoss().to(device)\n# optimizer = torch.optim.Adam(model.parameters(), lr=learing_rate)\n# history = []\n\n# # Start training\n# epochs = 10\n# for epoch in range(epochs):\n#     time_start = time.time()\n#     print(f'==========Epoch {epoch+1} Start Training==========')\n#     model.train()\n\n#     train_loss = 0.0\n#     valid_loss = 0.0\n\n#     train_acc = 0\n#     valid_acc = 0\n\n#     start = timer()\n#     pbar = tqdm(enumerate(train_loader), total=len(train_loader))\n#     for step, (img, label) in pbar:\n#         img = img.to(device).float()\n#         label = label.to(device).long()\n\n#         output = model(img)\n#         loss = loss_fn(output, label)\n\n#         optimizer.zero_grad()\n#         loss.backward()\n#         optimizer.step()\n\n#         train_loss += loss.item() * img.size(0)\n#         # Calculate accuracy by finding max log probability\n#         _, pred = torch.max(output, dim=1)\n#         correct_tensor = pred.eq(label.data.view_as(pred))\n#         # Need to convert correct tensor from int to float to average\n#         accuracy = torch.mean(correct_tensor.type(torch.FloatTensor))\n#         # Multiply average accuracy times the number of examples in batch\n#         train_acc += accuracy.item() * img.size(0)\n\n#         # Track training progress\n#         print(f'Epoch: {epoch}\\t{100 * (step + 1) / len(train_loader):.2f}% complete. {timer() - start:.2f} seconds elapsed in epoch.',end='\\r')\n\n\n#     model.epochs += 1\n#     with torch.no_grad():\n#         model.eval()\n#         pbar = tqdm(enumerate(valid_loader), total=len(valid_loader))\n#         for step, (img, label) in pbar:\n#             img = img.to(device).float()\n#             label = label.to(device).long()\n\n#             output = model(img)\n\n#             loss = loss_fn(output, label)\n\n#             valid_loss += loss.item() * data.size(0)\n#             # Calculate validation accuracy\n#             _, pred = torch.max(output, dim=1)\n#             correct_tensor = pred.eq(label.data.view_as(pred))\n#             accuracy = torch.mean(\n#                 correct_tensor.type(torch.FloatTensor))\n#             # Multiply average accuracy times the number of examples\n#             valid_acc += accuracy.item() * data.size(0)\n\n\n#     # Calculate average loss      \n#     train_loss = train_loss / len(train_loader.dataset)\n#     valid_loss = valid_loss / len(valid_loader.dataset)\n\n#     # Calculate average accuracy\n#     train_acc = train_acc / len(train_loader.dataset)\n#     valid_acc = valid_acc / len(valid_loader.dataset)\n\n#     history.append([train_loss, valid_loss, train_acc, valid_acc])\n#     print(f'\\nEpoch: {epoch} \\tTraining Loss: {train_loss:.4f} \\tValidation Loss: {valid_loss:.4f}')\n#     print(f'\\t\\tTraining Accuracy: {100 * train_acc:.2f}%\\t Validation Accuracy: {100 * valid_acc:.2f}%')\n\n#     if valid_loss < valid_loss_min:\n#         # Save model\n#         torch.save(model.state_dict(), save_file_name)\n#         # Track improvement\n#         epochs_no_improve = 0\n#         valid_loss_min = valid_loss\n#         valid_best_acc = valid_acc\n#         best_epoch = epoch\n#     else:\n#         epochs_no_improve += 1\n#         # Trigger early stopping\n#         if epochs_no_improve >= max_epochs_stop:\n#             print(\n#                 f'\\nEarly Stopping! Total epochs: {epoch}. Best epoch: {best_epoch} with loss: {valid_loss_min:.2f} and acc: {100 * valid_acc:.2f}%'\n#             )\n#             total_time = timer() - overall_start\n#             print(\n#                 f'{total_time:.2f} total seconds elapsed. {total_time / (epoch+1):.2f} seconds per epoch.'\n#             )\n\n#             # Load the best state dict\n#             #model.load_state_dict(torch.load(save_file_name))\n#             # Attach the optimizer\n#             model.optimizer = optimizer\n\n#             # Format history\n#             history = pd.DataFrame(\n#                 history,\n#                 columns=[\n#                     'train_loss', 'valid_loss', 'train_acc', 'valid_acc'\n#                 ])\n#             break\n\n#     # print results from this epoch\n#     exec_t = int((time.time() - time_start)/60)\n#     print(\n#         f'Epoch : {epoch+1} - loss : {epoch_loss:.4f} - acc: {epoch_accuracy:.4f} / Exec time {exec_t} min\\n'\n#     )\n\n# # Attach the optimizer\n# model.optimizer = optimizer\n# # Record overall time and print out stats\n# total_time = timer() - overall_start\n# print(\n#     f'\\nBest epoch: {best_epoch} with loss: {valid_loss_min:.2f} and acc: {100 * valid_acc:.2f}%'\n# )\n# print(\n#     f'{total_time:.2f} total seconds elapsed. {total_time / (epoch):.2f} seconds per epoch.'\n# )\n# # Format history\n# history = pd.DataFrame(\n#     history,\n#     columns=['train_loss', 'valid_loss', 'train_acc', 'valid_acc'])\n\n\n\n# # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"a8da46ad-e5cf-4f3b-ba40-c97c26e420e9","_cell_guid":"d7b14f16-e381-4eeb-974c-919f228bc70b","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-06-12T17:47:00.920384Z","iopub.execute_input":"2024-06-12T17:47:00.920786Z","iopub.status.idle":"2024-06-12T17:47:00.930678Z","shell.execute_reply.started":"2024-06-12T17:47:00.920746Z","shell.execute_reply":"2024-06-12T17:47:00.929731Z"},"trusted":true},"execution_count":null,"outputs":[]}]}