[
  {
    "path": "README.md",
    "content": "## 华为云垃圾分类挑战杯亚军方案分享\n\n### 1.代码结构\n\n```\n {repo_root}\n  ├── models\t//模型文件夹\n  ├── utils\t\t//一些函数包\n  |   ├── eval.py\t\t// 求精度\n  │   ├── misc.py\t\t// 模型保存，参数初始化，优化函数选择\n  │   ├── radam.py\n  │   └── ...\n  ├── args.py\t\t//参数配置文件\n  ├── build_net.py\t\t//搭建模型\n  ├── dataset.py\t\t//数据批量加载文件\n  ├── preprocess.py\t\t//数据预处理文件，生成坐标标签\n  ├── train.py\t\t//训练运行文件\n  ├── transform.py\t\t//数据增强文件\n```\n\n### 2. 环境设置\n\n可以直接通过`pip install -r requirements.txt`安装指定的函数包，python版本为3.6，具体的函数包如下：\n\n* pytorch>=1.0.1\n* torchvision==0.2.2\n* matplotlib>=3.1.0\n* numpy>=1.16.4\n* scikit-image\n* pandas\n* sklearn\n\n注：py3.7训练的话，要修改下面的代码\n`if use_cuda: inputs, targets = inputs.cuda(), targets.cuda(async=True) inputs, targets = torch.autograd.Variable(inputs), torch.autograd.Variable(targets)`\n\\#python3.7已经移除了async关键字，而用non_blocking代替。(导致apache-airflow也出了问题)\n\\#cuda() 本身也没有async.\n\n就是把 async=True去掉\n\nif use_cuda:\ninputs, targets = inputs.cuda(), targets.cuda()\ninputs, targets = torch.autograd.Variable(inputs), torch.autograd.Variable(targets)`\n\n## 3.运行步骤\n\n1. 建立文件夹data，把garbage_classify全部解压缩到data下\n2. 运行preprocess.py，生成训练集和测试集运行文\n3. 单张显卡的话，修改arg.py 85行 parser.add_argument('--gpu-id', default='0, 1, 2, 3' 为'--gpu-id', default='0'，同时修改 '--train-batch'，'--test-batch'为适当的数字\n4. 运行train.py\n\n### 4.方案思路\n\n[方案讲解](https://mp.weixin.qq.com/s/7GhXMXQkBgH_JVcKMjCejQ)\n\n知乎专栏：[ML与DL成长之路](https://zhuanlan.zhihu.com/ai-growth)\n\n如果复现过程中有bug，麻烦反馈一下，会优化更新。如果对您有帮助记得给个**star**\n\n---\n\n**小尾巴**\n\nQQ群：AI成长社①：545702197\n\n微信群：添加微信号：Derek_wen8，备注：加群"
  },
  {
    "path": "args.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-08-15 14:25\n公众号：AI成长社\n知乎：https://www.zhihu.com/people/qlmx-61/columns\n\"\"\"\nimport argparse\nfrom build_net import model_names\n\n# Parse arguments\nparser = argparse.ArgumentParser(description='PyTorch ImageNet Training')\n\n# Datasets\nparser.add_argument('-train', '--trainroot', default='data/new_shu_label.txt', type=str) #new_shu_label\nparser.add_argument('-val', '--valroot', default='data/val1.txt', type=str)\n\nparser.add_argument('-j', '--workers', default=4, type=int, metavar='N',\n                    help='number of data loading workers (default: 4)')\n# Optimization options\nparser.add_argument('--epochs', default=200, type=int, metavar='N',\n                    help='number of total epochs to run')\nparser.add_argument('--num-classes', default=43, type=int, metavar='N',\n                    help='number of classfication of image')\nparser.add_argument('--image-size', default=288, type=int, metavar='N',\n                    help='the train image size')\nparser.add_argument('--start-epoch', default=0, type=int, metavar='N',\n                    help='manual epoch number (useful on restarts)')\nparser.add_argument('--train-batch', default=64, type=int, metavar='N',\n                    help='train batchsize (default: 256)')\nparser.add_argument('--test-batch', default=32, type=int, metavar='N',\n                    help='test batchsize (default: 200)')\nparser.add_argument('--optimizer', default='sgd',\n                         choices=['sgd', 'rmsprop', 'adam', 'AdaBound', 'radam'], metavar='N',\n                         help='optimizer (default=sgd)')\nparser.add_argument('--lr', '--learning-rate', default=0.001, type=float,\n                    metavar='LR', help='initial learning rate，1e-2， 1e-4, 0.001')\nparser.add_argument('--lr-fc-times', '--lft', default=5, type=int,\n                    metavar='LR', help='initial model last layer rate')\nparser.add_argument('--drop', '--dropout', default=0, type=float,\n                    metavar='Dropout', help='Dropout ratio')\nparser.add_argument('--schedule', type=int, nargs='+', default=[30, 50, 60],\n                        help='Decrease learning rate at these epochs.')\nparser.add_argument('--gamma', type=float, default=0.1, help='LR is multiplied by gamma on schedule.')\nparser.add_argument('--momentum', default=0.9, type=float, metavar='M',\n                    help='momentum')\nparser.add_argument('--no_nesterov', dest='nesterov',\n                         action='store_false',\n                         help='do not use Nesterov momentum')\nparser.add_argument('--alpha', default=0.99, type=float, metavar='M',\n                         help='alpha for ')\nparser.add_argument('--beta1', default=0.9, type=float, metavar='M',\n                         help='beta1 for Adam (default: 0.9)')\nparser.add_argument('--beta2', default=0.999, type=float, metavar='M',\n                         help='beta2 for Adam (default: 0.999)')\nparser.add_argument('--weight-decay', '--wd', default=1e-4, type=float,\n                    metavar='W', help='weight decay (default: 1e-4)')\nparser.add_argument('--final-lr', '--fl', default=1e-3,type=float,\n                    metavar='W', help='weight decay (default: 1e-3)')\n# Checkpoints\nparser.add_argument('-c', '--checkpoint', default='/data0/search/qlmx/clover/garbage/res_16_288_last1', type=str, metavar='PATH',\n                    help='path to save checkpoint (default: checkpoint)')\nparser.add_argument('--resume', default='', type=str, metavar='PATH',\n                    help='path to latest checkpoint (default: none)')\n# Architecture\nparser.add_argument('--arch', '-a', metavar='ARCH', default='resnext101_32x16d_wsl',\n                    choices=model_names,\n                    help='model architecture: ' +\n                        ' | '.join(model_names) +\n                        ' (default: resnext101_32x8d, pnasnet5large)')\nparser.add_argument('--depth', type=int, default=29, help='Model depth.')\nparser.add_argument('--cardinality', type=int, default=32, help='ResNet cardinality (group).')\nparser.add_argument('--base-width', type=int, default=4, help='ResNet base width.')\nparser.add_argument('--widen-factor', type=int, default=4, help='Widen factor. 4 -> 64, 8 -> 128, ...')\n# Miscs\nparser.add_argument('--manualSeed', type=int, help='manual seed')\nparser.add_argument('-e', '--evaluate', dest='evaluate', action='store_true',\n                    help='evaluate model on validation set')\nparser.add_argument('--pretrained', dest='pretrained', action='store_true',\n                    help='use pre-trained model')\n#Device options\nparser.add_argument('--gpu-id', default='0, 1, 2, 3', type=str,\n                    help='id(s) for CUDA_VISIBLE_DEVICES')\n\nargs = parser.parse_args()\n"
  },
  {
    "path": "build_net.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-08-15 14:30\n\"\"\"\nfrom torch import nn\nimport torchvision.models as models\nimport models as customized_models\n\n# Models\ndefault_model_names = sorted(name for name in models.__dict__\n                             if name.islower() and not name.startswith(\"__\")\n                             and callable(models.__dict__[name]))\n\ncustomized_models_names = sorted(name for name in customized_models.__dict__\n                                 if not name.startswith(\"__\")\n                                 and callable(customized_models.__dict__[name]))\n\nfor name in customized_models.__dict__:\n    if not name.startswith(\"__\") and callable(customized_models.__dict__[name]):\n        models.__dict__[name] = customized_models.__dict__[name]\n\nmodel_names = default_model_names + customized_models_names\n\n\ndef make_model(args):\n    print(\"=> creating model '{}'\".format(args.arch))\n    model = models.__dict__[args.arch](progress=True)\n    model.fc = nn.Sequential(\n        nn.Dropout(0.2),\n        nn.Linear(2048, args.num_classes)\n    )\n    return model\n\nif __name__=='__main__':\n    all_model = sorted(name for name in models.__dict__ if not name.startswith(\"__\"))\n    print(all_model)\n"
  },
  {
    "path": "dataset.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-09-07 20:27\n公众号：AI成长社\n知乎：https://www.zhihu.com/people/qlmx-61/columns\n\"\"\"\nimport random\nimport torch\nfrom torch.utils.data import Dataset\nfrom torch.utils.data import sampler\nimport torchvision.transforms as transforms\nimport pandas as pd\nimport six\nimport sys\nfrom PIL import Image\nimport numpy as np\n\nclass Dataset(Dataset):\n    def __init__(self, root=None, transform=None, target_transform=None, to=None):\n        if '.txt' in root:\n            self.env = list(open(root))\n        else:\n            self.env = root\n\n        if not self.env:\n            print('cannot creat lmdb from %s' % (root))\n            sys.exit(0)\n\n        self.len = len(self.env) - 1\n\n        self.transform = transform\n        self.target_transform = target_transform\n\n    def __len__(self):\n        return self.len\n\n    def __getitem__(self, index):\n        assert index <= len(self), 'index range error'\n        index += 1\n        img_path, label = self.env[index].strip().split(',')\n\n        try:\n            img = Image.open(img_path)\n        except:\n            print(img_path)\n            print('Corrupted image for %d' % index)\n            return self[index + 1]\n\n        if self.transform is not None:\n            if img.layers == 1:\n                print(img_path)\n            img = self.transform(img)\n\n        if self.target_transform is not None:\n            label = self.target_transform(label)\n        return (img, int(label))\n\nclass TestDataset(Dataset):\n    def __init__(self, root=None, transform=None, target_transform=None, to=None):\n        if '.txt' in root:\n            self.env = list(open(root))\n        else:\n            self.env = root\n\n        if not self.env:\n            print('cannot creat lmdb from %s' % (root))\n            sys.exit(0)\n\n        self.len = len(self.env) - 1\n\n        self.transform = transform\n        self.target_transform = target_transform\n        self.to = to\n\n    def __len__(self):\n        return self.len\n\n    def __getitem__(self, index):\n        assert index <= len(self), 'index range error'\n        index += 1\n        img_path, label = self.env[index].strip().split(',')\n\n        try:\n            img = Image.open(img_path)\n        except:\n            print(img_path)\n            print('Corrupted image for %d' % index)\n            return self[index + 1]\n\n        if self.transform is not None:\n            img = self.transform(img)\n\n\n        if self.target_transform is not None:\n            label = self.target_transform(label)\n\n        return (img, int(label))\n\n\nclass resizeNormalize(object):\n\n    def __init__(self, size, interpolation=Image.BILINEAR):\n        self.size = size\n        self.interpolation = interpolation\n        self.toTensor = transforms.ToTensor()\n\n    def __call__(self, img):\n        # padding\n        ratio = self.size[0] / self.size[1]\n        w, h = img.size\n        if w / h < ratio:\n            t = int(h * ratio)\n            w_padding = (t - w) // 2\n            img = img.crop((-w_padding, 0, w+w_padding, h))\n        else:\n            t = int(w / ratio)\n            h_padding = (t - h) // 2\n            img = img.crop((0, -h_padding, w, h+h_padding))\n\n        # img.show()\n        # resize\n        img = img.resize(self.size, self.interpolation)\n        img = self.toTensor(img)\n        img.sub_(0.5).div_(0.5)\n        return img"
  },
  {
    "path": "models/Res.py",
    "content": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the license found in the\n# LICENSE file in the root directory of this source tree.\n#\n\nimport torch.nn as nn\ntry:\n    from torch.hub import load_state_dict_from_url\nexcept ImportError:\n    from torch.utils.model_zoo import load_url as load_state_dict_from_url\n\n\n__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',\n           'resnet152', 'resnext50_32x4d', 'resnext101_32x8d']\n\n\nmodel_urls = {\n    'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',\n    'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',\n    'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',\n    'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',\n    'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',\n    'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth',\n    'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth',\n}\n\n\ndef conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):\n    \"\"\"3x3 convolution with padding\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,\n                     padding=dilation, groups=groups, bias=False, dilation=dilation)\n\n\ndef conv1x1(in_planes, out_planes, stride=1):\n    \"\"\"1x1 convolution\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)\n\n\nclass BasicBlock(nn.Module):\n    expansion = 1\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(BasicBlock, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        if groups != 1 or base_width != 64:\n            raise ValueError('BasicBlock only supports groups=1 and base_width=64')\n        if dilation > 1:\n            raise NotImplementedError(\"Dilation > 1 not supported in BasicBlock\")\n        # Both self.conv1 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv3x3(inplanes, planes, stride)\n        self.bn1 = norm_layer(planes)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = conv3x3(planes, planes)\n        self.bn2 = norm_layer(planes)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass Bottleneck(nn.Module):\n    expansion = 4\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(Bottleneck, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        width = int(planes * (base_width / 64.)) * groups\n        # Both self.conv2 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv1x1(inplanes, width)\n        self.bn1 = norm_layer(width)\n        self.conv2 = conv3x3(width, width, stride, groups, dilation)\n        self.bn2 = norm_layer(width)\n        self.conv3 = conv1x1(width, planes * self.expansion)\n        self.bn3 = norm_layer(planes * self.expansion)\n        self.relu = nn.ReLU(inplace=True)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n        out = self.relu(out)\n\n        out = self.conv3(out)\n        out = self.bn3(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass ResNet(nn.Module):\n\n    def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,\n                 groups=1, width_per_group=64, replace_stride_with_dilation=None,\n                 norm_layer=None):\n        super(ResNet, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        self._norm_layer = norm_layer\n\n        self.inplanes = 64\n        self.dilation = 1\n        if replace_stride_with_dilation is None:\n            # each element in the tuple indicates if we should replace\n            # the 2x2 stride with a dilated convolution instead\n            replace_stride_with_dilation = [False, False, False]\n        if len(replace_stride_with_dilation) != 3:\n            raise ValueError(\"replace_stride_with_dilation should be None \"\n                             \"or a 3-element tuple, got {}\".format(replace_stride_with_dilation))\n        self.groups = groups\n        self.base_width = width_per_group\n        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,\n                               bias=False)\n        self.bn1 = norm_layer(self.inplanes)\n        self.relu = nn.ReLU(inplace=True)\n        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.layer1 = self._make_layer(block, 64, layers[0])\n        self.layer2 = self._make_layer(block, 128, layers[1], stride=2,\n                                       dilate=replace_stride_with_dilation[0])\n        self.layer3 = self._make_layer(block, 256, layers[2], stride=2,\n                                       dilate=replace_stride_with_dilation[1])\n        self.layer4 = self._make_layer(block, 512, layers[3], stride=2,\n                                       dilate=replace_stride_with_dilation[2])\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(512 * block.expansion, num_classes)\n\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n        # Zero-initialize the last BN in each residual branch,\n        # so that the residual branch starts with zeros, and each residual block behaves like an identity.\n        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677\n        if zero_init_residual:\n            for m in self.modules():\n                if isinstance(m, Bottleneck):\n                    nn.init.constant_(m.bn3.weight, 0)\n                elif isinstance(m, BasicBlock):\n                    nn.init.constant_(m.bn2.weight, 0)\n\n    def _make_layer(self, block, planes, blocks, stride=1, dilate=False):\n        norm_layer = self._norm_layer\n        downsample = None\n        previous_dilation = self.dilation\n        if dilate:\n            self.dilation *= stride\n            stride = 1\n        if stride != 1 or self.inplanes != planes * block.expansion:\n            downsample = nn.Sequential(\n                conv1x1(self.inplanes, planes * block.expansion, stride),\n                norm_layer(planes * block.expansion),\n            )\n\n        layers = []\n        layers.append(block(self.inplanes, planes, stride, downsample, self.groups,\n                            self.base_width, previous_dilation, norm_layer))\n        self.inplanes = planes * block.expansion\n        for _ in range(1, blocks):\n            layers.append(block(self.inplanes, planes, groups=self.groups,\n                                base_width=self.base_width, dilation=self.dilation,\n                                norm_layer=norm_layer))\n\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = x.reshape(x.size(0), -1)\n        x = self.fc(x)\n\n        return x\n\n\ndef _resnet(arch, block, layers, pretrained, progress, **kwargs):\n    model = ResNet(block, layers, **kwargs)\n    if pretrained:\n        state_dict = load_state_dict_from_url(model_urls[arch],\n                                              progress=progress)\n        model.load_state_dict(state_dict)\n    return model\n\n\ndef resnet18(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-18 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet34(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-34 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet50(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-50 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet101(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet152(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-152 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnext50_32x4d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-50 32x4d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 4\n    return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3],\n                   pretrained, progress, **kwargs)\n\n\ndef resnext101_32x8d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x8d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 8\n    return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3],\n                   pretrained, progress, **kwargs)\n"
  },
  {
    "path": "models/__init__.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: ikkyu-wen\n@contact: wenruichn@gmail.com\n@time: 2019-08-17 01:47\n\"\"\"\nfrom __future__ import absolute_import\n\nfrom .resnetxt_wsl import *"
  },
  {
    "path": "models/resnet_cbam.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: ikkyu-wen\n@contact: wenruichn@gmail.com\n@time: 2019-09-17 12:39\n\"\"\"\nimport torch.nn as nn\nimport math\ntry:\n    from torch.hub import load_state_dict_from_url\nexcept ImportError:\n    from torch.utils.model_zoo import load_url as load_state_dict_from_url\nimport torch\n\n__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',\n           'resnet152', 'resnext50_32x4d', 'resnext101_32x8d']\n\n\nmodel_urls = {\n    'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',\n    'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',\n    'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',\n    'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',\n    'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',\n    'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth',\n    'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth',\n}\n\n\ndef conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):\n    \"\"\"3x3 convolution with padding\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,\n                     padding=dilation, groups=groups, bias=False, dilation=dilation)\n\n\ndef conv1x1(in_planes, out_planes, stride=1):\n    \"\"\"1x1 convolution\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)\n\n\n\nclass ChannelAttention(nn.Module):\n    def __init__(self, in_planes, ratio=16):\n        super(ChannelAttention, self).__init__()\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.max_pool = nn.AdaptiveMaxPool2d(1)\n\n        self.fc1   = nn.Conv2d(in_planes, in_planes // 16, 1, bias=False)\n        self.relu1 = nn.ReLU()\n        self.fc2   = nn.Conv2d(in_planes // 16, in_planes, 1, bias=False)\n\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))\n        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))\n        out = avg_out + max_out\n        return self.sigmoid(out)\n\nclass SpatialAttention(nn.Module):\n    def __init__(self, kernel_size=7):\n        super(SpatialAttention, self).__init__()\n\n        assert kernel_size in (3, 7), 'kernel size must be 3 or 7'\n        padding = 3 if kernel_size == 7 else 1\n\n        self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = torch.mean(x, dim=1, keepdim=True)\n        max_out, _ = torch.max(x, dim=1, keepdim=True)\n        x = torch.cat([avg_out, max_out], dim=1)\n        x = self.conv1(x)\n        return self.sigmoid(x)\n\n\nclass BasicBlock(nn.Module):\n    expansion = 1\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(BasicBlock, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        if groups != 1 or base_width != 64:\n            raise ValueError('BasicBlock only supports groups=1 and base_width=64')\n        if dilation > 1:\n            raise NotImplementedError(\"Dilation > 1 not supported in BasicBlock\")\n        # Both self.conv1 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv3x3(inplanes, planes, stride)\n        self.bn1 = norm_layer(planes)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = conv3x3(planes, planes)\n        self.bn2 = norm_layer(planes)\n\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass Bottleneck(nn.Module):\n    expansion = 4\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(Bottleneck, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        width = int(planes * (base_width / 64.)) * groups\n        # Both self.conv2 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv1x1(inplanes, width)\n        self.bn1 = norm_layer(width)\n        self.conv2 = conv3x3(width, width, stride, groups, dilation)\n        self.bn2 = norm_layer(width)\n        self.conv3 = conv1x1(width, planes * self.expansion)\n        self.bn3 = norm_layer(planes * self.expansion)\n        self.relu = nn.ReLU(inplace=True)\n\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n        out = self.relu(out)\n\n        out = self.conv3(out)\n        out = self.bn3(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass ResNet(nn.Module):\n\n    def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,\n                 groups=1, width_per_group=64, replace_stride_with_dilation=None,\n                 norm_layer=None):\n        super(ResNet, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        self._norm_layer = norm_layer\n\n        self.inplanes = 64\n        self.dilation = 1\n        if replace_stride_with_dilation is None:\n            # each element in the tuple indicates if we should replace\n            # the 2x2 stride with a dilated convolution instead\n            replace_stride_with_dilation = [False, False, False]\n        if len(replace_stride_with_dilation) != 3:\n            raise ValueError(\"replace_stride_with_dilation should be None \"\n                             \"or a 3-element tuple, got {}\".format(replace_stride_with_dilation))\n        self.groups = groups\n        self.base_width = width_per_group\n        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,\n                               bias=False)\n        self.bn1 = norm_layer(self.inplanes)\n        self.relu = nn.ReLU(inplace=True)\n\n        self.ca = ChannelAttention(self.inplanes)\n        self.sa = SpatialAttention()\n\n        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.layer1 = self._make_layer(block, 64, layers[0])\n        self.layer2 = self._make_layer(block, 128, layers[1], stride=2,\n                                       dilate=replace_stride_with_dilation[0])\n        self.layer3 = self._make_layer(block, 256, layers[2], stride=2,\n                                       dilate=replace_stride_with_dilation[1])\n        self.layer4 = self._make_layer(block, 512, layers[3], stride=2,\n                                       dilate=replace_stride_with_dilation[2])\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(512 * block.expansion, num_classes)\n\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n        # Zero-initialize the last BN in each residual branch,\n        # so that the residual branch starts with zeros, and each residual block behaves like an identity.\n        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677\n        if zero_init_residual:\n            for m in self.modules():\n                if isinstance(m, Bottleneck):\n                    nn.init.constant_(m.bn3.weight, 0)\n                elif isinstance(m, BasicBlock):\n                    nn.init.constant_(m.bn2.weight, 0)\n\n    def _make_layer(self, block, planes, blocks, stride=1, dilate=False):\n        norm_layer = self._norm_layer\n        downsample = None\n        previous_dilation = self.dilation\n        if dilate:\n            self.dilation *= stride\n            stride = 1\n        if stride != 1 or self.inplanes != planes * block.expansion:\n            downsample = nn.Sequential(\n                conv1x1(self.inplanes, planes * block.expansion, stride),\n                norm_layer(planes * block.expansion),\n            )\n\n        layers = []\n        layers.append(block(self.inplanes, planes, stride, downsample, self.groups,\n                            self.base_width, previous_dilation, norm_layer))\n        self.inplanes = planes * block.expansion\n        for _ in range(1, blocks):\n            layers.append(block(self.inplanes, planes, groups=self.groups,\n                                base_width=self.base_width, dilation=self.dilation,\n                                norm_layer=norm_layer))\n\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.ca(x) * x\n        x = self.sa(x) * x\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = x.reshape(x.size(0), -1)\n        x = self.fc(x)\n\n        return x\n\n\ndef _resnet(arch, block, layers, pretrained, progress, **kwargs):\n    model = ResNet(block, layers, **kwargs)\n    if pretrained:\n        state_dict = load_state_dict_from_url(model_urls[arch],\n                                              progress=progress)\n        new_state_dict = model.state_dict()\n        new_state_dict.update(state_dict)\n        model.load_state_dict(new_state_dict)\n    return model\n\n\n\ndef resnet18(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-18 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet34(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-34 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet50(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-50 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet101(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet152(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-152 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnext50_32x4d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-50 32x4d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 4\n    return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3],\n                   pretrained, progress, **kwargs)\n\n\ndef resnext101_32x8d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x8d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 8\n    return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3],\n                   pretrained, progress, **kwargs)\n"
  },
  {
    "path": "models/resnetxt_wsl.py",
    "content": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the license found in the\n# LICENSE file in the root directory of this source tree.\n\n# Optional list of dependencies required by the package\n\n'''\n    Code From : https://github.com/facebookresearch/WSL-Images/blob/master/hubconf.py\n'''\n__all__ = ['resnext101_32x8d_wsl', 'resnext101_32x16d_wsl', 'resnext101_32x32d_wsl', 'resnext101_32x48d_wsl']\n\ndependencies = ['torch', 'torchvision']\n\ntry:\n    from torch.hub import load_state_dict_from_url\nexcept ImportError:\n    from torch.utils.model_zoo import load_url as load_state_dict_from_url\n\n# from .Res import ResNet, Bottleneck\nfrom .resnet_cbam import ResNet, Bottleneck\n\nmodel_urls = {\n    'resnext101_32x8d': 'https://download.pytorch.org/models/ig_resnext101_32x8-c38310e5.pth',\n    'resnext101_32x16d': 'https://download.pytorch.org/models/ig_resnext101_32x16-c6f796b0.pth',\n    'resnext101_32x32d': 'https://download.pytorch.org/models/ig_resnext101_32x32-e4b90b00.pth',\n    'resnext101_32x48d': 'https://download.pytorch.org/models/ig_resnext101_32x48-3e41cc8a.pth',\n}\n\n\n# def _resnext(arch, block, layers, pretrained, progress, **kwargs):\n#     model = ResNet(block, layers, **kwargs)\n#     state_dict = load_state_dict_from_url(model_urls[arch], progress=progress)\n#     model.load_state_dict(state_dict)\n#     return model\n\n#使用部分加载\ndef _resnext(arch, block, layers, pretrained, progress, **kwargs):\n    model = ResNet(block, layers, **kwargs)\n    state_dict = load_state_dict_from_url(model_urls[arch], progress=progress)\n    new_state_dict = model.state_dict()\n    new_state_dict.update(state_dict)\n    model.load_state_dict(new_state_dict)\n    return model\n\n\ndef resnext101_32x8d_wsl(progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x8 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 8\n    return _resnext('resnext101_32x8d', Bottleneck, [3, 4, 23, 3], True, progress, **kwargs)\n\n\ndef resnext101_32x16d_wsl(progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x16 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:zz\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 16\n    return _resnext('resnext101_32x16d', Bottleneck, [3, 4, 23, 3], True, progress, **kwargs)\n\n\ndef resnext101_32x32d_wsl(progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x32 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 32\n    return _resnext('resnext101_32x32d', Bottleneck, [3, 4, 23, 3], True, progress, **kwargs)\n\n\ndef resnext101_32x48d_wsl(progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x48 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 48\n    return _resnext('resnext101_32x48d', Bottleneck, [3, 4, 23, 3], True, progress, **kwargs)\n"
  },
  {
    "path": "predict/Res.py",
    "content": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the license found in the\n# LICENSE file in the root directory of this source tree.\n#\n\nimport torch.nn as nn\ntry:\n    from torch.hub import load_state_dict_from_url\nexcept ImportError:\n    from torch.utils.model_zoo import load_url as load_state_dict_from_url\n\n\n__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',\n           'resnet152', 'resnext50_32x4d', 'resnext101_32x8d']\n\n\nmodel_urls = {\n    'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',\n    'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',\n    'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',\n    'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',\n    'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',\n    'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth',\n    'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth',\n}\n\n\ndef conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):\n    \"\"\"3x3 convolution with padding\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,\n                     padding=dilation, groups=groups, bias=False, dilation=dilation)\n\n\ndef conv1x1(in_planes, out_planes, stride=1):\n    \"\"\"1x1 convolution\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)\n\n\nclass BasicBlock(nn.Module):\n    expansion = 1\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(BasicBlock, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        if groups != 1 or base_width != 64:\n            raise ValueError('BasicBlock only supports groups=1 and base_width=64')\n        if dilation > 1:\n            raise NotImplementedError(\"Dilation > 1 not supported in BasicBlock\")\n        # Both self.conv1 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv3x3(inplanes, planes, stride)\n        self.bn1 = norm_layer(planes)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = conv3x3(planes, planes)\n        self.bn2 = norm_layer(planes)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass Bottleneck(nn.Module):\n    expansion = 4\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(Bottleneck, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        width = int(planes * (base_width / 64.)) * groups\n        # Both self.conv2 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv1x1(inplanes, width)\n        self.bn1 = norm_layer(width)\n        self.conv2 = conv3x3(width, width, stride, groups, dilation)\n        self.bn2 = norm_layer(width)\n        self.conv3 = conv1x1(width, planes * self.expansion)\n        self.bn3 = norm_layer(planes * self.expansion)\n        self.relu = nn.ReLU(inplace=True)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n        out = self.relu(out)\n\n        out = self.conv3(out)\n        out = self.bn3(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass ResNet(nn.Module):\n\n    def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,\n                 groups=1, width_per_group=64, replace_stride_with_dilation=None,\n                 norm_layer=None):\n        super(ResNet, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        self._norm_layer = norm_layer\n\n        self.inplanes = 64\n        self.dilation = 1\n        if replace_stride_with_dilation is None:\n            # each element in the tuple indicates if we should replace\n            # the 2x2 stride with a dilated convolution instead\n            replace_stride_with_dilation = [False, False, False]\n        if len(replace_stride_with_dilation) != 3:\n            raise ValueError(\"replace_stride_with_dilation should be None \"\n                             \"or a 3-element tuple, got {}\".format(replace_stride_with_dilation))\n        self.groups = groups\n        self.base_width = width_per_group\n        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,\n                               bias=False)\n        self.bn1 = norm_layer(self.inplanes)\n        self.relu = nn.ReLU(inplace=True)\n        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.layer1 = self._make_layer(block, 64, layers[0])\n        self.layer2 = self._make_layer(block, 128, layers[1], stride=2,\n                                       dilate=replace_stride_with_dilation[0])\n        self.layer3 = self._make_layer(block, 256, layers[2], stride=2,\n                                       dilate=replace_stride_with_dilation[1])\n        self.layer4 = self._make_layer(block, 512, layers[3], stride=2,\n                                       dilate=replace_stride_with_dilation[2])\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(512 * block.expansion, num_classes)\n\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n        # Zero-initialize the last BN in each residual branch,\n        # so that the residual branch starts with zeros, and each residual block behaves like an identity.\n        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677\n        if zero_init_residual:\n            for m in self.modules():\n                if isinstance(m, Bottleneck):\n                    nn.init.constant_(m.bn3.weight, 0)\n                elif isinstance(m, BasicBlock):\n                    nn.init.constant_(m.bn2.weight, 0)\n\n    def _make_layer(self, block, planes, blocks, stride=1, dilate=False):\n        norm_layer = self._norm_layer\n        downsample = None\n        previous_dilation = self.dilation\n        if dilate:\n            self.dilation *= stride\n            stride = 1\n        if stride != 1 or self.inplanes != planes * block.expansion:\n            downsample = nn.Sequential(\n                conv1x1(self.inplanes, planes * block.expansion, stride),\n                norm_layer(planes * block.expansion),\n            )\n\n        layers = []\n        layers.append(block(self.inplanes, planes, stride, downsample, self.groups,\n                            self.base_width, previous_dilation, norm_layer))\n        self.inplanes = planes * block.expansion\n        for _ in range(1, blocks):\n            layers.append(block(self.inplanes, planes, groups=self.groups,\n                                base_width=self.base_width, dilation=self.dilation,\n                                norm_layer=norm_layer))\n\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = x.reshape(x.size(0), -1)\n        x = self.fc(x)\n\n        return x\n\n\ndef _resnet(arch, block, layers, pretrained, progress, **kwargs):\n    model = ResNet(block, layers, **kwargs)\n    if pretrained:\n        state_dict = load_state_dict_from_url(model_urls[arch],\n                                              progress=progress)\n        model.load_state_dict(state_dict)\n    return model\n\n\ndef resnet18(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-18 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet34(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-34 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet50(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-50 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet101(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet152(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-152 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnext50_32x4d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-50 32x4d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 4\n    return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3],\n                   pretrained, progress, **kwargs)\n\n\ndef resnext101_32x8d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x8d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 8\n    return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3],\n                   pretrained, progress, **kwargs)\n"
  },
  {
    "path": "predict/config.json",
    "content": "{\n    \"model_type\": \"PyTorch\",\n    \"runtime\":\"python3.6\",\n    \"model_algorithm\": \"image_classification\",\n    \"metrics\": {\n        \"f1\": 0.345294,\n        \"accuracy\": 0.462963,\n        \"precision\": 0.338977,\n        \"recall\": 0.351852\n    },\n    \"apis\": [{\n        \"protocol\": \"http\",\n        \"url\": \"/\",\n        \"method\": \"post\",\n        \"request\": {\n            \"Content-type\": \"multipart/form-data\",\n            \"data\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"input_img\": {\"type\": \"file\"}\n                },\n                \"required\": [\"input_img\"]\n            }\n        },\n        \"response\": {\n            \"Content-type\": \"multipart/form-data\",\n            \"data\": {\n                \"type\": \"object\",\n                \"properties\": {\n                    \"result\": {\"type\": \"string\"}\n                },\n                \"required\": [\"result\"]\n            }\n        }\n    }],\n    \"dependencies\": [{\n        \"installer\": \"pip\",\n        \"packages\": [\n            {\n                \"restraint\": \"ATLEAST\",\n                \"package_version\": \"5.2.0\",\n                \"package_name\": \"Pillow\"\n            }\n        ]\n    }]\n}"
  },
  {
    "path": "predict/customize_service.py",
    "content": "#!usr/bin/env python\n#-*- coding:utf-8 _*-\n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-08-14 16:07\n\"\"\"\nimport torchvision.transforms as transforms\nimport torch\nfrom torch import nn\nfrom PIL import Image\nimport torch.nn.functional as F\nfrom resnetxt_wsl import resnext101_32x8d_wsl, resnext101_32x16d_wsl, resnext101_32x32d_wsl\n\n\nfrom model_service.pytorch_model_service import PTServingBaseService\n\nimport time\nfrom metric.metrics_manager import MetricsManager\nimport log\nlogger = log.getLogger(__name__)\n\n\nargs = {}\nargs['arch'] = 'resnext101_32x16d_wsl'\nargs['pretrained'] = False\nargs['num_classes'] = 43\nargs['big_size'] = 327\nargs['image_size'] = 288\ntorch.backends.cudnn.benchmark = True\n\nclass classfication_service(PTServingBaseService):\n    def __init__(self, model_name, model_path):\n        super(classfication_service, self).__init__(model_name, model_path)\n        self.pre_img = self.preprocess_img1()\n        self.model = self.build_model(model_path)\n        self.model = self.model.cuda()\n        self.model.eval()\n\n        self.label_id_name_dict = \\\n            {\n                \"0\": \"其他垃圾/一次性快餐盒\",\n                \"1\": \"其他垃圾/污损塑料\",\n                \"2\": \"其他垃圾/烟蒂\",\n                \"3\": \"其他垃圾/牙签\",\n                \"4\": \"其他垃圾/破碎花盆及碟碗\",\n                \"5\": \"其他垃圾/竹筷\",\n                \"6\": \"厨余垃圾/剩饭剩菜\",\n                \"7\": \"厨余垃圾/大骨头\",\n                \"8\": \"厨余垃圾/水果果皮\",\n                \"9\": \"厨余垃圾/水果果肉\",\n                \"10\": \"厨余垃圾/茶叶渣\",\n                \"11\": \"厨余垃圾/菜叶菜根\",\n                \"12\": \"厨余垃圾/蛋壳\",\n                \"13\": \"厨余垃圾/鱼骨\",\n                \"14\": \"可回收物/充电宝\",\n                \"15\": \"可回收物/包\",\n                \"16\": \"可回收物/化妆品瓶\",\n                \"17\": \"可回收物/塑料玩具\",\n                \"18\": \"可回收物/塑料碗盆\",\n                \"19\": \"可回收物/塑料衣架\",\n                \"20\": \"可回收物/快递纸袋\",\n                \"21\": \"可回收物/插头电线\",\n                \"22\": \"可回收物/旧衣服\",\n                \"23\": \"可回收物/易拉罐\",\n                \"24\": \"可回收物/枕头\",\n                \"25\": \"可回收物/毛绒玩具\",\n                \"26\": \"可回收物/洗发水瓶\",\n                \"27\": \"可回收物/玻璃杯\",\n                \"28\": \"可回收物/皮鞋\",\n                \"29\": \"可回收物/砧板\",\n                \"30\": \"可回收物/纸板箱\",\n                \"31\": \"可回收物/调料瓶\",\n                \"32\": \"可回收物/酒瓶\",\n                \"33\": \"可回收物/金属食品罐\",\n                \"34\": \"可回收物/锅\",\n                \"35\": \"可回收物/食用油桶\",\n                \"36\": \"可回收物/饮料瓶\",\n                \"37\": \"有害垃圾/干电池\",\n                \"38\": \"有害垃圾/软膏\",\n                \"39\": \"有害垃圾/过期药物\",\n                \"40\": \"可回收物/毛巾\",\n                \"41\": \"可回收物/饮料盒\",\n                \"42\": \"可回收物/纸袋\"\n            }\n\n    def build_model(self, model_path):\n        model = resnext101_32x16d_wsl(pretrained=False, progress=False)\n        model.fc = nn.Sequential(\n            nn.Dropout(0.2),\n            nn.Linear(2048, 43)\n        )\n        model.load_state_dict(torch.load(model_path))\n        return model\n\n    def preprocess_img(self):\n        mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]\n        infer_transformation = transforms.Compose([\n            Resize((args['image_size'], args['image_size'])),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=mean, std=std),\n        ])\n        return infer_transformation\n\n    def preprocess_img1(self):\n        mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]\n        return transforms.Compose([\n            Resize((329, 329)),\n            transforms.CenterCrop(288),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=mean, std=std),\n        ])\n\n    def _preprocess(self, data):\n        preprocessed_data = {}\n        for k, v in data.items():\n            for file_name, file_content in v.items():\n                img = Image.open(file_content)\n                img = self.pre_img(img)\n                preprocessed_data[k] = img\n        return preprocessed_data\n\n    def _inference(self, data):\n        img = data['input_img']\n        img = img.unsqueeze(0).cuda()\n        with torch.no_grad():\n            pred_score = self.model(img)\n\n        if pred_score is not None:\n            _, pred_label = torch.max(pred_score.data, 1)\n            return {'result': self.label_id_name_dict[str(pred_label[0].item())]}\n        else:\n            return {'result': 'predict score is None'}\n\n        # return result\n\n    def _postprocess(self, data):\n        return data\n\n\nclass Resize(object):\n    def __init__(self, size, interpolation=Image.BILINEAR):\n        self.size = size\n        self.interpolation = interpolation\n\n    def __call__(self, img):\n        ratio = 1\n        w, h = img.size\n        if w / h < ratio:\n            t = int(h * ratio)\n            w_padding = (t - w) // 2\n            img = img.crop((-w_padding, 0, w+w_padding, h))\n        else:\n            t = int(w / ratio)\n            h_padding = (t - h) // 2\n            img = img.crop((0, -h_padding, w, h+h_padding))\n\n        img = img.resize(self.size, self.interpolation)\n\n        return img"
  },
  {
    "path": "predict/predict.py",
    "content": "#!usr/bin/env python\n#-*- coding:utf-8 _*-\n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-08-14 16:07\n\"\"\"\nimport torchvision.transforms as transforms\nimport torch\nfrom PIL import Image\nfrom collections import OrderedDict\nimport torch.nn.functional as F\nfrom efficientnet_pytorch import EfficientNet\nfrom torch import nn\nimport os, time\nimport torchvision.models as models\nfrom resnetxt_wsl import resnext101_32x8d_wsl, resnext101_32x16d_wsl, resnext101_32x32d_wsl\nos.environ[\"CUDA_VISIBLE_DEVICES\"] = \"3\"\n\nargs = {}\nargs['arch'] = 'resnext101_32x16d_wsl'\nargs['pretrained'] = False\nargs['num_classes'] = 43\nargs['image_size'] = 320\n\n\nclass classfication_service():\n    def __init__(self, model_path):\n        self.model = self.build_model(model_path)\n        self.pre_img = self.preprocess_img()\n        self.model.eval()\n        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n        self.label_id_name_dict = \\\n            {\n                \"0\": \"其他垃圾/一次性快餐盒\",\n                \"1\": \"其他垃圾/污损塑料\",\n                \"2\": \"其他垃圾/烟蒂\",\n                \"3\": \"其他垃圾/牙签\",\n                \"4\": \"其他垃圾/破碎花盆及碟碗\",\n                \"5\": \"其他垃圾/竹筷\",\n                \"6\": \"厨余垃圾/剩饭剩菜\",\n                \"7\": \"厨余垃圾/大骨头\",\n                \"8\": \"厨余垃圾/水果果皮\",\n                \"9\": \"厨余垃圾/水果果肉\",\n                \"10\": \"厨余垃圾/茶叶渣\",\n                \"11\": \"厨余垃圾/菜叶菜根\",\n                \"12\": \"厨余垃圾/蛋壳\",\n                \"13\": \"厨余垃圾/鱼骨\",\n                \"14\": \"可回收物/充电宝\",\n                \"15\": \"可回收物/包\",\n                \"16\": \"可回收物/化妆品瓶\",\n                \"17\": \"可回收物/塑料玩具\",\n                \"18\": \"可回收物/塑料碗盆\",\n                \"19\": \"可回收物/塑料衣架\",\n                \"20\": \"可回收物/快递纸袋\",\n                \"21\": \"可回收物/插头电线\",\n                \"22\": \"可回收物/旧衣服\",\n                \"23\": \"可回收物/易拉罐\",\n                \"24\": \"可回收物/枕头\",\n                \"25\": \"可回收物/毛绒玩具\",\n                \"26\": \"可回收物/洗发水瓶\",\n                \"27\": \"可回收物/玻璃杯\",\n                \"28\": \"可回收物/皮鞋\",\n                \"29\": \"可回收物/砧板\",\n                \"30\": \"可回收物/纸板箱\",\n                \"31\": \"可回收物/调料瓶\",\n                \"32\": \"可回收物/酒瓶\",\n                \"33\": \"可回收物/金属食品罐\",\n                \"34\": \"可回收物/锅\",\n                \"35\": \"可回收物/食用油桶\",\n                \"36\": \"可回收物/饮料瓶\",\n                \"37\": \"有害垃圾/干电池\",\n                \"38\": \"有害垃圾/软膏\",\n                \"39\": \"有害垃圾/过期药物\",\n                \"40\": \"可回收物/毛巾\",\n                \"41\": \"可回收物/饮料盒\",\n                \"42\": \"可回收物/纸袋\"\n            }\n\n    def build_model(self, model_path):\n        if args['arch'] == 'resnext101_32x16d_wsl':\n            model = resnext101_32x16d_wsl(pretrained=False, progress=False)\n        if args['arch'] == 'resnext101_32x8d':\n            model = models.__dict__[args['arch']]()\n        elif args['arch'] == 'efficientnet-b7':\n            model = EfficientNet.from_name(args['arch'])\n\n        layerName, layer = list(model.named_children())[-1]\n        exec(\"model.\" + layerName + \"=nn.Linear(layer.in_features,\" + str(args['num_classes']) + \")\")\n\n        if torch.cuda.is_available():\n            modelState = torch.load(model_path)\n            model.load_state_dict(modelState)\n            model = model.cuda()\n        else:\n            modelState = torch.load(model_path, map_location='cpu')\n            model.load_state_dict(modelState)\n        return model\n\n    def preprocess_img(self):\n        mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]\n        infer_transformation = transforms.Compose([\n            Resize((args['image_size'], args['image_size'])),\n            transforms.ToTensor(),\n            transforms.Normalize(mean=mean, std=std),\n        ])\n        return infer_transformation\n\n    def _preprocess(self, data):\n        preprocessed_data = {}\n        for k, v in data.items():\n            for file_name, file_content in v.items():\n                img = Image.open(file_content)\n                img = self.pre_img(img)\n                preprocessed_data[k] = img\n        return preprocessed_data\n\n    def _inference(self, data):\n        \"\"\"\n        model inference function\n        Here are a inference example of resnet, if you use another model, please modify this function\n        \"\"\"\n        img = data['input_img']\n        img = img.unsqueeze(0)\n        img = img.to(self.device)\n        with torch.no_grad():\n            pred_score = self.model(img)\n\n        if pred_score is not None:\n            _, pred_label = torch.max(pred_score.data, 1)\n            result = {'result': self.label_id_name_dict[str(pred_label[0].item())]}\n        else:\n            result = {'result': 'predict score is None'}\n\n        return result\n\n    def _postprocess(self, data):\n        return data\n\n\nclass Resize(object):\n    def __init__(self, size, interpolation=Image.BILINEAR):\n        self.size = size\n        self.interpolation = interpolation\n\n    def __call__(self, img):\n        ratio = self.size[0] / self.size[1]\n        w, h = img.size\n        if w / h < ratio:\n            t = int(h * ratio)\n            w_padding = (t - w) // 2\n            img = img.crop((-w_padding, 0, w+w_padding, h))\n        else:\n            t = int(w / ratio)\n            h_padding = (t - h) // 2\n            img = img.crop((0, -h_padding, w, h+h_padding))\n\n        img = img.resize(self.size, self.interpolation)\n\n        return img\n\nif __name__ == '__main__':\n    model_path = '/Users/QLMX/Documents/' + 'model_19_9992_9590.pth'\n    infer = classfication_service(model_path)\n    input_dir = '/Users/QLMX/Downloads/garbage_classify_v3_select_100'\n    files = os.listdir(input_dir)\n    t1 = int(time.time()*1000)\n    for file_name in files:\n        file_path = os.path.join(input_dir, file_name)\n        img = Image.open(file_path)\n\n        img = infer.pre_img(img)\n        tt1 = int(time.time() * 1000)\n        result = infer._inference({'input_img': img})\n        tt2 = int(time.time() * 1000)\n        print((tt2 - tt1) / 100)\n    t2 = int(time.time()*1000)\n    print((t2 - t1)/100)\n\n"
  },
  {
    "path": "predict/resnet_cbam.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: ikkyu-wen\n@contact: wenruichn@gmail.com\n@time: 2019-09-17 12:39\n\"\"\"\nimport torch.nn as nn\nimport math\ntry:\n    from torch.hub import load_state_dict_from_url\nexcept ImportError:\n    from torch.utils.model_zoo import load_url as load_state_dict_from_url\nimport torch\n\n__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',\n           'resnet152', 'resnext50_32x4d', 'resnext101_32x8d']\n\n\nmodel_urls = {\n    'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',\n    'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',\n    'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',\n    'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',\n    'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',\n    'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth',\n    'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth',\n}\n\n\ndef conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):\n    \"\"\"3x3 convolution with padding\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,\n                     padding=dilation, groups=groups, bias=False, dilation=dilation)\n\n\ndef conv1x1(in_planes, out_planes, stride=1):\n    \"\"\"1x1 convolution\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)\n\n\n\nclass ChannelAttention(nn.Module):\n    def __init__(self, in_planes, ratio=16):\n        super(ChannelAttention, self).__init__()\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.max_pool = nn.AdaptiveMaxPool2d(1)\n\n        self.fc1   = nn.Conv2d(in_planes, in_planes // 16, 1, bias=False)\n        self.relu1 = nn.ReLU()\n        self.fc2   = nn.Conv2d(in_planes // 16, in_planes, 1, bias=False)\n\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))\n        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))\n        out = avg_out + max_out\n        return self.sigmoid(out)\n\nclass SpatialAttention(nn.Module):\n    def __init__(self, kernel_size=7):\n        super(SpatialAttention, self).__init__()\n\n        assert kernel_size in (3, 7), 'kernel size must be 3 or 7'\n        padding = 3 if kernel_size == 7 else 1\n\n        self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = torch.mean(x, dim=1, keepdim=True)\n        max_out, _ = torch.max(x, dim=1, keepdim=True)\n        x = torch.cat([avg_out, max_out], dim=1)\n        x = self.conv1(x)\n        return self.sigmoid(x)\n\n\nclass BasicBlock(nn.Module):\n    expansion = 1\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(BasicBlock, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        if groups != 1 or base_width != 64:\n            raise ValueError('BasicBlock only supports groups=1 and base_width=64')\n        if dilation > 1:\n            raise NotImplementedError(\"Dilation > 1 not supported in BasicBlock\")\n        # Both self.conv1 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv3x3(inplanes, planes, stride)\n        self.bn1 = norm_layer(planes)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = conv3x3(planes, planes)\n        self.bn2 = norm_layer(planes)\n\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass Bottleneck(nn.Module):\n    expansion = 4\n\n    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,\n                 base_width=64, dilation=1, norm_layer=None):\n        super(Bottleneck, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        width = int(planes * (base_width / 64.)) * groups\n        # Both self.conv2 and self.downsample layers downsample the input when stride != 1\n        self.conv1 = conv1x1(inplanes, width)\n        self.bn1 = norm_layer(width)\n        self.conv2 = conv3x3(width, width, stride, groups, dilation)\n        self.bn2 = norm_layer(width)\n        self.conv3 = conv1x1(width, planes * self.expansion)\n        self.bn3 = norm_layer(planes * self.expansion)\n        self.relu = nn.ReLU(inplace=True)\n\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n        out = self.relu(out)\n\n        out = self.conv3(out)\n        out = self.bn3(out)\n\n        if self.downsample is not None:\n            identity = self.downsample(x)\n\n        out += identity\n        out = self.relu(out)\n\n        return out\n\n\nclass ResNet(nn.Module):\n\n    def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,\n                 groups=1, width_per_group=64, replace_stride_with_dilation=None,\n                 norm_layer=None):\n        super(ResNet, self).__init__()\n        if norm_layer is None:\n            norm_layer = nn.BatchNorm2d\n        self._norm_layer = norm_layer\n\n        self.inplanes = 64\n        self.dilation = 1\n        if replace_stride_with_dilation is None:\n            # each element in the tuple indicates if we should replace\n            # the 2x2 stride with a dilated convolution instead\n            replace_stride_with_dilation = [False, False, False]\n        if len(replace_stride_with_dilation) != 3:\n            raise ValueError(\"replace_stride_with_dilation should be None \"\n                             \"or a 3-element tuple, got {}\".format(replace_stride_with_dilation))\n        self.groups = groups\n        self.base_width = width_per_group\n        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,\n                               bias=False)\n        self.bn1 = norm_layer(self.inplanes)\n        self.relu = nn.ReLU(inplace=True)\n\n        self.ca = ChannelAttention(self.inplanes)\n        self.sa = SpatialAttention()\n\n        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n        self.layer1 = self._make_layer(block, 64, layers[0])\n        self.layer2 = self._make_layer(block, 128, layers[1], stride=2,\n                                       dilate=replace_stride_with_dilation[0])\n        self.layer3 = self._make_layer(block, 256, layers[2], stride=2,\n                                       dilate=replace_stride_with_dilation[1])\n        self.layer4 = self._make_layer(block, 512, layers[3], stride=2,\n                                       dilate=replace_stride_with_dilation[2])\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(512 * block.expansion, num_classes)\n\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n        # Zero-initialize the last BN in each residual branch,\n        # so that the residual branch starts with zeros, and each residual block behaves like an identity.\n        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677\n        if zero_init_residual:\n            for m in self.modules():\n                if isinstance(m, Bottleneck):\n                    nn.init.constant_(m.bn3.weight, 0)\n                elif isinstance(m, BasicBlock):\n                    nn.init.constant_(m.bn2.weight, 0)\n\n    def _make_layer(self, block, planes, blocks, stride=1, dilate=False):\n        norm_layer = self._norm_layer\n        downsample = None\n        previous_dilation = self.dilation\n        if dilate:\n            self.dilation *= stride\n            stride = 1\n        if stride != 1 or self.inplanes != planes * block.expansion:\n            downsample = nn.Sequential(\n                conv1x1(self.inplanes, planes * block.expansion, stride),\n                norm_layer(planes * block.expansion),\n            )\n\n        layers = []\n        layers.append(block(self.inplanes, planes, stride, downsample, self.groups,\n                            self.base_width, previous_dilation, norm_layer))\n        self.inplanes = planes * block.expansion\n        for _ in range(1, blocks):\n            layers.append(block(self.inplanes, planes, groups=self.groups,\n                                base_width=self.base_width, dilation=self.dilation,\n                                norm_layer=norm_layer))\n\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.ca(x) * x\n        x = self.sa(x) * x\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = x.reshape(x.size(0), -1)\n        x = self.fc(x)\n\n        return x\n\n\ndef _resnet(arch, block, layers, pretrained, progress, **kwargs):\n    model = ResNet(block, layers, **kwargs)\n    if pretrained:\n        state_dict = load_state_dict_from_url(model_urls[arch],\n                                              progress=progress)\n        new_state_dict = model.state_dict()\n        new_state_dict.update(state_dict)\n        model.load_state_dict(new_state_dict)\n    return model\n\n\n\ndef resnet18(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-18 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet34(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-34 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet50(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-50 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet101(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-101 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnet152(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNet-152 model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress,\n                   **kwargs)\n\n\ndef resnext50_32x4d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-50 32x4d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 4\n    return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3],\n                   pretrained, progress, **kwargs)\n\n\ndef resnext101_32x8d(pretrained=False, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x8d model.\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n        progress (bool): If True, displays a progress bar of the download to stderr\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 8\n    return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3],\n                   pretrained, progress, **kwargs)\n"
  },
  {
    "path": "predict/resnetxt_wsl.py",
    "content": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the license found in the\n# LICENSE file in the root directory of this source tree.\n\n# Optional list of dependencies required by the package\n\n'''\n    Code From : https://github.com/facebookresearch/WSL-Images/blob/master/hubconf.py\n'''\n__all__ = ['resnext101_32x8d_wsl', 'resnext101_32x16d_wsl', 'resnext101_32x32d_wsl', 'resnext101_32x48d_wsl']\n\ndependencies = ['torch', 'torchvision']\n\ntry:\n    from torch.hub import load_state_dict_from_url\nexcept ImportError:\n    from torch.utils.model_zoo import load_url as load_state_dict_from_url\n\n# from Res import ResNet, Bottleneck\nfrom .resnet_cbam import ResNet, Bottleneck\n\nmodel_urls = {\n    'resnext101_32x8d': 'https://download.pytorch.org/models/ig_resnext101_32x8-c38310e5.pth',\n    'resnext101_32x16d': 'https://download.pytorch.org/models/ig_resnext101_32x16-c6f796b0.pth',\n    'resnext101_32x32d': 'https://download.pytorch.org/models/ig_resnext101_32x32-e4b90b00.pth',\n    'resnext101_32x48d': 'https://download.pytorch.org/models/ig_resnext101_32x48-3e41cc8a.pth',\n}\n\n\n# def _resnext(arch, block, layers, pretrained, progress, **kwargs):\n#     model = ResNet(block, layers, **kwargs)\n#     if pretrained:\n#         state_dict = load_state_dict_from_url(model_urls[arch], progress=progress)\n#         model.load_state_dict(state_dict)\n#     return model\n\n#使用部分加载\ndef _resnext(arch, block, layers, pretrained, progress, **kwargs):\n    model = ResNet(block, layers, **kwargs)\n    if pretrained:\n        state_dict = load_state_dict_from_url(model_urls[arch], progress=progress)\n        new_state_dict = model.state_dict()\n        new_state_dict.update(state_dict)\n        model.load_state_dict(new_state_dict)\n    return model\n\n\ndef resnext101_32x8d_wsl(pretrained=True, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x8 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 8\n    return _resnext('resnext101_32x8d', Bottleneck, [3, 4, 23, 3], pretrained, progress, **kwargs)\n\n\ndef resnext101_32x16d_wsl(pretrained=True, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x16 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 16\n    return _resnext('resnext101_32x16d', Bottleneck, [3, 4, 23, 3], pretrained, progress, **kwargs)\n\n\ndef resnext101_32x32d_wsl(pretrained=True, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x32 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 32\n    return _resnext('resnext101_32x32d', Bottleneck, [3, 4, 23, 3], pretrained, progress, **kwargs)\n\n\ndef resnext101_32x48d_wsl(pretrained=True, progress=True, **kwargs):\n    \"\"\"Constructs a ResNeXt-101 32x48 model pre-trained on weakly-supervised data\n    and finetuned on ImageNet from Figure 5 in\n    `\"Exploring the Limits of Weakly Supervised Pretraining\" <https://arxiv.org/abs/1805.00932>`_\n    Args:\n        progress (bool): If True, displays a progress bar of the download to stderr.\n    \"\"\"\n    kwargs['groups'] = 32\n    kwargs['width_per_group'] = 48\n    return _resnext('resnext101_32x48d', Bottleneck, [3, 4, 23, 3], pretrained, progress, **kwargs)\n"
  },
  {
    "path": "preprocess.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-08-14 11:16\n公众号：AI成长社\n知乎：https://www.zhihu.com/people/qlmx-61/columns\n\"\"\"\nfrom glob import glob\nimport os\nimport codecs\nimport random\nimport numpy as np\nfrom sklearn.model_selection import KFold, StratifiedKFold\n\n\nbase_path = 'data/'\ndata_path = base_path + 'garbage_classify/train_data'\n\nlabel_files = glob(os.path.join(data_path, '*.txt'))\nimg_paths = []\nlabels = []\nresult = []\nlabel_dict = {}\ndata_dict = {}\n\nfor index, file_path in enumerate(label_files):\n    with codecs.open(file_path, 'r', 'utf-8') as f:\n        line = f.readline()\n    line_split = line.strip().split(', ')\n    if len(line_split) != 2:\n        print('%s contain error lable' % os.path.basename(file_path))\n        continue\n    img_name = line_split[0]\n    label = int(line_split[1])\n    img_paths.append(os.path.join(data_path, img_name))\n    labels.append(label)\n    result.append(os.path.join(data_path, img_name) + ',' + str(label))\n    label_dict[label] = label_dict.get(label, 0) + 1\n    if label not in data_dict:\n        data_dict[label] = []\n    data_dict[label].append(os.path.join(data_path, img_name) + ',' + str(label))\n\ndata_path_add = base_path + 'garbage_classify_v3'\nlabel_files_add = glob(os.path.join(data_path_add, '*.txt'))\n\nfor index, file_path in enumerate(label_files_add):\n    with codecs.open(file_path, 'r', 'utf-8') as f:\n        line = f.readline()\n    line_split = line.strip().split(', ')\n    if len(line_split) != 2:\n        print('%s contain error lable' % os.path.basename(file_path))\n        continue\n    img_name = line_split[0]\n    label = int(line_split[1])\n    img_paths.append(os.path.join(data_path_add, img_name))\n    labels.append(label)\n    result.append(os.path.join(data_path_add, img_name) + ',' + str(label))\n    label_dict[label] = label_dict.get(label, 0) + 1\n    if label not in data_dict:\n        data_dict[label] = []\n    data_dict[label].append(os.path.join(data_path_add, img_name) + ',' + str(label))\n\n\nfolds = StratifiedKFold(n_splits=10, shuffle=True, random_state=2019)\nfor fold_, (trn_idx, val_idx) in enumerate(folds.split(result, labels)):\n    train_data = list(np.array(result)[trn_idx])\n    val_data = list(np.array(result)[val_idx])\n\nprint(len(train_data), len(val_data))\n\nwith open(base_path + 'train1.txt', 'w') as f1:\n    for item in train_data:\n        f1.write(item + '\\n')\n\nwith open(base_path + 'val1.txt', 'w') as f2:\n    for item in val_data:\n        f2.write(item + '\\n')\n\n\nfrom PIL import Image\n\n###predata 2\nall_data = []\ntrain = []\nval = []\nrate = 0.9\nimport cv2\nfrom tqdm import tqdm\n\nerror_list = ['data/additional_train_data/38/242.jpg',\n              'data/additional_train_data/34/79.jpg',\n              'data/additional_train_data/27/55.jpg'\n              'data/new/8/0.jpg'\n              ]\n\ndata_path = base_path + 'new/'\nfor i in range(40):\n    na_item = []\n    img_files = glob(os.path.join(data_path, str(i), '*.jpg'))\n    for item in tqdm(img_files):\n        ii = cv2.imread(item)\n        if item not in error_list:\n\n            jj = Image.open(item).layers\n            if jj == 1:\n                print(item)\n            all_data.append(item + ',' + str(i))\n            na_item.append(item + ',' + str(i))\n    random.shuffle(na_item)\n    train.extend(na_item[ : int(len(na_item)*rate)])\n    val.extend(na_item[int(len(na_item)*rate):])\nprint(len(train), len(val))\n\nrandom.shuffle(all_data)\nrandom.shuffle(train)\nrandom.shuffle(val)\n\nprint(len(all_data))\n\nold = []\nwith open(base_path + 'train1.txt', 'r') as f:\n    for i in f.readlines():\n        old.append(i.strip())\nfor i in all_data:\n    img_path, label = i.strip().split(',')\n\nall_data.extend(old)\nprint(len(all_data))\nrandom.shuffle(all_data)\n\nwith open(base_path + 'new_shu_label.txt', 'w') as f1:\n    for item in all_data:\n        f1.write(item + '\\n')"
  },
  {
    "path": "requirements.txt",
    "content": "pytorch==1.0.1\ntorchvision==0.2.2\nmatplotlib==3.1.0\nnumpy==1.16.4\nscikit-image\npandas\nsklearn\n"
  },
  {
    "path": "train.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-08-14 11:08\n公众号：AI成长社\n知乎：https://www.zhihu.com/people/qlmx-61/columns\n\"\"\"\nfrom __future__ import print_function\n\nimport os\nimport time\nimport random\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.parallel\nimport torch.backends.cudnn as cudnn\nimport torch.utils.data as data\nimport torchvision.transforms as transforms\nimport dataset\nimport numpy as np\nfrom args import args\nfrom build_net import make_model\nfrom transform import get_transforms\n\nfrom utils import Bar, Logger, AverageMeter, accuracy, mkdir_p, savefig, get_optimizer, save_checkpoint\n\n\nstate = {k: v for k, v in args._get_kwargs()}\n\n# Use CUDA\nos.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id\nuse_cuda = torch.cuda.is_available()\n\n# Random seed\nif args.manualSeed is None:\n    args.manualSeed = random.randint(1, 10000)\nrandom.seed(args.manualSeed)\ntorch.manual_seed(args.manualSeed)\nif use_cuda:\n    torch.cuda.manual_seed_all(args.manualSeed)\nbest_acc = 0  # best test accuracy\n\ndef main():\n    global best_acc\n    start_epoch = args.start_epoch  # start from epoch 0 or last checkpoint epoch\n\n    if not os.path.isdir(args.checkpoint):\n        mkdir_p(args.checkpoint)\n\n    # Data\n    transform = get_transforms(input_size=args.image_size, test_size=args.image_size, backbone=None)\n\n\n    print('==> Preparing dataset %s' % args.trainroot)\n    trainset = dataset.Dataset(root=args.trainroot, transform=transform['val_train'])\n    train_loader = data.DataLoader(trainset, batch_size=args.train_batch, shuffle=True, num_workers=args.workers, pin_memory=True)\n\n    valset = dataset.TestDataset(root=args.valroot, transform=transform['val_test'])\n    val_loader = data.DataLoader(valset, batch_size=args.test_batch, shuffle=False, num_workers=args.workers, pin_memory=True)\n\n    model = make_model(args)\n\n    if args.arch.startswith('alexnet') or args.arch.startswith('vgg'):\n        model.features = torch.nn.DataParallel(model.features)\n        model.cuda()\n    else:\n        model = torch.nn.DataParallel(model).cuda()\n\n    cudnn.benchmark = True\n    print('    Total params: %.2fM' % (sum(p.numel() for p in model.parameters())/1000000.0))\n\n    # define loss function (criterion) and optimizer\n    criterion = nn.CrossEntropyLoss().cuda()\n    optimizer = get_optimizer(model, args)\n    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.2, patience=5, verbose=False)\n\n    # Resume\n    title = 'ImageNet-' + args.arch\n    if args.resume:\n        # Load checkpoint.\n        print('==> Resuming from checkpoint..')\n        assert os.path.isfile(args.resume), 'Error: no checkpoint directory found!'\n        args.checkpoint = os.path.dirname(args.resume)\n        checkpoint = torch.load(args.resume)\n        best_acc = checkpoint['best_acc']\n        start_epoch = checkpoint['epoch']\n        model.module.load_state_dict(checkpoint['state_dict'])\n        optimizer.load_state_dict(checkpoint['optimizer'])\n        logger = Logger(os.path.join(args.checkpoint, 'log.txt'), title=title, resume=True)\n    else:\n        logger = Logger(os.path.join(args.checkpoint, 'log.txt'), title=title)\n        logger.set_names(['Learning Rate', 'Train Loss', 'Valid Loss', 'Train Acc.', 'Valid Acc.'])\n\n\n    if args.evaluate:\n        print('\\nEvaluation only')\n        test_loss, test_acc = test(val_loader, model, criterion, start_epoch, use_cuda)\n        print(' Test Loss:  %.8f, Test Acc:  %.2f' % (test_loss, test_acc))\n        return\n\n    # Train and val\n    for epoch in range(start_epoch, args.epochs):\n        print('\\nEpoch: [%d | %d] LR: %f' % (epoch + 1, args.epochs, optimizer.param_groups[0]['lr']))\n\n        train_loss, train_acc, train_5 = train(train_loader, model, criterion, optimizer, epoch, use_cuda)\n        test_loss, test_acc, test_5 = test(val_loader, model, criterion, epoch, use_cuda)\n\n        scheduler.step(test_loss)\n\n        # append logger file\n        logger.append([state['lr'], train_loss, test_loss, train_acc, test_acc])\n        print('train_loss:%f, val_loss:%f, train_acc:%f, train_5:%f, val_acc:%f, val_5:%f' % (train_loss, test_loss, train_acc, train_5, test_acc, test_5))\n\n        # save model\n        is_best = test_acc > best_acc\n        best_acc = max(test_acc, best_acc)\n\n        if len(args.gpu_id) > 1:\n            save_checkpoint({\n                'fold': 0,\n                'epoch': epoch + 1,\n                'state_dict': model.module.state_dict(),\n                'train_acc': train_acc,\n                'acc': test_acc,\n                'best_acc': best_acc,\n                'optimizer': optimizer.state_dict(),\n            }, is_best, single=True, checkpoint=args.checkpoint)\n        else:\n            save_checkpoint({\n                    'fold': 0,\n                    'epoch': epoch + 1,\n                    'state_dict': model.state_dict(),\n                    'train_acc':train_acc,\n                    'acc': test_acc,\n                    'best_acc': best_acc,\n                    'optimizer' : optimizer.state_dict(),\n                }, is_best, single=True, checkpoint=args.checkpoint)\n\n    logger.close()\n    logger.plot()\n    savefig(os.path.join(args.checkpoint, 'log.eps'))\n\n    print('Best acc:')\n    print(best_acc)\n\ndef train(train_loader, model, criterion, optimizer, epoch, use_cuda):\n    # switch to train mode\n    model.train()\n\n    batch_time = AverageMeter()\n    data_time = AverageMeter()\n    losses = AverageMeter()\n    top1 = AverageMeter()\n    top5 = AverageMeter()\n    end = time.time()\n\n    bar = Bar('Processing', max=len(train_loader))\n    for batch_idx, (inputs, targets) in enumerate(train_loader):\n        # measure data loading time\n        data_time.update(time.time() - end)\n\n        if use_cuda:\n            inputs, targets = inputs.cuda(), targets.cuda(async=True)\n        inputs, targets = torch.autograd.Variable(inputs), torch.autograd.Variable(targets)\n\n        # compute output\n        outputs = model(inputs)\n        loss = criterion(outputs, targets)\n\n        # measure accuracy and record loss\n        prec1, prec5 = accuracy(outputs.data, targets.data, topk=(1, 5))\n        losses.update(loss.item(), inputs.size(0))\n        top1.update(prec1.item(), inputs.size(0))\n        top5.update(prec5.item(), inputs.size(0))\n\n        # compute gradient and do SGD step\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        # measure elapsed time\n        batch_time.update(time.time() - end)\n        end = time.time()\n\n        # plot progress\n        bar.suffix  = '({batch}/{size}) Data: {data:.3f}s | Batch: {bt:.3f}s | Total: {total:} | ETA: {eta:} | Loss: {loss:.4f} | top1: {top1: .4f} | top5: {top5: .4f}'.format(\n                    batch=batch_idx + 1,\n                    size=len(train_loader),\n                    data=data_time.val,\n                    bt=batch_time.val,\n                    total=bar.elapsed_td,\n                    eta=bar.eta_td,\n                    loss=losses.avg,\n                    top1=top1.avg,\n                    top5=top5.avg,\n                    )\n        bar.next()\n    bar.finish()\n    return (losses.avg, top1.avg, top5.avg)\n\ndef test(val_loader, model, criterion, epoch, use_cuda):\n    global best_acc\n\n    batch_time = AverageMeter()\n    data_time = AverageMeter()\n    losses = AverageMeter()\n    top1 = AverageMeter()\n    top5 = AverageMeter()\n\n    # switch to evaluate mode\n    model.eval()\n\n    end = time.time()\n    bar = Bar('Processing', max=len(val_loader))\n    for batch_idx, (inputs, targets) in enumerate(val_loader):\n        # measure data loading time\n        data_time.update(time.time() - end)\n\n        if use_cuda:\n            inputs, targets = inputs.cuda(), targets.cuda()\n        inputs, targets = torch.autograd.Variable(inputs), torch.autograd.Variable(targets)\n\n        # compute output\n        outputs = model(inputs)\n        loss = criterion(outputs, targets)\n\n        # measure accuracy and record loss\n        prec1, prec5 = accuracy(outputs.data, targets.data, topk=(1, 5))\n        losses.update(loss.item(), inputs.size(0))\n        top1.update(prec1.item(), inputs.size(0))\n        top5.update(prec5.item(), inputs.size(0))\n\n        # measure elapsed time\n        batch_time.update(time.time() - end)\n        end = time.time()\n\n        # plot progress\n        bar.suffix  = '({batch}/{size}) Data: {data:.3f}s | Batch: {bt:.3f}s | Total: {total:} | ETA: {eta:} | Loss: {loss:.4f} | top1: {top1: .4f} | top5: {top5: .4f}'.format(\n                    batch=batch_idx + 1,\n                    size=len(val_loader),\n                    data=data_time.avg,\n                    bt=batch_time.avg,\n                    total=bar.elapsed_td,\n                    eta=bar.eta_td,\n                    loss=losses.avg,\n                    top1=top1.avg,\n                    top5=top5.avg,\n                    )\n        bar.next()\n    bar.finish()\n    return (losses.avg, top1.avg, top5.avg)\n\n\nif __name__ == '__main__':\n    main()\n\n"
  },
  {
    "path": "transform.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-09-07 18:54\n公众号：AI成长社\n知乎：https://www.zhihu.com/people/qlmx-61/columns\n\"\"\"\nimport random\nimport math\nimport torch\n\nfrom PIL import Image, ImageOps, ImageFilter\nfrom torchvision import transforms\n\nclass Resize(object):\n    def __init__(self, size, interpolation=Image.BILINEAR):\n        self.size = size\n        self.interpolation = interpolation\n\n    def __call__(self, img):\n        # padding\n        ratio = self.size[0] / self.size[1]\n        w, h = img.size\n        if w / h < ratio:\n            t = int(h * ratio)\n            w_padding = (t - w) // 2\n            img = img.crop((-w_padding, 0, w+w_padding, h))\n        else:\n            t = int(w / ratio)\n            h_padding = (t - h) // 2\n            img = img.crop((0, -h_padding, w, h+h_padding))\n\n        img = img.resize(self.size, self.interpolation)\n\n        return img\n\nclass RandomRotate(object):\n    def __init__(self, degree, p=0.5):\n        self.degree = degree\n        self.p = p\n\n    def __call__(self, img):\n        if random.random() < self.p:\n            rotate_degree = random.uniform(-1*self.degree, self.degree)\n            img = img.rotate(rotate_degree, Image.BILINEAR)\n        return img\n\nclass RandomGaussianBlur(object):\n    def __init__(self, p=0.5):\n        self.p = p\n    def __call__(self, img):\n        if random.random() < self.p:\n            img = img.filter(ImageFilter.GaussianBlur(\n                radius=random.random()))\n        return img\n\ndef get_train_transform(mean, std, size):\n    train_transform = transforms.Compose([\n        Resize((int(size * (256 / 224)), int(size * (256 / 224)))),\n        transforms.RandomCrop(size),\n\n        transforms.RandomHorizontalFlip(),\n        # RandomRotate(15, 0.3),\n        # RandomGaussianBlur(),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=mean, std=std),\n    ])\n    return train_transform\n\ndef get_test_transform(mean, std, size):\n    return transforms.Compose([\n        Resize((int(size * (256 / 224)), int(size * (256 / 224)))),\n        transforms.CenterCrop(size),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=mean, std=std),\n    ])\n\ndef get_transforms(input_size=224, test_size=224, backbone=None):\n    mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]\n    if backbone is not None and backbone in ['pnasnet5large', 'nasnetamobile']:\n        mean, std = [0.5, 0.5, 0.5], [0.5, 0.5, 0.5]\n    transformations = {}\n    transformations['val_train'] = get_train_transform(mean, std, input_size)\n    transformations['val_test'] = get_test_transform(mean, std, test_size)\n    return transformations\n\n"
  },
  {
    "path": "utils/__init__.py",
    "content": "\"\"\"Useful utils\n\"\"\"\nfrom .misc import *\nfrom .logger import *\nfrom .visualize import *\nfrom .eval import *\nfrom .utils import *\nfrom .radam import *\n\n# progress bar\nimport os, sys\nsys.path.append(os.path.join(os.path.dirname(__file__), \"progress\"))\nprint(os.path.dirname(__file__))\nfrom progress.bar import Bar as Bar"
  },
  {
    "path": "utils/eval.py",
    "content": "from __future__ import print_function, absolute_import\n\n__all__ = ['accuracy', 'precision']\n\ndef accuracy(output, target, topk=(1,)):\n    \"\"\"Computes the precision@k for the specified values of k\"\"\"\n    maxk = max(topk)\n    batch_size = target.size(0)\n\n    _, pred = output.topk(maxk, 1, True, True)\n    pred = pred.t()\n    correct = pred.eq(target.view(1, -1).expand_as(pred))\n\n    res = []\n    for k in topk:\n        correct_k = correct[:k].view(-1).float().sum(0)\n        res.append(correct_k.mul_(100.0 / batch_size))\n    return res\n\ndef precision(output, target):\n    pass"
  },
  {
    "path": "utils/logger.py",
    "content": "# A simple torch style logger\n# (C) Wei YANG 2017\nfrom __future__ import absolute_import\nimport matplotlib.pyplot as plt\nimport os\nimport sys\nimport numpy as np\n\n__all__ = ['Logger', 'LoggerMonitor', 'savefig']\n\ndef savefig(fname, dpi=None):\n    dpi = 150 if dpi == None else dpi\n    plt.savefig(fname, dpi=dpi)\n    \ndef plot_overlap(logger, names=None):\n    names = logger.names if names == None else names\n    numbers = logger.numbers\n    for _, name in enumerate(names):\n        x = np.arange(len(numbers[name]))\n        plt.plot(x, np.asarray(numbers[name]))\n    return [logger.title + '(' + name + ')' for name in names]\n\nclass Logger(object):\n    '''Save training process to log file with simple plot function.'''\n    def __init__(self, fpath, title=None, resume=False): \n        self.file = None\n        self.resume = resume\n        self.title = '' if title == None else title\n        if fpath is not None:\n            if resume: \n                self.file = open(fpath, 'r') \n                name = self.file.readline()\n                self.names = name.rstrip().split('\\t')\n                self.numbers = {}\n                for _, name in enumerate(self.names):\n                    self.numbers[name] = []\n\n                for numbers in self.file:\n                    numbers = numbers.rstrip().split('\\t')\n                    for i in range(0, len(numbers)):\n                        self.numbers[self.names[i]].append(numbers[i])\n                self.file.close()\n                self.file = open(fpath, 'a')  \n            else:\n                self.file = open(fpath, 'w')\n\n    def set_names(self, names):\n        if self.resume: \n            pass\n        # initialize numbers as empty list\n        self.numbers = {}\n        self.names = names\n        for _, name in enumerate(self.names):\n            self.file.write(name)\n            self.file.write('\\t')\n            self.numbers[name] = []\n        self.file.write('\\n')\n        self.file.flush()\n\n\n    def append(self, numbers):\n        assert len(self.names) == len(numbers), 'Numbers do not match names'\n        for index, num in enumerate(numbers):\n            self.file.write(\"{0:.6f}\".format(num))\n            self.file.write('\\t')\n            self.numbers[self.names[index]].append(num)\n        self.file.write('\\n')\n        self.file.flush()\n\n    def plot(self, names=None):   \n        names = self.names if names == None else names\n        numbers = self.numbers\n        for _, name in enumerate(names):\n            x = np.arange(len(numbers[name]))\n            plt.plot(x, np.asarray(numbers[name]))\n        plt.legend([self.title + '(' + name + ')' for name in names])\n        plt.grid(True)\n\n    def close(self):\n        if self.file is not None:\n            self.file.close()\n\nclass LoggerMonitor(object):\n    '''Load and visualize multiple logs.'''\n    def __init__ (self, paths):\n        '''paths is a distionary with {name:filepath} pair'''\n        self.loggers = []\n        for title, path in paths.items():\n            logger = Logger(path, title=title, resume=True)\n            self.loggers.append(logger)\n\n    def plot(self, names=None):\n        plt.figure()\n        plt.subplot(121)\n        legend_text = []\n        for logger in self.loggers:\n            legend_text += plot_overlap(logger, names)\n        plt.legend(legend_text, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)\n        plt.grid(True)\n                    \nif __name__ == '__main__':\n    # # Example\n    # logger = Logger('test.txt')\n    # logger.set_names(['Train loss', 'Valid loss','Test loss'])\n\n    # length = 100\n    # t = np.arange(length)\n    # train_loss = np.exp(-t / 10.0) + np.random.rand(length) * 0.1\n    # valid_loss = np.exp(-t / 10.0) + np.random.rand(length) * 0.1\n    # test_loss = np.exp(-t / 10.0) + np.random.rand(length) * 0.1\n\n    # for i in range(0, length):\n    #     logger.append([train_loss[i], valid_loss[i], test_loss[i]])\n    # logger.plot()\n\n    # Example: logger monitor\n    paths = {\n    'resadvnet20':'/home/wyang/code/pytorch-classification/checkpoint/cifar10/resadvnet20/log.txt', \n    'resadvnet32':'/home/wyang/code/pytorch-classification/checkpoint/cifar10/resadvnet32/log.txt',\n    'resadvnet44':'/home/wyang/code/pytorch-classification/checkpoint/cifar10/resadvnet44/log.txt',\n    }\n\n    field = ['Valid Acc.']\n\n    monitor = LoggerMonitor(paths)\n    monitor.plot(names=field)\n    savefig('test.eps')"
  },
  {
    "path": "utils/misc.py",
    "content": "'''Some helper functions for PyTorch, including:\n    - get_mean_and_std: calculate the mean and std value of dataset.\n    - msr_init: net parameter initialization.\n    - progress_bar: progress bar mimic xlua.progress.\n'''\nimport errno\nimport os\nimport sys\nimport time\nimport math\n\nimport torch.nn as nn\nimport torch.nn.init as init\nfrom torch.autograd import Variable\nimport torch\nimport shutil\nimport adabound\nfrom utils.radam import RAdam, AdamW\nimport torchvision.transforms as transforms\n\n\n\n__all__ = ['get_mean_and_std', 'init_params', 'mkdir_p', 'AverageMeter', 'get_optimizer', 'save_checkpoint']\n\n\ndef get_mean_and_std(dataset):\n    '''Compute the mean and std value of dataset.'''\n    dataloader = trainloader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True, num_workers=2)\n\n    mean = torch.zeros(3)\n    std = torch.zeros(3)\n    print('==> Computing mean and std..')\n    for inputs, targets in dataloader:\n        for i in range(3):\n            mean[i] += inputs[:,i,:,:].mean()\n            std[i] += inputs[:,i,:,:].std()\n    mean.div_(len(dataset))\n    std.div_(len(dataset))\n    return mean, std\n\ndef init_params(net):\n    '''Init layer parameters.'''\n    for m in net.modules():\n        if isinstance(m, nn.Conv2d):\n            init.kaiming_normal(m.weight, mode='fan_out')\n            if m.bias:\n                init.constant(m.bias, 0)\n        elif isinstance(m, nn.BatchNorm2d):\n            init.constant(m.weight, 1)\n            init.constant(m.bias, 0)\n        elif isinstance(m, nn.Linear):\n            init.normal(m.weight, std=1e-3)\n            if m.bias:\n                init.constant(m.bias, 0)\n\ndef mkdir_p(path):\n    '''make dir if not exist'''\n    try:\n        os.makedirs(path)\n    except OSError as exc:  # Python >2.5\n        if exc.errno == errno.EEXIST and os.path.isdir(path):\n            pass\n        else:\n            raise\n\nclass AverageMeter(object):\n    \"\"\"Computes and stores the average and current value\n       Imported from https://github.com/pytorch/examples/blob/master/imagenet/main.py#L247-L262\n    \"\"\"\n    def __init__(self):\n        self.reset()\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count\n\ndef get_optimizer(model, args):\n    parameters = []\n    for name, param in model.named_parameters():\n        if 'fc' in name or 'class' in name or 'last_linear' in name or 'ca' in name or 'sa' in name:\n            parameters.append({'params': param, 'lr': args.lr * args.lr_fc_times})\n        else:\n            parameters.append({'params': param, 'lr': args.lr})\n\n    if args.optimizer == 'sgd':\n        return torch.optim.SGD(parameters,\n                            # model.parameters(),\n                               args.lr,\n                               momentum=args.momentum, nesterov=args.nesterov,\n                               weight_decay=args.weight_decay)\n    elif args.optimizer == 'rmsprop':\n        return torch.optim.RMSprop(parameters,\n                                # model.parameters(),\n                                   args.lr,\n                                   alpha=args.alpha,\n                                   weight_decay=args.weight_decay)\n    elif args.optimizer == 'adam':\n        return torch.optim.Adam(parameters,\n                                # model.parameters(),\n                                args.lr,\n                                betas=(args.beta1, args.beta2),\n                                weight_decay=args.weight_decay)\n    elif args.optimizer == 'AdaBound':\n        return adabound.AdaBound(parameters,\n                                # model.parameters(),\n                                lr=args.lr, final_lr=args.final_lr)\n    elif args.optimizer == 'radam':\n        return RAdam(parameters, lr=args.lr, betas=(args.beta1, args.beta2),\n                          weight_decay=args.weight_decay)\n\n    else:\n        raise NotImplementedError\n\n\ndef save_checkpoint(state, is_best, single=True, checkpoint='checkpoint', filename='checkpoint.pth.tar'):\n    if single:\n        fold = ''\n    else:\n        fold = str(state['fold']) + '_'\n    cur_name = 'checkpoint.pth.tar'\n    filepath = os.path.join(checkpoint, fold + cur_name)\n    curpath = os.path.join(checkpoint, fold + 'model_cur.pth')\n\n    torch.save(state, filepath)\n    torch.save(state['state_dict'], curpath)\n\n    if is_best and state['epoch'] >= 5:\n        model_name = 'model_' + str(state['epoch']) + '_' + str(int(round(state['train_acc']*100, 0))) + '_' + str(int(round(state['acc']*100, 0))) + '.pth'\n        model_path = os.path.join(checkpoint, fold + model_name)\n        torch.save(state['state_dict'], model_path)\n\n\ndef save_checkpoint2(state, is_best, checkpoint='checkpoint', filename='checkpoint.pth.tar'):\n    # best_model = '/application/search/qlmx/clover/garbage/code/image_classfication/predict/'\n    fold = str(state['fold']) + '_'\n    filepath = os.path.join(checkpoint, fold + filename)\n    model_path = os.path.join(checkpoint, fold + 'model_cur.pth')\n\n    torch.save(state, filepath)\n    torch.save(state['state_dict'], model_path)\n    if is_best:\n        shutil.copyfile(filepath, os.path.join(checkpoint, fold + 'model_best.pth.tar'))\n        shutil.copyfile(model_path, os.path.join(checkpoint, fold + 'model_best.pth'))\n"
  },
  {
    "path": "utils/progress/LICENSE",
    "content": "# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this software for any\n# purpose with or without fee is hereby granted, provided that the above\n# copyright notice and this permission notice appear in all copies.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "utils/progress/MANIFEST.in",
    "content": "include README.rst LICENSE\n"
  },
  {
    "path": "utils/progress/README.rst",
    "content": "Easy progress reporting for Python\n==================================\n\n|pypi|\n\n|demo|\n\n.. |pypi| image:: https://img.shields.io/pypi/v/progress.svg\n.. |demo| image:: https://raw.github.com/verigak/progress/master/demo.gif\n   :alt: Demo\n\nBars\n----\n\nThere are 7 progress bars to choose from:\n\n- ``Bar``\n- ``ChargingBar``\n- ``FillingSquaresBar``\n- ``FillingCirclesBar``\n- ``IncrementalBar``\n- ``PixelBar``\n- ``ShadyBar``\n\nTo use them, just call ``next`` to advance and ``finish`` to finish:\n\n.. code-block:: python\n\n    from progress.bar import Bar\n\n    bar = Bar('Processing', max=20)\n    for i in range(20):\n        # Do some work\n        bar.next()\n    bar.finish()\n\nThe result will be a bar like the following: ::\n\n    Processing |#############                   | 42/100\n\nTo simplify the common case where the work is done in an iterator, you can\nuse the ``iter`` method:\n\n.. code-block:: python\n\n    for i in Bar('Processing').iter(it):\n        # Do some work\n\nProgress bars are very customizable, you can change their width, their fill\ncharacter, their suffix and more:\n\n.. code-block:: python\n\n    bar = Bar('Loading', fill='@', suffix='%(percent)d%%')\n\nThis will produce a bar like the following: ::\n\n    Loading |@@@@@@@@@@@@@                   | 42%\n\nYou can use a number of template arguments in ``message`` and ``suffix``:\n\n==========  ================================\nName        Value\n==========  ================================\nindex       current value\nmax         maximum value\nremaining   max - index\nprogress    index / max\npercent     progress * 100\navg         simple moving average time per item (in seconds)\nelapsed     elapsed time in seconds\nelapsed_td  elapsed as a timedelta (useful for printing as a string)\neta         avg * remaining\neta_td      eta as a timedelta (useful for printing as a string)\n==========  ================================\n\nInstead of passing all configuration options on instatiation, you can create\nyour custom subclass:\n\n.. code-block:: python\n\n    class FancyBar(Bar):\n        message = 'Loading'\n        fill = '*'\n        suffix = '%(percent).1f%% - %(eta)ds'\n\nYou can also override any of the arguments or create your own:\n\n.. code-block:: python\n\n    class SlowBar(Bar):\n        suffix = '%(remaining_hours)d hours remaining'\n        @property\n        def remaining_hours(self):\n            return self.eta // 3600\n\n\nSpinners\n========\n\nFor actions with an unknown number of steps you can use a spinner:\n\n.. code-block:: python\n\n    from progress.spinner import Spinner\n\n    spinner = Spinner('Loading ')\n    while state != 'FINISHED':\n        # Do some work\n        spinner.next()\n\nThere are 5 predefined spinners:\n\n- ``Spinner``\n- ``PieSpinner``\n- ``MoonSpinner``\n- ``LineSpinner``\n- ``PixelSpinner``\n\n\nOther\n=====\n\nThere are a number of other classes available too, please check the source or\nsubclass one of them to create your own.\n\n\nLicense\n=======\n\nprogress is licensed under ISC\n"
  },
  {
    "path": "utils/progress/progress/__init__.py",
    "content": "# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this software for any\n# purpose with or without fee is hereby granted, provided that the above\n# copyright notice and this permission notice appear in all copies.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nfrom __future__ import division\n\nfrom collections import deque\nfrom datetime import timedelta\nfrom math import ceil\nfrom sys import stderr\nfrom time import time\n\n\n__version__ = '1.3'\n\n\nclass Infinite(object):\n    file = stderr\n    sma_window = 10         # Simple Moving Average window\n\n    def __init__(self, *args, **kwargs):\n        self.index = 0\n        self.start_ts = time()\n        self.avg = 0\n        self._ts = self.start_ts\n        self._xput = deque(maxlen=self.sma_window)\n        for key, val in kwargs.items():\n            setattr(self, key, val)\n\n    def __getitem__(self, key):\n        if key.startswith('_'):\n            return None\n        return getattr(self, key, None)\n\n    @property\n    def elapsed(self):\n        return int(time() - self.start_ts)\n\n    @property\n    def elapsed_td(self):\n        return timedelta(seconds=self.elapsed)\n\n    def update_avg(self, n, dt):\n        if n > 0:\n            self._xput.append(dt / n)\n            self.avg = sum(self._xput) / len(self._xput)\n\n    def update(self):\n        pass\n\n    def start(self):\n        pass\n\n    def finish(self):\n        pass\n\n    def next(self, n=1):\n        now = time()\n        dt = now - self._ts\n        self.update_avg(n, dt)\n        self._ts = now\n        self.index = self.index + n\n        self.update()\n\n    def iter(self, it):\n        try:\n            for x in it:\n                yield x\n                self.next()\n        finally:\n            self.finish()\n\n\nclass Progress(Infinite):\n    def __init__(self, *args, **kwargs):\n        super(Progress, self).__init__(*args, **kwargs)\n        self.max = kwargs.get('max', 100)\n\n    @property\n    def eta(self):\n        return int(ceil(self.avg * self.remaining))\n\n    @property\n    def eta_td(self):\n        return timedelta(seconds=self.eta)\n\n    @property\n    def percent(self):\n        return self.progress * 100\n\n    @property\n    def progress(self):\n        return min(1, self.index / self.max)\n\n    @property\n    def remaining(self):\n        return max(self.max - self.index, 0)\n\n    def start(self):\n        self.update()\n\n    def goto(self, index):\n        incr = index - self.index\n        self.next(incr)\n\n    def iter(self, it):\n        try:\n            self.max = len(it)\n        except TypeError:\n            pass\n\n        try:\n            for x in it:\n                yield x\n                self.next()\n        finally:\n            self.finish()\n"
  },
  {
    "path": "utils/progress/progress/bar.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this software for any\n# purpose with or without fee is hereby granted, provided that the above\n# copyright notice and this permission notice appear in all copies.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nfrom __future__ import unicode_literals\nfrom . import Progress\nfrom .helpers import WritelnMixin\n\n\nclass Bar(WritelnMixin, Progress):\n    width = 32\n    message = ''\n    suffix = '%(index)d/%(max)d'\n    bar_prefix = ' |'\n    bar_suffix = '| '\n    empty_fill = ' '\n    fill = '#'\n    hide_cursor = True\n\n    def update(self):\n        filled_length = int(self.width * self.progress)\n        empty_length = self.width - filled_length\n\n        message = self.message % self\n        bar = self.fill * filled_length\n        empty = self.empty_fill * empty_length\n        suffix = self.suffix % self\n        line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix,\n                        suffix])\n        self.writeln(line)\n\n\nclass ChargingBar(Bar):\n    suffix = '%(percent)d%%'\n    bar_prefix = ' '\n    bar_suffix = ' '\n    empty_fill = '∙'\n    fill = '█'\n\n\nclass FillingSquaresBar(ChargingBar):\n    empty_fill = '▢'\n    fill = '▣'\n\n\nclass FillingCirclesBar(ChargingBar):\n    empty_fill = '◯'\n    fill = '◉'\n\n\nclass IncrementalBar(Bar):\n    phases = (' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█')\n\n    def update(self):\n        nphases = len(self.phases)\n        filled_len = self.width * self.progress\n        nfull = int(filled_len)                      # Number of full chars\n        phase = int((filled_len - nfull) * nphases)  # Phase of last char\n        nempty = self.width - nfull                  # Number of empty chars\n\n        message = self.message % self\n        bar = self.phases[-1] * nfull\n        current = self.phases[phase] if phase > 0 else ''\n        empty = self.empty_fill * max(0, nempty - len(current))\n        suffix = self.suffix % self\n        line = ''.join([message, self.bar_prefix, bar, current, empty,\n                        self.bar_suffix, suffix])\n        self.writeln(line)\n\n\nclass PixelBar(IncrementalBar):\n    phases = ('⡀', '⡄', '⡆', '⡇', '⣇', '⣧', '⣷', '⣿')\n\n\nclass ShadyBar(IncrementalBar):\n    phases = (' ', '░', '▒', '▓', '█')\n"
  },
  {
    "path": "utils/progress/progress/counter.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this software for any\n# purpose with or without fee is hereby granted, provided that the above\n# copyright notice and this permission notice appear in all copies.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nfrom __future__ import unicode_literals\nfrom . import Infinite, Progress\nfrom .helpers import WriteMixin\n\n\nclass Counter(WriteMixin, Infinite):\n    message = ''\n    hide_cursor = True\n\n    def update(self):\n        self.write(str(self.index))\n\n\nclass Countdown(WriteMixin, Progress):\n    hide_cursor = True\n\n    def update(self):\n        self.write(str(self.remaining))\n\n\nclass Stack(WriteMixin, Progress):\n    phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█')\n    hide_cursor = True\n\n    def update(self):\n        nphases = len(self.phases)\n        i = min(nphases - 1, int(self.progress * nphases))\n        self.write(self.phases[i])\n\n\nclass Pie(Stack):\n    phases = ('○', '◔', '◑', '◕', '●')\n"
  },
  {
    "path": "utils/progress/progress/helpers.py",
    "content": "# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this software for any\n# purpose with or without fee is hereby granted, provided that the above\n# copyright notice and this permission notice appear in all copies.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nfrom __future__ import print_function\n\n\nHIDE_CURSOR = '\\x1b[?25l'\nSHOW_CURSOR = '\\x1b[?25h'\n\n\nclass WriteMixin(object):\n    hide_cursor = False\n\n    def __init__(self, message=None, **kwargs):\n        super(WriteMixin, self).__init__(**kwargs)\n        self._width = 0\n        if message:\n            self.message = message\n\n        if self.file.isatty():\n            if self.hide_cursor:\n                print(HIDE_CURSOR, end='', file=self.file)\n            print(self.message, end='', file=self.file)\n            self.file.flush()\n\n    def write(self, s):\n        if self.file.isatty():\n            b = '\\b' * self._width\n            c = s.ljust(self._width)\n            print(b + c, end='', file=self.file)\n            self._width = max(self._width, len(s))\n            self.file.flush()\n\n    def finish(self):\n        if self.file.isatty() and self.hide_cursor:\n            print(SHOW_CURSOR, end='', file=self.file)\n\n\nclass WritelnMixin(object):\n    hide_cursor = False\n\n    def __init__(self, message=None, **kwargs):\n        super(WritelnMixin, self).__init__(**kwargs)\n        if message:\n            self.message = message\n\n        if self.file.isatty() and self.hide_cursor:\n            print(HIDE_CURSOR, end='', file=self.file)\n\n    def clearln(self):\n        if self.file.isatty():\n            print('\\r\\x1b[K', end='', file=self.file)\n\n    def writeln(self, line):\n        if self.file.isatty():\n            self.clearln()\n            print(line, end='', file=self.file)\n            self.file.flush()\n\n    def finish(self):\n        if self.file.isatty():\n            print(file=self.file)\n            if self.hide_cursor:\n                print(SHOW_CURSOR, end='', file=self.file)\n\n\nfrom signal import signal, SIGINT\nfrom sys import exit\n\n\nclass SigIntMixin(object):\n    \"\"\"Registers a signal handler that calls finish on SIGINT\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super(SigIntMixin, self).__init__(*args, **kwargs)\n        signal(SIGINT, self._sigint_handler)\n\n    def _sigint_handler(self, signum, frame):\n        self.finish()\n        exit(0)\n"
  },
  {
    "path": "utils/progress/progress/spinner.py",
    "content": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this software for any\n# purpose with or without fee is hereby granted, provided that the above\n# copyright notice and this permission notice appear in all copies.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\nfrom __future__ import unicode_literals\nfrom . import Infinite\nfrom .helpers import WriteMixin\n\n\nclass Spinner(WriteMixin, Infinite):\n    message = ''\n    phases = ('-', '\\\\', '|', '/')\n    hide_cursor = True\n\n    def update(self):\n        i = self.index % len(self.phases)\n        self.write(self.phases[i])\n\n\nclass PieSpinner(Spinner):\n    phases = ['◷', '◶', '◵', '◴']\n\n\nclass MoonSpinner(Spinner):\n    phases = ['◑', '◒', '◐', '◓']\n\n\nclass LineSpinner(Spinner):\n    phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻']\n\nclass PixelSpinner(Spinner):\n    phases = ['⣾','⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽']\n"
  },
  {
    "path": "utils/progress/setup.py",
    "content": "#!/usr/bin/env python\n\nfrom setuptools import setup\n\nimport progress\n\n\nsetup(\n    name='progress',\n    version=progress.__version__,\n    description='Easy to use progress bars',\n    long_description=open('README.rst').read(),\n    author='Giorgos Verigakis',\n    author_email='verigak@gmail.com',\n    url='http://github.com/verigak/progress/',\n    license='ISC',\n    packages=['progress'],\n    classifiers=[\n        'Environment :: Console',\n        'Intended Audience :: Developers',\n        'License :: OSI Approved :: ISC License (ISCL)',\n        'Programming Language :: Python :: 2.6',\n        'Programming Language :: Python :: 2.7',\n        'Programming Language :: Python :: 3.3',\n        'Programming Language :: Python :: 3.4',\n        'Programming Language :: Python :: 3.5',\n        'Programming Language :: Python :: 3.6',\n    ]\n)\n"
  },
  {
    "path": "utils/progress/test_progress.py",
    "content": "#!/usr/bin/env python\n\nfrom __future__ import print_function\n\nimport random\nimport time\n\nfrom progress.bar import (Bar, ChargingBar, FillingSquaresBar,\n                          FillingCirclesBar, IncrementalBar, PixelBar,\n                          ShadyBar)\nfrom progress.spinner import (Spinner, PieSpinner, MoonSpinner, LineSpinner,\n                              PixelSpinner)\nfrom progress.counter import Counter, Countdown, Stack, Pie\n\n\ndef sleep():\n    t = 0.01\n    t += t * random.uniform(-0.1, 0.1)  # Add some variance\n    time.sleep(t)\n\n\nfor bar_cls in (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar):\n    suffix = '%(index)d/%(max)d [%(elapsed)d / %(eta)d / %(eta_td)s]'\n    bar = bar_cls(bar_cls.__name__, suffix=suffix)\n    for i in bar.iter(range(200)):\n        sleep()\n\nfor bar_cls in (IncrementalBar, PixelBar, ShadyBar):\n    suffix = '%(percent)d%% [%(elapsed_td)s / %(eta)d / %(eta_td)s]'\n    bar = bar_cls(bar_cls.__name__, suffix=suffix)\n    for i in bar.iter(range(200)):\n        sleep()\n\nfor spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner, PixelSpinner):\n    for i in spin(spin.__name__ + ' ').iter(range(100)):\n        sleep()\n    print()\n\nfor singleton in (Counter, Countdown, Stack, Pie):\n    for i in singleton(singleton.__name__ + ' ').iter(range(100)):\n        sleep()\n    print()\n\nbar = IncrementalBar('Random', suffix='%(index)d')\nfor i in range(100):\n    bar.goto(random.randint(0, 100))\n    sleep()\nbar.finish()\n"
  },
  {
    "path": "utils/radam.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-09-13 10:49\n\"\"\"\nimport math\nimport torch\nfrom torch.optim.optimizer import Optimizer, required\n\n\nclass RAdam(Optimizer):\n\n    def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0):\n        defaults = dict(lr=lr, betas=betas, eps=eps, weight_decay=weight_decay)\n        self.buffer = [[None, None, None] for ind in range(10)]\n        super(RAdam, self).__init__(params, defaults)\n\n    def __setstate__(self, state):\n        super(RAdam, self).__setstate__(state)\n\n    def step(self, closure=None):\n\n        loss = None\n        if closure is not None:\n            loss = closure()\n\n        for group in self.param_groups:\n\n            for p in group['params']:\n                if p.grad is None:\n                    continue\n                grad = p.grad.data.float()\n                if grad.is_sparse:\n                    raise RuntimeError('RAdam does not support sparse gradients')\n\n                p_data_fp32 = p.data.float()\n\n                state = self.state[p]\n\n                if len(state) == 0:\n                    state['step'] = 0\n                    state['exp_avg'] = torch.zeros_like(p_data_fp32)\n                    state['exp_avg_sq'] = torch.zeros_like(p_data_fp32)\n                else:\n                    state['exp_avg'] = state['exp_avg'].type_as(p_data_fp32)\n                    state['exp_avg_sq'] = state['exp_avg_sq'].type_as(p_data_fp32)\n\n                exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']\n                beta1, beta2 = group['betas']\n\n                exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)\n                exp_avg.mul_(beta1).add_(1 - beta1, grad)\n\n                state['step'] += 1\n                buffered = self.buffer[int(state['step'] % 10)]\n                if state['step'] == buffered[0]:\n                    N_sma, step_size = buffered[1], buffered[2]\n                else:\n                    buffered[0] = state['step']\n                    beta2_t = beta2 ** state['step']\n                    N_sma_max = 2 / (1 - beta2) - 1\n                    N_sma = N_sma_max - 2 * state['step'] * beta2_t / (1 - beta2_t)\n                    buffered[1] = N_sma\n\n                    # more conservative since it's an approximated value\n                    if N_sma >= 5:\n                        step_size = math.sqrt(\n                            (1 - beta2_t) * (N_sma - 4) / (N_sma_max - 4) * (N_sma - 2) / N_sma * N_sma_max / (\n                                        N_sma_max - 2)) / (1 - beta1 ** state['step'])\n                    else:\n                        step_size = 1.0 / (1 - beta1 ** state['step'])\n                    buffered[2] = step_size\n\n                if group['weight_decay'] != 0:\n                    p_data_fp32.add_(-group['weight_decay'] * group['lr'], p_data_fp32)\n\n                # more conservative since it's an approximated value\n                if N_sma >= 5:\n                    denom = exp_avg_sq.sqrt().add_(group['eps'])\n                    p_data_fp32.addcdiv_(-step_size * group['lr'], exp_avg, denom)\n                else:\n                    p_data_fp32.add_(-step_size * group['lr'], exp_avg)\n\n                p.data.copy_(p_data_fp32)\n\n        return loss\n\n\nclass PlainRAdam(Optimizer):\n\n    def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0):\n        defaults = dict(lr=lr, betas=betas, eps=eps, weight_decay=weight_decay)\n\n        super(PlainRAdam, self).__init__(params, defaults)\n\n    def __setstate__(self, state):\n        super(PlainRAdam, self).__setstate__(state)\n\n    def step(self, closure=None):\n\n        loss = None\n        if closure is not None:\n            loss = closure()\n\n        for group in self.param_groups:\n\n            for p in group['params']:\n                if p.grad is None:\n                    continue\n                grad = p.grad.data.float()\n                if grad.is_sparse:\n                    raise RuntimeError('RAdam does not support sparse gradients')\n\n                p_data_fp32 = p.data.float()\n\n                state = self.state[p]\n\n                if len(state) == 0:\n                    state['step'] = 0\n                    state['exp_avg'] = torch.zeros_like(p_data_fp32)\n                    state['exp_avg_sq'] = torch.zeros_like(p_data_fp32)\n                else:\n                    state['exp_avg'] = state['exp_avg'].type_as(p_data_fp32)\n                    state['exp_avg_sq'] = state['exp_avg_sq'].type_as(p_data_fp32)\n\n                exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']\n                beta1, beta2 = group['betas']\n\n                exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)\n                exp_avg.mul_(beta1).add_(1 - beta1, grad)\n\n                state['step'] += 1\n                beta2_t = beta2 ** state['step']\n                N_sma_max = 2 / (1 - beta2) - 1\n                N_sma = N_sma_max - 2 * state['step'] * beta2_t / (1 - beta2_t)\n\n                if group['weight_decay'] != 0:\n                    p_data_fp32.add_(-group['weight_decay'] * group['lr'], p_data_fp32)\n\n                # more conservative since it's an approximated value\n                if N_sma >= 5:\n                    step_size = group['lr'] * math.sqrt(\n                        (1 - beta2_t) * (N_sma - 4) / (N_sma_max - 4) * (N_sma - 2) / N_sma * N_sma_max / (\n                                    N_sma_max - 2)) / (1 - beta1 ** state['step'])\n                    denom = exp_avg_sq.sqrt().add_(group['eps'])\n                    p_data_fp32.addcdiv_(-step_size, exp_avg, denom)\n                else:\n                    step_size = group['lr'] / (1 - beta1 ** state['step'])\n                    p_data_fp32.add_(-step_size, exp_avg)\n\n                p.data.copy_(p_data_fp32)\n\n        return loss\n\n\nclass AdamW(Optimizer):\n\n    def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0, warmup=0):\n        defaults = dict(lr=lr, betas=betas, eps=eps,\n                        weight_decay=weight_decay, warmup=warmup)\n        super(AdamW, self).__init__(params, defaults)\n\n    def __setstate__(self, state):\n        super(AdamW, self).__setstate__(state)\n\n    def step(self, closure=None):\n        loss = None\n        if closure is not None:\n            loss = closure()\n\n        for group in self.param_groups:\n\n            for p in group['params']:\n                if p.grad is None:\n                    continue\n                grad = p.grad.data.float()\n                if grad.is_sparse:\n                    raise RuntimeError('Adam does not support sparse gradients, please consider SparseAdam instead')\n\n                p_data_fp32 = p.data.float()\n\n                state = self.state[p]\n\n                if len(state) == 0:\n                    state['step'] = 0\n                    state['exp_avg'] = torch.zeros_like(p_data_fp32)\n                    state['exp_avg_sq'] = torch.zeros_like(p_data_fp32)\n                else:\n                    state['exp_avg'] = state['exp_avg'].type_as(p_data_fp32)\n                    state['exp_avg_sq'] = state['exp_avg_sq'].type_as(p_data_fp32)\n\n                exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']\n                beta1, beta2 = group['betas']\n\n                state['step'] += 1\n\n                exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)\n                exp_avg.mul_(beta1).add_(1 - beta1, grad)\n\n                denom = exp_avg_sq.sqrt().add_(group['eps'])\n                bias_correction1 = 1 - beta1 ** state['step']\n                bias_correction2 = 1 - beta2 ** state['step']\n\n                if group['warmup'] > state['step']:\n                    scheduled_lr = 1e-8 + state['step'] * group['lr'] / group['warmup']\n                else:\n                    scheduled_lr = group['lr']\n\n                step_size = scheduled_lr * math.sqrt(bias_correction2) / bias_correction1\n\n                if group['weight_decay'] != 0:\n                    p_data_fp32.add_(-group['weight_decay'] * scheduled_lr, p_data_fp32)\n\n                p_data_fp32.addcdiv_(-step_size, exp_avg, denom)\n\n                p.data.copy_(p_data_fp32)\n\n        return loss"
  },
  {
    "path": "utils/utils.py",
    "content": "#!usr/bin/env python  \n#-*- coding:utf-8 _*- \n\"\"\"\n@version: python3.6\n@author: QLMX\n@contact: wenruichn@gmail.com\n@time: 2019-08-20 00:55\n\"\"\"\nimport torch.nn as nn\nimport cv2\nimport torch\ndevice=torch.device(\"cuda\")\nimport os\nimport urllib.parse as urlparse\nimport requests\nimport torch\n\n__all__ = ['GetEncoder', 'GetPreTrainedModel', 'load_pretrained', 'l2_norm']\n\n\n#修改模型以进行特征提取\ndef GetEncoder(model):\n    layerName,layer=list(model.named_children())[-1]\n    exec(\"model.\"+layerName+\"=nn.Linear(layer.in_features,layer.in_features)\")\n    exec(\"torch.nn.init.eye_(model.\"+layerName+\".weight)\")\n    for param in model.parameters():\n        param.requires_grad=False\n    return model,layer.in_features\n\n#修改模型以进行微调，n_ZeroChild和n_ZeroLayer用来设置参数固定层，当children为Sequential时使用n_ZeroLayer，可对其内部进行设置\ndef GetPreTrainedModel(model,n_Output,n_ZeroChild,n_ZeroLayer=None):\n    for i,children in enumerate(model.children()):\n        if i==n_ZeroChild:\n            if n_ZeroLayer is not None:\n                for j,layer in enumerate(children):\n                    if j==n_ZeroLayer:\n                        break\n                    for param in layer.parameters():\n                        param.requires_grad=False\n            break\n        for param in children.parameters():\n            param.requires_grad=False\n    layerName,layer=list(model.named_children())[-1]\n    exec(\"model.\"+layerName+\"=nn.Linear(layer.in_features,\"+str(n_Output)+\")\")\n    return model\n\n\nclass StackNet2(nn.Module):\n    def __init__(self,models,n_Target):\n        super(StackNet,self).__init__()\n        self.models=models\n        n_Out=0\n        for i,(model,scale_In,n_ZeroChild,n_ZeroLayer) in enumerate(self.models):\n            for j,children in enumerate(model.children()):\n                if j==n_ZeroChild:\n                    if n_ZeroLayer is not None:\n                        for k,layer in enumerate(children):\n                            if k==n_ZeroLayer:\n                                break\n                            for param in layer.parameters():\n                                param.requires_grad=False\n                    break\n\n            layerName,layer=list(model.named_children())[-1]\n            n_Out+=layer.in_features\n            exec(\"model.\"+layerName+\"=nn.Linear(layer.in_features,layer.in_features)\")\n            exec(\"torch.nn.init.eye_(model.\"+layerName+\".weight)\")\n            exec(\"layer=model.\"+layerName)\n            for param in layer.parameters():\n                param.requires_grad=False\n            exec(\"self.model\"+str(i)+\"=model\")\n        self.fc=nn.Linear(n_Out,n_Target)\n    def forward(self,x):\n        feature=[]\n        for model,scale_In,_,_ in self.models:\n            feature.append(model(x))\n        feature=torch.cat(feature,dim=1)\n        return self.fc(feature)\n\n\ndef _download_file_from_google_drive(fid, dest):\n    def _get_confirm_token(res):\n        for k, v in res.cookies.items():\n            if k.startswith('download_warning'): return v\n        return None\n\n    def _save_response_content(res, dest):\n        CHUNK_SIZE = 32768\n        with open(dest, \"wb\") as f:\n            for chunk in res.iter_content(CHUNK_SIZE):\n                if chunk: f.write(chunk)\n\n    URL = \"https://docs.google.com/uc?export=download\"\n    sess = requests.Session()\n    res = sess.get(URL, params={'id': fid}, stream=True)\n    token = _get_confirm_token(res)\n\n    if token:\n        params = {'id': fid, 'confirm': token}\n        res = sess.get(URL, params=params, stream=True)\n    _save_response_content(res, dest)\n\n\ndef _load_url(url, dest):\n    if os.path.isfile(dest) and os.path.exists(dest): return dest\n    print('[INFO]: Downloading weights...')\n    fid = urlparse.parse_qs(urlparse.urlparse(url).query)['id'][0]\n    _download_file_from_google_drive(fid, dest)\n    return dest\n\n\ndef load_pretrained(m, meta, dest, pretrained=False):\n    if pretrained:\n        if len(meta) == 0:\n            print('[INFO]: Pretrained model not available')\n            return m\n        if dest is None: dest = meta[0]\n        else:\n            dest = dest + '/' + meta[0]\n        print(dest)\n        m.load_state_dict(torch.load(_load_url(meta[1], dest)))\n    return m\n\ndef l2_norm(input,axis=1):\n    norm = torch.norm(input,2,axis,True)\n    output = torch.div(input, norm)\n    return output"
  },
  {
    "path": "utils/visualize.py",
    "content": "import matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torchvision\nimport torchvision.transforms as transforms\nimport numpy as np\nfrom .misc import *   \n\n__all__ = ['make_image', 'show_batch', 'show_mask', 'show_mask_single']\n\n# functions to show an image\ndef make_image(img, mean=(0,0,0), std=(1,1,1)):\n    for i in range(0, 3):\n        img[i] = img[i] * std[i] + mean[i]    # unnormalize\n    npimg = img.numpy()\n    return np.transpose(npimg, (1, 2, 0))\n\ndef gauss(x,a,b,c):\n    return torch.exp(-torch.pow(torch.add(x,-b),2).div(2*c*c)).mul(a)\n\ndef colorize(x):\n    ''' Converts a one-channel grayscale image to a color heatmap image '''\n    if x.dim() == 2:\n        torch.unsqueeze(x, 0, out=x)\n    if x.dim() == 3:\n        cl = torch.zeros([3, x.size(1), x.size(2)])\n        cl[0] = gauss(x,.5,.6,.2) + gauss(x,1,.8,.3)\n        cl[1] = gauss(x,1,.5,.3)\n        cl[2] = gauss(x,1,.2,.3)\n        cl[cl.gt(1)] = 1\n    elif x.dim() == 4:\n        cl = torch.zeros([x.size(0), 3, x.size(2), x.size(3)])\n        cl[:,0,:,:] = gauss(x,.5,.6,.2) + gauss(x,1,.8,.3)\n        cl[:,1,:,:] = gauss(x,1,.5,.3)\n        cl[:,2,:,:] = gauss(x,1,.2,.3)\n    return cl\n\ndef show_batch(images, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):\n    images = make_image(torchvision.utils.make_grid(images), Mean, Std)\n    plt.imshow(images)\n    plt.show()\n\n\ndef show_mask_single(images, mask, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):\n    im_size = images.size(2)\n\n    # save for adding mask\n    im_data = images.clone()\n    for i in range(0, 3):\n        im_data[:,i,:,:] = im_data[:,i,:,:] * Std[i] + Mean[i]    # unnormalize\n\n    images = make_image(torchvision.utils.make_grid(images), Mean, Std)\n    plt.subplot(2, 1, 1)\n    plt.imshow(images)\n    plt.axis('off')\n\n    # for b in range(mask.size(0)):\n    #     mask[b] = (mask[b] - mask[b].min())/(mask[b].max() - mask[b].min())\n    mask_size = mask.size(2)\n    # print('Max %f Min %f' % (mask.max(), mask.min()))\n    mask = (upsampling(mask, scale_factor=im_size/mask_size))\n    # mask = colorize(upsampling(mask, scale_factor=im_size/mask_size))\n    # for c in range(3):\n    #     mask[:,c,:,:] = (mask[:,c,:,:] - Mean[c])/Std[c]\n\n    # print(mask.size())\n    mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask.expand_as(im_data)))\n    # mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask), Mean, Std)\n    plt.subplot(2, 1, 2)\n    plt.imshow(mask)\n    plt.axis('off')\n\ndef show_mask(images, masklist, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):\n    im_size = images.size(2)\n\n    # save for adding mask\n    im_data = images.clone()\n    for i in range(0, 3):\n        im_data[:,i,:,:] = im_data[:,i,:,:] * Std[i] + Mean[i]    # unnormalize\n\n    images = make_image(torchvision.utils.make_grid(images), Mean, Std)\n    plt.subplot(1+len(masklist), 1, 1)\n    plt.imshow(images)\n    plt.axis('off')\n\n    for i in range(len(masklist)):\n        mask = masklist[i].data.cpu()\n        # for b in range(mask.size(0)):\n        #     mask[b] = (mask[b] - mask[b].min())/(mask[b].max() - mask[b].min())\n        mask_size = mask.size(2)\n        # print('Max %f Min %f' % (mask.max(), mask.min()))\n        mask = (upsampling(mask, scale_factor=im_size/mask_size))\n        # mask = colorize(upsampling(mask, scale_factor=im_size/mask_size))\n        # for c in range(3):\n        #     mask[:,c,:,:] = (mask[:,c,:,:] - Mean[c])/Std[c]\n\n        # print(mask.size())\n        mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask.expand_as(im_data)))\n        # mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask), Mean, Std)\n        plt.subplot(1+len(masklist), 1, i+2)\n        plt.imshow(mask)\n        plt.axis('off')\n\n\n\n# x = torch.zeros(1, 3, 3)\n# out = colorize(x)\n# out_im = make_image(out)\n# plt.imshow(out_im)\n# plt.show()"
  }
]