{"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":"**The goal of this competition is to classify the blood clot origins in ischemic stroke.**","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.execute_input":"2022-09-11T06:20:58.668466Z","iopub.status.busy":"2022-09-11T06:20:58.668027Z","iopub.status.idle":"2022-09-11T06:20:59.817085Z","shell.execute_reply":"2022-09-11T06:20:59.815966Z"},"papermill":{"duration":1.161212,"end_time":"2022-09-11T06:20:59.820012","exception":false,"start_time":"2022-09-11T06:20:58.6588","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"**This is my first competiton in kaggle and english is not my natural language. So if there are some grammar errors or misuse of words, please comment.**","metadata":{}},{"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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n#import seaborn as sns\nimport os, sys, random, gc\nimport matplotlib.pyplot as plt\nimport matplotlib as matp\nimport matplotlib.gridspec as gridspec \n#import cv2, math, shutil # OpenCV => cv2\nfrom sklearn.model_selection import train_test_split\nfrom zipfile import ZipFile\n#from torch.utils.data import Dataset, DataLoader\nfrom sklearn.metrics import roc_auc_score\nfrom tqdm.notebook import tqdm \n#from transformers import get_cosine_schedule_with_warmup # 스케줄러\nfrom PIL import Image\nImage.MAX_IMAGE_PIXELS=None\n%matplotlib inline\nimport warnings\nwarnings.simplefilter(action='ignore', category=FutureWarning)\n\n                      \n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, GlobalMaxPooling2D\nfrom tensorflow.keras.callbacks import LearningRateScheduler, EarlyStopping, Callback","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:20:59.833943Z","iopub.status.busy":"2022-09-11T06:20:59.833144Z","iopub.status.idle":"2022-09-11T06:21:06.074351Z","shell.execute_reply":"2022-09-11T06:21:06.073438Z"},"papermill":{"duration":6.25077,"end_time":"2022-09-11T06:21:06.076929","exception":false,"start_time":"2022-09-11T06:20:59.826159","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Yeah, read csv!**","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv('../input/mayo-clinic-strip-ai/train.csv')\ntest = pd.read_csv('../input/mayo-clinic-strip-ai/test.csv')\n","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.090913Z","iopub.status.busy":"2022-09-11T06:21:06.089779Z","iopub.status.idle":"2022-09-11T06:21:06.111888Z","shell.execute_reply":"2022-09-11T06:21:06.110848Z"},"papermill":{"duration":0.03137,"end_time":"2022-09-11T06:21:06.114412","exception":false,"start_time":"2022-09-11T06:21:06.083042","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"target\"] = train[\"label\"].apply(lambda x : 1 if x==\"CE\" else 0)\ntrain.head()","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.128124Z","iopub.status.busy":"2022-09-11T06:21:06.127551Z","iopub.status.idle":"2022-09-11T06:21:06.153705Z","shell.execute_reply":"2022-09-11T06:21:06.152619Z"},"papermill":{"duration":0.03584,"end_time":"2022-09-11T06:21:06.156322","exception":false,"start_time":"2022-09-11T06:21:06.120482","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I can not open image file because they are too big.\n\nI solved it refer to link.\n\nUsing rasterio and Garbage collector.\n\nI just plus directory code through labels. I set LAA=0, CE=1, {top_directory} - [{0}-{LAA images}], [{1}-{CE images}]","metadata":{}},{"cell_type":"code","source":"import rasterio\nfrom rasterio.enums import Resampling\nfrom rasterio.transform import Affine\n\ntrain_data_path = '../input/mayo-clinic-strip-ai/train'\ntrain_img_ids = train['image_id']\nimage_scalar = 512\n\n\n\ndef train_convert_512_img(train_ids):\n    for img_id in tqdm(train_img_ids):\n        try:\n            img_path = f'{train_data_path}/{img_id}.tif'\n            image = rasterio.open(img_path)\n            image = image.read(out_shape=(image.count, int(image_scalar), int(image_scalar)),\n                             resampling=Resampling.bilinear)\n            label = train[train['image_id']==img_id]['label'].iloc[0]\n            if label == 'CE':\n                with rasterio.open(f'./convert_train_512/1/{img_id}.png', 'w', driver='png', height = image.shape[1], width = image.shape[2], dtype = image.dtype, count=3) as images: # count => Image Channel 개수 (RGB의 경우 3개)\n                    images.write(image)\n                #image.save(f'./convert_train/{img_id}.png', 'png')\n                # Image 용량이 너무 커서 Ram 커널 반복적으로 죽는 상황 발생 => @JIRKA BOROVEC님 코드 참조 => Garbage Collection 활용, 누수되는 Ram Memory 활용\n                    del image\n                    gc.collect()\n            elif label == 'LAA':\n                with rasterio.open(f'./convert_train_512/0/{img_id}.png', 'w', driver='png', height = image.shape[1], width = image.shape[2], dtype = image.dtype, count=3) as images: # count => Image Channel 개수 (RGB의 경우 3개)\n                    images.write(image)\n                #image.save(f'./convert_train/{img_id}.png', 'png')\n                # Image 용량이 너무 커서 Ram 커널 반복적으로 죽는 상황 발생 => @JIRKA BOROVEC님 코드 참조 => Garbage Collection 활용, 누수되는 Ram Memory 활용\n                    del image\n                    gc.collect()\n\n        except OSError as e:\n            print(e)","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.189375Z","iopub.status.busy":"2022-09-11T06:21:06.188437Z","iopub.status.idle":"2022-09-11T06:21:06.461943Z","shell.execute_reply":"2022-09-11T06:21:06.460802Z"},"papermill":{"duration":0.283516,"end_time":"2022-09-11T06:21:06.464819","exception":false,"start_time":"2022-09-11T06:21:06.181303","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"First, I used my resized images(512x512). \n\nBut i found seam-carving dataset(I can not use seam-carving in my notebook, so i just downloaded in dataset).","metadata":{}},{"cell_type":"code","source":"# train_convert_512_img(train['image_id'])","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.479259Z","iopub.status.busy":"2022-09-11T06:21:06.478865Z","iopub.status.idle":"2022-09-11T06:21:06.48331Z","shell.execute_reply":"2022-09-11T06:21:06.482562Z"},"papermill":{"duration":0.013771,"end_time":"2022-09-11T06:21:06.485376","exception":false,"start_time":"2022-09-11T06:21:06.471605","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!zip -r convert_train_512.zip ./*","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.499886Z","iopub.status.busy":"2022-09-11T06:21:06.49912Z","iopub.status.idle":"2022-09-11T06:21:06.503562Z","shell.execute_reply":"2022-09-11T06:21:06.502504Z"},"papermill":{"duration":0.014159,"end_time":"2022-09-11T06:21:06.505714","exception":false,"start_time":"2022-09-11T06:21:06.491555","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As i said, i can not use seam-carving in my notebook. \n\nTest Images are not resized using seam-carving. \n\nIf you use seam-carving in test set, i think model will predict better.**","metadata":{}},{"cell_type":"code","source":"test_data_path = '/kaggle/input/mayo-clinic-strip-ai'\ntest_img_ids = test['image_id']\nimage_scalar = 512\ndef test_convert_512_img(test_img_ids):\n    for img_id in tqdm(test_img_ids):\n        try:\n            img_path = f'{test_data_path}/test/{img_id}.tif'\n            image = rasterio.open(img_path)\n            image = image.read(out_shape=(image.count, int(image_scalar), int(image_scalar)),\n                             resampling=Resampling.bilinear)\n            with rasterio.open(f'./convert_test_512/test/{img_id}.png', 'w', driver='png', height = image.shape[1], width = image.shape[2], dtype = image.dtype, count=3) as images: # count => Image Channel 개수 (RGB의 경우 3개)\n                images.write(image)\n            #image.save(f'./convert_train/{img_id}.png', 'png')\n            # Image 용량이 너무 커서 Ram 커널 반복적으로 죽는 상황 발생 => @JIRKA BOROVEC님 코드 참조 => Garbage Collection 활용, 누수되는 Ram Memory 활용\n            del image\n            gc.collect()\n\n        except OSError as e:\n            print(e)","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.519784Z","iopub.status.busy":"2022-09-11T06:21:06.51909Z","iopub.status.idle":"2022-09-11T06:21:06.527864Z","shell.execute_reply":"2022-09-11T06:21:06.527064Z"},"papermill":{"duration":0.017938,"end_time":"2022-09-11T06:21:06.529764","exception":false,"start_time":"2022-09-11T06:21:06.511826","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.makedirs('convert_test_512', exist_ok=True)\nos.makedirs('convert_test_512/test', exist_ok=True)","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.544235Z","iopub.status.busy":"2022-09-11T06:21:06.543493Z","iopub.status.idle":"2022-09-11T06:21:06.548597Z","shell.execute_reply":"2022-09-11T06:21:06.547603Z"},"papermill":{"duration":0.014943,"end_time":"2022-09-11T06:21:06.550911","exception":false,"start_time":"2022-09-11T06:21:06.535968","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Resizing...**","metadata":{}},{"cell_type":"code","source":"test_convert_512_img(test['image_id'])","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:21:06.564687Z","iopub.status.busy":"2022-09-11T06:21:06.564255Z","iopub.status.idle":"2022-09-11T06:22:43.660366Z","shell.execute_reply":"2022-09-11T06:22:43.659335Z"},"papermill":{"duration":97.111823,"end_time":"2022-09-11T06:22:43.668858","exception":false,"start_time":"2022-09-11T06:21:06.557035","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Flow_from_directory is gorgeous. Just input my directory, it does everything i want.\n\nTrain_gen form 80% of sc_train directory. Vaild_gen from 20% of that.\n\nI skiiped EDA, but we know 73% CE(547 files) and 27%(207 files) LAA imbalanced. So i added LAA datas on local.\n\nFinally, there are CE(547) + LAA(207*3 = 621) = 1168 image files in my dataset.\nI know upscaling less data is not pretty good for my model but i just do it :) (As a general rule, use class_weight)\n\n\n**My dataset link** : https://www.kaggle.com/datasets/limseonggeun/scaug","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport tensorflow as tf\nimport math\nfrom tensorflow.keras.callbacks import LearningRateScheduler, EarlyStopping, Callback\n\n\nfrom keras.preprocessing.image import ImageDataGenerator\ntrain_datagen = ImageDataGenerator(rescale = 1./255,\n                                    validation_split=0.2,\n                                   rotation_range=30,\n                                    horizontal_flip=True                            \n                                    )\n\ntrain_gen = train_datagen.flow_from_directory('../input/scaug/sc_train',\n                                                 target_size = (512, 512),\n                                                 batch_size = 32,\n                                                 class_mode = 'binary',subset='training')\nval_gen  = train_datagen.flow_from_directory('../input/scaug/sc_train',\n                                                 target_size = (512, 512),\n                                                 batch_size = 32,\n                                                 class_mode = 'binary',subset='validation')\n\n","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:22:43.683662Z","iopub.status.busy":"2022-09-11T06:22:43.683035Z","iopub.status.idle":"2022-09-11T06:22:43.904575Z","shell.execute_reply":"2022-09-11T06:22:43.903049Z"},"papermill":{"duration":0.231754,"end_time":"2022-09-11T06:22:43.907078","exception":false,"start_time":"2022-09-11T06:22:43.675324","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"CE(547) : LAA(621) is about 1:1, so i do not use class_weight.\n\nI changed my models about hundreds times, but it is my best score model.\n\nCE, LAA => Binary Image Classification => Use 'sigmoid' in last layer. loss='binary_crossentropy'\n\n935 images are very few for model. I read articles in stackoverflow few data and big model must overfits. And image rarely use maxpooling(right? comment \nplz)\n\nSo i do not use maxpool and make my model small.","metadata":{}},{"cell_type":"code","source":"class_weight = {0: 1,\n                1: 1}\n\ndef step_decay(epoch):\n    initial_lrate = 0.001\n    drop = 0.5\n    epochs_drop = 10.0\n    lrate = initial_lrate * math.pow(drop, math.floor((epoch)/epochs_drop))\n    return lrate\n\nlrate = LearningRateScheduler(step_decay)\nearstop = EarlyStopping(monitor = 'val_loss', min_delta = 0, patience = 5)\n\n# Initialising the CNN\ncnn = tf.keras.models.Sequential()\n\n\ncnn.add(tf.keras.layers.Conv2D(filters=16, kernel_size=3, strides=2, activation='relu', input_shape=[512, 512, 3]))\ncnn.add(tf.keras.layers.Conv2D(filters=32, kernel_size=3, strides=2, activation='relu'))\ncnn.add(tf.keras.layers.Conv2D(filters=32, kernel_size=3, strides=2, activation='relu'))\n#cnn.add(tf.keras.layers.BatchNormalization())\ncnn.add(tf.keras.layers.Dropout(0.5))\n#cnn.add(tf.keras.layers.Dense(32, activation='relu'))\n\ncnn.add(tf.keras.layers.Conv2D(filters=16, kernel_size=3, strides=2, activation='relu'))\ncnn.add(tf.keras.layers.Conv2D(filters=32, kernel_size=3, strides=2, activation='relu'))\ncnn.add(tf.keras.layers.Dropout(0.5))\n\n#cnn.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))\n\ncnn.add(tf.keras.layers.Flatten())\ncnn.add(tf.keras.layers.Dense(16, activation='relu'))\n\ncnn.add(tf.keras.layers.Dense(units=1, activation='sigmoid', kernel_regularizer=tf.keras.regularizers.l2(0.1)))\n\ncnn.compile(optimizer = 'adam', \n            loss = 'binary_crossentropy', \n            metrics = ['accuracy'])\ncnn.summary()","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:22:43.922808Z","iopub.status.busy":"2022-09-11T06:22:43.921956Z","iopub.status.idle":"2022-09-11T06:22:44.119576Z","shell.execute_reply":"2022-09-11T06:22:44.117617Z"},"papermill":{"duration":0.208348,"end_time":"2022-09-11T06:22:44.122405","exception":false,"start_time":"2022-09-11T06:22:43.914057","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = cnn.fit(x = train_gen, validation_data = val_gen, epochs = 100, callbacks=[lrate,earstop])#, class_weight=class_weight)","metadata":{"execution":{"iopub.execute_input":"2022-09-11T06:22:44.136373Z","iopub.status.busy":"2022-09-11T06:22:44.135998Z","iopub.status.idle":"2022-09-11T07:35:20.888705Z","shell.execute_reply":"2022-09-11T07:35:20.886291Z"},"papermill":{"duration":4356.828957,"end_time":"2022-09-11T07:35:20.957537","exception":false,"start_time":"2022-09-11T06:22:44.12858","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnn.save(\"my_model\")","metadata":{"execution":{"iopub.execute_input":"2022-09-11T07:35:21.102745Z","iopub.status.busy":"2022-09-11T07:35:21.10166Z","iopub.status.idle":"2022-09-11T07:36:06.338366Z","shell.execute_reply":"2022-09-11T07:36:06.337355Z"},"papermill":{"duration":45.312525,"end_time":"2022-09-11T07:36:06.34116","exception":false,"start_time":"2022-09-11T07:35:21.028635","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.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='upper left')\nplt.show()","metadata":{"execution":{"iopub.execute_input":"2022-09-11T07:36:06.484315Z","iopub.status.busy":"2022-09-11T07:36:06.483929Z","iopub.status.idle":"2022-09-11T07:36:06.757319Z","shell.execute_reply":"2022-09-11T07:36:06.756369Z"},"papermill":{"duration":0.347949,"end_time":"2022-09-11T07:36:06.759754","exception":false,"start_time":"2022-09-11T07:36:06.411805","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.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 left')\nplt.show()","metadata":{"execution":{"iopub.execute_input":"2022-09-11T07:36:06.905737Z","iopub.status.busy":"2022-09-11T07:36:06.904757Z","iopub.status.idle":"2022-09-11T07:36:07.123747Z","shell.execute_reply":"2022-09-11T07:36:07.122887Z"},"papermill":{"duration":0.294141,"end_time":"2022-09-11T07:36:07.125882","exception":false,"start_time":"2022-09-11T07:36:06.831741","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**I can see acc and loss goes pretty good but loss not decrease under 0.6. Underfitting.\n\nFor solving underfitting: Train more data(Data augmentation), bigger model, use seam-carving for testset.(my opinion)**","metadata":{}},{"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1/255.)\ntest_flow_gen = test_gen.flow_from_directory(directory='convert_test_512',\n                                            target_size=(512, 512),  # 사용할 CNN 모델 입력 사이즈에 맞게 resize\n                                            class_mode='binary',\n                                            batch_size=32,\n                                            shuffle=False)","metadata":{"execution":{"iopub.execute_input":"2022-09-11T07:36:07.272484Z","iopub.status.busy":"2022-09-11T07:36:07.271771Z","iopub.status.idle":"2022-09-11T07:36:07.381167Z","shell.execute_reply":"2022-09-11T07:36:07.379964Z"},"papermill":{"duration":0.185821,"end_time":"2022-09-11T07:36:07.383501","exception":false,"start_time":"2022-09-11T07:36:07.19768","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnn_pred = cnn.predict(test_flow_gen)\ncnn_pred","metadata":{"execution":{"iopub.execute_input":"2022-09-11T07:36:07.604871Z","iopub.status.busy":"2022-09-11T07:36:07.604487Z","iopub.status.idle":"2022-09-11T07:36:07.902977Z","shell.execute_reply":"2022-09-11T07:36:07.901685Z"},"papermill":{"duration":0.449891,"end_time":"2022-09-11T07:36:07.905376","exception":false,"start_time":"2022-09-11T07:36:07.455485","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub = pd.DataFrame(test[\"patient_id\"].copy())\nsub[\"CE\"] = cnn_pred\nsub[\"CE\"] = sub[\"CE\"].apply(lambda x : 0 if x<0 else x)\nsub[\"CE\"] = sub[\"CE\"].apply(lambda x : 1 if x>1 else x)\nsub[\"LAA\"] = 1- sub[\"CE\"]\n\nsub = sub.groupby(\"patient_id\").mean()\nsub = sub[[\"CE\", \"LAA\"]].round(6).reset_index()\nsub","metadata":{"execution":{"iopub.execute_input":"2022-09-11T07:36:08.050741Z","iopub.status.busy":"2022-09-11T07:36:08.050319Z","iopub.status.idle":"2022-09-11T07:36:08.092402Z","shell.execute_reply":"2022-09-11T07:36:08.091615Z"},"papermill":{"duration":0.117636,"end_time":"2022-09-11T07:36:08.094463","exception":false,"start_time":"2022-09-11T07:36:07.976827","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv(\"submission.csv\", index = False)\n!head submission.csv","metadata":{"execution":{"iopub.execute_input":"2022-09-11T07:36:08.241697Z","iopub.status.busy":"2022-09-11T07:36:08.240589Z","iopub.status.idle":"2022-09-11T07:36:09.447314Z","shell.execute_reply":"2022-09-11T07:36:09.446089Z"},"papermill":{"duration":1.283171,"end_time":"2022-09-11T07:36:09.449971","exception":false,"start_time":"2022-09-11T07:36:08.1668","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"It scored 0.6 in public.","metadata":{}},{"cell_type":"markdown","source":"I can learn from many codes in kaggle. Thank you.\nhttps://www.kaggle.com/code/jonathanma02/cnn-blood-clot-origin-classifier\n\nhttps://www.kaggle.com/code/qcqced/strip-ai-eda-data-preprocessing-1k-png\n\nhttps://www.kaggle.com/code/rishavnandi/mayo-clinic\n\nhttps://www.kaggle.com/code/kirderf/mayo-inference-memory-and-gpu-quota-efficient\n\nhttps://www.kaggle.com/datasets/kalelpark/mayo-seam512 <- non-aug original seam-carving data\n","metadata":{}}]}