{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport albumentations\nimport argparse\nimport collections\nimport cv2\nimport datetime\nimport gc\nimport glob\nimport logging\nimport math\nimport operator\nimport os \nimport pickle\nimport pkg_resources\nimport random\nimport re\nimport scipy.stats as stats\nimport seaborn as sns\nimport shutil\nimport sys\nimport time\nimport torch\nimport torch.nn as nn\nimport torch.utils.data\nimport torch.nn.functional as F\nimport torchvision\nfrom torchvision import models, transforms\nfrom contextlib import contextmanager\nfrom collections import OrderedDict\n# from nltk.stem import PorterStemmer\nfrom sklearn import metrics\nfrom sklearn import model_selection\nfrom sklearn.model_selection import KFold, GroupKFold\nfrom sklearn.feature_extraction.text import TfidfVectorizer\nfrom sklearn.decomposition import TruncatedSVD\nfrom sklearn.metrics import mean_squared_log_error\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder, OneHotEncoder, StandardScaler\nfrom torch.nn import CrossEntropyLoss, MSELoss\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import (Dataset,DataLoader, RandomSampler, SequentialSampler,\n                              TensorDataset)\nimport tensorflow as tf\nfrom PIL import Image\n\n%load_ext autoreload\n%autoreload 2\n%matplotlib inline\n# from tqdm import tqdm, tqdm_notebook, trange\nfrom tqdm._tqdm_notebook import tqdm_notebook as tqdm\ntqdm.pandas()\nfrom IPython.core.interactiveshell import InteractiveShell\nInteractiveShell.ast_node_interactivity = \"all\"\nimport warnings\nwarnings.filterwarnings('ignore')\n# from apex import amp\n\n# import sys\n# sys.path.append(\"drive/My Drive/transformers\")\n\nfrom torch.utils.data.distributed import DistributedSampler\n\ntry:\n    from torch.utils.tensorboard import SummaryWriter\nexcept:\n    from tensorboardX import SummaryWriter\n\nimport matplotlib.pyplot as plt\nfrom matplotlib.font_manager import FontProperties\n\nSEED = 1129\n\ndef seed_everything(seed=1129):\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\nseed_everything(SEED)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import logging\nimport sys\n\nLOGGER = logging.getLogger()\nFORMATTER = logging.Formatter(\"%(asctime)s - %(levelname)s - %(message)s\")\n\n\ndef setup_logger(out_file=None, stderr=True, stderr_level=logging.INFO, file_level=logging.DEBUG):\n    LOGGER.handlers = []\n    LOGGER.setLevel(min(stderr_level, file_level))\n\n    if stderr:\n        handler = logging.StreamHandler(sys.stderr)\n        handler.setFormatter(FORMATTER)\n        handler.setLevel(stderr_level)\n        LOGGER.addHandler(handler)\n\n    if out_file is not None:\n        handler = logging.FileHandler(out_file)\n        handler.setFormatter(FORMATTER)\n        handler.setLevel(file_level)\n        LOGGER.addHandler(handler)\n\n    LOGGER.info(\"logger set up\")\n    return LOGGER\n\n# ===============\n# Settings\n# ===============\n# SEED = np.random.randint(100000)\ndevice = \"cuda\"\nOUT_DIR = '/kaggle/working'\n\nbatch_size = 4\naccumulation_steps = 8\n# fold_id = 0\n# epochs = 5\nEXP_ID = \"exp1\"\nLOGGER_PATH = f\"log_{EXP_ID}.txt\"\nmodel_path = None\n\nsetup_logger(out_file=LOGGER_PATH)\nLOGGER.info(\"seed={}\".format(SEED))\n\n\n@contextmanager\ndef timer(name):\n    t0 = time.time()\n    yield\n    LOGGER.info('[{}] done in {} s'.format(name, round(time.time() - t0, 2)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# !ls ../input/bengali-preprocessed-zip-resize128128-otsumethod/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import albumentations\nfrom albumentations import pytorch as AT\nimport torchvision.transforms as transforms\n\ndef image_to_tensor(image, normalize=None):\n    tensor = torch.from_numpy(np.moveaxis(image / (255. if image.dtype == np.uint8 else 1), -1, 0).astype(np.float32))\n    if normalize is not None:\n        return F.normalize(tensor)\n    return tensor\n\ndata_transforms = albumentations.Compose([\n    albumentations.Resize(128, 128),\n    # albumentations.Flip(p=0.5),\n    # albumentations.Normalize(),\n    # AT.ToTensor()\n    ])\n\ndata_transforms_test = albumentations.Compose([\n    albumentations.Resize(128, 128),\n    # albumentations.Normalize(),\n    # AT.ToTensor()\n    ])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class ResidualBlock(nn.Module):\n    def __init__(self,in_channels,out_channels,stride=1,kernel_size=3,padding=1,bias=False):\n        super(ResidualBlock,self).__init__()\n        self.cnn1 =nn.Sequential(\n            nn.Conv2d(in_channels,out_channels,kernel_size,stride,padding,bias=False),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(True)\n        )\n        self.cnn2 = nn.Sequential(\n            nn.Conv2d(out_channels,out_channels,kernel_size,1,padding,bias=False),\n            nn.BatchNorm2d(out_channels)\n        )\n        if stride != 1 or in_channels != out_channels:\n            self.shortcut = nn.Sequential(\n                nn.Conv2d(in_channels,out_channels,kernel_size=1,stride=stride,bias=False),\n                nn.BatchNorm2d(out_channels)\n            )\n        else:\n            self.shortcut = nn.Sequential()\n            \n    def forward(self,x):\n        residual = x\n        x = self.cnn1(x)\n        x = self.cnn2(x)\n        x += self.shortcut(residual)\n        x = nn.ReLU(True)(x)\n\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"hidden_size = 64\nchannel_size = 1\n\nclass ResNet18(nn.Module):\n    def __init__(self):\n        super(ResNet18,self).__init__()\n        \n        self.block1 = nn.Sequential(\n            nn.Conv2d(channel_size,hidden_size,kernel_size=2,stride=2,padding=3,bias=False),\n            nn.BatchNorm2d(hidden_size),\n            nn.ReLU(True)\n        )\n        \n        self.block2 = nn.Sequential(\n            nn.MaxPool2d(1,1),\n            ResidualBlock(hidden_size,hidden_size),\n            ResidualBlock(hidden_size,hidden_size,2)\n        )\n        \n        self.block3 = nn.Sequential(\n            ResidualBlock(hidden_size,hidden_size*2),\n            ResidualBlock(hidden_size*2,hidden_size*2,2)\n        )\n        \n        self.block4 = nn.Sequential(\n            ResidualBlock(hidden_size*2,hidden_size*4),\n            ResidualBlock(hidden_size*4,hidden_size*4,2)\n        )\n        self.block5 = nn.Sequential(\n            ResidualBlock(hidden_size*4,hidden_size*8),\n            ResidualBlock(hidden_size*8,hidden_size*8,2)\n        )\n        \n        self.avgpool = nn.AvgPool2d(2)\n        self.fc = nn.Linear(512*4,512)  \n        # vowel_diacritic\n        self.fc1 = nn.Linear(512,11)\n        # grapheme_root\n        self.fc2 = nn.Linear(512,168)\n        # consonant_diacritic\n        self.fc3 = nn.Linear(512,7)\n        \n    def forward(self,x):\n        x = self.block1(x)\n        x = self.block2(x)\n        x = self.block3(x)\n        x = self.block4(x)\n        x = self.block5(x)\n        x = self.avgpool(x)\n        x = x.view(x.size(0),-1)\n        x = self.fc(x)\n        x1 = self.fc1(x)\n        x2 = self.fc2(x)\n        x3 = self.fc3(x)\n        return x1,x2,x3","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ls ../input/bengali-exp5/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with timer('create model'):\n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    # model = torchvision.models.resnet50(pretrained=True)\n    # model.load_state_dict(torch.load(\"../input/pytorch-pretrained-models/resnet101-5d3b4d8f.pth\"))\n    \n    model = ResNet18()\n    model.load_state_dict(torch.load(\"../input/bengali-exp5/exp1_fold0.pth\"))\n    model = model.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import PIL\ndef threshold_image(img):\n    '''\n    Helper function for thresholding the images\n    '''\n    gray = PIL.Image.fromarray(np.uint8(img), 'L')\n    ret,th = cv2.threshold(np.array(gray),0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)\n    return th","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class BengaliAIDatasetTest(torch.utils.data.Dataset):\n    def __init__(self,df,transform=None):\n        self.df = df\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self,idx):\n        \n        input_dic = {}\n        image = self.df.iloc[idx][1:].values.reshape(128,128).astype(np.float)\n        image = threshold_image(image)\n        image = self.transform(image=image)['image']\n        image = (image.astype(np.float32) - 0.0692) / 0.2051\n        image = image_to_tensor(image, normalize=False) \n        \n        input_dic['image'] = image\n        \n        return input_dic","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Credits: https://www.kaggle.com/phoenix9032/pytorch-efficientnet-starter-code/data\n\nSIZE = 128\nHEIGHT=137\nWIDTH=236\n\ndef bbox(img):\n    rows = np.any(img, axis=1)\n    cols = np.any(img, axis=0)\n    rmin, rmax = np.where(rows)[0][[0, -1]]\n    cmin, cmax = np.where(cols)[0][[0, -1]]\n    return rmin, rmax, cmin, cmax\n\ndef crop_resize(img0, size=SIZE, pad=16):\n    \n    #crop a box around pixels large than the threshold \n    #some images contain line at the sides\n    ymin,ymax,xmin,xmax = bbox(img0[5:-5,5:-5] > 80)\n    \n    #cropping may cut too much, so we need to add it back\n    xmin = xmin - 13 if (xmin > 13) else 0\n    ymin = ymin - 10 if (ymin > 10) else 0\n    xmax = xmax + 13 if (xmax < WIDTH - 13) else WIDTH\n    ymax = ymax + 10 if (ymax < HEIGHT - 10) else HEIGHT\n    img = img0[ymin:ymax,xmin:xmax]\n    \n    #remove lo intensity pixels as noise\n    img[img < 28] = 0\n    lx, ly = xmax-xmin,ymax-ymin\n    l = max(lx,ly) + pad\n    \n    #make sure that the aspect ratio is kept in rescaling\n    img = np.pad(img, [((l-ly)//2,), ((l-lx)//2,)], mode='constant')\n    return cv2.resize(img,(size,size))\n\ndef Resize(df,size=128):\n    resized = {} \n    df = df.set_index('image_id')\n    \n    for i in tqdm(range(df.shape[0])): \n        image0 = 255 - df.loc[df.index[i]].values.reshape(137,236).astype(np.uint8)\n        \n        #normalize each image by its max val\n        img = (image0*(255.0/image0.max())).astype(np.uint8)\n        image = crop_resize(img)\n        resized[df.index[i]] = image.reshape(-1)\n    resized = pd.DataFrame(resized).T.reset_index()\n    resized.columns = resized.columns.astype(str)\n    resized.rename(columns={'index':'image_id'},inplace=True)\n    return resized","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# !ls ../input/bengaliaicv19feather/\n\nwith timer('predict'):\n    model.eval()\n    test_data = [\n        '../input/bengaliaicv19feather/test_image_data_0.feather',\n        '../input/bengaliaicv19feather/test_image_data_1.feather',\n        '../input/bengaliaicv19feather/test_image_data_2.feather',\n        '../input/bengaliaicv19feather/test_image_data_3.feather',\n    ]\n    predictions = []\n    batch_size=1\n    for fname in tqdm(test_data):\n        data = pd.read_feather(fname)\n        data = Resize(data,size=128)\n        test_dataset = BengaliAIDatasetTest(data, transform=data_transforms_test)\n        test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=0, pin_memory=True)\n        with torch.no_grad():\n            for step, (input_dic) in tqdm(enumerate(test_loader), total=len(test_loader)):\n                for k in input_dic.keys():\n                    input_dic[k] = input_dic[k].to(device)\n\n                    outputs1,outputs2,outputs3 = model(input_dic[\"image\"].unsqueeze(1))\n                    predictions.append(outputs3.argmax(1).cpu().detach().numpy())\n                    predictions.append(outputs2.argmax(1).cpu().detach().numpy())\n                    predictions.append(outputs1.argmax(1).cpu().detach().numpy())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = pd.read_csv('/kaggle/input/bengaliai-cv19/sample_submission.csv')\nsubmission.target = np.hstack(predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"LOGGER.info('submission head10 : {}'.format(submission.head(10)))\n\nLOGGER.info('target value_counts : {}'.format(submission.target.value_counts()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.to_csv('submission.csv',index=False)","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":1}