{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":5048,"databundleVersionId":868335,"sourceType":"competition"}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-07-26T16:37:15.462481Z","iopub.execute_input":"2023-07-26T16:37:15.463599Z","iopub.status.idle":"2023-07-26T16:37:15.475236Z","shell.execute_reply.started":"2023-07-26T16:37:15.463536Z","shell.execute_reply":"2023-07-26T16:37:15.474077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install keras","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:39:17.209792Z","iopub.execute_input":"2023-07-26T16:39:17.211135Z","iopub.status.idle":"2023-07-26T16:39:31.652354Z","shell.execute_reply.started":"2023-07-26T16:39:17.210991Z","shell.execute_reply":"2023-07-26T16:39:31.650109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install --upgrade tensorflow","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:37:44.059902Z","iopub.execute_input":"2023-07-26T16:37:44.060412Z","iopub.status.idle":"2023-07-26T16:39:17.199406Z","shell.execute_reply.started":"2023-07-26T16:37:44.060365Z","shell.execute_reply":"2023-07-26T16:39:17.196191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install --upgrade tensorflow-gpu","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:42:51.483237Z","iopub.execute_input":"2023-07-26T16:42:51.483703Z","iopub.status.idle":"2023-07-26T16:42:57.801670Z","shell.execute_reply.started":"2023-07-26T16:42:51.483649Z","shell.execute_reply":"2023-07-26T16:42:57.800139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Part 1 : Loading Dataset ","metadata":{}},{"cell_type":"code","source":"import os\nfrom glob import glob\nimport random\nimport time\nimport tensorflow\nimport datetime\nos.environ['KERAS_BACKEND'] = 'tensorflow'\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # 3 = INFO, WARNING, and ERROR\nfrom tqdm import tqdm\nimport numpy as np\nimport pandas as pd\nfrom IPython.display import FileLink\nimport matplotlib.pyplot as plt\nimport warnings\nwarnings.filterwarnings('ignore')\nimport seaborn as sns \n%matplotlib inline\nfrom IPython.display import display, Image\nimport matplotlib.image as mpimg\nimport cv2\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.datasets import load_files       \nfrom keras.utils import np_utils\nfrom sklearn.utils import shuffle\nfrom sklearn.metrics import log_loss\n\nfrom tensorflow import keras \n\nfrom keras.models import Sequential, Model\nfrom keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization, GlobalAveragePooling2D\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.preprocessing import image\nfrom keras.callbacks import ModelCheckpoint, EarlyStopping\nfrom keras.applications.vgg16 import VGG16\n\n\ndataset = pd.read_csv('../input/state-farm-distracted-driver-detection/driver_imgs_list.csv')\ndataset.head(5)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:43:11.944499Z","iopub.execute_input":"2023-07-26T16:43:11.944989Z","iopub.status.idle":"2023-07-26T16:43:22.410066Z","shell.execute_reply.started":"2023-07-26T16:43:11.944948Z","shell.execute_reply":"2023-07-26T16:43:22.408891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Groupby subjects\nby_drivers = dataset.groupby('subject') \n# Groupby unique drivers\nunique_drivers = by_drivers.groups.keys() # drivers id\nprint('There are : ',len(unique_drivers), ' unique drivers')\nprint('There is a mean of ',round(dataset.groupby('subject').count()['classname'].mean()), ' images by driver.')","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:43:30.692916Z","iopub.execute_input":"2023-07-26T16:43:30.693348Z","iopub.status.idle":"2023-07-26T16:43:30.734098Z","shell.execute_reply.started":"2023-07-26T16:43:30.693311Z","shell.execute_reply":"2023-07-26T16:43:30.732849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Some functions for loading and normalization","metadata":{}},{"cell_type":"markdown","source":"The 10 classes to classify are :\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","metadata":{}},{"cell_type":"code","source":"NUMBER_CLASSES = 10 # 10 classes","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:43:43.253390Z","iopub.execute_input":"2023-07-26T16:43:43.253797Z","iopub.status.idle":"2023-07-26T16:43:43.258821Z","shell.execute_reply.started":"2023-07-26T16:43:43.253749Z","shell.execute_reply":"2023-07-26T16:43:43.257837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Read with opencv\ndef get_cv2_image(path, img_rows, img_cols, color_type=3):\n    \"\"\"\n    Function that return an opencv image from the path and the right number of dimension\n    \"\"\"\n    if color_type == 1: # Loading as Grayscale image\n        img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n    elif color_type == 3: # Loading as color image\n        img = cv2.imread(path, cv2.IMREAD_COLOR)\n    img = cv2.resize(img, (img_rows, img_cols)) # Reduce size\n    return img\n\n# Loading Training dataset\ndef load_train(img_rows, img_cols, color_type=3):\n    \"\"\"\n    Return train images and train labels from the original path\n    \"\"\"\n    train_images = [] \n    train_labels = []\n    # Loop over the training folder \n    for classed in tqdm(range(NUMBER_CLASSES)):\n        print('Loading directory c{}'.format(classed))\n        files = glob(os.path.join('../input/state-farm-distracted-driver-detection/imgs/train/c' + str(classed), '*.jpg'))\n        for file in files:\n            img = get_cv2_image(file, img_rows, img_cols, color_type)\n            train_images.append(img)\n            train_labels.append(classed)\n    return train_images, train_labels \n\ndef read_and_normalize_train_data(img_rows, img_cols, color_type):\n    \"\"\"\n    Load + categorical + split\n    \"\"\"\n    X, labels = load_train(img_rows, img_cols, color_type)\n    y = np_utils.to_categorical(labels, 10) #categorical train label\n    x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # split into train and test\n    x_train = np.array(x_train, dtype=np.uint8).reshape(-1,img_rows,img_cols,color_type)\n    x_test = np.array(x_test, dtype=np.uint8).reshape(-1,img_rows,img_cols,color_type)\n    \n    return x_train, x_test, y_train, y_test\n\n# Loading validation dataset\ndef load_test(size=200000, img_rows=64, img_cols=64, color_type=3):\n    \"\"\"\n    Same as above but for validation dataset\n    \"\"\"\n    path = os.path.join('../input/state-farm-distracted-driver-detection/imgs/test', '*.jpg')\n    files = sorted(glob(path))\n    X_test, X_test_id = [], []\n    total = 0\n    files_size = len(files)\n    for file in tqdm(files):\n        if total >= size or total >= files_size:\n            break\n        file_base = os.path.basename(file)\n        img = get_cv2_image(file, img_rows, img_cols, color_type)\n        X_test.append(img)\n        X_test_id.append(file_base)\n        total += 1\n    return X_test, X_test_id\n\ndef read_and_normalize_sampled_test_data(size, img_rows, img_cols, color_type=3):\n    test_data, test_ids = load_test(size, img_rows, img_cols, color_type)   \n    test_data = np.array(test_data, dtype=np.uint8)\n    test_data = test_data.reshape(-1,img_rows,img_cols,color_type)\n    return test_data, test_ids","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:43:45.101774Z","iopub.execute_input":"2023-07-26T16:43:45.102157Z","iopub.status.idle":"2023-07-26T16:43:45.121593Z","shell.execute_reply.started":"2023-07-26T16:43:45.102126Z","shell.execute_reply":"2023-07-26T16:43:45.120369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_rows = 64 # dimension of images\nimg_cols = 64\ncolor_type = 1 # grey\nnb_test_samples = 200\n\n# loading train images\nx_train, x_test, y_train, y_test = read_and_normalize_train_data(img_rows, img_cols, color_type)\n\n# loading validation images\ntest_files, test_targets = read_and_normalize_sampled_test_data(nb_test_samples, img_rows, img_cols, color_type)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:43:46.831905Z","iopub.execute_input":"2023-07-26T16:43:46.832528Z","iopub.status.idle":"2023-07-26T16:48:17.424558Z","shell.execute_reply.started":"2023-07-26T16:43:46.832494Z","shell.execute_reply":"2023-07-26T16:48:17.423076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Part 2 : EDA ","metadata":{}},{"cell_type":"code","source":"# Statistics\n# Load the list of names\nnames = [item[17:19] for item in sorted(glob(\"../input/state-farm-distracted-driver-detection/imgs/train/*/\"))]\ntest_files_size = len(np.array(glob(os.path.join('../input/state-farm-distracted-driver-detection/imgs/test', '*.jpg'))))\nx_train_size = len(x_train)\ncategories_size = len(names)\nx_test_size = len(x_test)\nprint('There are %s total images.\\n' % (test_files_size + x_train_size + x_test_size))\nprint('There are %d training images.' % x_train_size)\nprint('There are %d total training categories.' % categories_size)\nprint('There are %d validation images.' % x_test_size)\nprint('There are %d test images.'% test_files_size)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:49:18.417399Z","iopub.execute_input":"2023-07-26T16:49:18.417802Z","iopub.status.idle":"2023-07-26T16:49:18.781804Z","shell.execute_reply.started":"2023-07-26T16:49:18.417771Z","shell.execute_reply":"2023-07-26T16:49:18.780719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Data visualisation","metadata":{}},{"cell_type":"markdown","source":"Number of images by category","metadata":{}},{"cell_type":"code","source":"import plotly.express as px\n\npx.histogram(dataset, x=\"classname\", color=\"classname\", title=\"Number of images by categories \")","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:49:25.990212Z","iopub.execute_input":"2023-07-26T16:49:25.990991Z","iopub.status.idle":"2023-07-26T16:49:28.687518Z","shell.execute_reply.started":"2023-07-26T16:49:25.990957Z","shell.execute_reply":"2023-07-26T16:49:28.686558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"--> It is well distributed","metadata":{}},{"cell_type":"code","source":"# Find the frequency of images per driver\ndrivers_id = pd.DataFrame((dataset['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":"2023-07-26T16:49:34.894020Z","iopub.execute_input":"2023-07-26T16:49:34.894567Z","iopub.status.idle":"2023-07-26T16:49:35.106822Z","shell.execute_reply.started":"2023-07-26T16:49:34.894524Z","shell.execute_reply":"2023-07-26T16:49:35.105641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Images overview","metadata":{}},{"cell_type":"markdown","source":"Let's take a look at the various images in the dataset.\n* I'll plot an image for each of the 10 classes.","metadata":{}},{"cell_type":"code","source":"activity_map = {'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\nplt.figure(figsize = (12, 20))\nimage_count = 1\nBASE_URL = '../input/state-farm-distracted-driver-detection/imgs/train/'\nfor directory in os.listdir(BASE_URL):\n    if directory[0] != '.':\n        for i, file in enumerate(os.listdir(BASE_URL + directory)):\n            if i == 1:\n                break\n            else:\n                fig = plt.subplot(5, 2, image_count)\n                image_count += 1\n                image = mpimg.imread(BASE_URL + directory + '/' + file)\n                plt.imshow(image)\n                plt.title(activity_map[directory])","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:49:37.324823Z","iopub.execute_input":"2023-07-26T16:49:37.325787Z","iopub.status.idle":"2023-07-26T16:49:40.975219Z","shell.execute_reply.started":"2023-07-26T16:49:37.325722Z","shell.execute_reply":"2023-07-26T16:49:40.973283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_submission(predictions, test_id, info):\n    \"\"\"\n    Submission function for participating to the competition\n    \"\"\"\n    result = pd.DataFrame(predictions, columns=['c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9'])\n    result.loc[:, 'img'] = pd.Series(test_id, index=result.index)\n    \n    now = datetime.datetime.now()\n    \n    if not os.path.isdir('kaggle_submissions'):\n        os.mkdir('kaggle_submissions')\n\n    suffix = \"{}_{}\".format(info,str(now.strftime(\"%Y-%m-%d-%H-%M\")))\n    sub_file = os.path.join('kaggle_submissions', 'submission_' + suffix + '.csv')\n    \n    result.to_csv(sub_file, index=False)\n    \n    return sub_file","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:49:40.977218Z","iopub.execute_input":"2023-07-26T16:49:40.977581Z","iopub.status.idle":"2023-07-26T16:49:40.986993Z","shell.execute_reply.started":"2023-07-26T16:49:40.977547Z","shell.execute_reply":"2023-07-26T16:49:40.985511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a vanilla CNN model\nBuilding the model\nI'll develop the model with a total of 4 Convolutional layers, then a Flatten layer and then 2 Dense layers. I'll use the optimizer as rmsprop, and loss as categorical_crossentropy.","metadata":{}},{"cell_type":"markdown","source":"## Part 3 : CNN Model\nArchitecture :\n- 3 Convolutionnal layers (with Relu, Maxpooling and dropout)\n- A flatten layer\n- 2 Dense layers with Relu and Dropouts\n- 1 Dense layer with softmax for the classification","metadata":{}},{"cell_type":"code","source":"# Number of batch size and epochs\nbatch_size = 40 #40\nnb_epoch = 6 #10","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:49:53.198219Z","iopub.execute_input":"2023-07-26T16:49:53.198595Z","iopub.status.idle":"2023-07-26T16:49:53.203882Z","shell.execute_reply.started":"2023-07-26T16:49:53.198566Z","shell.execute_reply":"2023-07-26T16:49:53.202714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models_dir = \"saved_models\"\nif not os.path.exists(models_dir):\n    os.makedirs(models_dir)\n    \ncheckpointer = ModelCheckpoint(filepath='saved_models/weights_best_vanilla.hdf5', \n                               monitor='val_loss', mode='min',\n                               verbose=1, save_best_only=True)\nes = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=2)\n#callbacks = [checkpointer, es]","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:49:55.404204Z","iopub.execute_input":"2023-07-26T16:49:55.404598Z","iopub.status.idle":"2023-07-26T16:49:55.412185Z","shell.execute_reply.started":"2023-07-26T16:49:55.404568Z","shell.execute_reply":"2023-07-26T16:49:55.410895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_model():\n    model = Sequential()\n\n    ## CNN 1\n    model.add(Conv2D(32,(3,3),activation='relu',input_shape=(img_rows, img_cols, color_type)))\n    model.add(BatchNormalization())\n    model.add(Conv2D(32,(3,3),activation='relu',padding='same'))\n    model.add(BatchNormalization(axis = 3))\n    model.add(MaxPooling2D(pool_size=(2,2),padding='same'))\n    model.add(Dropout(0.3))\n\n    ## CNN 2\n    model.add(Conv2D(64,(3,3),activation='relu',padding='same'))\n    model.add(BatchNormalization())\n    model.add(Conv2D(64,(3,3),activation='relu',padding='same'))\n    model.add(BatchNormalization(axis = 3))\n    model.add(MaxPooling2D(pool_size=(2,2),padding='same'))\n    model.add(Dropout(0.3))\n\n    ## CNN 3\n    model.add(Conv2D(128,(3,3),activation='relu',padding='same'))\n    model.add(BatchNormalization())\n    model.add(Conv2D(128,(3,3),activation='relu',padding='same'))\n    model.add(BatchNormalization(axis = 3))\n    model.add(MaxPooling2D(pool_size=(2,2),padding='same'))\n    model.add(Dropout(0.5))\n\n    ## Output\n    model.add(Flatten())\n    model.add(Dense(512,activation='relu'))\n    model.add(BatchNormalization())\n    model.add(Dropout(0.5))\n    model.add(Dense(128,activation='relu'))\n    model.add(Dropout(0.25))\n    model.add(Dense(10,activation='softmax'))\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:49:58.761781Z","iopub.execute_input":"2023-07-26T16:49:58.762215Z","iopub.status.idle":"2023-07-26T16:49:58.777056Z","shell.execute_reply.started":"2023-07-26T16:49:58.762178Z","shell.execute_reply":"2023-07-26T16:49:58.776014Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = create_model()\n\n# More details about the layers\nmodel.summary()\n\n# Compiling the model\nmodel.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-07-26T16:50:02.418317Z","iopub.execute_input":"2023-07-26T16:50:02.418767Z","iopub.status.idle":"2023-07-26T16:50:02.967638Z","shell.execute_reply.started":"2023-07-26T16:50:02.418720Z","shell.execute_reply":"2023-07-26T16:50:02.966497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Training model","metadata":{}},{"cell_type":"code","source":"history = model.fit(x_train, y_train, \n          validation_data=(x_test, y_test),\n          epochs=nb_epoch, batch_size=batch_size, verbose=1)\n\n# #model.load_weights('saved_models/weights_best_vanilla.hdf5')\n# print('History of the training',history.history)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T17:24:32.624599Z","iopub.execute_input":"2023-07-26T17:24:32.624931Z","iopub.status.idle":"2023-07-26T17:58:54.682221Z","shell.execute_reply.started":"2023-07-26T17:24:32.624902Z","shell.execute_reply":"2023-07-26T17:58:54.680950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Prediction on test set","metadata":{}},{"cell_type":"code","source":"def plot_test_class(model, test_files, image_number, color_type=1):\n    \"\"\"\n    Function that tests or model on test images and show the results\n    \"\"\"\n    img_brute = test_files[image_number]\n    img_brute = cv2.resize(img_brute,(img_rows,img_cols))\n    plt.imshow(img_brute, cmap='gray')\n\n    new_img = img_brute.reshape(-1,img_rows,img_cols,color_type)\n\n    y_prediction = model.predict(new_img, batch_size=batch_size, verbose=1)\n    print('Y prediction: {}'.format(y_prediction))\n    print('Predicted: {}'.format(activity_map.get('c{}'.format(np.argmax(y_prediction)))))\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-07-26T18:03:09.391022Z","iopub.execute_input":"2023-07-26T18:03:09.391417Z","iopub.status.idle":"2023-07-26T18:03:09.398986Z","shell.execute_reply.started":"2023-07-26T18:03:09.391385Z","shell.execute_reply":"2023-07-26T18:03:09.397846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"score1 = model.evaluate(x_test, y_test, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T18:02:45.265501Z","iopub.execute_input":"2023-07-26T18:02:45.265930Z","iopub.status.idle":"2023-07-26T18:03:02.002206Z","shell.execute_reply.started":"2023-07-26T18:02:45.265892Z","shell.execute_reply":"2023-07-26T18:03:02.001026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print('Loss: ', score1[0])\nprint('Accuracy: ', score1[1]*100, ' %')","metadata":{"execution":{"iopub.status.busy":"2023-07-26T18:03:33.145356Z","iopub.execute_input":"2023-07-26T18:03:33.145857Z","iopub.status.idle":"2023-07-26T18:03:33.154593Z","shell.execute_reply.started":"2023-07-26T18:03:33.145816Z","shell.execute_reply":"2023-07-26T18:03:33.150801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for i in range(10):\n#     plot_test_class(model, test_files, i)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T18:04:54.194896Z","iopub.execute_input":"2023-07-26T18:04:54.195290Z","iopub.status.idle":"2023-07-26T18:04:54.199526Z","shell.execute_reply.started":"2023-07-26T18:04:54.195258Z","shell.execute_reply":"2023-07-26T18:04:54.198714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}