{"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 in \n'''\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nprint(os.listdir(\"../input\"))\nsub = pd.read_csv('../input/submit_csv.csv')\nsub.to_csv('submission.csv',index=False)\n# Any results you write to the current directory are saved as output.\n'''\nimport os\nimport argparse\nimport time\nfrom datetime import timedelta\nimport shutil\nfrom sklearn import metrics\nfrom PIL import Image, ImageOps\nimport torch.utils.data as data\nimport pandas as pd\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nfrom torch.autograd import Variable\nimport torch.backends.cudnn as cudnn\nfrom tqdm import tqdm\nimport numpy as np\nimport torchvision.transforms as transforms\nimport csv\nimport torch.nn.functional as F\nimport math\nfrom functools import partial","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torchvision.transforms as transforms\nimport random\nimport time\nfrom datetime import timedelta\nfrom PIL import Image, ImageOps\nimport numpy as np\nimport numbers\nimport math\nimport torch\nimport cv2\n\nclass GroupScale(object):\n    def __init__(self, size, interpolation=Image.BILINEAR):\n        self.worker = transforms.Resize(size, interpolation)\n    def __call__(self, img_group):\n        #for img in img_group:\n        #    img=cv2.cvtColor(np.asarray(img),cv2.COLOR_RGB2BGR)\n        #    cv2.imwrite('cv_out.png', img)\n        return [self.worker(img) for img in img_group]\n\nclass Stack(object):\n    def __init__(self, is_flow=False):\n        self.is_flow = is_flow\n    def __call__(self, img_group):\n        #  112 112 3\n        return np.stack(img_group, axis=0)\n        #1 112 112 3\n\nclass GroupCenterCrop(object):\n    def __init__(self, size):\n        self.worker = transforms.CenterCrop(size)\n\n    def __call__(self, img_group):\n        return [self.worker(img) for img in img_group]\n\n\nclass GroupRandomHorizontalFlip(object):\n    \"\"\"Randomly horizontally flips the given PIL.Image with a probability of 0.5\n    \"\"\"\n    def __init__(self, is_flow=False):\n        self.is_flow = is_flow\n\n    def __call__(self, img_group, is_flow=False):\n        v = random.random()\n        if v < 0.5:\n            ret = [img.transpose(Image.FLIP_LEFT_RIGHT) for img in img_group]\n            if self.is_flow:\n                for i in range(0, len(ret), 2):\n                    ret[i] = ImageOps.invert(ret[i])  # invert flow pixel values when flipping\n            return ret\n        else:\n            return img_group\n\nclass GroupRandomVerticalFlip(object):\n    \"\"\"Randomly horizontally flips the given PIL.Image with a probability of 0.5\n    \"\"\"\n    def __init__(self, is_flow=False):\n        self.is_flow = is_flow\n\n    def __call__(self, img_group):\n        v = random.random()\n        if v < 0.5:\n            ret = [img.transpose(Image.FLIP_TOP_BOTTOM) for img in img_group]\n            if self.is_flow:\n                for i in range(1, len(ret), 2):\n                    ret[i] = ImageOps.invert(ret[i])  # invert flow pixel values when flipping\n            return ret\n        else:\n            return img_group\n\n\nclass GroupNormalize(object):\n    def __init__(self, mean, std):\n        self.mean = mean\n        self.std = std\n\n    def __call__(self, tensor):\n        rep_mean = self.mean * (tensor.size()[0]//len(self.mean))\n        rep_std = self.std * (tensor.size()[0]//len(self.std))\n\n        # TODO: make efficient\n        for t, m, s in zip(tensor, rep_mean, rep_std):\n            t.sub_(m).div_(s)\n\n        return tensor\n\n\n\nclass GroupMultiScaleCrop(object):\n    def __init__(self, input_size, scales=None, max_distort=1, fix_crop=True, more_fix_crop=True):\n        self.scales = scales if scales is not None else [1, .875, .75, .66]\n        self.max_distort = max_distort\n        self.fix_crop = fix_crop\n        self.more_fix_crop = more_fix_crop\n        self.input_size = input_size if not isinstance(input_size, int) else [input_size, input_size]\n        self.interpolation = Image.BILINEAR\n\n    def __call__(self, img_group):\n        im_size = img_group[0].size\n        crop_w, crop_h, offset_w, offset_h = self._sample_crop_size(im_size)\n        crop_img_group = [img.crop((offset_w, offset_h, offset_w + crop_w, offset_h + crop_h)) for img in img_group]\n        ret_img_group = [img.resize((self.input_size[0], self.input_size[1]), self.interpolation) for img in crop_img_group]\n        return ret_img_group\n\n    def _sample_crop_size(self, im_size):\n        image_w, image_h = im_size[0], im_size[1]\n\n        # find a crop size\n        base_size = min(image_w, image_h)\n        crop_sizes = [int(base_size * x) for x in self.scales]\n        crop_h = [self.input_size[1] if abs(x - self.input_size[1]) < 3 else x for x in crop_sizes]\n        crop_w = [self.input_size[0] if abs(x - self.input_size[0]) < 3 else x for x in crop_sizes]\n\n        pairs = []\n        for i, h in enumerate(crop_h):\n            for j, w in enumerate(crop_w):\n                if abs(i - j) <= self.max_distort:\n                    pairs.append((w, h))\n\n        crop_pair = random.choice(pairs)\n        if not self.fix_crop:\n            w_offset = random.randint(0, image_w - crop_pair[0])\n            h_offset = random.randint(0, image_h - crop_pair[1])\n        else:\n            w_offset, h_offset = self._sample_fix_offset(image_w, image_h, crop_pair[0], crop_pair[1])\n\n        return crop_pair[0], crop_pair[1], w_offset, h_offset\n\n    def _sample_fix_offset(self, image_w, image_h, crop_w, crop_h):\n        offsets = self.fill_fix_offset(self.more_fix_crop, image_w, image_h, crop_w, crop_h)\n        return random.choice(offsets)\n\n    @staticmethod\n    def fill_fix_offset(more_fix_crop, image_w, image_h, crop_w, crop_h):\n        w_step = (image_w - crop_w) / 4\n        h_step = (image_h - crop_h) / 4\n\n        ret = list()\n        ret.append((0, 0))  # upper left\n        ret.append((4 * w_step, 0))  # upper right\n        ret.append((0, 4 * h_step))  # lower left\n        ret.append((4 * w_step, 4 * h_step))  # lower right\n        ret.append((2 * w_step, 2 * h_step))  # center\n\n        if more_fix_crop:\n            ret.append((0, 2 * h_step))  # center left\n            ret.append((4 * w_step, 2 * h_step))  # center right\n            ret.append((2 * w_step, 4 * h_step))  # lower center\n            ret.append((2 * w_step, 0 * h_step))  # upper center\n\n            ret.append((1 * w_step, 1 * h_step))  # upper left quarter\n            ret.append((3 * w_step, 1 * h_step))  # upper right quarter\n            ret.append((1 * w_step, 3 * h_step))  # lower left quarter\n            ret.append((3 * w_step, 3 * h_step))  # lower righ quarter\n\n        return ret\n\nclass GroupColorJitter(object):\n    def __init__(self, brightness=0, contrast=0, saturation=0, hue=0):\n        self.worker = transforms.ColorJitter(brightness=brightness, contrast=contrast, saturation=saturation, hue=hue)\n\n    def __call__(self, img_group):\n        return [self.worker(img) for img in img_group]\n\nclass GroupRandomRotate90(object):\n    def __init__(self, is_flow=False):\n        self.is_flow = is_flow\n\n    def __call__(self, img_group):\n        v = random.random()\n        if v < 0.5:\n            ret = [img.rotate(90) for img in img_group]\n            if self.is_flow:\n                ret2 = []\n                for i in range(0, len(ret), 2):\n                    ret2.append(ret[i+1])\n                    ret2.append(ret[i])  #change x, y flow when rotate\n                ret = ret2\n            return ret\n        else:\n            return img_group\n\n\nclass ToTorchFormatTensor(object):\n    \"\"\" Converts a PIL.Image (RGB) or numpy.ndarray (H x W x C) in the range [0, 255]\n    to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0] \"\"\"\n    def __init__(self, div=True):\n        self.div = div\n    def __call__(self, pic):\n        img = torch.from_numpy(pic).permute(3, 0, 1, 2).contiguous()\n        return img.float().div(255) if self.div else img.float()\n\n\nclass GroupRandomRotateAnyAngle_byLFN(object):\n    def __init__(self, angle=10):\n        self.angle = angle\n\n    def __call__(self, img_group):\n        v = random.uniform(-self.angle, self.angle)\n        ret = [img.rotate(v, expand=True) for img in img_group]\n        return ret\n\n\nclass LFN_crop(object):\n    def __init__(self, out_channel=1):\n        self.out_channel = out_channel\n    def __call__(self, img_group):\n        #start_time = time.time()\n        img_group1 = [cv2.cvtColor(np.asarray(img),cv2.COLOR_RGB2BGR) for img in img_group]\n        img_group2 = [LFN1_crop_and_resize(img) for img in img_group1]\n        img_group3 = [Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) for img in img_group2]\n        #print(str(timedelta(seconds=time.time()-start_time)))\n        return img_group3\ndef LFN1_crop_and_resize(img):\n    IMG_SIZE = 512\n    image = LFN1_crop_image3(img)\n    image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n    return image\n\n\nclass LFN_trick_1(object):\n    def __init__(self, out_channel=1):\n        self.out_channel = out_channel\n    def __call__(self, img_group):\n        #start_time = time.time()\n        img_group1 = [cv2.cvtColor(np.asarray(img),cv2.COLOR_RGB2BGR) for img in img_group]\n        img_group2 = [LFN1_gray_and_crop(img) for img in img_group1]\n        img_group3 = [Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) for img in img_group2]\n        #print(str(timedelta(seconds=time.time()-start_time)))\n        return img_group3\ndef LFN1_gray_and_crop(img):\n    dpi = 80 #inch\n    IMG_SIZE = 512\n    image = LFN1_crop_image3(img)\n    image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n    image=cv2.addWeighted(image,4, cv2.GaussianBlur(image,(0,0),IMG_SIZE/10),-4,128)\n    return image\ndef LFN1_crop_image1(img,tol=7):\n    # img is image data\n    # tol  is tolerance  \n    mask = img>tol\n    return img[np.ix_(mask.any(1),mask.any(0))]\n# The above code work only for 1-channel. Here is my simple extension for 3-channels image\ndef LFN1_crop_image3(img,tol=7):\n    h,w,_=img.shape\n    img1=cv2.resize(LFN1_crop_image1(img[:,:,0]),(w,h))\n    img2=cv2.resize(LFN1_crop_image1(img[:,:,1]),(w,h))\n    img3=cv2.resize(LFN1_crop_image1(img[:,:,2]),(w,h))\n    img[:,:,0]=img1\n    img[:,:,1]=img2\n    img[:,:,2]=img3\n    return img\n\nTransforms = {\n                'val':transforms.Compose([\n                                            LFN_trick_1(),\n                                            Stack(is_flow=False),\n                                            ToTorchFormatTensor(div=True),\n                                            GroupNormalize(mean=[110.63666788 / 255., 103.16065604 / 255., 96.29023126 / 255.], std=[38.7568578 / 255., 37.88248729 / 255., 40.02898126 / 255.])\n                                            ])\n            }","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def conv3x3(in_planes, out_planes, stride=1):\n    # 3x3 convolution with padding\n    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias=False)\n\n\ndef downsample_basic_block(x, planes, stride):\n    out = F.avg_pool2d(x, kernel_size=1, stride=stride)\n    zero_pads = torch.Tensor(out.size(0), planes - out.size(1), out.size(2), out.size(3),out.size(4)).zero_()\n    if isinstance(out.data, torch.cuda.FloatTensor):\n        zero_pads = zero_pads.cuda()\n    out = Variable(torch.cat([out.data, zero_pads], dim=1))\n    return out\n\n\nclass BasicBlock(nn.Module):\n    expansion = 1\n    def __init__(self, inplanes, planes, stride=1, downsample=None):\n        super(BasicBlock, self).__init__()\n        self.conv1 = conv3x3(inplanes, planes, stride)\n        self.bn1 = nn.BatchNorm2d(planes)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = conv3x3(planes, planes)\n        self.bn2 = nn.BatchNorm2d(planes)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        residual = x\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n        out = self.conv2(out)\n        out = self.bn2(out)\n        if self.downsample is not None:\n            residual = self.downsample(x)\n        out += residual\n        out = self.relu(out)\n        return out\n\nclass Bottleneck(nn.Module):\n    expansion = 4\n    def __init__(self, inplanes, planes, stride=1, downsample=None):\n        super(Bottleneck, self).__init__()\n        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(planes)\n        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)\n        self.bn2 = nn.BatchNorm2d(planes)\n        self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)\n        self.bn3 = nn.BatchNorm2d(planes * 4)\n        self.relu = nn.ReLU(inplace=True)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        residual = x\n        #print('^^^^^^^^^^^^^1',x.shape)\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n        #print('^^^^^^^^^^^^^2',out.shape)\n        out = self.conv2(out)\n        out = self.bn2(out)\n        out = self.relu(out)\n        #print('^^^^^^^^^^^^^3',out.shape)\n        out = self.conv3(out)\n        out = self.bn3(out)#256\n        #print('^^^^^^^^^^^^^4',out.shape)\n        if self.downsample is not None:\n            residual = self.downsample(x)\n            #print('highway')\n        #print('%%%%%%%%%%%%%%%',residual.shape)\n        out += residual\n        #print('###############',out.shape)\n        out = self.relu(out)\n\n        return out\n\nclass ResNet(nn.Module):\n\n    def __init__(self, block, layers, sample_size, sample_duration, shortcut_type, num_classes, dropout):\n        self.inplanes = 64\n\n        super(ResNet, self).__init__()\n\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)\n        self.bn1 = nn.BatchNorm2d(64)\n        self.relu = nn.ReLU(inplace=True)\n        self.maxpool = nn.MaxPool2d(kernel_size=(3, 3), stride=2, padding=1)\n\n        self.layer1 = self._make_layer(block, 64, layers[0], shortcut_type)\n        self.layer2 = self._make_layer(block, 128, layers[1], shortcut_type, stride=2)\n        self.layer3 = self._make_layer(block, 256, layers[2], shortcut_type, stride=2)\n        self.layer4 = self._make_layer(block, 512, layers[3], shortcut_type, stride=2)\n\n        last_duration = int(math.ceil(sample_duration / 16.))\n        last_size = int(math.ceil(sample_size / 32.))\n\n        self.avgpool = nn.AvgPool2d((last_size, last_size), stride=1)\n        self.drop = nn.Dropout(p=dropout)\n        self.fc = nn.Linear(512 * block.expansion, num_classes)\n\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                m.weight = nn.init.kaiming_normal_(m.weight, mode='fan_out')\n            elif isinstance(m, nn.BatchNorm2d):\n                m.weight.data.fill_(1)\n                m.bias.data.zero_()\n\n    def _make_layer(self, block, planes, blocks, shortcut_type, stride=1):\n        downsample = None\n        \n        if stride != 1 or self.inplanes != planes * block.expansion: \n        #如果： 步长 != 1 // 输入通道数 != 此块原始输入通道数*此块预计通道扩充倍数\n            if shortcut_type == 'A':\n                downsample = partial(downsample_basic_block,planes=planes * block.expansion,stride=stride)\n            else:\n                downsample = nn.Sequential(\n                    nn.Conv2d(self.inplanes, planes * block.expansion, kernel_size=1, stride=stride, bias=False), \n                    nn.BatchNorm2d(planes * block.expansion))\n\n        layers = []\n                               #1024          512       2       No.2\n        layers.append(block(self.inplanes, planes, stride, downsample))\n        #print('0',self.inplanes, planes)\n        self.inplanes = planes * block.expansion\n        for i in range(1, blocks):\n            layers.append(block(self.inplanes, planes))\n            #print(i,self.inplanes, planes)\n\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        #print('0',x.shape)\n        x = self.conv1(x)\n        #print('1',x.shape)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n        #print('2',x.shape)\n        x = self.layer1(x)\n        #print('3',x.shape)\n        x = self.layer2(x)\n        #print('4',x.shape)\n        x = self.layer3(x)\n        #print('5',x.shape)\n        x = self.layer4(x)\n        #print('6',x.shape)\n\n\n        x = self.avgpool(x)\n        #print('7',x.shape)\n\n        x = x.view(x.size(0), -1)\n        x = self.drop(x)\n        x = self.fc(x)\n\n        return x\n\ndef resnet34(**kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    \"\"\"\n    model = ResNet(BasicBlock, [3, 4, 6, 3], **kwargs)\n    return model\n\ndef resnet50(**kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    \"\"\"\n    model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs)\n    return model\n\ndef resnet101(**kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    \"\"\"\n    model = ResNet(Bottleneck, [3, 4, 23, 3], **kwargs)\n    return model\n\ndef resnet152(**kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    \"\"\"\n    model = ResNet(Bottleneck, [3, 8, 36, 3], **kwargs)\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.environ['CUDA_VISIBLE_DEVICES'] = '0'\n\nmodel_dict = {\n'34': [resnet34, 'A'],\n'50': [resnet50, 'B'],\n'101':[resnet101, 'B'],\n'152':[resnet152, 'B']\n}\nweights = '../input/weights2/blind_resnet50_best_80.08298754131481.pth'\nmodel = model_dict['50'][0](sample_size=512, sample_duration=16, shortcut_type=model_dict['50'], num_classes=5, dropout=0)\nmodel = torch.nn.DataParallel(model)\nmodel = model.cuda()\nckpt = torch.load(weights)\nmodel.load_state_dict(ckpt['state_dict'])\nmodel.eval()\nprint('Validating...')","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"imgs_dict = {}\nfinal = []\nimgs = pd.read_csv(os.path.join('../input/aptos2019-blindness-detection', 'test.csv'), usecols=[0])\nimg_group = []\nnum = imgs.shape[0]\nsub = []\n\nfor i in tqdm(range(num)):\n    final.append(imgs.loc[i][0])\n    img_name = final[i]+'.png'\n    #print(img_name)\n    transform_val = Transforms['val']\n    img_group.append(Image.open('../input/aptos2019-blindness-detection/test_images/' + img_name))\n    img = transform_val(img_group)\n    img_group = []\n    img = img.view(-1,3,512,512)\n    #print(img_name,img.shape)\n    input_ = img\n    input_var = Variable(input_)\n    with torch.no_grad():\n        output = model(input_var)\n\n    _, pred = output.topk(1, 1, True, True)\n    pred_1 = pred.t()\n    #print(pred_1.item())\n    sub.append(str(pred_1.item()))\n    #print(i,sub[i])\nprint(len(sub))\nsample = pd.read_csv(\"../input/aptos2019-blindness-detection/sample_submission.csv\")\n#sample.diagnosis = sub\nsample['diagnosis'] = sub\nsample.to_csv(\"submission.csv\", index=False)\nsample.head()\nprint (\"write over\")\n","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}