{"cells":[{"metadata":{"id":"QJW4nPqdFulM"},"cell_type":"markdown","source":"Hi,as we are known that Yolo v5 is out of the competition.But V5 did work.As the [discussion](https://www.kaggle.com/search) mention:\n\n    First --> It is doing gradient accumulation by default to a batch size of 64\n    second --> It is also giving mixed precision training(fp16) by default if we have apex installed\n    \n    \nSo let change it to EfficientDet.May be work :))  Hope the notebook will be helpful for someone. please feel free to upvote","execution_count":null},{"metadata":{"id":"PpaluOiwFulO"},"cell_type":"markdown","source":"This notebook is base on the [Alex's job](https://www.kaggle.com/shonenkov/training-efficientdet)","execution_count":null},{"metadata":{"id":"U3vnOnYAFulP","outputId":"e462eec7-1258-446b-e7a8-b29c585eb5b1","trusted":true},"cell_type":"code","source":"#!pip install --upgrade pip","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_kg_hide-input":true,"_kg_hide-output":true,"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","id":"yUZN9vqEFulf","outputId":"820e3825-1b98-4d68-b1b4-df1982a8dfd8","trusted":true},"cell_type":"code","source":"#!pip install --no-deps '../input/timm-package/timm-0.1.26-py3-none-any.whl' > /dev/null\n#!pip install --no-deps '../input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl' > /dev/null\n#!kaggle kernels pull reighns/augmentations-data-cleaning-and-bounding-boxes https://www.kaggle.com/reighns/augmentations-data-cleaning-and-bounding-boxes\n#!kaggle kernels pull ravi02516/cleaning-and-preprocessing-train-csv https://www.kaggle.com/ravi02516/cleaning-and-preprocessing-train-csv\n#!kaggle kernels pull raininbox/check-clean-big-small-bboxes https://www.kaggle.com/raininbox/check-clean-big-small-bboxes\n#!wget https://github.com/DhruvMakwana/Global-Wheat-Detection/blob/master/Global_Wheat_Detection_EDA.ipynb\n#!wget https://github.com/Kaushal28/Global-Wheat-Detection/blob/master/EfficientDet-5-fold-CV/gwd-efficientdet-training-fold4.ipynb\n\n#!kaggle datasets download -d shonenkov/omegaconf\n#!kaggle datasets download -d kaushal2896/pycocotools\n#!wget https://github.com/rwightman/efficientdet-pytorch/releases/download/v0.1/tf_efficientdet_d5-ef44aea8.pth\n#!pip install kaggle --force\n#!mkdir -p ~/.kaggle\n#!cp kaggle.json ~/.kaggle/\n#!kaggle competitions download -c global-wheat-detection -p ./data/\n#!mkdir ./data/\n#!mkdir ./data/train_images\n#!git clone https://github.com/NVIDIA/apex\n#!pip install -v --no-cache-dir  ./apex\n#!mv *.jpg ./data/train_images\n#import os\n#!unzip -q ./data/global-wheat-detection.zip -d  ./data/\n#!cp *.csv ./data/\n#!pip install albumentations --force\n#!pip install timm\n#!pip install effdet","execution_count":null,"outputs":[]},{"metadata":{"id":"cdr7Zf23Fulj","trusted":true},"cell_type":"code","source":"#!kaggle datasets download -d shonenkov/timm-efficientdet-pytorch\n#!pip install effdet\n#!pip install omegaconf\n#!kaggle competitions download -c global-wheat-detection -p ./data/\n#!mkdir ./data/\n#!mkdir ./data/train_images\n#!mv *.jpg ./data/train_images\n#import os\n#!unzip -q ./data/global-wheat-detection.zip -d  ./data/\n#!cp train_clean.csv ./data/\n#len(os.listdir('./data/train_images'))\n#!pip install kaggle --force\n#!pip install omegaconf\n#%%writefile setup.sh\n\n'/kaggle/input'","execution_count":null,"outputs":[]},{"metadata":{"id":"kUiWVqMnFulX","trusted":true},"cell_type":"code","source":"apex_on =  True\nif apex_on:\n    #! pip install --no-cache-dir --global-option=\"--cpp_ext\" --global-option=\"--cuda_ext\" ../input/nvidiaapex/.\n    ! pip install  --no-cache-dir ../input/nvidia-apex/ \n#if apex_on:\n#    from apex import amp\n\n!pip install --no-deps '../input/timm-package/timm-0.1.26-py3-none-any.whl' > /dev/null\n!pip install --no-deps '../input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl' > /dev/null","execution_count":null,"outputs":[]},{"metadata":{"id":"O85lU3jLQPMn","trusted":true},"cell_type":"code","source":"!pip install --no-deps '../input/timm-package/timm-0.1.26-py3-none-any.whl' > /dev/null\n!pip install --no-deps '../input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl' > /dev/null","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"id":"LmYw4A4sFulq","trusted":true},"cell_type":"code","source":"import sys\nsys.path.insert(0, \"../input/timm-efficientdet-pytorch\")\nsys.path.insert(0, \"../input/omegaconf\")\nsys.path.insert(0, \"../input/timm\")\nfrom apex import amp\nimport torch\nimport os\nfrom datetime import datetime\nimport time\nimport random\nimport cv2\nimport pandas as pd\nimport numpy as np\nimport albumentations as A\nimport matplotlib.pyplot as plt\nfrom albumentations.pytorch  import ToTensorV2\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom torch.utils.data import Dataset,DataLoader\nfrom torch.utils.data.sampler import SequentialSampler, RandomSampler\nfrom glob import glob\n#from apex import amp\nSEED = 49\n\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n\nseed_everything(SEED)","execution_count":null,"outputs":[]},{"metadata":{"id":"AzRKdm8FFulx"},"cell_type":"markdown","source":"1. mixed_precision:True = using the apex\n2. accumulate: how many batches to make the gradient accumulation e.g batch_size = 2 & accumulate = 16 -> real batch is 2*16 =32","execution_count":null},{"metadata":{"id":"CC0is6mdFulz","outputId":"158d0fd1-082f-4e5f-863b-1e5a9a0fbd90","trusted":true},"cell_type":"code","source":"class TrainGlobalConfig:\n    num_workers = 10\n    batch_size = 14\n    n_epochs = 8 # n_epochs = 40\n    lr =2e-4\n    mixed_precision = True\n    accumulate = 4\n    folder = 'effdet5-cutmix'\n\n    # -------------------\n    verbose = True\n    verbose_step = 1\n    # -------------------\n\n    # --------------------\n    step_scheduler = False  # do scheduler.step after optimizer.step\n    validation_scheduler = True  # do scheduler.step after validation stage loss\n\n    #     SchedulerClass = torch.optim.lr_scheduler.OneCycleLR\n    #     scheduler_params = dict(\n    #         max_lr=0.001,\n    #         epochs=n_epochs,\n    #         steps_per_epoch=int(len(train_dataset) / batch_size),\n    #         pct_start=0.1,\n    #         anneal_strategy='cos',\n    #         final_div_factor=10**5\n    #     )\n\n    SchedulerClass = torch.optim.lr_scheduler.ReduceLROnPlateau\n    scheduler_params = dict(\n        mode='min',\n        factor=0.5,\n        patience=2,\n        verbose=False,\n        threshold=0.0001,\n        threshold_mode='abs',\n        cooldown=0,\n        min_lr=1e-8,\n        eps=1e-08\n    )\nprint('x')","execution_count":null,"outputs":[]},{"metadata":{"id":"iy1pEcJsFul3","trusted":true},"cell_type":"code","source":"clean='Y'\nif clean=='Y':\n    \n    #marking = pd.read_csv('/data/modified_cleaned_data.csv')\n    marking = pd.read_csv('/kaggle/input/clean-data/modified_cleaned_data.csv')\n    marking.drop(columns=['bbox'], inplace=True)\n    marking.columns=['image_id', 'width', 'height', 'source', 'area', 'x','y', 'w', 'h']\nelse:\n    marking = pd.read_csv('../input/global-wheat-detection/train.csv')\n#pd.read_csv('train.csv')\n#('../input/global-wheat-detection/train.csv')\n\n    bboxs = np.stack(marking['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))\n    for i, column in enumerate(['x', 'y', 'w', 'h']):\n        marking[column] = bboxs[:,i]\n    marking.drop(columns=['bbox'], inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"id":"KxKbvjyDFul-","outputId":"4cf79d9c-fb22-492d-a295-dbdb69116632","trusted":true},"cell_type":"code","source":"#bad_boxes = [3687, 117344,173,113947,52868,2159,2169,121633,121634,147504,118211,52727,147552]\nmarking.image_id.unique()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nx_tot=[]\nx2_tot=[]\nunique_list=marking.image_id.unique().tolist()\nfrom  tqdm import tqdm_notebook as tqdm\nfrom PIL import Image as PILImage\nfor name in  tqdm(unique_list) :\n    #print(os.path.join(data_dir,name+'.tiff'))\n    #img = skimage.io.MultiImage(os.path.join(data_dir,name+'.tiff'))[-2]\n                 \n    #img=Image.open(save_dir + img_id+'_'+str(index)+'.png')\n    #mask = skimage.io.MultiImage(os.path.join(MASKS,name+'_mask.tiff'))[-1]\n    #print(name)\n    #img_cnt=slice_cnt_df[slice_cnt_df.image_id==name].count_img.values[0]  \n    #print(img_cnt,name)\n    tiles = PILImage.open('../input/global-wheat-detection/train' +'/'+ name+ '.jpg') \n              \n    img=np.asarray(tiles)\n    x_tot.append((img/255.0).reshape(-1,3).mean(0))#channel wise for each 20 tiles\n    x2_tot.append(((img/255.0)**2).reshape(-1,3).mean(0)) \n     \n''' ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#img_avr =  np.array(x_tot).mean(0)\n#img_std =  np.sqrt(np.array(x2_tot).mean(0) - img_avr**2) #456 stats\n#print('mean:',img_avr, ', std:', np.sqrt(img_std))\n\n#(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225) \n#mean: [0.31463625 0.31740943 0.21443922] , std: [0.49570253 0.48870521 0.44089793]","execution_count":null,"outputs":[]},{"metadata":{"id":"-Zdxw_7cFumH"},"cell_type":"markdown","source":"About data splitting you can read [here](https://www.kaggle.com/shonenkov/wbf-approach-for-ensemble):","execution_count":null},{"metadata":{"_kg_hide-output":true,"id":"FCP1YS0kFumI","trusted":true},"cell_type":"code","source":"skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n\ndf_folds = marking[['image_id']].copy()\n\ndf_folds.loc[:, 'bbox_count'] = 1\n \ndf_folds = df_folds.groupby('image_id').count()\ndf_folds.loc[:, 'source'] = marking[['image_id', 'source']].groupby('image_id').min()['source']\ndf_folds.loc[:, 'stratify_group'] = np.char.add(\n    df_folds['source'].values.astype(str),\n    df_folds['bbox_count'].apply(lambda x: f'_{x // 15}').values.astype(str)\n)\ndf_folds=df_folds.reset_index(level=0)\n#df_folds=df_folds[(df_folds.bbox_count<60)] #take subset\ndf_folds.loc[:, 'fold'] = 0\n\nfor fold_number, (train_index, val_index) in enumerate(skf.split(X=df_folds.index, y=df_folds['stratify_group'])):\n    df_folds.loc[df_folds.iloc[val_index].index, 'fold'] = fold_number","execution_count":null,"outputs":[]},{"metadata":{"id":"XZvh0G_6FumN","outputId":"f17b3923-589c-49df-dedc-347721b3a7eb","trusted":true},"cell_type":"code","source":"\n\n#train_image_ids=df_folds[df_folds!=0].image_id.values.tolist() #train images\n#index.train_image_ids=df_folds[(df_folds!=0)&(df_folds<40)].image_id.values.tolist() #train images\ndf_folds.index.size","execution_count":null,"outputs":[]},{"metadata":{"id":"H1VPX-jTFumP","outputId":"aaa2ada8-d502-4e5a-e368-4184fab0a14b","trusted":true},"cell_type":"code","source":"#df_folds.index.size","execution_count":null,"outputs":[]},{"metadata":{"id":"UhSY6RL6FumU","trusted":true},"cell_type":"code","source":"TRAIN_ROOT_PATH ='../input/global-wheat-detection/train'\nfrom PIL import Image as PILImage, ImageDraw, ImageEnhance\nfrom collections import OrderedDict \ndef group_boxes(group):\n    #print(group)\n    boundaries = group['bbox'].str.split(',', expand=True)\n    #print(boundaries.shape)\n    boundaries[0] = boundaries[0].str.slice(start=1)\n    boundaries[3] = boundaries[3].str.slice(stop=-1)\n    \n    return boundaries.values.astype(float)\n\ndef load_image(image_id):\n    image = PILImage.open('TRAIN_ROOT_PATH/' + image_id + \".jpg\")\n    #image = image.resize((256, 256))\n    \n    return np.asarray(image)\n\ndef draw_bboxes(image_id, bboxes, source='./data/train'):   #'./data/train'\n    #image = PILImage.open('../input/global-wheat-detection/' + source +'/' + image_id + \".jpg\")\n    image = PILImage.open(    TRAIN_ROOT_PATH +'/' + image_id + \".jpg\")\n    #image = image.resize((256,256))\n    \n    draw = ImageDraw.Draw(image)\n            \n    for bbox in bboxes:\n        draw_bbox(draw, bbox)\n    \n    return np.asarray(image)\nimport cv2\n\ndef draw_bbox(draw, bbox):\n    x, y, width, height = bbox\n    draw.rectangle([x, y, x + width, y + height], width=10, outline='red')\ndef show_images(image_ids, bboxes, source='train'):\n    pixels = []\n    i=0\n    for image_id in image_ids:\n        if i==0:\n            \n            #bboxes_list=np.stack(marking[marking.image_id==image_id]['bbox'].apply(lambda x: np.fromstring(x[1:-1], sep=',')))\n            bboxes_list=[np.array(bboxes_list)  for bboxes_list in bboxes]\n            print(bboxes_list)\n        else:\n            #bboxes_list=bboxes[image_id]\n            bboxes_list=[np.array(bboxes_list)  for bboxes_list in bboxes]\n            print(bboxes_list)\n        i=i+1\n        pixels.append(\n            draw_bboxes(image_id, bboxes_list, source)\n        )\n    \n    num_of_images = len(image_ids)\n    print(num_of_images)\n    fig, axes = plt.subplots(\n        1, \n        num_of_images, \n        figsize=(5 * 4, 5 * 4)\n    )\n    \n    for i, image_pixels in enumerate(pixels):\n        axes[0].imshow(image_pixels)\n        image = cv2.imread(    TRAIN_ROOT_PATH +'/' + image_id + \".jpg\")\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)#.astype(np.float32)\n        print(image.shape)\n        #aug=A.IAAEmboss  (p=1)\n        #aug1=A.OneOf([A.IAAEmboss  (p=0.0),A.CLAHE((1.5,4),p=0.8),A.IAASharpen(p=0.4)],p=1)\n        aug1=A.Compose([A.CLAHE((1.5,4),p=0.7),A.IAAEmboss  (p=0.0),A.IAASharpen(p=0.4)],p=0.8)\n        #aug=A.Compose([aug1,A.CLAHE((1.5,4),p=1)],p=1)\n        #aug= A.RandomContrast( limit=(0.2,0.4),p=1) \n        #aug= A.RandomBrightness( limit=(0.2,0.4),p=1) \n        #aug=A.RandomBrightnessContrast(brightness_limit=(0.2,0.3), \n        #                                   contrast_limit=(0.2,0.4), p=1)\n        #aug=A.CLAHE((1.5,4),p=1)\n        #                                   contrast_limit=0.0, p=1)\n        #aug=A.HueSaturationValue(hue_shift_limit=(0.1,0.25), sat_shift_limit= (0.1,0.25), \n        #                             val_shift_limit=(0.1,0.25), p=1)\n        #A.imgaug.transforms.IAAPerspective((0.08,0.15),p=1)\n        #aug=A.OneOf([A.IAAEmboss  (p=0.4),A.IAASharpen(p=0.4)],p=1)\n        #print(aug(image=image).shape)\n        axes[1].imshow(aug1(image=image)['image'])\n        \n        \n        \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"records =marking[marking['image_id'] == '50ee1a4fc']\nbboxes = records[['x', 'y', 'w', 'h']].values","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"bboxes=np.array([[29.5,  0. , 76. , 67. ],[192.  ,  0.,  225.5 , 53.5],[229.  ,  0. , 275. ,  61.5]])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#show_images(['50ee1a4fc','50ee1a4fc'],bboxes)","execution_count":null,"outputs":[]},{"metadata":{"id":"oJwoE0eZFumY","trusted":true},"cell_type":"code","source":"'''\nlabels = pd.read_csv('train.csv')\nlabels = labels.groupby('image_id').apply(group_boxes)\ntrain_pixels = OrderedDict() \ntrain_labels = OrderedDict() \nfrom tqdm import tqdm\nfor image_id in tqdm(train_image_ids):\n    train_pixels[image_id] = load_image(image_id)\n    train_labels[image_id] = labels[image_id].copy() # / 4\n'''","execution_count":null,"outputs":[]},{"metadata":{"id":"D_jup2RqFumd","outputId":"df1cf3fc-9c56-4ed5-eca9-c497bbc70837","trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"id":"obyMRAhVFumh","trusted":true},"cell_type":"code","source":"def clean_labels(train_image_ids, train_labels):\n    good_labels = {}\n    \n    for i, image_id in enumerate(train_image_ids):\n        good_labels[image_id] = []\n        \n        for j, label in enumerate(train_labels[image_id]):\n\n            # remove huge bbox\n            if label[2] * label[3] > 8000 and i not in [1079, 1371, 2020]:\n                continue\n\n            # remove tiny bbox\n            elif label[2] < 5 or label[3] < 5:\n                continue\n                \n            else:\n                good_labels[image_id].append(\n                    train_labels[image_id][j]\n                )\n                \n    return good_labels\n\n#train_labels_cln = clean_labels(train_image_ids, train_labels)","execution_count":null,"outputs":[]},{"metadata":{"id":"QA5qGshOFumn","outputId":"7d526a4b-c343-4e21-dd2b-6c5829d90ae8","trusted":true},"cell_type":"code","source":"#np.array(train_labels_cln['b6ab77fd7']).shape ,marking.head()\nrecords =marking[marking['image_id'] == '005b0d8bb']\nboxes = records[['x', 'y', 'w', 'h']].values\nboxes.shape","execution_count":null,"outputs":[]},{"metadata":{"id":"vNmdb2ezKXtu","outputId":"71e8c115-c788-494e-f630-8ef0fa30720b","trusted":true},"cell_type":"code","source":"#show_images(['005b0d8bb','005b0d8bb'], boxes, source='./data/train')#","execution_count":null,"outputs":[]},{"metadata":{"id":"qm9uC4sQFumt","outputId":"fa2c083f-e513-458d-a26c-9ea9275a7851","trusted":true},"cell_type":"code","source":"#transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]\nboxes[:,2] =np.clip(boxes[:,0]+boxes[:,2],0,1024-1)\nboxes[:,2]","execution_count":null,"outputs":[]},{"metadata":{"id":"yAXMQolaFumw"},"cell_type":"markdown","source":"## Albumentations","execution_count":null},{"metadata":{"id":"Okui6dGVFumw","trusted":true},"cell_type":"code","source":"def get_train_transforms():\n    return A.Compose(\n        [\n            A.RandomSizedCrop(min_max_height=(800, 800), height=1024, width=1024, p=0.5),\n            #A.RandomCrop(768, 768, always_apply=False, p=0.5),#New\n            A.OneOf([\n                A.HueSaturationValue(hue_shift_limit=(0.1,0.2), sat_shift_limit= (0.1,0.2), \n                                     val_shift_limit=(0.1,0.2), p=0.8), #0.9\n                A.RandomBrightnessContrast(brightness_limit=(0.1,0.2), \n                                           contrast_limit=(0.1,0.3), p=0.8), #0.9\n            ],p=0.9),\n            #A.RandomSunFlare(p=0.4,num_flare_circles_lower=4, num_flare_circles_upper=8, src_radius=300),#new\n            #A.CLAHE(p=0.9),#New\n            A.RandomShadow(shadow_roi=(0, 0.5, 1, 1), num_shadows_lower=1, \n                       num_shadows_upper=2, shadow_dimension=5, always_apply=False, p=0.5) ,#new\n            #A.ToGray(p=0.01),\n            #A.HorizontalFlip(p=0.5),\n            #A.VerticalFlip(p=0.5),\n            A.Flip(p=0.5),\n            #A.RGBShift(p=0.35),\n            A.Resize(height=512, width=512, p=1),\n            #A.Cutout(num_holes=8, max_h_size=64, max_w_size=64, fill_value=0, p=0.5),\n            #A.Cutout(num_holes=6, max_h_size=48, max_w_size=48, fill_value=0, p=0.2),\n         # A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225), max_pixel_value=255.0, \n         #               always_apply=False, p=1.0),\n            ToTensorV2(p=1.0)\n        ], \n        p=1.0, \n        bbox_params=A.BboxParams(\n            format='pascal_voc',\n            min_area=0, \n            min_visibility=0,\n            label_fields=['labels']\n        )\n    )\n\ndef get_valid_transforms():\n    return A.Compose(\n        [\n            A.Resize(height=512, width=512, p=1.0),\n             \n            ToTensorV2 (p=1.0)\n        ], \n        p=1.0, \n        bbox_params=A.BboxParams(\n            format='pascal_voc',\n            min_area=0, \n            min_visibility=0,\n            label_fields=['labels']\n        )\n    )","execution_count":null,"outputs":[]},{"metadata":{"id":"jdJDw2cUFum0","trusted":true},"cell_type":"code","source":"'''\nif self.transforms:\n    for i in range(10):\n        sample = self.transforms(**{\n            'image': image,\n            'bboxes': target['boxes'],\n            'labels': labels\n        })\n        assert len(sample['bboxes']) == labels.shape[0], 'not equal!'\n\n        if len(sample['bboxes']) > 0:\n            image = sample['image']\n            target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n            #yxyx: be warning\n            target['boxes'][:,[0,1,2,3]] = target['boxes'][:,[1,0,3,2]]  \n            target['labels'] = torch.stack(sample['labels']) # <--- add this!\n            break\n'''","execution_count":null,"outputs":[]},{"metadata":{"id":"eXLcm_CoFum2","outputId":"5ac4f95d-7e0e-4cf1-f7e9-dc7338531c89","trusted":true},"cell_type":"code","source":"#!ls -l ./data/train_images/00333207f.jpg","execution_count":null,"outputs":[]},{"metadata":{"id":"SKiaad9UFum7"},"cell_type":"markdown","source":"## Dataset","execution_count":null},{"metadata":{"id":"jlXvIjt6Fum8","outputId":"830bdd6a-ecf3-4f8f-affd-8d592be74455","trusted":true},"cell_type":"code","source":"\n#'./data/train'\n#'../input/global-wheat-detection/train'\n\nclass DatasetRetriever(Dataset):\n\n    def __init__(self, marking, image_ids, transforms=None, test=False):\n        super().__init__()\n\n        self.image_ids = image_ids\n        self.marking = marking\n        self.transforms = transforms\n        self.test = test\n    def stitch_boxes(self, index, imsize=1024):\n        \n        # Increase this to pick less number of boxes from each image and vice versa.\n        BOX_NUM_SELECTOR = 5\n        \n        all_boxes = []\n        \n        image, boxes = self.load_image_and_boxes(index)\n        for box in boxes:\n            all_boxes.append([int(x) for x in box])\n        \n        indexes = [random.randint(0, self.image_ids.shape[0] - 1) for _ in range(3)]\n        \n        for i, idx in enumerate(indexes):\n            _im, _boxes = self.load_image_and_boxes(idx)\n            _bi = [int(x) for x in random.sample(list(range(len(_boxes))), len(_boxes)//BOX_NUM_SELECTOR)]\n            \n            _b = _boxes[_bi]\n            for box in _b:\n                box = [int(x) for x in box]\n                all_boxes.append(box)\n                image[box[1]:box[3], box[0]:box[2]] = _im[box[1]:box[3], box[0]:box[2]]\n        \n        return image, np.array(all_boxes)\n    def load_cutmix_image_and_boxes(self, index, imsize=1024):\n        \"\"\" \n        This implementation of cutmix author:  https://www.kaggle.com/nvnnghia \n        Refactoring and adaptation: https://www.kaggle.com/shonenkov\n        \"\"\"\n        w, h = imsize, imsize\n        s = imsize // 2\n    \n        xc, yc = [int(random.uniform(imsize * 0.25, imsize * 0.75)) for _ in range(2)]  # center x, y\n        indexes = [index] + [random.randint(0, self.image_ids.shape[0] - 1) for _ in range(3)]\n\n        result_image = np.full((imsize, imsize, 3), 1, dtype=np.float32)\n        result_boxes = []\n\n        for i, index in enumerate(indexes):\n            image, boxes = self.load_image_and_boxes(index)\n            if i == 0:\n                x1a, y1a, x2a, y2a = max(xc - w, 0), max(yc - h, 0), xc, yc  # xmin, ymin, xmax, ymax (large image)\n                x1b, y1b, x2b, y2b = w - (x2a - x1a), h - (y2a - y1a), w, h  # xmin, ymin, xmax, ymax (small image)\n            elif i == 1:  # top right\n                x1a, y1a, x2a, y2a = xc, max(yc - h, 0), min(xc + w, s * 2), yc\n                x1b, y1b, x2b, y2b = 0, h - (y2a - y1a), min(w, x2a - x1a), h\n            elif i == 2:  # bottom left\n                x1a, y1a, x2a, y2a = max(xc - w, 0), yc, xc, min(s * 2, yc + h)\n                x1b, y1b, x2b, y2b = w - (x2a - x1a), 0, max(xc, w), min(y2a - y1a, h)\n            elif i == 3:  # bottom right\n                x1a, y1a, x2a, y2a = xc, yc, min(xc + w, s * 2), min(s * 2, yc + h)\n                x1b, y1b, x2b, y2b = 0, 0, min(w, x2a - x1a), min(y2a - y1a, h)\n            result_image[y1a:y2a, x1a:x2a] = image[y1b:y2b, x1b:x2b]\n            padw = x1a - x1b\n            padh = y1a - y1b\n\n            boxes[:, 0] += padw\n            boxes[:, 1] += padh\n            boxes[:, 2] += padw\n            boxes[:, 3] += padh\n\n            result_boxes.append(boxes)\n\n        result_boxes = np.concatenate(result_boxes, 0)\n        np.clip(result_boxes[:, 0:], 0, 2 * s, out=result_boxes[:, 0:])\n        result_boxes = result_boxes.astype(np.int32)\n        result_boxes = result_boxes[np.where((result_boxes[:,2]-result_boxes[:,0])*(result_boxes[:,3]-result_boxes[:,1]) > 0)]\n        return result_image, result_boxes\n\n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        '''\n        if self.test or random.random() > 0.5:\n            image, boxes = self.load_image_and_boxes(index)\n        else:\n            image, boxes = self.load_cutmix_image_and_boxes(index)\n        '''\n        if self.test or random.random() > 0.4:\n            if random.random()>0.5:\n              #print('x')\n              image, boxes=self.stitch_boxes(index)\n            else:\n\n              image, boxes = self.load_image_and_boxes(index)\n        else:\n            image, boxes = self.load_cutmix_image_and_boxes(index)\n        #image, boxes = self.load_image_and_boxes(index)\n        # there is only one class\n        labels = torch.ones((boxes.shape[0],), dtype=torch.int64)\n        \n        target = {}\n        target['boxes'] = boxes\n        target['labels'] = labels\n        target['image_id'] = torch.tensor([index])\n        #print(target['image_id'],index)\n\n        if self.transforms:\n            for i in range(10):\n                sample = self.transforms(**{\n                    'image': image,\n                    'bboxes': target['boxes'],\n                    'labels': labels\n                })\n                if len(sample['bboxes']) > 0:\n                    image = sample['image']\n                    \n                    target['boxes'] = torch.stack(tuple(map(torch.tensor, zip(*sample['bboxes'])))).permute(1, 0)\n                    target['boxes'][:,[0,1,2,3]] = target['boxes'][:,[1,0,3,2]]  #yxyx: be warning\n                    target['labels'] = torch.stack(sample['labels']) #bug\n                    break\n        #image=image.astype(np.float32)\n        #print(image.size())\n        #image /= 255.0\n        #image.float().div_(255.)\n        return image, target, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]\n\n    def load_image_and_boxes(self, index):\n        image_id = self.image_ids[index]\n        #print(f'{TRAIN_ROOT_PATH}/{image_id}.jpg')\n        image = cv2.imread(f'{TRAIN_ROOT_PATH}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image=A.CLAHE(p=0.6)(image=image)['image'] \n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n        #.astype('uint8')\n        ##.astype(np.float32)\n        image /= 255.0\n        records = self.marking[self.marking['image_id'] == image_id]\n        boxes = records[['x', 'y', 'w', 'h']].values\n        #print('image',image_id)\n        #boxes=np.array(train_labels_cln[image_id])\n        #print(boxes.shape,records[['x', 'y', 'w', 'h']].values.shape)\n        #boxes = records[['x', 'y', 'w', 'h']].values\n        boxes[:, 2] =np.clip(boxes[:,0]+boxes[:,2],0,1024-1) \n        #boxes[:, 0] + boxes[:, 2]\n        boxes[:, 3] = np.clip(boxes[:,1]+boxes[:,3],0,1024-1)\n        #boxes[:, 1] + boxes[:, 3]\n        return image, boxes\nprint('x')","execution_count":null,"outputs":[]},{"metadata":{"id":"xbiqDgZqFum_","trusted":true},"cell_type":"code","source":"fold_number = 0\n\ntrain_dataset = DatasetRetriever(\n    image_ids=df_folds[df_folds['fold'] != fold_number].image_id.values,#.index.values,\n    marking=marking,\n    transforms=get_train_transforms(),\n    test=False,\n)\n\nvalidation_dataset = DatasetRetriever(\n    image_ids=df_folds[df_folds['fold'] == fold_number].image_id.values,#.index.values,\n    marking=marking,\n    transforms=get_valid_transforms(),\n    test=True,\n)","execution_count":null,"outputs":[]},{"metadata":{"id":"yHuqoaKqFunC","outputId":"c2783414-40a4-4ffe-a3a6-538401dfbb08","trusted":true},"cell_type":"code","source":"image, target, image_id = train_dataset[1]\nprint(image_id )\nboxes = target['boxes'].cpu().numpy().astype(np.int32)\n\nnumpy_image = image.permute(1,2,0).cpu().numpy()\n\nfig, ax = plt.subplots(1, 1, figsize=(16, 8))\n\nfor box in boxes:\n    cv2.rectangle(numpy_image, (box[1], box[0]), (box[3],  box[2]), (0, 2, 0), 2)\n    \nax.set_axis_off()\nax.imshow(numpy_image );","execution_count":null,"outputs":[]},{"metadata":{"id":"-J2mJJ_OFunH"},"cell_type":"markdown","source":"## Fitter","execution_count":null},{"metadata":{"id":"szQbW8ENFunJ","trusted":true},"cell_type":"code","source":"class AverageMeter(object):\n    \"\"\"Computes and stores the average and current value\"\"\"\n    def __init__(self):\n        self.reset()\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count","execution_count":null,"outputs":[]},{"metadata":{"id":"HFzKqD6DbJEy","trusted":true},"cell_type":"code","source":"# from google.colab import output","execution_count":null,"outputs":[]},{"metadata":{"id":"Hy6vp3qLsYtV","outputId":"c0444782-7bc4-4a36-9e64-517d7e72a3a0","trusted":true},"cell_type":"code","source":"step=15\nif step+1%16:\n  print('x')","execution_count":null,"outputs":[]},{"metadata":{"id":"0MqlGFowFunN"},"cell_type":"markdown","source":"I adjust the train code with apex and gradient accumulation ","execution_count":null},{"metadata":{"id":"kMvRJtSsFune","trusted":true},"cell_type":"code","source":"device = torch.device('cuda:0')\ndef collate_fn(batch):\n    return tuple(zip(*batch))\ntrain_loader = torch.utils.data.DataLoader(\n        train_dataset,\n        batch_size=TrainGlobalConfig.batch_size,\n        sampler=RandomSampler(train_dataset),\n        pin_memory=False,\n        drop_last=True,\n        num_workers=TrainGlobalConfig.num_workers,\n        collate_fn=collate_fn,\n    )\nval_loader = torch.utils.data.DataLoader(\n        validation_dataset, \n        batch_size=TrainGlobalConfig.batch_size,\n        num_workers=TrainGlobalConfig.num_workers,\n        shuffle=False,\n        sampler=SequentialSampler(validation_dataset),\n        pin_memory=False,\n        collate_fn=collate_fn,\n    )","execution_count":null,"outputs":[]},{"metadata":{"id":"ZLrr_S3PFunN","outputId":"e2b3ca56-9989-47f9-c918-9bb9b2c6671b","trusted":true},"cell_type":"code","source":"import warnings\n\nwarnings.filterwarnings(\"ignore\")\n\nclass Fitter:\n\n    def __init__(self, model, device, config,train_loader):\n        self.config = config\n        self.epoch = 0\n\n        self.base_dir = f'./{config.folder}'\n        if not os.path.exists(self.base_dir):\n            os.makedirs(self.base_dir)\n\n        self.log_path = f'{self.base_dir}/log.txt'\n        self.best_summary_loss = 10 ** 5\n        self.model = model\n        self.device = device\n        self.mixed_precision = config.mixed_precision\n        self.accumulate = config.accumulate\n        param_optimizer = list(self.model.named_parameters())\n        no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']\n        optimizer_grouped_parameters = [\n            {'params': [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], 'weight_decay': 0.001},\n            {'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}\n        ]\n\n        self.optimizer = torch.optim.AdamW(self.model.parameters(), lr=config.lr)\n        self.model = model.to(device)\n        if self.mixed_precision:\n            self.model, self.optimizer = amp.initialize(self.model, self.optimizer, opt_level=\"O1\", verbosity=0)\n\n        self.scheduler = config.SchedulerClass(self.optimizer, **config.scheduler_params)\n        #torch.optim.lr_scheduler.OneCycleLR( self.optimizer, max_lr=8e-4, pct_start=0.15,\n        #                                                     cycle_momentum=False,\n        #                                                     steps_per_epoch=len(train_loader), epochs=18)\n        #config.SchedulerClass(self.optimizer, **config.scheduler_params)\n        #optim.lr_scheduler.OneCycleLR(optimizer, max_lr=1e-3, steps_per_epoch=len(train_loader), epochs=13,div_factor=7\n#                                        ,cycle_momentum=False,pct_start=0.33 )\n        self.log(f'Fitter prepared. Device is {self.device}')\n\n    \n\n    def validation(self, val_loader):\n        self.model.eval()\n        summary_loss = AverageMeter()\n        t = time.time()\n        for step, (images, targets, image_ids) in enumerate(val_loader):\n            if self.config.verbose:\n                if step % self.config.verbose_step == 0:\n                    \n                   \n\n                    print(f'Val Step {step}/{len(val_loader)}, ' + \\\n                            f'summary_loss: {summary_loss.avg:.5f}, ' + \\\n                            f'time: {(time.time() - t):.5f}', end='\\r'  )\n                    \n                     \n            with torch.no_grad():\n                images = torch.stack(images)\n                images = images.to(self.device).float()\n                batch_size = images.shape[0]\n                #boxes = [target['boxes'].to(self.device).float() for target in targets]\n            #labels = [target['labels'].to(self.device).float() for target in targets] causes forward error\n            #print('boxes',boxes.size())\n                target_res = {}\n                boxes = [target['boxes'].to(self.device).float() for target in targets]\n                labels = [target['labels'].to(self.device).float() for target in targets]\n                '''\n                target_res['bbox'] = boxes\n                target_res['cls'] = labels \n                target_res['img_scale'] = torch.tensor([1.0] * batch_size, dtype=torch.float).to(self.device)\n                target_res['img_size'] = torch.tensor([images[0].shape[-2:]] * batch_size, dtype=torch.float).to(self.device)\n            #loss, _, _ = self.model(images, boxes, labels)\n                outputs = self.model(images, target_res)\n                loss = outputs['loss']\n                '''\n                boxes = [target['boxes'].to(self.device).float() for target in targets]\n                labels = [target['labels'].to(self.device).float() for target in targets]\n\n                loss, _, _ = self.model(images, boxes, labels)\n                summary_loss.update(loss.detach().item(), batch_size)\n\n        return summary_loss\n\n    def train_one_epoch(self, train_loader):\n        self.model.train()\n        summary_loss = AverageMeter()\n        t = time.time()\n        for step, (images, targets, image_ids) in enumerate(train_loader):\n            #if self.config.verbose:\n                #print('x')\n            if step % 1 == 0:\n\n              #print(f'summary_loss: {summary_loss.avg:.5f}', end='\\r')\n              #output.clear('status_text')\n              #with output.use_tags('status_text'):\n\n                print(\n                                f'Train Step {step}/{len(train_loader)}, ' + \\\n                                f'summary_loss: {summary_loss.avg:.5f}, ' + \\\n                                f'time: {(time.time() - t):.5f}', end='\\r'\n                    )\n\n            images = torch.stack(images)\n            images = images.to(self.device).float()\n            #print('train',images.size())\n            batch_size = images.shape[0]\n            #boxes = [target['boxes'].to(self.device).float() for target in targets]\n            #labels = [target['labels'].to(self.device).float() for target in targets] causes forward error\n            #print('boxes',boxes.size())\n            '''\n            target_res = {}\n            boxes = [target['boxes'].to(self.device).float() for target in targets]\n            labels = [target['labels'].to(self.device).float() for target in targets]\n\n            target_res['bbox'] = boxes\n            target_res['cls'] = labels \n            loss, _, _ = self.model(images, boxes, labels)\n            outputs = self.model(images, target_res)\n            loss = outputs['loss']#/self.accumulate\n            '''\n            boxes = [target['boxes'].to(self.device).float() for target in targets]\n            labels = [target['labels'].to(self.device).float() for target in targets]\n\n            loss, _, _ = self.model(images, boxes, labels)\n            # The code from YOLO V5\n            if self.mixed_precision:\n                with amp.scale_loss(loss, self.optimizer) as scaled_loss:\n                    scaled_loss.backward()\n            else:\n                loss.backward()\n            #print('step+1 % self.accumulate',(step+1) % self.accumulate,step,self.accumulate)\n             \n            if (step+1) % 1 == 0:\n              #print('x')\n              #for p in (self.model.parameters()):\n              #  if p.requires_grad: p.grad.div_(self.accumulate)\n              #loss =loss/self.accumulate\n              self.optimizer.step()\n              self.optimizer.zero_grad()\n                \n              if self.config.step_scheduler:\n                    self.scheduler.step()\n              summary_loss.update(loss.detach().item(), batch_size)\n\n        return summary_loss\n    def fit(self, train_loader, validation_loader,epochs):\n        for e in range(epochs):\n            if self.config.verbose:\n                lr = self.optimizer.param_groups[0]['lr']\n                #lr=self.scheduler.get_lr()[0]\n                timestamp = datetime.utcnow().isoformat()\n                self.log(f'\\n{timestamp}\\nLR: {lr}')\n\n            t = time.time()\n            summary_loss = self.train_one_epoch(train_loader)\n\n            self.log(\n                f'[RESULT]: Train. Epoch: {self.epoch}, summary_loss: {summary_loss.avg:.5f}, time: {(time.time() - t):.5f}')\n            self.save(f'{self.base_dir}/last-checkpoint.bin')\n\n            t = time.time()\n            summary_loss = self.validation(validation_loader)\n\n            self.log(\n                f'[RESULT]: Val. Epoch: {self.epoch}, summary_loss: {summary_loss.avg:.5f}, time: {(time.time() - t):.5f}')\n            if summary_loss.avg < self.best_summary_loss:\n                self.best_summary_loss = summary_loss.avg\n                self.model.eval()\n                self.save(f'{self.base_dir}/best-checkpoint-{str(self.epoch).zfill(3)}epoch.bin')\n                for path in sorted(glob(f'{self.base_dir}/best-checkpoint-*epoch.bin'))[:-3]:\n                    os.remove(path)\n\n            if self.config.validation_scheduler:\n                self.scheduler.step(metrics=summary_loss.avg)\n\n            self.epoch += 1\n\n    def save(self, path):\n\n        self.model.eval()\n        torch.save({\n            'model_state_dict': self.model.model.state_dict(),\n            #'optimizer_state_dict': self.optimizer.state_dict(),\n            #'scheduler_state_dict': self.scheduler.state_dict(),\n            #'best_summary_loss': self.best_summary_loss,\n           # 'epoch': self.epoch,\n        }, path)\n\n    def load(self, path=None):\n        #checkpoint = torch.load('effdet5-cutmix-augmix'+'/'+path)\n        #checkpoint = torch.load('effdet5-cutmix-augmix'+'/'+path)\n        \n        checkpoint = torch.load('../input/gwd-eff-det-train-like-yolo/model_b4.bin')\n        #checkpoint = {k: v for k, v in zip(self.model.model.state_dict().keys(),checkpoint.values())}\n        #print(checkpoint)\n        self.model.load_state_dict(checkpoint['model_state_dict'])\n        #self.optimizer.load_state_dict(checkpoint['optimizer_state_dict'])\n        #self.scheduler.load_state_dict(checkpoint['scheduler_state_dict'])\n        #self.best_summary_loss = checkpoint['best_summary_loss']\n        #self.epoch = checkpoint['epoch'] + 1\n\n    def log(self, message):\n        if self.config.verbose:\n            print(message)\n        with open(self.log_path, 'a+') as logger:\n            logger.write(f'{message}\\n')\nprint('x')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#summary_loss = Fitter(model=net, device=device, config=TrainGlobalConfig,train_loader=train_loader).validation(val_loader)","execution_count":null,"outputs":[]},{"metadata":{"id":"ZMyM-nfIFunV","outputId":"8dec0686-5622-4903-9382-d47d58648f48","trusted":true},"cell_type":"code","source":"import gc\ntorch.cuda.empty_cache()\ngc.collect()\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#net.state_dict().keys()","execution_count":null,"outputs":[]},{"metadata":{"id":"NiW_blsyTAbS","outputId":"93fff6a5-9487-4e32-e336-6f8c9370b21b","trusted":true},"cell_type":"code","source":"#!pip install timm\n#!pip install effdet\n#!pip install  Omegaconf","execution_count":null,"outputs":[]},{"metadata":{"id":"7Mfn0n_4Funh","trusted":true},"cell_type":"code","source":"from effdet import get_efficientdet_config, EfficientDet, DetBenchTrain\nfrom effdet.efficientdet import HeadNet\nfrom torch.utils import *\n\ndef get_net():\n    config = get_efficientdet_config('tf_efficientdet_d4')\n    #print(config)\n    net = EfficientDet(config, pretrained_backbone=False)\n    #print(net.state_dict().keys())\n    \n    #checkpoint = model_zoo.load_url('https://github.com/rwightman/efficientdet-pytorch/releases/download/v0.1/tf_efficientdet_d4-5b370b7a.pth')\n    #('https://github.com/rwightman/efficientdet-pytorch/releases/download/v0.1/tf_efficientdet_d4-ef44aea8.pth')\n    #('../input/efficientdet/efficientdet_d5-ef44aea8.pth') /home/temp/.cache/torch/checkpoints/tf_efficientdet_d5-ef44aea8.pth\n    #net.load_state_dict(checkpoint)\n    config.num_classes = 1\n    config.image_size = 512\n    net.class_net = HeadNet(config, num_outputs=config.num_classes, norm_kwargs=dict(eps=.001, momentum=.01))\n    return DetBenchTrain(net, config)\n\nnet = get_net()","execution_count":null,"outputs":[]},{"metadata":{"id":"HXHWW3jPFunQ","outputId":"4bc5d113-9937-4996-8822-48fd80978e46","trusted":true},"cell_type":"code","source":"#torch.cuda.set_device(4)\n\n\ndef run_training(train_loader,val_loader,epochs,path=None):\n    device = torch.device('cuda:0')\n    net.to(device)\n\n    \n\n    fitter = Fitter(model=net, device=device, config=TrainGlobalConfig,train_loader=train_loader)\n    #if path is not None:\n    fitter.load(path)\n    fitter.fit(train_loader, val_loader,epochs=epochs)\nprint('x')","execution_count":null,"outputs":[]},{"metadata":{"id":"6aMBWUlMFunl","outputId":"3ce40454-b8f7-4b60-f3fc-329467400db9","trusted":true},"cell_type":"code","source":"#net\n#!nvidia-smi\n#summary_loss = Fitter(model=net, device= torch.device('cuda:4'), config=TrainGlobalConfig,train_loader=train_loader).validation(val_loader=val_loader)\n'''\nlass ExtendDetBenchTrain(DetBenchTrain):\n\ndef __init__(self, model, config):\n    super(ExtendDetBenchTrain, self).__init__(model, config)\n\ndef forward(self, x, target):\n    class_out, box_out = self.model(x)\n    cls_targets, box_targets, num_positives = self.anchor_labeler.batch_label_anchors(\n        x.shape[0], target['bbox'], target['cls'])\n    loss, class_loss, box_loss = self.loss_fn(class_out, box_out, cls_targets, box_targets,      num_positives)\n    output = dict(loss=loss, class_loss=class_loss, box_loss=box_loss)\n   return output\n'''\n ","execution_count":null,"outputs":[]},{"metadata":{"id":"5vKhWzvsFunn","outputId":"f2c2fba0-ac16-4ef4-8c2b-788d15c724e6","trusted":true},"cell_type":"code","source":"#model.load_state_dict(torch.load('/kaggle/working/model_best.pth'))\nrun_training(train_loader, val_loader,10,path='../input/gwd-eff-det-train-like-yolo/model_b4.bin' )","execution_count":null,"outputs":[]},{"metadata":{"id":"PYrIz-oUFunr","outputId":"494b9670-f03a-4cd2-91f8-f7ba491e693f","trusted":true},"cell_type":"code","source":"#run_training(train_loader, val_loader,17,'best-checkpoint-024epoch')\n","execution_count":null,"outputs":[]},{"metadata":{"id":"_xBXpR-FFunv","outputId":"27425482-1ad1-4c40-991a-d72204be824a","trusted":true},"cell_type":"code","source":"#run_training()\ntorch.save({\n            'model_state_dict': net.state_dict()},'/kaggle/working/model_b4_stich_mix.bin'\n             \n)","execution_count":null,"outputs":[]},{"metadata":{"id":"rmtK4nyhFun0"},"cell_type":"markdown","source":"### Thank you for reading my kernel!\n\n# If it is helpful to you ,upvote it please :D","execution_count":null},{"metadata":{"id":"a6yDypdGFun1","trusted":true},"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}