{"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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\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\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames[:5]:\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","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"!pip install torch==1.7.1+cu101 torchvision==0.8.2+cu101 torchaudio==0.7.2 -f https://download.pytorch.org/whl/torch_stable.html\n!pip install -U 'git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI'\n!pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu101/torch1.7/index.html","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from detectron2.structures import BoxMode\nimport pycocotools\nimport pandas as pd\nimport numpy as np\nimport gc, collections\nimport cv2\nfrom pathlib import Path\nfrom sklearn.model_selection import train_test_split","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from detectron2.structures import BoxMode\nimport pycocotools\nimport pandas as pd\nimport numpy as np\nimport gc, collections\nimport cv2\nfrom pathlib import Path\nfrom sklearn.model_selection import train_test_split\nfrom tqdm import tqdm\n\n\n\ndef generate_coco_data_imaterialist(data_dir):\n    traincsv_dir = '/kaggle/input/imaterialist-fashion-2020-fgvc7/'\n#     print(traincsv_dir)\n    df = pd.read_csv(traincsv_dir+'/train.csv')\n#     df = df[0:100]\n    df = df.sample(frac=0.3)\n    # Get bboxes for each mask\n    bboxes = [rle2bbox(c.EncodedPixels, (c.Height, c.Width)) for n, c in df.iterrows()]\n    assert len(bboxes) == df.shape[0]\n    bboxes_array = np.array(bboxes)\n    # Add each coordinate as a column\n    df['x0'], df['y0'], df['x1'], df['y1'] = bboxes_array[:,0], bboxes_array[:,1], bboxes_array[:,2], bboxes_array[:,3]\n    del bboxes\n    gc.collect()\n    dataset_dicts = []\n    for idx, filename in tqdm(enumerate(df['ImageId'].unique().tolist())):\n        print(idx)\n        record = {}\n        record['height'] = int(df[df['ImageId']==filename]['Height'].values[0])\n        record['width'] = int(df[df['ImageId']==filename]['Width'].values[0])\n        record['file_name'] = data_dir+'train/'+filename+'.jpg'\n        record['image_id'] = idx\n        objs = []\n        for index, row in df[(df['ImageId']==filename)].iterrows():\n#             mask = rle_decode_string(row['EncodedPixels'], row['Height'], row['Width'])\n            # transform the mask from binary to polygon\n#             contours,hierarchy = cv2.findContours((mask).astype(np.uint8), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)\n#             segmentation = []\n#             for contour in contours:\n#                 contour = contour.flatten().tolist()\n                # segmentation.append(contour)\n#                 if len(contour) > 4:\n#                     segmentation.append(contour)    \n            obj = {\n                'bbox': [row['x0'], row['y0'], row['x1'], row['y1']],\n                'bbox_mode': BoxMode.XYXY_ABS,\n                'category_id': row['ClassId'],\n#                 'segmentation': pycocotools.mask.encode(np.asarray(mask, order=\"F\")),\n#                 'iscrowd': 0\n            }\n            objs.append(obj)\n        record['annotations'] = objs\n        dataset_dicts.append(record)\n    train, test = train_test_split(dataset_dicts, test_size=0.001)\n    return train, test\n\n\n# Rle helper functions\n\ndef rle_decode_string(string, h, w):\n    mask = np.full(h*w, 0, dtype=np.uint8)\n    annotation = [int(x) for x in string.split(' ')]\n    for i, start_pixel in enumerate(annotation[::2]):\n        mask[start_pixel: start_pixel+annotation[2*i+1]] = 1\n    mask = mask.reshape((h, w), order='F')\n\n    \n    return mask\n\ndef rle2bbox(rle, shape):\n    '''\n    Get a bbox from a mask which is required for Detectron 2 dataset\n    rle: run-length encoded image mask, as string\n    shape: (height, width) of image on which RLE was produced\n    Returns (x0, y0, x1, y1) tuple describing the bounding box of the rle mask\n    \n    Note on image vs np.array dimensions:\n    \n        np.array implies the `[y, x]` indexing order in terms of image dimensions,\n        so the variable on `shape[0]` is `y`, and the variable on the `shape[1]` is `x`,\n        hence the result would be correct (x0,y0,x1,y1) in terms of image dimensions\n        for RLE-encoded indices of np.array (which are produced by widely used kernels\n        and are used in most kaggle competitions datasets)\n    '''\n    \n    a = np.fromiter(rle.split(), dtype=np.uint)\n    a = a.reshape((-1, 2))  # an array of (start, length) pairs\n    a[:,0] -= 1  # `start` is 1-indexed\n    \n    y0 = a[:,0] % shape[0]\n    y1 = y0 + a[:,1]\n    if np.any(y1 > shape[0]):\n        # got `y` overrun, meaning that there are a pixels in mask on 0 and shape[0] position\n        y0 = 0\n        y1 = shape[0]\n    else:\n        y0 = np.min(y0)\n        y1 = np.max(y1)\n    \n    x0 = a[:,0] // shape[0]\n    x1 = (a[:,0] + a[:,1]) // shape[0]\n    x0 = np.min(x0)\n    x1 = np.max(x1)\n    \n    if x1 > shape[1]:\n        # just went out of the image dimensions\n        raise ValueError(\"invalid RLE or image dimensions: x1=%d > shape[1]=%d\" % (\n            x1, shape[1]\n        ))\n\n    return x0, y0, x1, y1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# traincsv = pd.read_csv('/kaggle/input/imaterialist-fashion-2020-fgvc7/train.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# traincsv['ImageId'].nunique(), traincsv.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# from collections import Counter\n# ls = list(traincsv['ClassId'])\n# dict(Counter(ls))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"traincsv","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# s = generate_coco_data_imaterialist('/kaggle/input/imaterialist-fashion-2020-fgvc7/')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch, torchvision\n# torch.cuda.set_device(1)\nimport detectron2\nfrom detectron2.utils.logger import setup_logger\nimport numpy as np\nimport cv2\nfrom detectron2 import model_zoo\nfrom detectron2.engine import DefaultTrainer, DefaultPredictor\nfrom detectron2.config import get_cfg\nfrom detectron2.utils.visualizer import Visualizer, GenericMask\nfrom detectron2.data import MetadataCatalog, DatasetCatalog\nimport matplotlib.pyplot as plt\nimport os\nimport json\nfrom detectron2.structures import BoxMode\nimport torch.nn as nn\nimport torchvision.models as models\nimport torchvision.transforms as transforms\nfrom torch.autograd import Variable\nimport configparser\n# from image_segmentation.detectron2.deepfashion.load_data import generate_coco_data_deepfashion\n# from image_segmentation.detectron2.imaterialist.load_data import generate_coco_data_imaterialist\n# from image_segmentation.detectron2.config import *\n# # from image_segmentation.detectron2.generate import GetSegmentation\n# from image_segmentation.detectron2.LossEvalHook import *\nfrom detectron2.evaluation import COCOEvaluator, DatasetEvaluators","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":" from detectron2.engine.hooks import HookBase\nfrom detectron2.evaluation import inference_context\nfrom detectron2.utils.logger import log_every_n_seconds\nfrom detectron2.data import DatasetMapper, build_detection_test_loader\nimport detectron2.utils.comm as comm\nimport torch\nimport time\nimport datetime\nimport numpy as np\nimport logging\n\nclass LossEvalHook(HookBase):\n    def __init__(self, eval_period, model, data_loader):\n        self._model = model\n        self._period = eval_period\n        self._data_loader = data_loader\n    \n    def _do_loss_eval(self):\n        # Copying inference_on_dataset from evaluator.py\n        total = len(self._data_loader)\n        num_warmup = min(5, total - 1)\n            \n        start_time = time.perf_counter()\n        total_compute_time = 0\n        losses = []\n        for idx, inputs in enumerate(self._data_loader):            \n            if idx == num_warmup:\n                start_time = time.perf_counter()\n                total_compute_time = 0\n            start_compute_time = time.perf_counter()\n            if torch.cuda.is_available():\n                torch.cuda.synchronize()\n            total_compute_time += time.perf_counter() - start_compute_time\n            iters_after_start = idx + 1 - num_warmup * int(idx >= num_warmup)\n            seconds_per_img = total_compute_time / iters_after_start\n            if idx >= num_warmup * 2 or seconds_per_img > 5:\n                total_seconds_per_img = (time.perf_counter() - start_time) / iters_after_start\n                eta = datetime.timedelta(seconds=int(total_seconds_per_img * (total - idx - 1)))\n                log_every_n_seconds(\n                    logging.INFO,\n                    \"Loss on Validation  done {}/{}. {:.4f} s / img. ETA={}\".format(\n                        idx + 1, total, seconds_per_img, str(eta)\n                    ),\n                    n=5,\n                )\n            loss_batch = self._get_loss(inputs)\n            losses.append(loss_batch)\n        mean_loss = np.mean(losses)\n        self.trainer.storage.put_scalar('validation_loss', mean_loss)\n        comm.synchronize()\n\n        return losses\n            \n    def _get_loss(self, data):\n        # How loss is calculated on train_loop \n        metrics_dict = self._model(data)\n        metrics_dict = {\n            k: v.detach().cpu().item() if isinstance(v, torch.Tensor) else float(v)\n            for k, v in metrics_dict.items()\n        }\n        total_losses_reduced = sum(loss for loss in metrics_dict.values())\n        return total_losses_reduced\n        \n        \n    def after_step(self):\n        next_iter = self.trainer.iter + 1\n        is_final = next_iter == self.trainer.max_iter\n        if is_final or (self._period > 0 and next_iter % self._period == 0):\n            self._do_loss_eval()\n        self.trainer.storage.put_scalars(timetest=12)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATASET_CLASSES = ['shirt, blouse', 'top, t-shirt, sweatshirt', 'sweater', 'cardigan', 'jacket', 'vest',\n'pants', 'shorts', 'skirt', 'coat', 'dress', 'jumpsuit', 'cape', 'glasses', 'hat',\n'headband, head covering, hair accessory', 'tie', 'glove', 'watch', 'belt', 'leg warmer',\n'tights, stockings', 'sock', 'shoe', 'bag, wallet', 'scarf', 'umbrella', 'hood', 'collar', 'lapel',\n'epaulette', 'sleeve', 'pocket', 'neckline', 'buckle', 'zipper', 'applique', 'bead', 'bow', 'flower',\n'fringe', 'ribbon', 'rivet', 'ruffle', 'sequin', 'tassel']\nARCH_FILE = 'COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml'\nTEST_INTERVAL=50\nNUM_OF_WORKERS = 2\nWEIGHT_INIT_FILE = 'COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml'\nIMAGES_PER_BATCH = 2\nLR = 0.0001\nNUM_OF_EPOCH = 1000\nBATCH_SIZE_PER_IMAGE = 64\nTRAIN_MODEL_OUTPUT_PATH = '/kaggle/working/'\nrpath = '/kaggle/input/imaterialist-fashion-2020-fgvc7/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = generate_coco_data_imaterialist(rpath)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# data[0][0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DatasetCatalog.register(\"train\", lambda rpath=rpath: load_train_data(data))\nMetadataCatalog.get(\"train\").set(thing_classes=DATASET_CLASSES)\nDatasetCatalog.register(\"test\", lambda rpath=rpath: load_test_data(data))\nMetadataCatalog.get(\"test\").set(thing_classes=DATASET_CLASSES)\ntrain_metadata = MetadataCatalog.get(\"train\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cfg = get_cfg()\ncfg.merge_from_file(model_zoo.get_config_file(ARCH_FILE))\ncfg.DATASETS.TRAIN = (\"train\",)\ncfg.DATASETS.TEST = (\"test\",)\ncfg.TEST.EVAL_PERIOD = TEST_INTERVAL\ncfg.DATALOADER.NUM_WORKERS = NUM_OF_WORKERS","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(WEIGHT_INIT_FILE)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_MODEL_OUTPUT_PATH = '/kaggle/working/'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cfg.SOLVER.IMS_PER_BATCH = IMAGES_PER_BATCH\ncfg.SOLVER.BASE_LR = LR  # pick a good LR\ncfg.SOLVER.MAX_ITER = NUM_OF_EPOCH   # 300 iterations seems good enough for this toy dataset; you may need to train longer for a practical dataset\ncfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = BATCH_SIZE_PER_IMAGE   # faster, and good enough for this toy dataset (default: 512)\ncfg.MODEL.ROI_HEADS.NUM_CLASSES = len(DATASET_CLASSES)  # only has one class (ballon)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class MyTrainer(DefaultTrainer):\n    @classmethod\n    def build_evaluator(cls, cfg, dataset_name, output_folder=None):\n        if output_folder is None:\n            output_folder = os.path.join(cfg.OUTPUT_DIR, \"inference\")\n        return COCOEvaluator(dataset_name, cfg, True, output_folder)\n\n    def build_hooks(self):\n        cfg = self.cfg.clone()\n#         print(cfg)\n        hooks = super().build_hooks()\n        hooks.insert(-1,LossEvalHook(\n            cfg.TEST.EVAL_PERIOD,\n            self.model,\n            build_detection_test_loader(\n                cfg,\n                cfg.DATASETS.TEST[0],\n                DatasetMapper(cfg,True)\n            )\n        ))\n        return hooks\n    \ndef load_train_data(tpl):\n    list_dict = tpl[0]\n    return list_dict\n\ndef load_test_data(tpl):\n    list_dict = tpl[1]\n    return list_dict","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nif not os.path.exists(TRAIN_MODEL_OUTPUT_PATH):\n    os.makedirs(TRAIN_MODEL_OUTPUT_PATH)\ncfg.OUTPUT_DIR = TRAIN_MODEL_OUTPUT_PATH\ntrainer = MyTrainer(cfg)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trainer.resume_or_load(resume=False)\ntrainer.train()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nos.listdir('/kaggle/input/imaterialist-fashion-2020-fgvc7/')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir('/kaggle/')","execution_count":null,"outputs":[]},{"metadata":{"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}