{"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":"import pandas as pd\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D\nfrom tensorflow.keras.layers import MaxPooling2D\nfrom tensorflow.keras.layers import Dense\nfrom tensorflow.keras.layers import Flatten","metadata":{"_uuid":"e661afe4-a291-452e-9280-22fc3e21714f","_cell_guid":"4877ee53-ed2b-4a29-a7cb-3aba5bdbc46d","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:41.574676Z","iopub.execute_input":"2022-04-23T15:44:41.57544Z","iopub.status.idle":"2022-04-23T15:44:47.895348Z","shell.execute_reply.started":"2022-04-23T15:44:41.575322Z","shell.execute_reply":"2022-04-23T15:44:47.894504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_data = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')\ntesting_data = pd.read_csv(\"/kaggle/input/digit-recognizer/test.csv\")","metadata":{"execution":{"iopub.status.busy":"2022-04-23T15:44:47.896848Z","iopub.execute_input":"2022-04-23T15:44:47.897087Z","iopub.status.idle":"2022-04-23T15:44:53.376315Z","shell.execute_reply.started":"2022-04-23T15:44:47.897059Z","shell.execute_reply":"2022-04-23T15:44:53.375558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training = training_data.isnull().sum().sum()\nprint(f\"Nulls in training: {training}\")\n\nvalidation = testing_data.isnull().sum().sum()\nprint(f\"Nulls in validation: {validation}\")","metadata":{"_uuid":"7042d034-8c5f-4d8d-9186-4edf51f5625b","_cell_guid":"965389fa-e01d-4681-b54d-fdf0301c1e40","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:53.377352Z","iopub.execute_input":"2022-04-23T15:44:53.377563Z","iopub.status.idle":"2022-04-23T15:44:53.459231Z","shell.execute_reply.started":"2022-04-23T15:44:53.377536Z","shell.execute_reply":"2022-04-23T15:44:53.458512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# separate x and y for test and train data\n\ntrain_X = training_data.iloc[: , 1:]\n\ntrain_Y = training_data.iloc[:,0]\n\ntest_X = testing_data\n\ntrain_X.shape, train_Y.shape","metadata":{"_uuid":"bed6e394-40cb-4858-ba59-dec5559481c7","_cell_guid":"349c80df-c0f7-4dd9-8808-019c3ebde470","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:53.460876Z","iopub.execute_input":"2022-04-23T15:44:53.461117Z","iopub.status.idle":"2022-04-23T15:44:53.46978Z","shell.execute_reply.started":"2022-04-23T15:44:53.461088Z","shell.execute_reply":"2022-04-23T15:44:53.469215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# data normalization\n\ntrain_X = train_X / 255.0\ntest_X = test_X / 255.0","metadata":{"_uuid":"d38b40a9-3545-4d08-b69f-930d291cdeef","_cell_guid":"2dac7299-479e-48c2-b90e-1d64dbcbbb42","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:53.470769Z","iopub.execute_input":"2022-04-23T15:44:53.471423Z","iopub.status.idle":"2022-04-23T15:44:53.582293Z","shell.execute_reply.started":"2022-04-23T15:44:53.471356Z","shell.execute_reply":"2022-04-23T15:44:53.581455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# reshape data\n\ntrain_X = train_X.values.reshape(-1, 28, 28, 1)\ntest_X = test_X.values.reshape(-1, 28, 28, 1)\n\ntrain_X.shape, test_X.shape","metadata":{"_uuid":"bea9b811-cc42-4c51-b84f-5b60b1a35ba0","_cell_guid":"9c5eddf1-1f25-44bc-8c45-aba2cde21b1c","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:53.583549Z","iopub.execute_input":"2022-04-23T15:44:53.583778Z","iopub.status.idle":"2022-04-23T15:44:53.591546Z","shell.execute_reply.started":"2022-04-23T15:44:53.583751Z","shell.execute_reply":"2022-04-23T15:44:53.590553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# split data into train and test slices\n\ntrain_X, val_X, train_Y, val_Y = train_test_split(train_X, train_Y, test_size=0.3)\n\ntrain_X.shape, val_X.shape, train_Y.shape, val_Y.shape","metadata":{"_uuid":"202ead97-aa44-48e3-945d-f1384a954b25","_cell_guid":"72a394de-5f46-481d-8bf3-e8e52fc5ded6","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:53.592693Z","iopub.execute_input":"2022-04-23T15:44:53.592958Z","iopub.status.idle":"2022-04-23T15:44:54.024292Z","shell.execute_reply.started":"2022-04-23T15:44:53.592923Z","shell.execute_reply":"2022-04-23T15:44:54.023684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# one hot encoding\n\ntrain_Y = keras.utils.to_categorical(train_Y, num_classes=10)\nval_Y = keras.utils.to_categorical(val_Y, num_classes=10)\n\ntrain_Y.shape, val_Y.shape","metadata":{"_uuid":"826ff06f-2889-446c-9dcb-e1100722c9d7","_cell_guid":"59ce2ed0-3570-4a82-bee4-645ed28ec24c","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:54.0253Z","iopub.execute_input":"2022-04-23T15:44:54.025896Z","iopub.status.idle":"2022-04-23T15:44:54.033734Z","shell.execute_reply.started":"2022-04-23T15:44:54.025859Z","shell.execute_reply":"2022-04-23T15:44:54.032945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_train_number(idx):\n  plt.imshow(train_X[idx].reshape(28, 28))  # (rows, columns)\n  plt.title(f\"Digit: {np.where(train_Y[idx] == np.amax(train_Y[idx]))[0]}\")\n  plt.show() \n\ndef show_val_number(idx):\n  plt.imshow(val_X[idx].reshape(28, 28))  # (rows, columns)\n  plt.title(f\"Digit: {np.where(val_Y[idx] == np.amax(val_Y[idx]))[0]}\")\n  plt.show() \n\ndef show_testing_data(idx):\n  plt.imshow(testing_data[idx].reshape(28, 28))  # (rows, columns)\n  plt.show()","metadata":{"_uuid":"3fd63a8f-3f66-46c4-9373-fce9ee20b7ef","_cell_guid":"c43ba02e-3a8c-401a-87e8-ee13a816b655","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:54.035018Z","iopub.execute_input":"2022-04-23T15:44:54.035244Z","iopub.status.idle":"2022-04-23T15:44:54.041774Z","shell.execute_reply.started":"2022-04-23T15:44:54.035217Z","shell.execute_reply":"2022-04-23T15:44:54.04118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\ndef get_data_generator(zoom, height, width, rotation):\n    datagen = ImageDataGenerator(zoom_range = zoom,\n                             height_shift_range = height,\n                             width_shift_range = width,\n                             rotation_range = rotation)\n    return datagen","metadata":{"execution":{"iopub.status.busy":"2022-04-23T15:44:54.043976Z","iopub.execute_input":"2022-04-23T15:44:54.044594Z","iopub.status.idle":"2022-04-23T15:44:54.054876Z","shell.execute_reply.started":"2022-04-23T15:44:54.044556Z","shell.execute_reply":"2022-04-23T15:44:54.054114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def convolutional_model(normalization, dropout):\n    input_img = tf.keras.Input(shape=(28,28,1))\n    Z1 = tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), strides=(1, 1), padding='same')(input_img)\n    if (normalization == 1):\n      Z1 = tf.keras.layers.BatchNormalization(axis = 3) (Z1, training = True)\n    A1 = tf.keras.layers.ReLU()(Z1)\n    P1 = tf.keras.layers.MaxPool2D(pool_size = (2,2), strides = 2, padding = 'same')(A1)\n    \n    D1 = tf.keras.layers.Dropout(dropout)(P1)\n    \n    Z2 = tf.keras.layers.Conv2D(filters = 16, kernel_size = (2,2), strides=(1, 1), padding='same')(P1)\n    if (normalization == 1):\n      Z2 = tf.keras.layers.BatchNormalization(axis = 3) (Z2, training = True)\n    A2 = tf.keras.layers.ReLU()(Z2)\n    P2 = tf.keras.layers.MaxPool2D(pool_size = (2,2), strides = 2, padding = 'same')(A2)\n    \n    F = tf.keras.layers.Flatten()(P2)\n    D2 = tf.keras.layers.Dropout(dropout)(F)\n\n    \n    outputs = tf.keras.layers.Dense(units = 10, activation = 'softmax') (D2)\n        \n    model = tf.keras.Model(inputs=input_img, outputs=outputs)\n    \n    return model","metadata":{"_uuid":"eb8cd2c1-a99c-44c0-be4b-f91143faef55","_cell_guid":"56a80098-6ffd-497e-9feb-db8a21e60f9b","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:54.056176Z","iopub.execute_input":"2022-04-23T15:44:54.056603Z","iopub.status.idle":"2022-04-23T15:44:54.070659Z","shell.execute_reply.started":"2022-04-23T15:44:54.056565Z","shell.execute_reply":"2022-04-23T15:44:54.07006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model initialization\n\nnum_models = 12\nmodel = [0] * num_models\ndatagens = [0] * num_models\n\nmodel[0] = convolutional_model(0, 0) # no normalization and no dropout\nmodel[1] = convolutional_model(1, 0) # normalization and no dropout\nmodel[2] = convolutional_model(0, 0.4) # no normalization and 0.4 dropout\nmodel[3] = convolutional_model(1, 0.4) # normalization and 0.4 dropout\nmodel[4] = convolutional_model(0, 0.6) # no normalization and 0.6 dropout\nmodel[5] = convolutional_model(1, 0.6) # normalization and 0.6 dropout\n\ndatagens[0] = get_data_generator(0, 0, 0, 0)\ndatagens[1] = get_data_generator(0, 0, 0, 0)\ndatagens[2] = get_data_generator(0, 0, 0, 0)\ndatagens[3] = get_data_generator(0, 0, 0, 0)\ndatagens[4] = get_data_generator(0, 0, 0, 0)\ndatagens[5] = get_data_generator(0, 0, 0, 0)\n\nmodel[6] = convolutional_model(0, 0) # no normalization and no dropout\nmodel[7] = convolutional_model(1, 0) # normalization and no dropout\nmodel[8] = convolutional_model(0, 0.4) # no normalization and 0.4 dropout\nmodel[9] = convolutional_model(1, 0.4) # normalization and 0.4 dropout\nmodel[10] = convolutional_model(0, 0.6) # no normalization and 0.6 dropout\nmodel[11] = convolutional_model(1, 0.6) # normalization and 0.6 dropout\n\ndatagens[6] = get_data_generator(0.1, 0.1, 0.1, 5)\ndatagens[7] = get_data_generator(0.1, 0.1, 0.1, 5)\ndatagens[8] = get_data_generator(0.1, 0.1, 0.1, 5)\ndatagens[9] = get_data_generator(0.1, 0.1, 0.1, 5)\ndatagens[10] = get_data_generator(0.1, 0.1, 0.1, 5)\ndatagens[11] = get_data_generator(0.1, 0.1, 0.1, 5)\n\nfor j in range(num_models):\n    model[j].compile(optimizer='adam',\n                  loss='categorical_crossentropy',\n                  metrics=['accuracy'])\n\n# initiate early stopping to prevent overfitting\nearly_stopping = keras.callbacks.EarlyStopping(\n    patience=4,\n    min_delta=0.001,\n    restore_best_weights=True,\n)\n\nhistory = [0] * num_models\nnames = [\"NoNorm-NoDrop\",\"Norm-NoDrop\",\"NoNorm-04Drop\",\"Norm-04Drop\",\"NoNorm-06Drop\",\"Norm-06Drop\",\n         \"NoNorm-NoDrop-DA\",\"Norm-NoDrop-DA\",\"NoNorm-04Drop-DA\",\"Norm-04Drop-DA\",\"NoNorm-06Drop-DA\",\"Norm-06Drop-DA\"]\nepochs = 20\nfor j in range(num_models):\n    history[j] = model[j].fit(datagens[j].flow(train_X, train_Y, batch_size=128),\n                         epochs=epochs,\n                         validation_data=(val_X, val_Y),\n                         batch_size=128,\n                         callbacks=[early_stopping]) \n\n    print(\"CNN {0}: Epochs={1:d}, Train accuracy={2:.5f}, Validation accuracy={3:.5f}\".format(\n        names[j],epochs,max(history[j].history['accuracy']),max(history[j].history['val_accuracy']) ))\n\n","metadata":{"_uuid":"dcfe482f-7aca-4ad8-804f-7a4fb9d1916c","_cell_guid":"d36a0999-2af1-45df-a223-b5d3efdcaa21","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T15:44:54.07198Z","iopub.execute_input":"2022-04-23T15:44:54.072354Z","iopub.status.idle":"2022-04-23T16:18:25.831782Z","shell.execute_reply.started":"2022-04-23T15:44:54.072326Z","shell.execute_reply":"2022-04-23T16:18:25.830926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"styles=[':','-.','--','-',':','-.','--','-',':','-.','--','-']\n\n# PLOT ACCURACIES\nplt.figure(figsize=(15,5))\nfor i in range(num_models):\n    plt.plot(history[i].history['val_accuracy'],linestyle=styles[i])\nplt.title('model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(names, loc='upper left')\naxes = plt.gca()\naxes.set_ylim([0.95,1])\nplt.show()","metadata":{"_uuid":"af97a835-2e60-4830-b867-3706f63ebeb2","_cell_guid":"0ff58869-b613-4d95-b392-c25d818eba37","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T16:20:14.21061Z","iopub.execute_input":"2022-04-23T16:20:14.211245Z","iopub.status.idle":"2022-04-23T16:20:14.490947Z","shell.execute_reply.started":"2022-04-23T16:20:14.211213Z","shell.execute_reply":"2022-04-23T16:20:14.490107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PRUEBA CON UN ELEMENTO DEL CONJUNTO DE DATOS QUE NOS HEMOS GUARDADO PARA VALIDAR\n\nvalIdx = 25;\nmodelIndex = 4;\n\noutput = model[modelIndex].predict(val_X)[valIdx]\n\n# convertimos la salida del modelo en un único valor\nres = np.where(output == np.amax(output))\n\n# convertimos el hotmap array de lo esperado en un valor\nexpected = np.where(val_Y[valIdx] == np.amax(val_Y[valIdx]))\n\nprint(f\"Valor esperado: {expected[0]}\")\nprint(f\"Valor de la predicción: {res[0]}\")\nshow_val_number(valIdx)","metadata":{"_uuid":"9de740ed-ce98-4386-81e6-dd7f28c87ba9","_cell_guid":"66598dac-1d04-45f0-a128-8bc7ddcab7b9","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T16:21:15.846379Z","iopub.execute_input":"2022-04-23T16:21:15.84687Z","iopub.status.idle":"2022-04-23T16:21:16.942992Z","shell.execute_reply.started":"2022-04-23T16:21:15.846816Z","shell.execute_reply":"2022-04-23T16:21:16.9424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Note, this code is taken straight from the SKLEARN website, an nice way of viewing confusion matrix.\nfrom sklearn.metrics import confusion_matrix\nimport itertools\n\ndef plot_confusion_matrix(cm, classes, title,\n                          normalize=False,\n                          cmap=plt.cm.Blues):\n    \"\"\"\n    This function prints and plots the confusion matrix.\n    Normalization can be applied by setting `normalize=True`.\n    \"\"\"\n    plt.figure()\n\n    plt.imshow(cm, interpolation='nearest', cmap=cmap)\n    plt.title(title)\n    plt.colorbar()\n    tick_marks = np.arange(len(classes))\n    plt.xticks(tick_marks, classes, rotation=45)\n    plt.yticks(tick_marks, classes)\n\n    if normalize:\n        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n\n    thresh = cm.max() / 2.\n    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n        plt.text(j, i, cm[i, j],\n                 horizontalalignment=\"center\",\n                 color=\"white\" if cm[i, j] > thresh else \"black\")\n\n    plt.tight_layout()\n    plt.ylabel('True label')\n    plt.xlabel('Predicted label')\n    \nfor i in range(num_models):\n    # Predict the values from the validation dataset\n    Y_pred = model[i].predict(val_X)\n\n    # Convert predictions classes to numbers\n    Y_pred_classes = np.argmax(Y_pred, axis = 1) \n \n    # Convert validation observations to one hot vectors\n    #Y_true = np.argmax(val_Y, axis = 1) \n    # compute the confusion matrix\n    confusion_mtx = confusion_matrix(np.argmax(val_Y,  axis = 1), Y_pred_classes)\n    \n    #print(confusion_mtx)\n    \n    # plot the confusion matrix\n    plot_confusion_matrix(confusion_mtx, classes = range(10), title = names[i])","metadata":{"_uuid":"def44dcb-5496-4045-8fcc-00862d8cbbe7","_cell_guid":"fd68cadd-50d0-4a9c-8ab6-2b27c172ecac","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T16:49:52.430738Z","iopub.execute_input":"2022-04-23T16:49:52.43104Z","iopub.status.idle":"2022-04-23T16:50:13.860455Z","shell.execute_reply.started":"2022-04-23T16:49:52.431006Z","shell.execute_reply":"2022-04-23T16:50:13.859468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# evaluate the model\nloss_and_metrics = model.evaluate(val_X, val_Y, verbose=2)\n\nprint(\"Val Loss\", loss_and_metrics[0])\nprint(\"Val Accuracy\", loss_and_metrics[1])\n\n# plotting the metrics\nfig = plt.figure(figsize=(8,6))\nplt.subplot(2,1,1)\nplt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\nplt.title('Model Accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'val'], loc='lower right')\n\nplt.subplot(2,1,2)\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('Model Loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'val'], loc='upper right')\n\nplt.tight_layout()\nplt.show()","metadata":{"_uuid":"90190de8-073b-4876-b019-0d98202ee845","_cell_guid":"be20af06-bea5-4955-b096-68053242fdc5","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T16:18:26.490702Z","iopub.status.idle":"2022-04-23T16:18:26.491172Z","shell.execute_reply.started":"2022-04-23T16:18:26.490906Z","shell.execute_reply":"2022-04-23T16:18:26.490929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# predict results\nsubmissionPredictions = model.predict(test_X)\n\n# select the indix with the maximum probability\nsubmissionPredictions = np.argmax(submissionPredictions,axis = 1)\n\nsubmissionPredictions = pd.Series(submissionPredictions,name=\"Label\")","metadata":{"_uuid":"1cc171ba-ec2b-4276-853a-b759bdbb5f05","_cell_guid":"cc1aa73f-8f60-46a4-a9ad-94ec7fc60b17","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T16:18:26.492504Z","iopub.status.idle":"2022-04-23T16:18:26.492941Z","shell.execute_reply.started":"2022-04-23T16:18:26.4927Z","shell.execute_reply":"2022-04-23T16:18:26.492724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PRUEBA CON UN ELEMENTO DEL TESTSET\nitemToTest = 851\nplt.imshow(test_X[itemToTest].reshape(28, 28))\n# the label of the first number\nplt.title(f\"Digit: {submissionPredictions[itemToTest]}\")\nplt.show()","metadata":{"_uuid":"9c7451db-353c-48d9-8f46-c8e35aa7be87","_cell_guid":"47a6320b-c0b0-47ee-97f8-1423bd05fb99","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T16:18:26.494353Z","iopub.status.idle":"2022-04-23T16:18:26.494853Z","shell.execute_reply.started":"2022-04-23T16:18:26.494567Z","shell.execute_reply":"2022-04-23T16:18:26.494604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# PREPARAR LA ENTREGA\n\nsubmission = pd.DataFrame({'ImageId':pd.Series(list(range(1, len(submissionPredictions)+1))),\n                                   'Label':pd.Series(submissionPredictions)})\n\nsubmission.to_csv(\"submission.csv\", index=False)\n\nsubmission","metadata":{"_uuid":"32d5e612-aa25-4a31-b243-2cc6ef3220cb","_cell_guid":"7a2b1072-91da-4b43-bc8f-b110f9be8486","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-04-23T16:18:26.495988Z","iopub.status.idle":"2022-04-23T16:18:26.496468Z","shell.execute_reply.started":"2022-04-23T16:18:26.496197Z","shell.execute_reply":"2022-04-23T16:18:26.496221Z"},"trusted":true},"execution_count":null,"outputs":[]}]}