{"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":"%%capture\n\n!pip install -U tensorflow-addons\n!pip install patchify","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:22.123269Z","iopub.execute_input":"2023-05-20T10:07:22.123919Z","iopub.status.idle":"2023-05-20T10:07:45.358477Z","shell.execute_reply.started":"2023-05-20T10:07:22.123886Z","shell.execute_reply":"2023-05-20T10:07:45.357201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:45.360999Z","iopub.execute_input":"2023-05-20T10:07:45.361399Z","iopub.status.idle":"2023-05-20T10:07:46.354158Z","shell.execute_reply.started":"2023-05-20T10:07:45.361347Z","shell.execute_reply":"2023-05-20T10:07:46.352909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nos.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"2\"\n\nimport numpy as np\nimport cv2\nfrom glob import glob\nfrom sklearn.utils import shuffle\nfrom sklearn.model_selection import train_test_split\nfrom patchify import patchify\nimport tensorflow as tf\nfrom tensorflow.keras.callbacks import ModelCheckpoint, CSVLogger, ReduceLROnPlateau, EarlyStopping\n\nimport tensorflow as tf\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.models import Model","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:46.357262Z","iopub.execute_input":"2023-05-20T10:07:46.357689Z","iopub.status.idle":"2023-05-20T10:07:54.231217Z","shell.execute_reply.started":"2023-05-20T10:07:46.357649Z","shell.execute_reply":"2023-05-20T10:07:54.230072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hp = {}\n\nhp[\"num_layers\"] = 12\nhp[\"hidden_dim\"] = 768\nhp[\"mlp_dim\"] = 3072\nhp[\"num_heads\"] = 12\nhp[\"dropout_rate\"] = 0.1\nhp[\"image_size\"] = 200\nhp[\"patch_size\"] = 25\nhp[\"num_patches\"] = (hp[\"image_size\"]**2) // (hp[\"patch_size\"]**2)\nhp[\"num_classes\"] = 5\nhp[\"num_channels\"] = 3\n\nhp[\"flat_patches_shape\"] = (hp[\"num_patches\"], hp[\"patch_size\"]*hp[\"patch_size\"]*hp[\"num_channels\"])\n\nhp[\"batch_size\"] = 32\nhp[\"lr\"] = 1e-4\nhp[\"num_epochs\"] = 50\nhp[\"num_classes\"] = 5\nhp[\"class_names\"] = [\"daisy\", \"dandelion\", \"rose\", \"sunflower\", \"tulip\"]","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:54.234451Z","iopub.execute_input":"2023-05-20T10:07:54.235063Z","iopub.status.idle":"2023-05-20T10:07:54.245590Z","shell.execute_reply.started":"2023-05-20T10:07:54.235033Z","shell.execute_reply":"2023-05-20T10:07:54.244444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# config = {}\n# config[\"num_layers\"] = 12\n# config[\"hidden_dim\"] = 768\n# config[\"mlp_dim\"] = 3072\n# config[\"num_heads\"] = 12\n# config[\"dropout_rate\"] = 0.1\n# config[\"num_patches\"] = 256\n# config[\"patch_size\"] = 32\n# config[\"num_channels\"] = 3\n# config[\"num_classes\"] = 5","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:54.247349Z","iopub.execute_input":"2023-05-20T10:07:54.248388Z","iopub.status.idle":"2023-05-20T10:07:54.258754Z","shell.execute_reply.started":"2023-05-20T10:07:54.248082Z","shell.execute_reply":"2023-05-20T10:07:54.257545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Data Preparing**","metadata":{}},{"cell_type":"code","source":"def create_dir(path):\n    if not os.path.exists(path):\n        os.makedirs(path)\n\ndef load_data(path, split=0.1):\n    images = shuffle(glob(os.path.join(path, \"*\", \"*.jpg\")))\n\n    split_size = int(len(images) * split)\n    train_x, valid_x = train_test_split(images, test_size=split_size, random_state=42)\n    train_x, test_x = train_test_split(train_x, test_size=split_size, random_state=42)\n\n    return train_x, valid_x, test_x\n\ndef process_image_label(path):\n    \"\"\" Reading images \"\"\"\n    path = path.decode()\n    image = cv2.imread(path, cv2.IMREAD_COLOR)\n    image = cv2.resize(image, (hp[\"image_size\"], hp[\"image_size\"]))\n    image = image/255.0\n\n    \"\"\" Preprocessing to patches \"\"\"\n    patch_shape = (hp[\"patch_size\"], hp[\"patch_size\"], hp[\"num_channels\"])\n    patches = patchify(image, patch_shape, hp[\"patch_size\"])\n\n    # patches = np.reshape(patches, (64, 25, 25, 3))\n    # for i in range(64):\n    #     cv2.imwrite(f\"files/{i}.png\", patches[i])\n\n    patches = np.reshape(patches, hp[\"flat_patches_shape\"])\n    patches = patches.astype(np.float32)\n\n    \"\"\" Label \"\"\"\n    class_name = path.split(\"/\")[-2]\n    class_idx = hp[\"class_names\"].index(class_name)\n    class_idx = np.array(class_idx, dtype=np.int32)\n\n    return patches, class_idx\n\ndef parse(path):\n    patches, labels = tf.numpy_function(process_image_label, [path], [tf.float32, tf.int32])\n    labels = tf.one_hot(labels, hp[\"num_classes\"])\n\n    patches.set_shape(hp[\"flat_patches_shape\"])\n    labels.set_shape(hp[\"num_classes\"])\n\n    return patches, labels\n\ndef tf_dataset(images, batch=32):\n    ds = tf.data.Dataset.from_tensor_slices((images))\n    ds = ds.map(parse).batch(batch).prefetch(8)\n    return ds\n\n\nif __name__ == \"__main__\":\n    \"\"\" Seeding \"\"\"\n    np.random.seed(42)\n    tf.random.set_seed(42)\n\n    \"\"\" Directory for storing files \"\"\"\n    create_dir(\"files\")\n\n    \"\"\" Paths \"\"\"\n    dataset_path = \"/kaggle/input/flowers-recognition/flowers\"\n    model_path = os.path.join(\"/kaggle/working/\", \"model.h5\")\n    csv_path = os.path.join(\"/kaggle/working/\", \"log.csv\")\n\n    \"\"\" Dataset \"\"\"\n    train_x, valid_x, test_x = load_data(dataset_path)\n    print(f\"Train: {len(train_x)} - Valid: {len(valid_x)} - Test: {len(test_x)}\")\n\n    train_ds = tf_dataset(train_x, batch=hp[\"batch_size\"])\n    valid_ds = tf_dataset(valid_x, batch=hp[\"batch_size\"])","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:54.260747Z","iopub.execute_input":"2023-05-20T10:07:54.261199Z","iopub.status.idle":"2023-05-20T10:07:57.917756Z","shell.execute_reply.started":"2023-05-20T10:07:54.261166Z","shell.execute_reply":"2023-05-20T10:07:57.916798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# class_count = {'dandelion':0, 'daisy':1, 'sunflower':2, 'tulip':3, 'rose':4}","metadata":{"execution":{"iopub.status.busy":"2023-05-20T09:59:51.538753Z","iopub.execute_input":"2023-05-20T09:59:51.539620Z","iopub.status.idle":"2023-05-20T09:59:51.551077Z","shell.execute_reply.started":"2023-05-20T09:59:51.539588Z","shell.execute_reply":"2023-05-20T09:59:51.549889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def ReturnClassCount(data):\n    class_count = {'dandelion':0, 'daisy':0, 'sunflower':0, 'tulip':0, 'rose':0}\n    for ind in range(0,len(data)):\n        class_count[data[ind].split(\"/\")[-2]] += 1\n    return class_count","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:57.921407Z","iopub.execute_input":"2023-05-20T10:07:57.921742Z","iopub.status.idle":"2023-05-20T10:07:57.927155Z","shell.execute_reply.started":"2023-05-20T10:07:57.921716Z","shell.execute_reply":"2023-05-20T10:07:57.926293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ReturnClassCount(train_x)","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:57.928326Z","iopub.execute_input":"2023-05-20T10:07:57.929226Z","iopub.status.idle":"2023-05-20T10:07:57.943908Z","shell.execute_reply.started":"2023-05-20T10:07:57.929192Z","shell.execute_reply":"2023-05-20T10:07:57.943018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ReturnClassCount(valid_x)","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:07:57.945423Z","iopub.execute_input":"2023-05-20T10:07:57.946167Z","iopub.status.idle":"2023-05-20T10:07:57.957503Z","shell.execute_reply.started":"2023-05-20T10:07:57.946133Z","shell.execute_reply":"2023-05-20T10:07:57.956597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ReturnClassCount(test_x)","metadata":{"execution":{"iopub.status.busy":"2023-05-20T09:59:51.596110Z","iopub.execute_input":"2023-05-20T09:59:51.596596Z","iopub.status.idle":"2023-05-20T09:59:51.606728Z","shell.execute_reply.started":"2023-05-20T09:59:51.596564Z","shell.execute_reply":"2023-05-20T09:59:51.605821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Model Building**","metadata":{}},{"cell_type":"code","source":"class ClassToken(Layer):\n    def __init__(self):\n        super().__init__()\n\n    def build(self, input_shape):\n        w_init = tf.random_normal_initializer()\n        self.w = tf.Variable(\n            initial_value = w_init(shape=(1, 1, input_shape[-1]), dtype=tf.float32),\n            trainable = True\n        )\n\n    def call(self, inputs):\n        batch_size = tf.shape(inputs)[0]\n        hidden_dim = self.w.shape[-1]\n\n        cls = tf.broadcast_to(self.w, [batch_size, 1, hidden_dim])\n        cls = tf.cast(cls, dtype=inputs.dtype)\n        return cls\n\ndef mlp(x, cf):\n    x = Dense(cf[\"mlp_dim\"], activation=\"gelu\")(x)\n    x = Dropout(cf[\"dropout_rate\"])(x)\n    x = Dense(cf[\"hidden_dim\"])(x)\n    x = Dropout(cf[\"dropout_rate\"])(x)\n    return x\n\ndef transformer_encoder(x, cf):\n    skip_1 = x\n    x = LayerNormalization()(x)\n    x = MultiHeadAttention(\n        num_heads=cf[\"num_heads\"], key_dim=cf[\"hidden_dim\"]\n    )(x, x)\n    x = Add()([x, skip_1])\n\n    skip_2 = x\n    x = LayerNormalization()(x)\n    x = mlp(x, cf)\n    x = Add()([x, skip_2])\n\n    return x\n\ndef ViT(cf):\n    \"\"\" Inputs \"\"\"\n    input_shape = (cf[\"num_patches\"], cf[\"patch_size\"]*cf[\"patch_size\"]*cf[\"num_channels\"])\n    inputs = Input(input_shape)     ## (None, 256, 3072)\n\n    \"\"\" Patch + Position Embeddings \"\"\"\n    patch_embed = Dense(cf[\"hidden_dim\"])(inputs)   ## (None, 256, 768)\n\n    positions = tf.range(start=0, limit=cf[\"num_patches\"], delta=1)\n    pos_embed = Embedding(input_dim=cf[\"num_patches\"], output_dim=cf[\"hidden_dim\"])(positions) ## (256, 768)\n    embed = patch_embed + pos_embed ## (None, 256, 768)\n\n    \"\"\" Adding Class Token \"\"\"\n    token = ClassToken()(embed)\n    x = Concatenate(axis=1)([token, embed]) ## (None, 257, 768)\n\n    for _ in range(cf[\"num_layers\"]):\n        x = transformer_encoder(x, cf)\n\n    \"\"\" Classification Head \"\"\"\n    x = LayerNormalization()(x)     ## (None, 257, 768)\n    x = x[:, 0, :]\n    x = Dense(cf[\"num_classes\"], activation=\"softmax\")(x)\n\n    model = Model(inputs, x)\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:08:04.019994Z","iopub.execute_input":"2023-05-20T10:08:04.020355Z","iopub.status.idle":"2023-05-20T10:08:04.036330Z","shell.execute_reply.started":"2023-05-20T10:08:04.020328Z","shell.execute_reply":"2023-05-20T10:08:04.035297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = ViT(hp)\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:08:04.943804Z","iopub.execute_input":"2023-05-20T10:08:04.944157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(\n    loss=\"categorical_crossentropy\",\n    optimizer=tf.keras.optimizers.Adam(hp[\"lr\"], clipvalue=1.0),\n    metrics=[\"acc\"]\n)","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:08:14.191099Z","iopub.execute_input":"2023-05-20T10:08:14.191490Z","iopub.status.idle":"2023-05-20T10:08:14.219547Z","shell.execute_reply.started":"2023-05-20T10:08:14.191458Z","shell.execute_reply":"2023-05-20T10:08:14.218584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [\n    ModelCheckpoint(model_path, monitor='val_loss', verbose=1, save_best_only=True),\n    ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, min_lr=1e-10, verbose=1),\n    CSVLogger(csv_path),\n    EarlyStopping(monitor='val_loss', patience=50, restore_best_weights=False),\n]","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:08:14.765616Z","iopub.execute_input":"2023-05-20T10:08:14.766576Z","iopub.status.idle":"2023-05-20T10:08:14.773084Z","shell.execute_reply.started":"2023-05-20T10:08:14.766532Z","shell.execute_reply":"2023-05-20T10:08:14.772117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Start Training**","metadata":{}},{"cell_type":"code","source":"model.fit(\n    train_ds,\n    epochs=5,\n#     epochs=hp[\"num_epochs\"],\n    validation_data=valid_ds,\n    callbacks=callbacks\n)","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:09:18.692881Z","iopub.execute_input":"2023-05-20T10:09:18.693265Z","iopub.status.idle":"2023-05-20T10:21:41.133166Z","shell.execute_reply.started":"2023-05-20T10:09:18.693235Z","shell.execute_reply":"2023-05-20T10:21:41.132178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Save Model**","metadata":{}},{"cell_type":"code","source":"model.save(\"/kaggle/working/files/model_saved.h5\")","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:24:03.255010Z","iopub.execute_input":"2023-05-20T10:24:03.255393Z","iopub.status.idle":"2023-05-20T10:24:28.280011Z","shell.execute_reply.started":"2023-05-20T10:24:03.255346Z","shell.execute_reply":"2023-05-20T10:24:28.278580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Evaluate**","metadata":{}},{"cell_type":"code","source":"# custom_objects={'ClassToken': ClassToken()}\n# tf.keras.models.load_model(\"/kaggle/working/files/model_saved.h5\", custom_objects=custom_objects)","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:29:46.067422Z","iopub.execute_input":"2023-05-20T10:29:46.068167Z","iopub.status.idle":"2023-05-20T10:29:46.074551Z","shell.execute_reply.started":"2023-05-20T10:29:46.068134Z","shell.execute_reply":"2023-05-20T10:29:46.072500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = tf_dataset(test_x, batch=hp[\"batch_size\"])\nresult = model.evaluate(test_ds)","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:31:54.136187Z","iopub.execute_input":"2023-05-20T10:31:54.136553Z","iopub.status.idle":"2023-05-20T10:31:59.301542Z","shell.execute_reply.started":"2023-05-20T10:31:54.136524Z","shell.execute_reply":"2023-05-20T10:31:59.300088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred = model.predict(test_ds)\n\nResult = []\nfor ind in range(len(test_x)):\n    max_ind = np.argmax(pred[ind],axis=0)\n    condfidence = np.round(pred[ind][max_ind]*100,2)\n    class_name = hp[\"class_names\"][max_ind]\n    Result.append({\"Predicted Class\" : class_name, \"Actual Class\":test_x[ind].split(\"/\")[-2], \"Confidence\": condfidence})","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:32:22.708644Z","iopub.execute_input":"2023-05-20T10:32:22.708993Z","iopub.status.idle":"2023-05-20T10:32:29.760927Z","shell.execute_reply.started":"2023-05-20T10:32:22.708962Z","shell.execute_reply":"2023-05-20T10:32:29.759622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\ndf = pd.DataFrame(Result)\ndf['Class_Val_Count']  = None\ndf['Class_Val_Count'] = [1 if p == a else 0 for p, a in zip(df['Predicted Class'], df['Actual Class'])]","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:32:34.614403Z","iopub.execute_input":"2023-05-20T10:32:34.614775Z","iopub.status.idle":"2023-05-20T10:32:34.638558Z","shell.execute_reply.started":"2023-05-20T10:32:34.614745Z","shell.execute_reply":"2023-05-20T10:32:34.637597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:32:37.408595Z","iopub.execute_input":"2023-05-20T10:32:37.409267Z","iopub.status.idle":"2023-05-20T10:32:37.429674Z","shell.execute_reply.started":"2023-05-20T10:32:37.409235Z","shell.execute_reply":"2023-05-20T10:32:37.428850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['Class_Val_Count'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:32:43.450504Z","iopub.execute_input":"2023-05-20T10:32:43.450970Z","iopub.status.idle":"2023-05-20T10:32:43.466896Z","shell.execute_reply.started":"2023-05-20T10:32:43.450929Z","shell.execute_reply":"2023-05-20T10:32:43.465846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Plotting Patch Images**","metadata":{}},{"cell_type":"code","source":"# import matplotlib.pyplot as plt\n\n# fig, axe = plt.subplots(nrows=8, ncols=8,gridspec_kw={'wspace': 0.1,'hspace':0.1})\n# ax = axe.ravel()\n\n# patches = np.reshape(patches, (64, 25, 25, 3))\n\n# for i in range(64):\n#     image = patches[i]\n#     image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # Convert image from BGR to RGB\n#     ax[i].imshow(image_rgb)\n#     ax[i].axis('off')\n\n\n# plt.tight_layout()\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:33:36.617271Z","iopub.execute_input":"2023-05-20T10:33:36.617832Z","iopub.status.idle":"2023-05-20T10:33:36.622510Z","shell.execute_reply.started":"2023-05-20T10:33:36.617800Z","shell.execute_reply":"2023-05-20T10:33:36.621462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_img = model.predict(tf_dataset(test_x[:3], batch=1))","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:51:47.104086Z","iopub.execute_input":"2023-05-20T10:51:47.104572Z","iopub.status.idle":"2023-05-20T10:51:47.317094Z","shell.execute_reply.started":"2023-05-20T10:51:47.104532Z","shell.execute_reply":"2023-05-20T10:51:47.314914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_ind = 0\nprint(\"Actual Image :\", test_x[img_ind].split(\"/\")[-2])\nprint(\"Predicted Image :\", hp['class_names'][np.argmax(pred_img[img_ind],axis=0)])","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:52:00.547392Z","iopub.execute_input":"2023-05-20T10:52:00.548220Z","iopub.status.idle":"2023-05-20T10:52:00.556061Z","shell.execute_reply.started":"2023-05-20T10:52:00.548186Z","shell.execute_reply":"2023-05-20T10:52:00.554195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_ind = 1\nprint(\"Actual Image :\", test_x[img_ind].split(\"/\")[-2])\nprint(\"Predicted Image :\", hp['class_names'][np.argmax(pred_img[img_ind],axis=0)])","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:52:05.383984Z","iopub.execute_input":"2023-05-20T10:52:05.384335Z","iopub.status.idle":"2023-05-20T10:52:05.393047Z","shell.execute_reply.started":"2023-05-20T10:52:05.384307Z","shell.execute_reply":"2023-05-20T10:52:05.392031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_ind = 2\nprint(\"Actual Image :\", test_x[img_ind].split(\"/\")[-2])\nprint(\"Predicted Image :\", hp['class_names'][np.argmax(pred_img[img_ind],axis=0)])","metadata":{"execution":{"iopub.status.busy":"2023-05-20T10:52:13.738384Z","iopub.execute_input":"2023-05-20T10:52:13.738981Z","iopub.status.idle":"2023-05-20T10:52:13.747782Z","shell.execute_reply.started":"2023-05-20T10:52:13.738935Z","shell.execute_reply":"2023-05-20T10:52:13.746584Z"},"trusted":true},"execution_count":null,"outputs":[]}]}