{"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":"markdown","source":"# Import\n***","metadata":{}},{"cell_type":"code","source":"pip install ttach","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:54:54.942190Z","iopub.execute_input":"2023-10-11T15:54:54.942524Z","iopub.status.idle":"2023-10-11T15:55:05.151924Z","shell.execute_reply.started":"2023-10-11T15:54:54.942496Z","shell.execute_reply":"2023-10-11T15:55:05.150617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 系统\nimport numpy as np\nimport pandas as pd\nimport os\nimport re\nimport random\nimport math\nfrom tqdm import tqdm\nfrom collections import defaultdict\n\n# 图片处理\nimport cv2\nimport PIL\nfrom PIL import Image\nfrom PIL import ImageStat\nimport matplotlib.pyplot as plt\n\nimport albumentations\nfrom albumentations import OneOf, SomeOf\nfrom albumentations.pytorch.transforms import ToTensorV2\n\n\n# 模型\nimport torch\nimport torchvision\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.optim.lr_scheduler import CosineAnnealingLR\nimport timm\nimport ttach as tta\n\nfrom sklearn.preprocessing import LabelEncoder, OneHotEncoder\nfrom sklearn.model_selection import train_test_split, StratifiedKFold, cross_val_score, cross_validate\nfrom sklearn.metrics import accuracy_score, f1_score \n","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:55:07.500067Z","iopub.execute_input":"2023-10-11T15:55:07.500404Z","iopub.status.idle":"2023-10-11T15:55:13.591955Z","shell.execute_reply.started":"2023-10-11T15:55:07.500377Z","shell.execute_reply":"2023-10-11T15:55:13.591032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if torch.cuda.is_available():\n    device = torch.device('cuda')\nelse:\n    device = torch.device('cpu')\nprint(f'Using device: {device}')","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:55:20.050125Z","iopub.execute_input":"2023-10-11T15:55:20.050776Z","iopub.status.idle":"2023-10-11T15:55:20.080610Z","shell.execute_reply.started":"2023-10-11T15:55:20.050722Z","shell.execute_reply":"2023-10-11T15:55:20.079592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Seed Setting\n***","metadata":{}},{"cell_type":"code","source":"seed = 1009\n\nrandom.seed(seed)\nnp.random.seed(seed)\nos.environ['PYTHONHASHSEED'] = str(seed)\ntorch.manual_seed(seed)\ntorch.cuda.manual_seed(seed)\ntorch.cuda.manual_seed_all(seed)\ntorch.backends.cudnn.benchmark = False\ntorch.backends.cudnn.deterministic = True\n","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:55:22.305251Z","iopub.execute_input":"2023-10-11T15:55:22.306062Z","iopub.status.idle":"2023-10-11T15:55:22.316141Z","shell.execute_reply.started":"2023-10-11T15:55:22.306033Z","shell.execute_reply":"2023-10-11T15:55:22.315315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Reading\n***","metadata":{}},{"cell_type":"code","source":"path = '../input/classify-leaves'\ntrain_path = os.path.join(path, 'train.csv')\ntest_path = os.path.join(path, 'test.csv')\n\ndf_train = pd.read_csv(train_path)\ndf_test = pd.read_csv(test_path)\nprint('train data:')\ndisplay(df_train.head())\nprint('test data:')\ndisplay(df_test.head())","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:01.051169Z","iopub.execute_input":"2023-10-11T15:56:01.051490Z","iopub.status.idle":"2023-10-11T15:56:01.134542Z","shell.execute_reply.started":"2023-10-11T15:56:01.051465Z","shell.execute_reply":"2023-10-11T15:56:01.133717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"le = LabelEncoder()\nle.fit(df_train['label'])\ndf_train['label'] = le.transform(df_train['label'])\n\nleaf_to_num = dict(zip(le.classes_, le.transform(le.classes_)))  # leaf: num\nnum_to_leaf = {n:l for l, n in leaf_to_num.items()}  # num: leaf\nnum_labels = len(le.classes_) ","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:05.740366Z","iopub.execute_input":"2023-10-11T15:56:05.740701Z","iopub.status.idle":"2023-10-11T15:56:05.751886Z","shell.execute_reply.started":"2023-10-11T15:56:05.740670Z","shell.execute_reply":"2023-10-11T15:56:05.750981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Basic Visualize\n***","metadata":{}},{"cell_type":"code","source":"# 从训练集里面展示数据长啥样\ndef img_show(num = 8):\n    fig = plt.figure(figsize=(20, 12))\n    row = 2\n    col = int(num / 2)\n    \n    for idx in range(col * row):\n        ax = fig.add_subplot(row, col, idx+1, xticks=[], yticks=[])\n        label_ = num_to_leaf[df_train.loc[idx, 'label']]\n        img_path = os.path.join(path, df_train.loc[idx, 'image'])\n        \n        img_ = Image.open(img_path)\n        ax.set_title(label_)\n        plt.imshow(img_)\n    plt.show()\nimg_show()","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:07.920534Z","iopub.execute_input":"2023-10-11T15:56:07.920920Z","iopub.status.idle":"2023-10-11T15:56:08.649070Z","shell.execute_reply.started":"2023-10-11T15:56:07.920891Z","shell.execute_reply":"2023-10-11T15:56:08.648210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataSet & Image Augmentation & DataLoader\n***","metadata":{}},{"cell_type":"code","source":"def get_img_data(img_path, os_path=path):\n    img_path_ = os.path.join(os_path, img_path)\n    img_bgr = cv2.imread(img_path_)\n    return cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)\n    \n# Dataset\nclass TrainDataset(Dataset):\n    def __init__(self, df, train_indx, transforms = None):\n        self.df_train = df.loc[train_indx, :].reset_index(drop=True).copy()\n        self.transforms = transforms\n    \n    def __len__(self):\n        return len(self.df_train)\n    \n    def __getitem__(self, idx):\n        img_path = self.df_train.loc[idx, 'image']\n        img = get_img_data(img_path)\n        label = self.df_train.loc[idx, 'label']\n        \n        if self.transforms:\n            img = self.transforms(image=img)['image']\n        return img, label\n\nclass ValidDataset(Dataset):\n    def __init__(self, df, valid_indx, transforms = None):\n        self.df_valid = df.loc[valid_indx, :].reset_index(drop=True).copy()\n        self.transforms = transforms\n    \n    def __len__(self):\n        return len(self.df_valid)\n    \n    def __getitem__(self, idx):\n        img_path = self.df_valid.loc[idx, 'image']\n        img = get_img_data(img_path)\n        label = self.df_valid.loc[idx, 'label']\n        \n        if self.transforms:\n            img = self.transforms(image=img)['image']\n        return img, label\n\nclass TestDataset(Dataset):\n    def __init__(self, df, transforms = None):\n        self.df_test = df.reset_index(drop=True).copy()\n        self.transforms = transforms\n    \n    def __len__(self):\n        return len(self.df_test)\n    \n    def __getitem__(self, idx):\n        img_path = self.df_test.loc[idx, 'image']\n        img = get_img_data(img_path)\n        \n        if self.transforms:\n            img = self.transforms(image=img)['image']\n        return img","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:11.841925Z","iopub.execute_input":"2023-10-11T15:56:11.842245Z","iopub.status.idle":"2023-10-11T15:56:11.852795Z","shell.execute_reply.started":"2023-10-11T15:56:11.842219Z","shell.execute_reply":"2023-10-11T15:56:11.851972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data Augmentation\ndef train_transforms():\n    return albumentations.Compose([albumentations.Resize(320, 320),\n                                   OneOf([albumentations.CoarseDropout(p=0.5), albumentations.GaussNoise()]), \n                                   albumentations.HorizontalFlip(p=0.5), \n                                   albumentations.VerticalFlip(p=0), \n                                   albumentations.Rotate(limit=90, p=0.6), \n                                   albumentations.RandomBrightnessContrast(), \n                                   albumentations.ShiftScaleRotate(shift_limit=0.25, scale_limit=0.15, \n                                                                   rotate_limit=45, p=0.5), \n                                   albumentations.Normalize([0.485, 0.456, 0.406], \n                                                            [0.229, 0.224, 0.225], \n                                                            max_pixel_value = 255.0, p=1.0), \n                                   ToTensorV2(p=1.0)], p=1.0)\n\ndef valid_test_transforms():\n    return albumentations.Compose([albumentations.Resize(320, 320), \n                                   albumentations.Normalize([0.485, 0.456, 0.406], \n                                                            [0.229, 0.224, 0.225], \n                                                            max_pixel_value = 255.0, p=1.0), \n                                   ToTensorV2(p=1.0)], p=1.0)","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:14.532402Z","iopub.execute_input":"2023-10-11T15:56:14.532750Z","iopub.status.idle":"2023-10-11T15:56:14.539610Z","shell.execute_reply.started":"2023-10-11T15:56:14.532722Z","shell.execute_reply":"2023-10-11T15:56:14.538718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# DataLoader\ndef get_train_valid_loader(df, train_idx, valid_idx, params):\n    \n    train_dataset = TrainDataset(df, train_idx, train_transforms())\n    valid_dataset = ValidDataset(df, valid_idx, valid_test_transforms())\n    \n    train_loader = DataLoader(train_dataset, \n                              batch_size = params['BATCH_SIZE'], \n                              num_workers = params['NUM_WORKERS'],\n                              pin_memory = True, \n                              drop_last = True,\n                              shuffle = True)\n    valid_loader = DataLoader(valid_dataset, \n                              batch_size = params['BATCH_SIZE'], \n                              num_workers = params['NUM_WORKERS'], \n                              pin_memory = True, \n                              shuffle = True)\n    return train_loader, valid_loader\n\ndef get_test_loader(df, params):\n    test_dataset = TestDataset(df, valid_test_transforms())\n    \n    test_loader = DataLoader(test_dataset, \n                             batch_size = params['BATCH_SIZE'], \n                             num_workers = params['NUM_WORKERS'], \n                             pin_memory = True)\n    return test_loader","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:16.780965Z","iopub.execute_input":"2023-10-11T15:56:16.781301Z","iopub.status.idle":"2023-10-11T15:56:16.787381Z","shell.execute_reply.started":"2023-10-11T15:56:16.781277Z","shell.execute_reply":"2023-10-11T15:56:16.786413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Basic Metric Functions\n***","metadata":{}},{"cell_type":"code","source":"def get_accuracy(output, target):\n    y_pred = torch.softmax(output, dim=1)\n    y_pred = torch.argmax(y_pred, dim=1).cpu()\n    target = target.cpu()\n    return accuracy_score(target, y_pred)\n\ndef get_f1score(output, target):\n    y_pred = torch.softmax(output, dim=1)\n    y_pred = torch.argmax(y_pred, dim=1).cpu()\n    target = target.cpu()\n    return f1_score(target, y_pred, average='macro')\n\nclass MetricMonitor:\n    def __init__(self):\n        self.reset()\n    \n    def reset(self):\n        self.metrics = defaultdict(lambda: {'val': 0, 'count': 0, 'avg': 0})\n        \n    def update(self, metric_name, val):\n        metric = self.metrics[metric_name]\n        \n        metric['val'] += val\n        metric['count'] += 1\n        metric['avg'] = metric['val'] / metric['count']\n    \n    def __str__(self):\n        return \" | \".join([\"{metric_name}: {avg:.{float_precision}f}\".format(\n                                metric_name=metric_name, avg=metric[\"avg\"], float_precision=3)\n                           for (metric_name, metric) in self.metrics.items()])","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:19.781906Z","iopub.execute_input":"2023-10-11T15:56:19.782228Z","iopub.status.idle":"2023-10-11T15:56:19.789699Z","shell.execute_reply.started":"2023-10-11T15:56:19.782202Z","shell.execute_reply":"2023-10-11T15:56:19.788728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training\n***","metadata":{}},{"cell_type":"code","source":"# Model\nclass LeafModel(nn.Module):\n    def __init__(self, params):\n        super().__init__()\n        \n        model_name = params['MODEL']\n        pretrained_ = params['PRETRAINED']\n        output = params['OUT_FEATURES']\n        \n        self.model = timm.create_model(model_name, pretrained=pretrained_)\n        fea_in = self.model.fc.in_features\n        self.model.fc = nn.Linear(fea_in, output)\n    \n    def forward(self, X):\n        Y = self.model(X)\n        return Y","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:21.991789Z","iopub.execute_input":"2023-10-11T15:56:21.992109Z","iopub.status.idle":"2023-10-11T15:56:21.997926Z","shell.execute_reply.started":"2023-10-11T15:56:21.992083Z","shell.execute_reply":"2023-10-11T15:56:21.996916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train function\ndef train_one_epoch(epoch, model, train_loader, criterion, optimizer, scheduler, params):\n    metric_monitor = MetricMonitor()\n    model.train()\n    \n    pbar = tqdm(train_loader)\n    for images, labels in pbar:\n        images = images.to(device=params['DEVICE'])\n        labels = labels.to(device=params['DEVICE'])\n        \n        label_pre = model(images)\n        loss = criterion(label_pre, labels)\n        \n        f1_macro = get_f1score(label_pre, labels)\n        acc = get_accuracy(label_pre, labels)\n        metric_monitor.update('Loss', loss.item())\n        metric_monitor.update('f1', f1_macro)\n        metric_monitor.update('acc', acc)\n        \n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        pbar.set_description(f'Epoch {epoch}. Train: {metric_monitor}')\n    scheduler.step()\n#     return metric_monitor.metrics['acc']['avg']\n\ndef valid_one_epoch(epoch, model, valid_loader, criterion, params):\n    metric_monitor = MetricMonitor()\n    model.eval()\n    \n    pbar = tqdm(valid_loader)\n    with torch.no_grad():\n        for images, labels in pbar:\n            images = images.to(device=params['DEVICE'])\n            labels = labels.to(device=params['DEVICE'])\n            \n            label_pre = model(images)\n            loss = criterion(label_pre, labels)\n\n            f1_macro = get_f1score(label_pre, labels)\n            acc = get_accuracy(label_pre, labels)\n            metric_monitor.update('Loss', loss.item())\n            metric_monitor.update('f1', f1_macro)\n            metric_monitor.update('acc', acc)\n            \n            pbar.set_description(f'Epoch {epoch}. Valid: {metric_monitor}')\n    return metric_monitor.metrics['acc']['avg']","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:23.712242Z","iopub.execute_input":"2023-10-11T15:56:23.712561Z","iopub.status.idle":"2023-10-11T15:56:23.721253Z","shell.execute_reply.started":"2023-10-11T15:56:23.712536Z","shell.execute_reply":"2023-10-11T15:56:23.720345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters\nparams = {'MODEL': 'resnet50',\n          'DEVICE': device, \n          'LR': 5e-4, \n          'KFOLD': 5, \n          'EPOCHS': 15, \n          'BATCH_SIZE': 32, \n          'NUM_WORKERS': 0, \n          'OUT_FEATURES': num_labels, \n          'WEIGHT_DECAY': 1e-3, \n          'PRETRAINED': True}","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:30.458233Z","iopub.execute_input":"2023-10-11T15:56:30.458558Z","iopub.status.idle":"2023-10-11T15:56:30.463459Z","shell.execute_reply.started":"2023-10-11T15:56:30.458533Z","shell.execute_reply":"2023-10-11T15:56:30.462506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train LOOP\n# print('======================= Model Train ==========================')\n\n# kfold = StratifiedKFold(n_splits=params['KFOLD'])\n# results = {}\n\n# for k, (train_ind, valid_ind) in enumerate(kfold.split(df_train['image'], df_train['label'])):\n#     train_loader, valid_loader = get_train_valid_loader(df_train, train_ind, valid_ind, params)\n#     print(f'-------- Begin fold {k} training --------')\n#     model = LeafModel(params)\n#     model.to(device = params['DEVICE'])\n    \n#     criterion = nn.CrossEntropyLoss().to(device=params['DEVICE'])\n#     optimizer = torch.optim.AdamW(model.parameters(), lr=params['LR'], weight_decay=params['WEIGHT_DECAY'])\n#     scheduler = CosineAnnealingLR(optimizer, T_max=10)\n    \n#     fold_save_path = f'./model_fold_{k}/'\n#     if not os.path.exists(fold_save_path):\n#         os.makedirs(fold_save_path)\n    \n#     for epoch in range(params['EPOCHS']):\n#         # Do train & valid in each epoch\n#         train_one_epoch(epoch, model, train_loader, criterion, optimizer, scheduler, params)\n#         valid_acc = valid_one_epoch(epoch, model, valid_loader, criterion, params)\n        \n#         # Saving model\n#         if epoch > 10:\n#             save_path = os.path.join(fold_save_path, f'model_fold_{k}_{round(valid_acc, 3)}.pth')\n#             torch.save(model.state_dict(), save_path)\n# #         save_path = os.path.join(fold_save_path, f'model_fold_{k}_{round(valid_acc, 3)}.pth')\n# #         torch.save(model.state_dict(), save_path)\n        \n# #     # Saving model\n# #     save_path = f'./model_fold_{k}.pth'\n# #     torch.save(model.state_dict(), save_path)","metadata":{"execution":{"iopub.status.busy":"2023-10-11T15:56:45.091286Z","iopub.execute_input":"2023-10-11T15:56:45.091630Z","iopub.status.idle":"2023-10-11T15:56:45.096474Z","shell.execute_reply.started":"2023-10-11T15:56:45.091603Z","shell.execute_reply":"2023-10-11T15:56:45.095599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"model_path = '/kaggle/input/model-fold'\nprint('=================== Model Inference ================')\nmodel = LeafModel(params)\nmodel.to(device = params['DEVICE'])\n\ntest_loader = get_test_loader(df_test, params)\n\npredictions_all = []\nfor file in os.listdir(model_path):\n    model_path_ = os.path.join(model_path, file)\n    model.load_state_dict(torch.load(model_path_))\n    \n    model.eval()\n    \n    tta_model = tta.ClassificationTTAWrapper(model, tta.aliases.five_crop_transform(200, 200)) # todo:check width & height\n    \n    pre_fold = []  # saving prediction results of each fold-trained-model\n    \n    pbar = tqdm(test_loader)\n    for images in pbar:\n        images = images.to(device=params['DEVICE'])\n        \n        with torch.no_grad():\n            label_pre = tta_model(images)\n        \n        label_pre = label_pre.cpu().numpy().tolist()\n        pre_fold.extend(label_pre)\n        pbar.set_description(f'Model {file} predicting: ')\n    \n    predictions_all.append(pre_fold)\n\n# Mixing multi models' reselut\navg_model_pred = np.mean(predictions_all, axis=0)\ndf_test['label'] = np.argmax(avg_model_pred, axis=1)\n\ndf_test.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-11T16:00:44.515187Z","iopub.execute_input":"2023-10-11T16:00:44.515513Z","iopub.status.idle":"2023-10-11T16:08:35.482911Z","shell.execute_reply.started":"2023-10-11T16:00:44.515489Z","shell.execute_reply":"2023-10-11T16:08:35.481856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Test Inference\n# print('=================== Model Inference ================')\n# model = LeafModel(params)\n# model.to(device = params['DEVICE'])\n\n# test_loader = get_test_loader(df_test, params)\n\n# predictions_all = []\n# for f in range(params['KFOLD']):\n#     model_folder = f'model_fold_{f}'\n#     model_dict = {file: float(re.findall(r'0.[0-9]{3}', file)[0]) \n#                   for file in os.listdir(os.path.join(os.getcwd(), model_folder))}\n#     model_name = max(model_dict, key = model_dict.get)\n#     model_path = f'./model_fold_{f}/{model_name}'\n#     model.load_state_dict(torch.load(model_path))\n    \n#     model.eval()\n#     tta_model = tta.ClassificationTTAWrapper(model, tta.aliases.five_crop_transform(200, 200)) # todo:check width & height\n    \n#     pre_fold = []  # saving prediction results of each fold-trained-model\n    \n#     pbar = tqdm(test_loader)\n#     for images in pbar:\n#         images = images.to(device=params['DEVICE'])\n        \n#         with torch.no_grad():\n#             label_pre = tta_model(images)\n        \n#         label_pre = label_pre.cpu().numpy().tolist()\n#         pre_fold.extend(label_pre)\n#         pbar.set_description(f'Fold {f} | {model_name} predicting: ')\n    \n#     predictions_all.append(pre_fold)\n\n# # Mixing multi models' reselut\n# avg_model_pred = np.mean(predictions_all, axis=0)\n# df_test['label'] = np.argmax(avg_model_pred, axis=1)\n\n# df_test.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-11T16:09:23.346063Z","iopub.execute_input":"2023-10-11T16:09:23.346394Z","iopub.status.idle":"2023-10-11T16:09:23.351539Z","shell.execute_reply.started":"2023-10-11T16:09:23.346370Z","shell.execute_reply":"2023-10-11T16:09:23.350528Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test['label'] = df_test['label'].apply(lambda x: num_to_leaf[x])\ndf_test.to_csv('submission_v1.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-10-11T16:08:48.883595Z","iopub.execute_input":"2023-10-11T16:08:48.883975Z","iopub.status.idle":"2023-10-11T16:08:48.909266Z","shell.execute_reply.started":"2023-10-11T16:08:48.883949Z","shell.execute_reply":"2023-10-11T16:08:48.908457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test","metadata":{"execution":{"iopub.status.busy":"2023-10-11T16:09:00.469111Z","iopub.execute_input":"2023-10-11T16:09:00.469439Z","iopub.status.idle":"2023-10-11T16:09:00.480362Z","shell.execute_reply.started":"2023-10-11T16:09:00.469412Z","shell.execute_reply":"2023-10-11T16:09:00.479509Z"},"trusted":true},"execution_count":null,"outputs":[]}]}