{"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":"## PyTorch ResNet50 Inference","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np \nimport pandas as pd \nimport json\nimport sys\nimport gc\nimport random\nimport time\nfrom contextlib import contextmanager\nfrom pathlib import Path\nfrom collections import defaultdict, Counter\nimport cv2\nfrom PIL import Image\nfrom typing import Dict\nfrom functools import partial\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nfrom torch.optim import Adam, SGD\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision.models as models\n\nfrom albumentations import Compose, Normalize, Resize, RandomResizedCrop, RandomCrop, HorizontalFlip\nfrom albumentations.pytorch import ToTensorV2\n\n\nSEED = 777\nHEIGHT, WIDTH = 128, 128\nN_CLASSES = 3474\nbatch_size = 128\nTEST_DIR = '../input/imet-2021-fgvc8/test/test'\nmodel_dir = '../input/vimet2021fgvc8-add'\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ndevice","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv('../input/imet-2021-fgvc8/sample_solution.csv')\nsubmission.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ====================================================\n# Utils\n# ====================================================\n\n@contextmanager\ndef timer(name):\n    t0 = time.time()\n    LOGGER.info(f'[{name}] start')\n    yield\n    LOGGER.info(f'[{name}] done in {time.time() - t0:.0f} s.')\n\n    \ndef init_logger(log_file='train.log'):\n    from logging import getLogger, DEBUG, FileHandler,  Formatter,  StreamHandler\n    \n    log_format = '%(asctime)s %(levelname)s %(message)s'\n    \n    stream_handler = StreamHandler()\n    stream_handler.setLevel(DEBUG)\n    stream_handler.setFormatter(Formatter(log_format))\n    \n    file_handler = FileHandler(log_file)\n    file_handler.setFormatter(Formatter(log_format))\n    \n    logger = getLogger('Herbarium')\n    logger.setLevel(DEBUG)\n    logger.addHandler(stream_handler)\n    logger.addHandler(file_handler)\n    \n    return logger\n\nLOG_FILE = 'train.log'\nLOGGER = init_logger(LOG_FILE)\n\n\ndef seed_torch(seed=777):\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\n\nseed_torch(SEED)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_transform = Compose([\n    Resize(HEIGHT, WIDTH),\n])\n\ntensor_transform = Compose([\n    Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ToTensorV2(),\n])\n\ndef load_transform_image(item, image_transform):\n    image = load_image(item)\n    try:\n        image = image_transform(image)['image']\n    except:\n        c = Compose([\n            Resize(HEIGHT, WIDTH),\n        ])\n        image = c(image=image)['image']\n    return tensor_transform(image=image)['image']\n\n\ndef load_image(item) -> Image.Image:    \n    image = cv2.imread(str(TEST_DIR + '/' + f'{item}.png'))\n\n    if image is None:\n        image = cv2.imread(str(TEST_DIR + '/' + f'{item}.jpg'))\n\n    if image is None:\n        image = np.zeros([HEIGHT, WIDTH, 3])\n\n    image = cv2.cvtColor(image.astype(np.float32), cv2.COLOR_BGR2RGB)\n#     return Image.fromarray(image)\n    return image\n\n\nclass TestDataset:\n\n    def __init__(self, df, transform=None):\n        self.df = df\n        self._image_transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        file_name = self.df['id'].values[idx]\n        image = load_transform_image(file_name, self._image_transform)\n        return image","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = TestDataset(submission, test_transform)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from functools import partial\n\nimport torch\nfrom torch import nn\nfrom torch.nn import functional as F\nimport torchvision.models as M\n\nclass AvgPool(nn.Module):\n    def forward(self, x):\n        return F.avg_pool2d(x, x.shape[2:])\n\ndef create_net(net_cls, pretrained: bool):\n    if True and pretrained:\n        net = net_cls()\n        model_name = net_cls.__name__\n        weights_path = f'{model_dir}/{model_name}.pth'\n        net.load_state_dict(torch.load(weights_path))\n    else:\n        net = net_cls(pretrained=pretrained)\n    return net\n\n\nclass ResNet(nn.Module):\n    def __init__(self, num_classes,\n                 pretrained=False, net_cls=M.resnet50, dropout=False):\n        super().__init__()\n        self.net = create_net(net_cls, pretrained=pretrained)\n        self.net.avgpool = AvgPool()\n        if dropout:\n            self.net.fc = nn.Sequential(\n                nn.Dropout(),\n                nn.Linear(self.net.fc.in_features, num_classes),\n            )\n        else:\n            self.net.fc = nn.Linear(self.net.fc.in_features, num_classes)\n\n    def fresh_params(self):\n        return self.net.fc.parameters()\n\n    def forward(self, x):\n        return self.net(x)\n\n\nclass DenseNet(nn.Module):\n    def __init__(self, num_classes,\n                 pretrained=False, net_cls=M.densenet121):\n        super().__init__()\n        self.net = create_net(net_cls, pretrained=pretrained)\n        self.avg_pool = AvgPool()\n        self.net.classifier = nn.Linear(\n            self.net.classifier.in_features, num_classes)\n\n    def fresh_params(self):\n        return self.net.classifier.parameters()\n\n    def forward(self, x):\n        out = self.net.features(x)\n        out = F.relu(out, inplace=True)\n        out = self.avg_pool(out).view(out.size(0), -1)\n        out = self.net.classifier(out)\n        return out\n\n\n# resnet18 = partial(ResNet, net_cls=M.resnet18)\n# resnet34 = partial(ResNet, net_cls=M.resnet34)\nresnet50 = partial(ResNet, net_cls=M.resnet50)\n# resnet101 = partial(ResNet, net_cls=M.resnet101)\n# resnet152 = partial(ResNet, net_cls=M.resnet152)\n\n# densenet121 = partial(DenseNet, net_cls=M.densenet121)\n# densenet169 = partial(DenseNet, net_cls=M.densenet169)\n# densenet201 = partial(DenseNet, net_cls=M.densenet201)\n# densenet161 = partial(DenseNet, net_cls=M.densenet161)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = nn.BCEWithLogitsLoss(reduction='none')\nmodel = resnet50(num_classes=N_CLASSES, pretrained=True)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(model: nn.Module, path: Path) -> Dict:\n    state = torch.load(str(path))\n    model.load_state_dict(state['model'])\n#     print('Loaded model from epoch {epoch}, step {step:,}'.format(**state))\n    return model","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = load_model(model, f'{model_dir}/best-model.pt')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with timer('inference'):\n    \n    model.to(device) \n    \n    preds = []\n    tk0 = tqdm(enumerate(test_loader), total=len(test_loader))\n\n    for i, images in tk0:\n            \n        images = images.to(device)\n            \n        with torch.no_grad():\n            y_preds = model(images)\n            \n        preds.append(torch.sigmoid(y_preds).to('cpu').numpy())","metadata":{"scrolled":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"threshold = 0.10\npredictions = np.concatenate(preds) > threshold\n\nfor i, row in enumerate(predictions):\n    ids = np.nonzero(row)[0]\n    submission.iloc[i].attribute_ids = ' '.join([str(x) for x in ids])\n    \nsubmission.to_csv('submission.csv', index=False)\nsubmission.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.sum(preds[1], axis=1)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}