{"cells":[{"metadata":{},"cell_type":"markdown","source":"# ChangeLog\n- Imported version 1 of osic-intended as base\n#### v1.12 \n- Fixed Normalization:  Train Data and Test Data must not have any visibility into each other, there can be no leaks, otherwise this will lead to overfitting.  When you take an average/mean of combined train/test data, and then split, you have introduced a leak into the train set, as the normalization it is using is based on values in the Test set.  Therefore, normalization/scaling must always be done AFTER the train/test split.\n- Switched from KFold to GroupKFold https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GroupKFold.html.  Our data contains multiple observations from a single patient.  It is important that these observations NOT be split between folds.  You cannot train on a given paitent and also validate on the same patient, this is a data leak.  We will be using GroupKFold and declare patient id as a group.","execution_count":null},{"metadata":{"trusted":false},"cell_type":"code","source":"# intended one\n# me","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport seaborn as sns\n#import pydicom\nimport os\nimport random\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\n#from PIL import Image\nfrom sklearn.metrics import mean_absolute_error\nfrom sklearn.model_selection import KFold, GroupKFold","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow.keras.backend as backend   #K  \nimport tensorflow.keras.layers as layers     #L\nimport tensorflow.keras.models as models     #M","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# avoiding randomness to get the same result of the model asways\ndef seed_everything(seed=2020):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    return seed","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# # CONFIGURE GPUs\n# #os.environ[\"CUDA_VISIBLE_DEVICES\"]=\"0\"\n# gpus = tf.config.list_physical_devices('GPU'); print(gpus)\n# if len(gpus)==1: strategy = tf.distribute.OneDeviceStrategy(device=\"/gpu:0\")\n# else: strategy = tf.distribute.MirroredStrategy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# # ENABLE MIXED PRECISION for speed\n# #tf.config.optimizer.set_jit(True)\n# tf.config.optimizer.set_experimental_options({\"auto_mixed_precision\": True})\n# print('Mixed precision enabled')","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"path = \"../input/osic-pulmonary-fibrosis-progression\"\n\ntrain = pd.read_csv(f\"{path}/train.csv\")                        #tr\ntest  = pd.read_csv(f\"{path}/test.csv\")                         #chunk\nprint('****training data head 1 value****\\n')\nprint(train.head(1))\nprint('\\n****test data head 1 value****\\n')\nprint(test.head(1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"print('train_data_shape', train.shape)\nprint('test_data_shape', test.shape)\nprint('duplicates',train.duplicated().sum())\n\n# for now we are leaving this command but it could be useful to see its effect on the accuracy\nprint('duplicates',train.duplicated(subset=['Patient','Weeks']).sum())\ntrain.drop_duplicates(keep=False, inplace=True, subset=['Patient','Weeks'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"#reading the submission file\n# columns 'Patient_Week', 'FVC', 'Confidence'\nsub = pd.read_csv(f\"{path}/sample_submission.csv\")\n\n# creating the new colomn patient and week from the Patient_Week column\n# we are using the - as seprator key\nsub['Patient'] = sub['Patient_Week'].apply(lambda x:x.split('_')[0])\n\nsub['Weeks'] = sub['Patient_Week'].apply(lambda x: int(x.split('_')[-1]))\n\n\n# 'Patient_Week', 'FVC', 'Confidence', 'Patient', 'Weeks'\n# we are droping the FVC column\nsub =  sub[['Patient','Weeks','Confidence','Patient_Week']]","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# we are merging the submission data with test data [before merging removing the weeks column from it]\nsubmission = sub.merge(test.drop('Weeks', axis=1), on=\"Patient\")\nprint('****submission_data head 1 value*****\\n')\nprint(sub.head(1))\nprint('******test data head 1 value********')\nprint(test.head(1))\n\nsubmission.head(1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# adding new columns WHERE in train, test and submission data\ntrain['WHERE'] = 'train'\ntest['WHERE'] = 'val'\nsubmission['WHERE'] = 'test'\nprint('train data shape\\n\\n',train.shape)\nprint('\\ntest data shape\\n\\n',test.shape)\nprint('\\nsubmission data shape\\n\\n',submission.shape)\n\n# we append the test and submission data on to\ndata = train.append([test, submission])\nprint('\\ndata_shape',data.shape)\ndata.head(2)\n# 1535+5+730 = 2270","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# we know each patient have multiple entries so we are checking the unique entries\nprint(train.Patient.nunique(), data.Patient.nunique(), test.Patient.nunique(), submission.Patient.nunique())","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# creating a new column min_week \n# min week means the first week of patient's observation\ncheck_point_1 = data['min_week'] = data['Weeks']\n\n# putting the min_week to NAN value\ncheck_point_2 = data.loc[data.WHERE=='test','min_week'] = np.nan\n\ncheck_point_3 = data['min_week'] = data.groupby('Patient')['min_week'].transform('min')\n\nprint('check_point_1\\n',check_point_1.head(10))\nprint('\\ncheck_point_2\\n',check_point_2)\nprint('\\ncheck_point_3\\n',check_point_3)\ndata.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"base = data.loc[data.Weeks == data.min_week]\na = base\nbase = base[['Patient','FVC']].copy()\nb = base\n\nbase.columns = ['Patient','min_FVC']\nbase['nb'] = 1\nc = base\n\nbase['nb'] = base.groupby('Patient')['nb'].transform('cumsum')\nd = base\n\nbase = base[base.nb==1]\ne = base\n\nbase.drop('nb', axis=1, inplace=True)\nf = base\n\n# a.head(1)\n# b.head(1)\n# c.head(5)\n# d.head(5)\n# e.head(8)\n# f.head(5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"data = data.merge(base, on='Patient', how='left')\n\ndata['base_week'] = data['Weeks'] - data['min_week']\n\n\ndata.head(10)\ndel base","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"data.head(5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# creating dummies of all categorical values\n############## THIS METHORD IS BIT COMPLEX ONE ##############################3\n\nCOLS = ['Sex','SmokingStatus']\nFE = []\nfor col in COLS:\n    for mod in data[col].unique():\n        FE.append(mod)\n        #print(FE)\n        data[mod] = (data[col] == mod).astype(int)\n        #print(data)\n    #break","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Train / Test Split","execution_count":null},{"metadata":{"trusted":false},"cell_type":"code","source":"train = data.loc[data.WHERE=='train']\ntest = data.loc[data.WHERE=='val']\nsubmission = data.loc[data.WHERE=='test']\n\n\n# print('train data shape\\n',train.shape)\n# print('\\ntest data shape\\n',test.shape)\n# print('\\nsubmission data shape\\n',submission.shape)\n\ndel data","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Normalization","execution_count":null},{"metadata":{"trusted":false},"cell_type":"code","source":"train['age'] = (train['Age'] - train['Age'].min() ) / ( train['Age'].max() - train['Age'].min() )\ntrain['BASE'] = (train['min_FVC'] - train['min_FVC'].min() ) / ( train['min_FVC'].max() - train['min_FVC'].min() )\ntrain['week'] = (train['base_week'] - train['base_week'].min() ) / ( train['base_week'].max() - train['base_week'].min() )\ntrain['percent'] = (train['Percent'] - train['Percent'].min() ) / ( train['Percent'].max() - train['Percent'].min() )\n\ntest['age'] = (test['Age'] - test['Age'].min() ) / ( test['Age'].max() - test['Age'].min() )\ntest['BASE'] = (test['min_FVC'] - test['min_FVC'].min() ) / ( test['min_FVC'].max() - test['min_FVC'].min() )\ntest['week'] = (test['base_week'] - test['base_week'].min() ) / ( test['base_week'].max() - test['base_week'].min() )\ntest['percent'] = (test['Percent'] - test['Percent'].min() ) / ( test['Percent'].max() - test['Percent'].min() )\n\nsubmission['age'] = (submission['Age'] - submission['Age'].min() ) / ( submission['Age'].max() - submission['Age'].min() )\nsubmission['BASE'] = (submission['min_FVC'] - submission['min_FVC'].min() ) / ( submission['min_FVC'].max() - submission['min_FVC'].min() )\nsubmission['week'] = (submission['base_week'] - submission['base_week'].min() ) / ( submission['base_week'].max() - submission['base_week'].min() )\nsubmission['percent'] = (submission['Percent'] - submission['Percent'].min() ) / ( submission['Percent'].max() - submission['Percent'].min() )\n\nFE += ['age','percent','week','BASE']\n#FE += ['age','percent','BASE']","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"#FE","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"SEED = seed_everything(42)\nNFOLD      = 4\nBATCH_SIZE = 128\nEPOCHS     = 400","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# BASELINE NN","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Laplace Log Likelihood","execution_count":null},{"metadata":{"trusted":false},"cell_type":"code","source":"C1, C2 = tf.constant(70, dtype='float32'), tf.constant(1000, dtype=\"float32\")\n# print('C1 = ',C1)\n# print('C2 = ',C2)\n\ndef Laplace_log_Likelihood_score(y_true, y_pred):\n    \n    tf.dtypes.cast(y_true, tf.float32)  # converting y_true in float values\n    tf.dtypes.cast(y_pred, tf.float32)  # converting y_pred in float values\n    sigma = y_pred[:, 2] - y_pred[:, 0] # calculating the standard deviation \n    fvc_pred = y_pred[:, 1]\n    \n    #sigma_clip = sigma + C1\n    sigma_clip = tf.maximum(sigma, C1)  # clipping all standard deviation(sigma) the other values less than 70\n    \n    delta = tf.abs(y_true[:, 0] - fvc_pred) # |FVC_true - FVC_predicted| abs mean we need a +ve value as always\n    delta = tf.minimum(delta, C2)           # clipping all values greater than 1000\n    \n    sq2 = tf.sqrt( tf.dtypes.cast(2, dtype=tf.float32) ) # calculating sqr root of 2\n    \n    metric = -(delta / sigma_clip)*sq2 - tf.math.log(sigma_clip* sq2) # calculating metric as given in OSIC  evaluation\n    #print('matric value', metric)\n    #print('backend.mean(metric) from log laplace transform', backend.mean(metric))\n    #print('Calculating Laplace_log_Likelihood_score')\n    #print('value = ', backend.mean(metric))\n    return backend.mean(metric)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"def qloss(y_true, y_pred):\n    \n    # Pinball loss for multiple quantiles\n    qs = [0.2, 0.50, 0.8]\n    q = tf.constant(np.array([qs]), dtype=tf.float32)\n    e = y_true - y_pred\n    v = tf.maximum(q*e, (q-1)*e)\n    \n    #print('backend.mean(v)', backend.mean)\n    #print('Calculating qLoss')\n    #print('value = ', (v))\n    return backend.mean(v)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"def mloss(_lambda):\n    def loss(y_true, y_pred):\n        return _lambda * qloss(y_true, y_pred) + (1 - _lambda)*Laplace_log_Likelihood_score(y_true, y_pred)\n    #print('Calculating mLoss')\n    return loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"def make_model():                          #backend   #K layers     #L models     #M\n    z = layers.Input((9,), name=\"Patient\")\n    \n    x = layers.Dense(100, activation=\"relu\", name=\"d1\")(z)\n    #x = layers.Dropout(0.002)(x)\n    x = layers.Dense(100, activation=\"relu\", name=\"d2\")(x)\n    x = layers.Dropout(0.002)(x)\n#     x = layers.Dense(100, activation=\"relu\", name=\"d3\")(x)\n#     x = layers.Dense(100, activation=\"relu\", name=\"d4\")(x)\n#     x = layers.Dense(100, activation=\"relu\", name=\"d5\")(x)\n#     x = layers.Dense(100, activation=\"relu\", name=\"d6\")(x)\n    \n    p1 = layers.Dense(3, activation=\"linear\", name=\"p1\")(x)\n    #x = layers.Dropout(0.05)(x)\n    p2 = layers.Dense(3, activation=\"relu\", name=\"p2\")(x)\n    #x = layers.Dropout(0.05)(x)\n    preds = layers.Lambda(lambda x: x[0] + tf.cumsum(x[1], axis=1), \n                     name=\"preds\")([p1, p2])\n    \n    model = models.Model(z, preds, name=\"ANN\")\n    #model.compile(loss=qloss, optimizer=\"adam\", metrics=[Laplace_log_Likelihood_score]) #.775\n    model.compile(loss=mloss(0.8), optimizer=tf.keras.optimizers.Adam(lr=0.1, beta_1=0.9, \n                beta_2=0.999, epsilon=None, decay=0.009, amsgrad=False), metrics=[Laplace_log_Likelihood_score])\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"model = make_model()\nprint(model.summary())\nprint(model.count_params())","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"y = train['FVC'].values\nz = train[FE].values\nze = submission[FE].values\npe = np.zeros((ze.shape[0], 3))\npred = np.zeros((z.shape[0], 3))\ndelta = np.zeros((z.shape[0], 3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# kf = KFold(n_splits=NFOLD)\ngkf = GroupKFold(n_splits=NFOLD) \nprint(gkf)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"%%time\ntemp_val = []\ntemp_train = []\ncnt = 0\nfor train_idx, val_idx in gkf.split(z, groups=train['Patient']):\n\n\n    cnt += 1\n    print(f\"FOLD {cnt}\")\n    \n    model.fit(z[train_idx], y[train_idx], batch_size=BATCH_SIZE, epochs= EPOCHS, \n            validation_data=(z[val_idx], y[val_idx]), verbose=0) #\n    \n    \n    training   = model.evaluate(z[train_idx], y[train_idx], verbose=0, batch_size=BATCH_SIZE)\n    validation = model.evaluate(z[val_idx], y[val_idx], verbose=0, batch_size=BATCH_SIZE)\n    print('training', training)\n    print('validation', validation)\n    \n    temp_train.append(training)\n    \n    \n    temp_val.append(validation)\n    \n    #print(\"predict val...\")\n    pred[val_idx] = model.predict(z[val_idx], batch_size=BATCH_SIZE, verbose=0)\n    #print(\"predict test...\")\n    pe += model.predict(ze, batch_size=BATCH_SIZE, verbose=0) / NFOLD\n    delta += model.predict(z) / NFOLD","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# Scoring\n\no_clipped = np.maximum(delta[:,2] - delta[:,0], 70)\ndelta = np.minimum(np.abs(delta[:, 1] - y), 1000)\nsqrt = (np.sqrt((2)))\nscore = (-(sqrt * (delta))/(o_clipped)) - tf.math.log(sqrt * o_clipped)\n\nlogL_Score = np.mean(score)\nprint(np.mean(score))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# print(temp_train)\n# print(temp_val)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# sigma_opt mean_absolute_error   sigma_mean  unc_mean \nmean_absolute_error = mean_absolute_error(y, pred[:, 1]) # find  UNC \nunc = pred[:,2] - pred[:, 0]\nunc_mean = np.mean(unc)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# ########### RUN FIRST TIME ONLY ################\nstats = pd.DataFrame()\nindex = 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"data = [[index, logL_Score, mean_absolute_error, unc.mean(), unc.min(),  unc.max(), (unc>=0).mean(), BATCH_SIZE, EPOCHS,  NFOLD,  SEED]]\ncolumns = ['Run Kernal','logL_Score', 'mean_abs_err', 'unc.mean', 'unc.min', 'unc.max',  '(unc>=0).mean','batch_size', 'epochs', 'NFOLD','seed']\nkernal_stats = pd.DataFrame(data, columns=columns)\n# print(\"current kernal state\")\nkernal_stats","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"#temp = pd.read_csv('./kernal.csv')\n# temp = stats.tail(1)\n# temp_1 = temp['Run Kernal']\n# print(temp_1.shape)\n# print(temp_1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"stats = pd.concat([stats, kernal_stats])\nstats.to_csv('kernal.csv', index = False)\nindex+=1\n\n# print('kernal stats of every version')\nstats","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"print('we are using fix seed value always to avoid RANDOMIZATION (NEED TO GET SAME RESULT)')\nprint('Seed value          =',SEED)\nprint('Number of folds     =',BATCH_SIZE)\nprint('Number of epochs    =',EPOCHS)\n\nprint('\\nmean_absolute_error =',mean_absolute_error)\n#print('unc_mean            =',unc_mean)\n\nprint('unc_mean            =',unc.mean())\nprint('unc_min             =',unc.min())\nprint('unc_max             =',unc.max())\nprint('unc_mean            =',(unc>=0).mean())","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"idxs = np.random.randint(0, y.shape[0], 100)\nplt.plot(y[idxs], label=\"ground truth\")\nplt.plot(pred[idxs, 0], label=\"q25\")\nplt.plot(pred[idxs, 1], label=\"q50\")\nplt.plot(pred[idxs, 2], label=\"q75\")\nplt.legend(loc=\"best\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"sns.distplot(unc)\n#plt.(unc)\nplt.title(\"uncertainty in prediction\")\nplt.savefig('sns{}.png'.format(index))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"plt.hist(unc)\nplt.title(\"uncertainty in prediction\")\nplt.savefig('plt{}.png'.format(index))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### PREDICTION","execution_count":null},{"metadata":{"trusted":false},"cell_type":"code","source":"submission.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"submission['FVC1'] = pe[:, 1]\nsubmission['Confidence1'] = pe[:, 2] - pe[:, 0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"subm = submission[['Patient_Week','FVC','Confidence','FVC1','Confidence1']].copy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"subm.loc[~subm.FVC1.isnull()].head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# sigma_opt mean_absolute_error   sigma_mean  unc_mean \nsubm.loc[~subm.FVC1.isnull(),'FVC'] = subm.loc[~subm.FVC1.isnull(),'FVC1']\nif unc_mean<70:\n    subm['Confidence'] = mean_absolute_error\nelse:\n    subm.loc[~subm.FVC1.isnull(),'Confidence'] = subm.loc[~subm.FVC1.isnull(),'Confidence1']","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"subm.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"sns.distplot(subm.FVC)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"sns.distplot(subm.Confidence)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"subm.describe().T","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"otest = pd.read_csv('../input/osic-pulmonary-fibrosis-progression/test.csv')\nfor i in range(len(otest)):\n    subm.loc[subm['Patient_Week']==otest.Patient[i]+'_'+str(otest.Weeks[i]), 'FVC'] = otest.FVC[i]\n    subm.loc[subm['Patient_Week']==otest.Patient[i]+'_'+str(otest.Weeks[i]), 'Confidence'] = 0.1","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"subm[[\"Patient_Week\",\"FVC\",\"Confidence\"]].to_csv(\"submission.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# !pip install jovian --upgrade --quiet\n# jovian.commit(project='osic-new-era')\n# import jovian","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}