{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Clean PyTorch customizable pipeline [Inference]"},{"metadata":{},"cell_type":"markdown","source":"It's an inference part of \"Fast&Automated clean PyTorch pipeline\".   \nCheck out the training part [here](https://www.kaggle.com/vadimtimakin/fast-automated-clean-pytorch-pipeline-train).\n\nYou can use this inference for any PyTorch model. Just set its name in the config."},{"metadata":{},"cell_type":"markdown","source":"### Imports"},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch\nimport torchvision.models as models\nimport numpy as np\nimport pandas as pd\nimport random\nimport os\nimport cv2\nimport torch.nn as nn\nimport albumentations as A\nfrom albumentations.pytorch import ToTensor\nfrom tqdm.notebook import tqdm","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Config"},{"metadata":{"trusted":true},"cell_type":"code","source":"class cfg:\n    \"\"\"Main config.\"\"\"\n    \n    NUMCLASSES = 5  # CONST\n    seed = 42       # random seed\n    \n    pathtoimgs = \"../input/cassava-leaf-disease-classification/test_images\"  # Path to folder with train images\n    pathtocsv = \"../input/cassava-leaf-disease-classification/sample_submission.csv\"  # Path to csv-file with targets\n    chk = \"../input/cassava/weights.pt\"  # Path to model checkpoint (weights)\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")  # Device\n    modelname = \"resnet18\"  # PyTorch model\n    \n    apex = True            # Set True if you've used Apex for training\n    apexoptlvl = \"O1\"      # Apex optimization level you've used for training\n    batchsize = 1   # BatchSize\n    numworkers = 4  # Number of workers\n    \n    # Transforms\n    transforms = [\n        dict(\n            name=\"Resize\",\n            params=dict(\n                height=256,\n                width=256,\n                p=1.0,\n            )\n        ),\n        dict(\n            name=\"Normalize\",\n            params=dict(\n                mean=[0.485, 0.456, 0.406],\n                std=[0.229, 0.224, 0.225],\n                max_pixel_value=255.0,\n                p=1.0\n            )\n        ),\n        dict(\n            name=\"/custom/totensor\",\n            params=dict(\n            )\n        ),\n    ]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(cfg.device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if cfg.apex:    \n    !git clone https://github.com/NVIDIA/apex && cd apex && pip install -v --no-cache-dir --global-option=\"--cpp_ext\" --global-option=\"--cuda_ext\" . --user && cd .. && rm -rf apex\n    from apex import amp","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Custom transforms (check the training notebook)"},{"metadata":{"trusted":true},"cell_type":"code","source":"def totensor():\n    return A.pytorch.ToTensor()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Reproducibility"},{"metadata":{"trusted":true},"cell_type":"code","source":"def fullseed(seed=42):\n    \"\"\"Sets the random seeds.\"\"\"\n    random.seed(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    os.environ['PYTHONHASHSEED'] = str(seed)\n\n    \nfullseed(cfg.seed)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_model(cfg):\n    \"\"\"Get PyTorch model.\"\"\"\n    model = getattr(models, cfg.modelname)(pretrained=False)\n    lastlayer = list(model._modules)[-1]\n    setattr(model, lastlayer, nn.Linear(in_features=getattr(model, lastlayer).in_features,\n                                        out_features=cfg.NUMCLASSES, bias=True))\n    cp = torch.load(cfg.chk)\n    if 'model' in cp:\n        model.load_state_dict(cp['model'])\n    else:\n        model.load_state_dict(cp)\n    if \"amp\" in cp and \"optimizer\" in cp:\n        optimizer = cp[\"optimizer\"]\n        model, optimizer = amp.initialize(model, optimizer, opt_level=cfg.apexoptlvl, verbosity=0)\n        amp.load_state_dict(cp['amp'])\n    return model.to(cfg.device)\n\n\ndef get_transforms(cfg):\n    \"\"\"Get train and test augmentations.\"\"\"\n    transforms = [globals()[item[\"name\"][8:]](**item[\"params\"]) if item[\"name\"].startswith(\"/custom/\") \n                     else getattr(A, item[\"name\"])(**item[\"params\"]) for item in cfg.transforms]\n    return A.Compose(transforms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class CassavaDataset(torch.utils.data.Dataset):\n    \"\"\"Cassava Dataset for uploading images and targets.\"\"\"\n    \n    def __init__(self, cfg, images, transforms):\n        self.images = images           # List with images\n        self.transforms = transforms   # Transforms\n        self.cfg = cfg                 # Config\n        \n    def __getitem__(self, idx):\n        img = cv2.imread(os.path.join(self.cfg.pathtoimgs, self.images[idx]))\n        img = torch.FloatTensor(self.transforms(image=img)[\"image\"])\n        return img\n\n    def __len__(self):\n        return len(self.images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_loader(cfg):\n    \"\"\"Getting dataloaders for train, validation (and test, if needed).\"\"\"\n    data = pd.read_csv(cfg.pathtocsv)\n    imgs = list(data[\"image_id\"])\n    transforms = get_transforms(cfg)\n    dataset = CassavaDataset(cfg, imgs, transforms)\n    dataloader = torch.utils.data.DataLoader(dataset,\n                                             shuffle=False,\n                                             batch_size=cfg.batchsize,\n                                             pin_memory=True,\n                                             num_workers=cfg.numworkers)\n    return dataloader","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Inference"},{"metadata":{"trusted":true},"cell_type":"code","source":"torch.cuda.empty_cache()\ndataloader = get_loader(cfg)\nmodel = get_model(cfg) \nmodel.eval()\n\npreds = []\nwith torch.no_grad():\n    for img in tqdm(dataloader):\n        outputs = model(img.to(cfg.device))\n        preds.append(np.argmax(outputs.to('cpu').numpy()).tolist())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Creating submission file"},{"metadata":{"trusted":true},"cell_type":"code","source":"print(preds)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv(cfg.pathtocsv)\ndf.head()\ndf[\"label\"] = preds\ndf.to_csv('submission.csv', index=False)\ndf.head()","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}