{"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":"# Python librairies","metadata":{}},{"cell_type":"code","source":"# LOAD LIBRARIES\nimport gc\nimport os\nimport pickle\nimport pandas as pd\nimport numpy as np # CPU libraries\nimport cudf # GPU libraries\nimport xgboost as xgb\nfrom catboost import CatBoostClassifier\nprint('RAPIDS version',cudf.__version__)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-08-30T21:09:32.282228Z","iopub.execute_input":"2022-08-30T21:09:32.282615Z","iopub.status.idle":"2022-08-30T21:09:37.090248Z","shell.execute_reply.started":"2022-08-30T21:09:32.282585Z","shell.execute_reply":"2022-08-30T21:09:37.088515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# variables","metadata":{}},{"cell_type":"code","source":"# VERSION NAME FOR SAVED MODEL FILES\nVER = 4\n\n# TRAIN RANDOM SEED\nSEED = 42\n\n# FILL NAN VALUE\nNAN_VALUE = -127 # will fit in int8\n\n# FOLDS PER MODEL\nFOLDS = 5\n\nTRAIN_PATH = '../input/amex-data-integer-dtypes-parquet-format/train.parquet'\n\nTEST_PATH = '../input/amex-data-integer-dtypes-parquet-format/test.parquet'\n\nMODEL_PATH = \"../input/amex-outputs-echesneau-lr005\"\n\ncat_features = [\"B_30\", \"B_38\",\"D_114\",\"D_116\",\"D_117\",\"D_120\",\"D_126\",\"D_63\",\"D_64\",\"D_66\",\"D_68\"]","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:10:08.715514Z","iopub.execute_input":"2022-08-30T21:10:08.715910Z","iopub.status.idle":"2022-08-30T21:10:08.723395Z","shell.execute_reply.started":"2022-08-30T21:10:08.715880Z","shell.execute_reply":"2022-08-30T21:10:08.721848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(os.listdir(MODEL_PATH))","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:10:14.046928Z","iopub.execute_input":"2022-08-30T21:10:14.047521Z","iopub.status.idle":"2022-08-30T21:10:14.076873Z","shell.execute_reply.started":"2022-08-30T21:10:14.047475Z","shell.execute_reply":"2022-08-30T21:10:14.075457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"33 models are saved in the MODEL_PATH.\nThe average of the predictions will be calculated","metadata":{}},{"cell_type":"markdown","source":"# functions","metadata":{}},{"cell_type":"code","source":"def read_file(path = '', usecols = None):\n    \"\"\"\n    function to load dataset\n    The function is modified frm the original one\n    The Fillna is done only during the processing\n    \"\"\"\n    # LOAD DATAFRAME\n    if usecols is not None:\n        data = cudf.read_parquet(path, columns=usecols)\n    else:\n        data = cudf.read_parquet(path)\n    # REDUCE DTYPE FOR CUSTOMER AND DATE\n    data['customer_ID'] = data['customer_ID'].str[-16:].str.hex_to_int().astype('int64')\n    data.S_2 = cudf.to_datetime( data.S_2 )\n    print('shape of data:', data.shape)\n\n    return data","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:11:44.633608Z","iopub.execute_input":"2022-08-30T21:11:44.634009Z","iopub.status.idle":"2022-08-30T21:11:44.643034Z","shell.execute_reply.started":"2022-08-30T21:11:44.633980Z","shell.execute_reply":"2022-08-30T21:11:44.641364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def process_and_feature_engineer(data):\n    \"\"\"\n    function to process database\n    FEATURE ENGINEERING FROM\n    https://www.kaggle.com/code/huseyincot/amex-agg-data-how-it-created\n    \"\"\"\n    all_cols = [c for c in list(data.columns) if c not in ['customer_ID','S_2']]\n    cat_feat = [\"B_30\",\"B_38\",\"D_114\",\"D_116\",\"D_117\",\\\n                    \"D_120\",\"D_126\",\"D_63\",\"D_64\",\"D_66\",\"D_68\"]\n    num_features = [col for col in all_cols if col not in cat_feat]\n\n    test_num_agg = data.groupby(\"customer_ID\")[num_features].agg(['mean', \\\n                                                                  'std', \\\n                                                                  'min', \\\n                                                                  'max', \\\n                                                                  'last'])\n    test_num_agg.columns = ['_'.join(x) for x in test_num_agg.columns]\n\n    test_cat_agg = data.groupby(\"customer_ID\")[cat_feat].agg(['count', \\\n                                                              'last', \\\n                                                              'nunique'])\n    test_cat_agg.columns = ['_'.join(x) for x in test_cat_agg.columns]\n\n    data = cudf.concat([test_num_agg, test_cat_agg], axis=1)\n    del test_num_agg, test_cat_agg\n    data = data.fillna(NAN_VALUE)\n    return data","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:16:54.679953Z","iopub.execute_input":"2022-08-30T21:16:54.680568Z","iopub.status.idle":"2022-08-30T21:16:54.695709Z","shell.execute_reply.started":"2022-08-30T21:16:54.680520Z","shell.execute_reply":"2022-08-30T21:16:54.693842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def amex_metric_mod(y_true, y_pred):\n    \"\"\"\n    function to calculate the metric of the competion\n    from https://www.kaggle.com/kyakovlev\n    and https://www.kaggle.com/competitions/amex-default-prediction/discussion/327534\n    \"\"\"\n    labels     = np.transpose(np.array([y_true, y_pred]))\n    labels     = labels[labels[:, 1].argsort()[::-1]]\n    weights    = np.where(labels[:,0]==0, 20, 1)\n    cut_vals   = labels[np.cumsum(weights) <= int(0.04 * np.sum(weights))]\n    top_four   = np.sum(cut_vals[:,0]) / np.sum(labels[:,0])\n\n    gini = [0,0]\n    for i in [1,0]:\n        labels         = np.transpose(np.array([y_true, y_pred]))\n        labels         = labels[labels[:, i].argsort()[::-1]]\n        weight         = np.where(labels[:,0]==0, 20, 1)\n        weight_random  = np.cumsum(weight / np.sum(weight))\n        total_pos      = np.sum(labels[:, 0] *  weight)\n        cum_pos_found  = np.cumsum(labels[:, 0] * weight)\n        lorentz        = cum_pos_found / total_pos\n        gini[i]        = np.sum((lorentz - weight_random) * weight)\n\n    return 0.5 * (gini[1]/gini[0] + top_four)","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:16:56.396826Z","iopub.execute_input":"2022-08-30T21:16:56.397608Z","iopub.status.idle":"2022-08-30T21:16:56.409381Z","shell.execute_reply.started":"2022-08-30T21:16:56.397570Z","shell.execute_reply":"2022-08-30T21:16:56.407404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_rows(cust, data, num_parts = 4, verbose = ''):\n    \"\"\"\n    function to split the database\n    CALCULATE SIZE OF EACH SEPARATE TEST PART\n    \"\"\"\n    chunk = len(cust)//num_parts\n    if verbose != '':\n        print(f'We will process {verbose} data as {num_parts} separate parts.')\n        print(f'There will be {chunk} customers in each part (except the last part).')\n        print('Below are number of rows in each part:')\n    lrows = []\n\n    for n in range(num_parts):\n        if n == num_parts - 1:\n            ncust = cust[n*chunk:]\n        else:\n            ncust = cust[n*chunk:(n+1)*chunk]\n        cust_size = data.loc[data.customer_ID.isin(ncust)].shape[0]\n        lrows.append(cust_size)\n    if verbose != '':\n        print( lrows )\n    return lrows, chunk","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:17:30.677392Z","iopub.execute_input":"2022-08-30T21:17:30.677844Z","iopub.status.idle":"2022-08-30T21:17:30.687800Z","shell.execute_reply.started":"2022-08-30T21:17:30.677812Z","shell.execute_reply":"2022-08-30T21:17:30.686132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# load data","metadata":{}},{"cell_type":"markdown","source":"All models do not used the same features.\nThey are load from MODEL_PATH","metadata":{}},{"cell_type":"code","source":"if os.path.isfile(MODEL_PATH+\"/all_features.pkl\") :\n    with open(MODEL_PATH+\"/all_features.pkl\", 'rb') as f :\n        FEATURES = pickle.load(f)\nif os.path.isfile(MODEL_PATH+\"/all_features_2.pkl\") :\n    with open(MODEL_PATH+\"/all_features_2.pkl\", 'rb') as f :\n        FEATURES_2 = pickle.load(f)\nif os.path.isfile(MODEL_PATH+\"/all_features_3.pkl\") :\n    with open(MODEL_PATH+\"/all_features_3.pkl\", 'rb') as f :\n        FEATURES_3 = pickle.load(f)","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:18:45.494793Z","iopub.execute_input":"2022-08-30T21:18:45.495232Z","iopub.status.idle":"2022-08-30T21:18:45.521355Z","shell.execute_reply.started":"2022-08-30T21:18:45.495201Z","shell.execute_reply":"2022-08-30T21:18:45.520039Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test on train data","metadata":{}},{"cell_type":"markdown","source":"The accuracy is calculated on train set before test set.","metadata":{}},{"cell_type":"code","source":"NUM_PARTS = 3\nprint('Reading train data...')\ntrain = read_file(path = TRAIN_PATH, usecols = ['customer_ID','S_2'])\ncustomers = train[['customer_ID']].drop_duplicates().sort_index().values.flatten()\nrows,num_cust = get_rows(customers, train[['customer_ID']], num_parts = NUM_PARTS, verbose = 'test')","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:19:24.126137Z","iopub.execute_input":"2022-08-30T21:19:24.126518Z","iopub.status.idle":"2022-08-30T21:19:29.155753Z","shell.execute_reply.started":"2022-08-30T21:19:24.126489Z","shell.execute_reply":"2022-08-30T21:19:29.154031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# INFER Train DATA IN PARTS\nSKIP_rows = 0\nSKIP_CUST = 0\nfor k in range(NUM_PARTS):\n    # READ PART OF TRAIN DATA\n    print('\\nReading train data...')\n    train = read_file(path = TRAIN_PATH)\n    if k == 0 :\n        c = train[['customer_ID']].drop_duplicates().sort_index()['customer_ID'].to_pandas()\n        result_preds = pd.DataFrame(index=c.to_list())\n        del c\n        #result_preds = test[['P_2']].to_pandas().copy(deep=True)\n        #result_preds = result_preds[['customer_ID']].drop_duplicates().sort_index()\n    train = train.iloc[SKIP_ROWS:SKIP_ROWS+rows[k]]\n    print(f'=> Train part {k+1} has shape', train.shape )\n    print(f\"From line {SKIP_ROWS} to {SKIP_ROWS+rows[k]}\")\n    SKIP_ROWS += rows[k]\n\n    for file in os.listdir(MODEL_PATH) :\n        if os.path.isfile(MODEL_PATH+\"/\"+file) and not file.endswith('.pkl'):\n            print(f\"Process model : {file}\")\n            if \"_\".join(file.split('_')[1:3]) == \"all_features\" :\n                proc = process_and_feature_engineer(train).to_pandas()\n                proc = proc[FEATURES]\n            elif  \"_\".join(file.split('_')[1:3]) == \"nonan_features\" :\n                proc = process_and_feature_engineer(train).to_pandas()\n                proc = proc[FEATURES_2]\n            elif \"_\".join(file.split('_')[1:3]) == \"dc0_features\" :\n                proc = process_and_feature_engineer(train).to_pandas()\n                proc = proc[FEATURES_3]\n            else :\n                print(f\"Unknown preprocessing : {'_'.join(file.split('_')[1:3])}\")\n            if file.startswith(\"XGB\") :\n                tmp = proc[['B_2_max']].copy(deep=True)\n                dtest = xgb.DMatrix(data=proc)\n                model = xgb.Booster()\n                model.load_model(f'{MODEL_PATH}/{file}')\n                tmp[f\"{file}_parts-{k}\"] = model.predict(dtest)\n                tmp.drop('B_2_max', axis=1,inplace=True)\n                result_preds = result_preds.merge(tmp, left_index=True, \\\n                                                  right_index=True, how='left')\n                del dtest\n            elif file.startswith(\"CTB\") :\n                tmp = proc[['B_2_max']].copy(deep=True)\n                model = CatBoostClassifier()\n                model.load_model(f'{MODEL_PATH}/{file}')\n                tmp[f\"{file}_parts-{k}\"] = model.predict_proba(proc)[:,1]\n                tmp.drop('B_2_max', axis=1,inplace=True)\n                result_preds = result_preds.merge(tmp, left_index=True, \\\n                                                  right_index=True, how='left')\n            else :\n                print(f\"Unknown model {file}\")\n\n            try :\n                del proc, model, tmp\n                _ = gc.collect()\n            except NameError :\n                pass\n    del train\n    _ = gc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:19:43.392701Z","iopub.execute_input":"2022-08-30T21:19:43.393167Z","iopub.status.idle":"2022-08-30T21:37:08.789119Z","shell.execute_reply.started":"2022-08-30T21:19:43.393135Z","shell.execute_reply":"2022-08-30T21:37:08.787632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Results are store in a DataFrame.\nFolds are merge into one row.\nTargets are merge.","metadata":{}},{"cell_type":"code","source":"results = result_preds.groupby(['_'.join(col.split('_')[:-1]) \n                                for col in result_preds.columns],\n                               axis=1).mean()\ntargets = cudf.read_csv('../input/amex-default-prediction/train_labels.csv')\ntargets['customer_ID'] = targets['customer_ID'].str[-16:].str.hex_to_int().astype('int64')\ntargets = targets.set_index('customer_ID')","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:37:08.792332Z","iopub.execute_input":"2022-08-30T21:37:08.792962Z","iopub.status.idle":"2022-08-30T21:37:10.533629Z","shell.execute_reply.started":"2022-08-30T21:37:08.792920Z","shell.execute_reply":"2022-08-30T21:37:10.532217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = results.merge(targets.to_pandas(), left_index=True, right_index=True, how='left')","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:37:10.542933Z","iopub.execute_input":"2022-08-30T21:37:10.545359Z","iopub.status.idle":"2022-08-30T21:37:10.698113Z","shell.execute_reply.started":"2022-08-30T21:37:10.545297Z","shell.execute_reply":"2022-08-30T21:37:10.696802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The AMEX metric is calculated for all models","metadata":{}},{"cell_type":"code","source":"amex_metrix = pd.DataFrame(columns=['model', 'amex_metrics'])\nfor col in [columns for columns in results.columns if columns != 'target']:\n    amex_metrix = amex_metrix.append({\"model\" : col , \\\n                                      'amex_metrics' : amex_metric_mod(results['target'], \\\n                                                                       results[col])},\n                                    ignore_index=True)\namex_metrix","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:38:17.389550Z","iopub.execute_input":"2022-08-30T21:38:17.389990Z","iopub.status.idle":"2022-08-30T21:38:23.403494Z","shell.execute_reply.started":"2022-08-30T21:38:17.389959Z","shell.execute_reply":"2022-08-30T21:38:23.402212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"No conclusion on the accuracy of models could be done due to a overfitting on the train set.","metadata":{}},{"cell_type":"markdown","source":"# Create submission CSV","metadata":{}},{"cell_type":"markdown","source":"Prediction on the test set and creation of the submission file.","metadata":{}},{"cell_type":"code","source":"# COMPUTE SIZE OF 5 PARTS FOR TEST DATA\nNUM_PARTS = 5\nprint('Reading test data...')\ntest = read_file(path = TEST_PATH, usecols = ['customer_ID','S_2'])\ncustomers = test[['customer_ID']].drop_duplicates().sort_index().values.flatten()\nrows,num_cust = get_rows(customers, test[['customer_ID']], num_parts = NUM_PARTS, verbose = 'test')","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:38:42.941257Z","iopub.execute_input":"2022-08-30T21:38:42.941730Z","iopub.status.idle":"2022-08-30T21:38:45.863283Z","shell.execute_reply.started":"2022-08-30T21:38:42.941697Z","shell.execute_reply":"2022-08-30T21:38:45.861719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This part of the code could be modify to use only selection of models.","metadata":{}},{"cell_type":"code","source":"# INFER TEST DATA IN PARTS\nSKIP_ROWS = 0\nSKIP_CUST = 0\n#test_preds = []\nfor k in range(NUM_PARTS):\n    # READ PART OF TEST DATA\n    print('\\nReading test data...')\n    test = read_file(path = TEST_PATH)\n    if k == 0 :\n        c = test[['customer_ID']].drop_duplicates().sort_index()['customer_ID'].to_pandas()\n        result_preds = pd.DataFrame(index=c.to_list())\n        del c\n        #result_preds = test[['P_2']].to_pandas().copy(deep=True)\n        #result_preds = result_preds[['customer_ID']].drop_duplicates().sort_index()\n    test = test.iloc[SKIP_ROWS:SKIP_ROWS+rows[k]]\n    #test = test.to_pandas()\n    print(f'=> Test part {k+1} has shape', test.shape )\n    print(f\"From line {SKIP_ROWS} to {SKIP_ROWS+rows[k]}\")\n    SKIP_ROWS += rows[k]\n\n    for file in os.listdir(MODEL_PATH) :\n        if os.path.isfile(MODEL_PATH+\"/\"+file) and not file.endswith('.pkl'):\n            print(f\"Process model : {file}\")\n            if \"_\".join(file.split('_')[1:3]) == \"all_features\" :\n                proc = process_and_feature_engineer(test).to_pandas()\n                proc = proc[FEATURES]\n            elif  \"_\".join(file.split('_')[1:3]) == \"nonan_features\" :\n                proc = process_and_feature_engineer(test).to_pandas()\n                proc = proc[FEATURES_2]\n            elif \"_\".join(file.split('_')[1:3]) == \"dc0_features\" :\n                proc = process_and_feature_engineer(test).to_pandas()\n                proc = proc[FEATURES_3]\n            else :\n                print(f\"Unknown preprocessing : {'_'.join(file.split('_')[1:3])}\")\n            if file.startswith(\"XGB\") :\n                tmp = proc[['B_2_max']].copy(deep=True)\n                dtest = xgb.DMatrix(data=proc)\n                model = xgb.Booster()\n                model.load_model(f'{MODEL_PATH}/{file}')\n                tmp[f\"{file}_parts-{k}\"] = model.predict(dtest)\n                tmp.drop('B_2_max', axis=1,inplace=True)\n                result_preds = result_preds.merge(tmp, left_index=True, \\\n                                                  right_index=True, how='left')\n                del dtest\n            elif file.startswith(\"CTB\") :\n                tmp = proc[['B_2_max']].copy(deep=True)\n                #categ = []\n                #for col in proc.columns :\n                #    var = '_'.join(col.split('_')[:2])\n                #    if var in cat_features :\n                #        categ.append(col)\n                model = CatBoostClassifier()\n                model.load_model(f'{MODEL_PATH}/{file}')\n                tmp[f\"{file}_parts-{k}\"] = model.predict_proba(proc)[:,1]\n                tmp.drop('B_2_max', axis=1,inplace=True)\n                result_preds = result_preds.merge(tmp, left_index=True, \\\n                                                  right_index=True, how='left')\n            else :\n                print(f\"Unknown model {file}\")\n\n            try :\n                del proc, model, tmp\n                _ = gc.collect()\n            except NameError :\n                pass\n    del test\n    _ = gc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-08-30T21:40:53.047530Z","iopub.execute_input":"2022-08-30T21:40:53.047957Z","iopub.status.idle":"2022-08-30T22:17:17.505244Z","shell.execute_reply.started":"2022-08-30T21:40:53.047923Z","shell.execute_reply":"2022-08-30T22:17:17.503646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The final prediction is the mean value of each row.","metadata":{}},{"cell_type":"code","source":"pred = result_preds.mean(axis=1).reset_index()\npred.columns = [\"customer_ID\", \"prediction\"]\npred","metadata":{"execution":{"iopub.status.busy":"2022-08-30T22:17:17.508852Z","iopub.execute_input":"2022-08-30T22:17:17.509616Z","iopub.status.idle":"2022-08-30T22:17:20.584770Z","shell.execute_reply.started":"2022-08-30T22:17:17.509571Z","shell.execute_reply":"2022-08-30T22:17:20.583134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_preds","metadata":{"execution":{"iopub.status.busy":"2022-08-30T22:17:20.586897Z","iopub.execute_input":"2022-08-30T22:17:20.587376Z","iopub.status.idle":"2022-08-30T22:17:20.749459Z","shell.execute_reply.started":"2022-08-30T22:17:20.587336Z","shell.execute_reply":"2022-08-30T22:17:20.748217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A DataFrame is created on the expected format and saved.","metadata":{}},{"cell_type":"code","source":"sub = cudf.read_csv('../input/amex-default-prediction/sample_submission.csv')[['customer_ID']]\nsub['customer_ID_hash'] = sub['customer_ID'].str[-16:].str.hex_to_int().astype('int64')\nsub = sub.set_index('customer_ID_hash').to_pandas()\ntmp = pred.set_index(\"customer_ID\")\nsub = sub.merge(tmp[['prediction']], left_index=True, right_index=True, how='left')\nsub = sub.reset_index(drop=True)\nsub.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-30T22:17:20.752774Z","iopub.execute_input":"2022-08-30T22:17:20.754127Z","iopub.status.idle":"2022-08-30T22:17:22.812571Z","shell.execute_reply.started":"2022-08-30T22:17:20.754020Z","shell.execute_reply":"2022-08-30T22:17:22.811115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv(f'submission_xgb_v{VER}.csv',index=False)\nprint('Submission file shape is', sub.shape )","metadata":{"execution":{"iopub.status.busy":"2022-08-30T22:17:22.814788Z","iopub.execute_input":"2022-08-30T22:17:22.815260Z","iopub.status.idle":"2022-08-30T22:17:26.069414Z","shell.execute_reply.started":"2022-08-30T22:17:22.815218Z","shell.execute_reply":"2022-08-30T22:17:26.067773Z"},"trusted":true},"execution_count":null,"outputs":[]}]}