{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport imgaug\nimport glob\nimport random\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, roc_curve, roc_auc_score\n\nimport cv2\nimport imgaug as ia\nimport imgaug.augmenters as iaa\n\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e78bf07360e4f15e663abbd09ab34c5a75a47eb4"},"cell_type":"code","source":"sam = pd.read_csv('../input/sample_submission.csv')\nsam['label'].value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b477f6a2ee23c305c240c4110138d7c8b92cb422"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"train_labels = pd.read_csv('../input/train_labels.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"30e7e90773c14c5bbe49fd0230d824b6f5ad18bc"},"cell_type":"code","source":"train_labels.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cb92b5025cc9394c68d06fc8dd71db8509b96e67"},"cell_type":"code","source":"train_label_mapping = {k:v for k,v in zip(train_labels['id'].values,train_labels['label'].values)}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"00c8989183254989b37612bc613c5b5e63cbed70"},"cell_type":"code","source":"train_label_mapping","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1f56ad61e0a601449c159b8494dc0876990a8ac1"},"cell_type":"code","source":"train_imgs_path = glob.glob('../input/train/*.tif') #file paths of all train images\ntest_imgs_path = glob.glob('../input/test/*.tif') #filepaths of all test images","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3477b1fa7cdcaccdaa39c8c6ef8f0d5346d9629a"},"cell_type":"code","source":"train_imgs_path[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b65b3326d8f64577eeed1d57ba1693805404cff8"},"cell_type":"code","source":"test_imgs_path[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"54036cb7fee4a0bfdfa1a8f386b49da4d49d5407"},"cell_type":"code","source":"print(\"train_img size :\",len(train_imgs_path))\nprint(\"test_imgs size :\",len(test_imgs_path))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cc5059ce9543fae7f7c1fe4dd0f66284d66c4f00"},"cell_type":"code","source":"def get_id_from_img_path(img_path):\n    return img_path.split(os.path.sep)[-1].replace('.tif','')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ecbabc060b4aab6072be570e280f10b3d8293359"},"cell_type":"code","source":"train_imgs_path = train_imgs_path[:80000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"305669bfea35ed239710290faeaff947aa723651"},"cell_type":"code","source":"train,test = train_test_split(train_imgs_path, test_size = 0.2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d98bfdf76fd10310b78e24a4f946d7e795dc51ba"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c6df935e66c87f2b7e6a29ede3ef2b1cd332b789"},"cell_type":"code","source":"def get_label(df):\n    \n    y = []\n    for path in df:\n        img_id = get_id_from_img_path(path)\n        y.append(train_label_mapping[img_id])\n    return y","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f2e7690ace013992dbaa4cd797cdbddd5cb0c956"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a6c76a848a9ade05dc0e83f5adade30eda8f04bc"},"cell_type":"code","source":"y_train = get_label(train)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1a475f096cc75613b7d48127d594d1c63fe84e78"},"cell_type":"code","source":"y_train = y_train[:50000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e3501a482f5b90a94298e6bc59c100be41d75377"},"cell_type":"code","source":"y_test = get_label(test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a853918125b1755925ccfa856bd24a0a868e8386"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b1e4042e51e1f4ca1c7deea6700944a256bddfd3"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ab44e974d036de4d9c30c512a3afcd436661a734"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"393d5a6edb456f1d8a9f23de4f6279c61044daba"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0c70e9754a5c51861cb03a1313ccc5dd3e2d0263"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"00ad5b6730ae1e20f3a9c31c66de57dd19f99d78"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"af0a51ed7e824b0c33f8b11ae1357e5d1df87223"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cf6b9e8b5b2928f4ea6d7bba8eb852d0374d0697"},"cell_type":"code","source":"ia.seed(1)\n\n# Sometimes(0.5, ...) applies the given augmenter in 50% of all cases,\n# e.g. Sometimes(0.5, GaussianBlur(0.3)) would blur roughly every second\n# image.\nsometimes = lambda aug: iaa.Sometimes(0.5, aug)\ndef get_seq():\n    # Define our sequence of augmentation steps that will be applied to every image.\n    seq = iaa.Sequential([\n        iaa.Fliplr(0.5), #horizontally flip 50% images\n        iaa.Flipud(0.2), #vertically flip 20% images\n        \n        # crop some of the images by 0-10% of their height/width\n        sometimes(iaa.Crop(percent=(0,0.1))),\n        \n        # Apply affine transformations to some of the images\n        # - scale to 80-120% of image height/width (each axis independently)\n        # - translate by -20 to +20 relative to height/width (per axis)\n        # - rotate by -45 to +45 degrees\n        # - shear by -16 to +16 degrees\n        # - order: use nearest neighbour or bilinear interpolation (fast)\n        # - mode: use any available mode to fill newly created pixels\n        #         see API or scikit-image for which modes are available\n        # - cval: if the mode is constant, then use a random brightness\n        #         for the newly created pixels (e.g. sometimes black,\n        #         sometimes white)\n        sometimes(iaa.Affine(\n            scale = {\"x\":(0.8,1.2), \"y\":(0.8,1.2)},\n            translate_percent = {\"x\":(-0.2,0.2), \"y\":(-0.2,0.2)},\n            rotate = (-45,45),\n            shear = (-16,16),\n            order = [0,1],\n            cval = (0,255),\n            mode = ia.ALL\n        )),\n        \n        #\n        # Execute 0 to 5 of the following (less important) augmenters per\n        # image. Don't execute all of them, as that would often be way too\n        # strong.\n        #\n        iaa.SomeOf((0,5),\n                   [\n                       # Convert some images into their superpixel representation,\n                       # sample between 20 and 200 superpixels per image, but do\n                       # not replace all superpixels with their average, only\n                       # some of them (p_replace).\n                       sometimes(\n                           iaa.Superpixels(\n                           p_replace = (0, 1.0),\n                           n_segments = (20, 200)\n                           )\n                       ),\n                       \n                       # Blur each image with varying strength using\n                       # gaussian blur (sigma between 0 and 3.0),\n                       # average/uniform blur (kernel size between 2x2 and 7x7)\n                       # median blur (kernel size between 3x3 and 11x11).\n                       iaa.OneOf([\n                           iaa.GaussianBlur((0,3.0)),\n                           iaa.AverageBlur(k=(2,6)),\n                           iaa.MedianBlur(k=(3,7))\n                       ]),\n                       \n                       # Sharpen each image, overlay the result with the original\n                       # image using an alpha between 0 (no sharpening) and 1\n                       # (full sharpening effect).\n                       iaa.Sharpen(alpha=(0,1.0), lightness = (0.75, 1.5)),\n                       \n                       # Same as sharpen, but for an embossing effect.\n                       iaa.Emboss(alpha=(0,1.0), strength=(0,2.0)),\n                       \n                       # Search in some images either for all edges or for\n                       # directed edges. These edges are then marked in a black\n                       # and white image and overlayed with the original image\n                       # using an alpha of 0 to 0.7.\n                       sometimes(iaa.OneOf([\n                           iaa.EdgeDetect(alpha = (0,0.7)),\n                           iaa.DirectedEdgeDetect(alpha=(0,0.7), direction=(0.0,1.0))\n                       ])),\n                       \n                       # Add gaussian noise to some images.\n                       # In 50% of these cases, the noise is randomly sampled per\n                       # channel and pixel.\n                       # In the other 50% of all cases it is sampled once per\n                       # pixel (i.e. brightness change).\n                       iaa.AdditiveGaussianNoise(loc=0,scale=(0.0,0.05*255),per_channel=0.5),\n\n                       # Either drop randomly 1 to 10% of all pixels (i.e. set\n                       # them to black) or drop them on an image with 2-5% percent\n                       # of the original size, leading to large dropped\n                       # rectangles.\n                       iaa.OneOf([\n                           iaa.Dropout((0.01, 0.1),per_channel=0.5),\n                           iaa.CoarseDropout((0.03,0.15),size_percent=(0.02,0.05), per_channel=0.2)\n                       ]),\n                       \n                       # Invert each image's chanell with 5% probability.\n                       # This sets each pixel value v to 255-v.\n                       iaa.Invert(0.05, per_channel=True), #Invert colour channels\n                       \n                       # Add a value of -10 to 10 to each pixel.\n                       iaa.Add((-10,10), per_channel=0.5),\n                       \n                       # Change brightness of images (50-150% of original value).\n                       iaa.Multiply((0.5,1.5), per_channel=0.5),\n                       \n                       # Improve or worsen the contrast of images.\n                       iaa.ContrastNormalization((0.5,2.0),per_channel=0.5),\n                       \n                       # Convert each image to grayscale and then overlay the\n                       # result with the original with random alpha. I.e. remove\n                       # colors with varying strengths.\n                       iaa.Grayscale(alpha=(0.0,1.0)),\n                       \n                       # In some images move pixels locally around (with random\n                       # strengths).\n                       sometimes(iaa.ElasticTransformation(alpha=(0.5,3.5),sigma=0.25)),\n                       \n                       # In some images distort local areas with varying strength.\n                       sometimes(iaa.PiecewiseAffine(scale=(0.01,0.05)))\n                   ],\n                   #do all the above augmentations in random order\n                   random_order = True\n                  )\n            ],\n            random_order = True\n        )\n    return seq    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b57d36eb4eee3e9748e2654efa5bef123147dcd5"},"cell_type":"code","source":"def get_batch(data, batch_size):\n    return (data[i:i+batch_size] for i in range(0, len(data), batch_size))    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"af42f57be65ba1a2a72b5f3dae12965820b518e6"},"cell_type":"code","source":"seq = get_seq() ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6ba271d86f5729171d80412dfa645c7681cd25f4"},"cell_type":"code","source":"train_imgs = [cv2.imread(img_path) for img_path in train]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"904da7f210513a0143de2e3c6ae19c1d77f2cf60"},"cell_type":"code","source":"test_imgs = [cv2.imread(img_path) for img_path in test]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8690d97b4fe62399df3e828eb438a56c5ecce998"},"cell_type":"code","source":"test_imgs = np.array(test_imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"72e961867628b9796dce048ff329a41c936dda27"},"cell_type":"code","source":"np.array(train_imgs).shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f2395ffd5c42db33bb23504fb917f271c025b884"},"cell_type":"code","source":"np.array(test_imgs).shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"81c8f860bdc46ccfe26eca56a14e2a1d623ace17"},"cell_type":"code","source":"train_imgs = train_imgs[:50000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"149e37e339faf126e585e67012f413fe48f05718"},"cell_type":"code","source":"train_imgs = np.array(train_imgs)\ntest_imgs = np.array(test_imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"aa6f42dc7cd933c5d751989f1a2521ccc2de6a4a"},"cell_type":"code","source":"train_imgs = seq.augment_images(train_imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c6f1cb46949316128d8d551cf146909bf6d4d1ca"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d502a955c1daab00e5d5b92807d22c2fe598fe91"},"cell_type":"code","source":"# def data_aug(img_data,train_label_mapping,batch_size,augment = False):\n#     seq = get_seq()\n#     while True:\n#         random.shuffle(img_data)\n#         for batch in get_batch(img_data,batch_size):\n#             X = [cv2.imread(img_path) for img_path in batch]\n#             y = [train_label_mapping[get_id_from_img_path(img_path)] for img_path in batch]\n            \n#             if augment:\n#                 X = seq.augment_images(X)\n    \n#             yield np.array(X), np.array(y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f10463c6a3e815883e56df7107f6473b0a6fc36c"},"cell_type":"code","source":"from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D, GlobalMaxPooling2D\nfrom keras.layers import Dropout, Flatten, Dense\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom keras.models import Sequential\nfrom tensorflow import set_random_seed","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5d5ed10d80c891e0df405edc89f8458f4a589e3b"},"cell_type":"code","source":"set_random_seed(42)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e4baeef8993a7ff1c0b96c503f4c8eeac5191bfa"},"cell_type":"code","source":"model = Sequential()\nmodel.add(Conv2D(filters = 16, kernel_size = 3, padding = 'same', activation = 'relu', input_shape = (96, 96, 3)))\nmodel.add(Conv2D(filters = 16, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Conv2D(filters = 16, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Dropout(0.3))\nmodel.add(MaxPooling2D(pool_size = 3)) \n\nmodel.add(Conv2D(filters = 32, kernel_size = 3, padding = 'same', activation = 'relu')) \nmodel.add(Conv2D(filters = 32, kernel_size = 3, padding = 'same', activation = 'relu')) \nmodel.add(Conv2D(filters = 32, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Dropout(0.5))\nmodel.add(MaxPooling2D(pool_size = 3)) \n\nmodel.add(Conv2D(filters = 64, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Conv2D(filters = 64, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Conv2D(filters = 64, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Dropout(0.5))\nmodel.add(MaxPooling2D(pool_size = 3))\n\nmodel.add(Conv2D(filters = 128, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Conv2D(filters = 128, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Conv2D(filters = 256, kernel_size = 3, padding = 'same', activation = 'relu'))\nmodel.add(Dropout(0.5))\nmodel.add(MaxPooling2D(pool_size = 3))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9cd0c34008233f16ad1c690be98db0f1dbc93037"},"cell_type":"code","source":"model.add(Flatten())\nmodel.add(Dense(1, activation = 'sigmoid'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ecb9a75168f7c1c5777bfcde4900ca26cf788df5"},"cell_type":"code","source":"model.compile(optimizer= 'adam', loss='binary_crossentropy', metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0c281fbc23fef3d6111ea2f1b17b2f38b0933f9f"},"cell_type":"code","source":"batch_size = 128\nmodel.fit(train_imgs,np.array(y_train), batch_size = batch_size,epochs=16)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"061379d3a816d1761fef01928323a8213a2f1697"},"cell_type":"code","source":"train_imgs, y_train = next(g)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8a2bad65aeb7bc2ceda1ca2154210354606ca28b"},"cell_type":"code","source":"pred = (model.predict(test_imgs).ravel()*model.predict(test_imgs[:,::-1,:,:]).ravel()*model.predict(test_imgs[:,:,::-1,:]).ravel()*model.predict(test_imgs[:,::-1,::-1,:]).ravel())**0.25","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f5d90320c2b12b7ad245c7bf8d9e9f9eb0c95a6a"},"cell_type":"code","source":"pred","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f06249c596e513b6862ba036bc3bff69dc178556"},"cell_type":"code","source":"roc_auc_score(np.array(y_test),pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5c29827af5fe554398cd4ab8631c55319b56885c"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7a1e20e922115e37f7b4dcca113e010a23a2e164"},"cell_type":"code","source":"for i in range(len(pred)):\n    if pred[i] < 0.5:\n        pred[i] = 0\n    else:\n        pred[i] = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fbd45c300430294015399edf69b5021aa83726ea"},"cell_type":"code","source":"pred","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a7e8486c108d549899dd79f9cb52ccea194eb8e8"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a48b6f183554704619404cf62bbc66b0e9c13eb7"},"cell_type":"code","source":"test_img = [cv2.imread(imgpath) for imgpath in test_imgs_path]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"dd323d8329b16b23dc5cb19f62f49f9d69fe124e"},"cell_type":"code","source":"test_img = np.array(test_img)\ntest_img.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c10609f7dd744289a37067b557d9740af4f3626d"},"cell_type":"code","source":"preds = (model.predict(test_img).ravel()*model.predict(test_img[:,::-1,:,:]).ravel()*model.predict(test_img[:,:,::-1,:]).ravel()*model.predict(test_img[:,::-1,::-1,:]).ravel())**0.25","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"20abcd7d0ba98999effc8ee5d731e64aaa231233"},"cell_type":"code","source":"preds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"76c30c50efed6a16c38ffad01b93e46126e2e181"},"cell_type":"code","source":"# for i in range(len(preds)):\n#     if preds[i] < 0.5:\n#         preds[i] = 0\n#     else:\n#         preds[i] = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"63e2960fb0ff765d3d5baef7d69033893af44996"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3cf21c6e0467e9c36a6aa3dc38a0247d0a52924e"},"cell_type":"code","source":"test_imgs_path[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e3c4a14a1aa11fff5c01876e7813f434235cc7c2"},"cell_type":"code","source":"id = []\nfor path in test_imgs_path:\n    id.append(get_id_from_img_path(path))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8eab511eebc63839b1f80cd74a8e76ce96efd592"},"cell_type":"code","source":"df = pd.DataFrame({'id':id,'label':preds})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cdc6911a1147587ccc0ff9ac491d88626c3bd007"},"cell_type":"code","source":"df.to_csv(\"sub1.csv\",index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a7c9ccebbbf018d60464fc74ffad2493f5ad9db6"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}