[
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\n*.egg-info/\n.installed.cfg\n*.egg\nMANIFEST\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n.hypothesis/\n.pytest_cache/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\nlocal_settings.py\ndb.sqlite3\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# pyenv\n.python-version\n\n# celery beat schedule file\ncelerybeat-schedule\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n\n# checkpoints\ncheckpoints/\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Duo LI\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# face-attribute-prediction\nFace Attribute Prediction on [CelebA](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html) benchmark with PyTorch Implemantation, heavily borrowed from [my MobileNetV2 implementation](https://github.com/d-li14/mobilenetv2.pytorch).\n\n## Dependencies\n\n* Anaconda3 (Python 3.6+, with Numpy etc.)\n* PyTorch 0.4+\n* tensorboard, tensorboardX\n\n## Dataset\n\n[CelebA](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html) dataset is a large-scale face dataset with attribute-based annotations. Cropped and aligned face regions are utilized as the training source. For the pre-processed data and specific split, please feel free to contact me: <d-li14@mails.tsighua.edu.cn>\n\n## Features\n\n* Both ResNet and MobileNet as the backbone for scalability\n* Each of the 40 annotated attributes predicted with multi-head networks\n* Achieve ~92% average accuracy, comparative to state-of-the-art\n* Fast convergence (5~10 epochs) through finetuning the ImageNet pre-trained models\n"
  },
  {
    "path": "celeba.py",
    "content": "import torch\r\nimport torch.utils.data as data\r\n\r\nfrom PIL import Image\r\nimport os\r\nimport os.path\r\n\r\n\r\ndef pil_loader(path):\r\n    # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835)\r\n    with open(path, 'rb') as f:\r\n        img = Image.open(f)\r\n        return img.convert('RGB')\r\n\r\n\r\ndef accimage_loader(path):\r\n    import accimage\r\n    try:\r\n        return accimage.Image(path)\r\n    except IOError:\r\n        # Potentially a decoding problem, fall back to PIL.Image\r\n        return pil_loader(path)\r\n\r\n\r\ndef default_loader(path):\r\n    from torchvision import get_image_backend\r\n    if get_image_backend() == 'accimage':\r\n        return accimage_loader(path)\r\n    else:\r\n        return pil_loader(path)\r\n\r\n\r\nclass CelebA(data.Dataset):\r\n    def __init__(self, root, ann_file, transform=None, target_transform=None, loader=default_loader):\r\n        images = []\r\n        targets = []\r\n        \r\n        for line in open(os.path.join(root, ann_file), 'r'):\r\n            sample = line.split()\r\n            if len(sample) != 41:\r\n                raise(RuntimeError(\"# Annotated face attributes of CelebA dataset should not be different from 40\"))\r\n            images.append(sample[0])\r\n            targets.append([int(i) for i in sample[1:]])\r\n        self.images = [os.path.join(root, 'img_align_celeba_png', img) for img in images]\r\n        self.targets = targets\r\n        self.transform = transform\r\n        self.target_transform = target_transform\r\n        self.loader = loader\r\n\t\t\r\n    def __getitem__(self, index):\r\n        path = self.images[index]\r\n        sample = self.loader(path)\r\n        target = self.targets[index]\r\n        target = torch.LongTensor(target)\r\n        if self.transform is not None:\r\n            sample = self.transform(sample)\r\n        if self.target_transform is not None:\r\n            target = self.target_transform(target)\r\n\r\n        return sample, target\r\n\r\n    def __len__(self):\r\n        return len(self.images)\r\n\r\n"
  },
  {
    "path": "main.py",
    "content": "'''\nTraining script for ImageNet\nCopyright (c) Wei YANG, 2017\n'''\nfrom __future__ import print_function\n\nimport argparse\nimport os\nimport shutil\nimport time\nimport random\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.parallel\nimport torch.backends.cudnn as cudnn\nimport torch.distributed as dist\nimport torch.optim\nimport torch.utils.data\nimport torch.utils.data.distributed\nimport torchvision.transforms as transforms\nimport torchvision.datasets as datasets\nimport models\nfrom math import cos, pi\n\nfrom celeba import CelebA\nfrom utils import Bar, Logger, AverageMeter, accuracy, mkdir_p, savefig\nfrom tensorboardX import SummaryWriter\n\nmodel_names = sorted(name for name in models.__dict__\n    if name.islower() and not name.startswith(\"__\")\n    and callable(models.__dict__[name]))\n\n\n# Parse arguments\nparser = argparse.ArgumentParser(description='PyTorch ImageNet Training')\nparser.add_argument('-d', '--data', default='path to dataset', type=str)\nparser.add_argument('--arch', '-a', metavar='ARCH', default='resnet18',\n                    choices=model_names,\n                    help='model architecture: ' +\n                        ' | '.join(model_names) +\n                        ' (default: resnet18)')\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=90, type=int, metavar='N',\n                    help='number of total epochs to run')\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=256, type=int, metavar='N',\n                    help='train batchsize (default: 256)')\nparser.add_argument('--test-batch', default=200, type=int, metavar='N',\n                    help='test batchsize (default: 200)')\nparser.add_argument('--lr', '--learning-rate', default=0.1, type=float,\n                    metavar='LR', help='initial learning rate')\nparser.add_argument('--lr-decay', type=str, default='step',\n                    help='mode for learning rate decay')\nparser.add_argument('--step', type=int, default=30,\n                    help='interval for learning rate decay in step mode')\nparser.add_argument('--schedule', type=int, nargs='+', default=[150, 225],\n                    help='decrease learning rate at these epochs.')\nparser.add_argument('--turning-point', type=int, default=100,\n                    help='epoch number from linear to exponential decay mode')\nparser.add_argument('--gamma', type=float, default=0.1,\n                    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('--weight-decay', '--wd', default=1e-4, type=float,\n                    metavar='W', help='weight decay (default: 1e-4)')\n# Checkpoints\nparser.add_argument('-c', '--checkpoint', default='checkpoints', type=str, metavar='PATH',\n                    help='path to save checkpoint (default: checkpoints)')\nparser.add_argument('--resume', default='', type=str, metavar='PATH',\n                    help='path to latest checkpoint (default: none)')\n# Architecture\nparser.add_argument('--cardinality', type=int, default=32, help='ResNeXt model cardinality (group).')\nparser.add_argument('--base-width', type=int, default=4, help='ResNeXt model base width (number of channels in each group).')\nparser.add_argument('--groups', type=int, default=3, help='ShuffleNet model groups')\n# Miscs\nparser.add_argument('--manual-seed', 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')\nparser.add_argument('--world-size', default=1, type=int,\n                    help='number of distributed processes')\nparser.add_argument('--dist-url', default='tcp://224.66.41.62:23456', type=str,\n                    help='url used to set up distributed training')\nparser.add_argument('--dist-backend', default='gloo', type=str,\n                    help='distributed backend')\n# Device options\nparser.add_argument('--gpu-id', default='0', type=str,\n                    help='id(s) for CUDA_VISIBLE_DEVICES')\n\n\nbest_prec1 = 0\n\n\ndef main():\n    global args, best_prec1\n    args = parser.parse_args()\n\n    args.distributed = args.world_size > 1\n\n    if args.distributed:\n        dist.init_process_group(backend=args.dist_backend, init_method=args.dist_url,\n                                world_size=args.world_size)\n    # Use CUDA\n    os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id\n    use_cuda = torch.cuda.is_available()\n\n    # Random seed\n    if args.manual_seed is None:\n        args.manual_seed = random.randint(1, 10000)\n    random.seed(args.manual_seed)\n    torch.manual_seed(args.manual_seed)\n    if use_cuda:\n        torch.cuda.manual_seed_all(args.manual_seed)\n\n    # create model\n    if args.pretrained:\n        print(\"=> using pre-trained model '{}'\".format(args.arch))\n        model = models.__dict__[args.arch](pretrained=True)\n    elif args.arch.startswith('resnext'):\n        model = models.__dict__[args.arch](\n                    baseWidth=args.base_width,\n                    cardinality=args.cardinality,\n                )\n    elif args.arch.startswith('shufflenet'):\n        model = models.__dict__[args.arch](\n                    groups=args.groups\n                )\n    else:\n        print(\"=> creating model '{}'\".format(args.arch))\n        model = models.__dict__[args.arch]()\n\n    if not args.distributed:\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    else:\n        model.cuda()\n        model = torch.nn.parallel.DistributedDataParallel(model)\n\n    # define loss function (criterion) and optimizer\n    criterion = nn.CrossEntropyLoss().cuda()\n\n    optimizer = torch.optim.SGD(model.parameters(), args.lr,\n                                momentum=args.momentum,\n                                weight_decay=args.weight_decay)\n\n    # optionally resume from a checkpoint\n    title = 'CelebA-' + args.arch\n    if not os.path.isdir(args.checkpoint):\n        mkdir_p(args.checkpoint)\n\n    if args.resume:\n        if os.path.isfile(args.resume):\n            print(\"=> loading checkpoint '{}'\".format(args.resume))\n            checkpoint = torch.load(args.resume)\n            args.start_epoch = checkpoint['epoch']\n            best_prec1 = checkpoint['best_prec1']\n            model.load_state_dict(checkpoint['state_dict'])\n            optimizer.load_state_dict(checkpoint['optimizer'])\n            print(\"=> loaded checkpoint '{}' (epoch {})\"\n                  .format(args.resume, checkpoint['epoch']))\n            args.checkpoint = os.path.dirname(args.resume)\n            logger = Logger(os.path.join(args.checkpoint, 'log.txt'), title=title, resume=True)\n        else:\n            print(\"=> no checkpoint found at '{}'\".format(args.resume))\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    cudnn.benchmark = True\n\n    # Data loading code\n    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                                     std=[0.229, 0.224, 0.225])\n\n    train_dataset = CelebA(\n        args.data,\n        'train_40_att_list.txt',\n        transforms.Compose([\n            transforms.RandomHorizontalFlip(),\n            transforms.ToTensor(),\n            normalize,\n        ]))\n\n    if args.distributed:\n        train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)\n    else:\n        train_sampler = None\n\n    train_loader = torch.utils.data.DataLoader(\n        train_dataset, batch_size=args.train_batch, shuffle=(train_sampler is None),\n        num_workers=args.workers, pin_memory=True, sampler=train_sampler)\n\n    val_loader = torch.utils.data.DataLoader(\n        CelebA(args.data, 'val_40_att_list.txt', transforms.Compose([\n            transforms.ToTensor(),\n            normalize,\n        ])),\n        batch_size=args.test_batch, shuffle=False,\n        num_workers=args.workers, pin_memory=True)\n\n    test_loader = torch.utils.data.DataLoader(\n        CelebA(args.data, 'test_40_att_list.txt', transforms.Compose([\n            transforms.ToTensor(),\n            normalize,\n        ])),\n        batch_size=args.test_batch, shuffle=False,\n        num_workers=args.workers, pin_memory=True)\n\n    if args.evaluate:\n        validate(test_loader, model, criterion)\n        return\n\n    # visualization\n    writer = SummaryWriter(os.path.join(args.checkpoint, 'logs'))\n\n    for epoch in range(args.start_epoch, args.epochs):\n        if args.distributed:\n            train_sampler.set_epoch(epoch)\n        lr = adjust_learning_rate(optimizer, epoch)\n\n        print('\\nEpoch: [%d | %d] LR: %f' % (epoch + 1, args.epochs, lr))\n\n        # train for one epoch\n        train_loss, train_acc = train(train_loader, model, criterion, optimizer, epoch)\n\n        # evaluate on validation set\n        val_loss, prec1 = validate(val_loader, model, criterion)\n\n        # append logger file\n        logger.append([lr, train_loss, val_loss, train_acc, prec1])\n\n        # tensorboardX\n        writer.add_scalar('learning rate', lr, epoch + 1)\n        writer.add_scalars('loss', {'train loss': train_loss, 'validation loss': val_loss}, epoch + 1)\n        writer.add_scalars('accuracy', {'train accuracy': train_acc, 'validation accuracy': prec1}, epoch + 1)\n        #for name, param in model.named_parameters():\n        #    writer.add_histogram(name, param.clone().cpu().data.numpy(), epoch + 1)\n\n\n        is_best = prec1 > best_prec1\n        best_prec1 = max(prec1, best_prec1)\n        save_checkpoint({\n            'epoch': epoch + 1,\n            'arch': args.arch,\n            'state_dict': model.state_dict(),\n            'best_prec1': best_prec1,\n            'optimizer' : optimizer.state_dict(),\n        }, is_best, checkpoint=args.checkpoint)\n\n    logger.close()\n    logger.plot()\n    savefig(os.path.join(args.checkpoint, 'log.eps'))\n    writer.close()\n\n    print('Best accuracy:')\n    print(best_prec1)\n\n\ndef train(train_loader, model, criterion, optimizer, epoch):\n    bar = Bar('Processing', max=len(train_loader))\n\n    batch_time = AverageMeter()\n    data_time = AverageMeter()\n    losses = [AverageMeter() for _ in range(40)]\n    top1 = [AverageMeter() for _ in range(40)]\n\n    # switch to train mode\n    model.train()\n\n    end = time.time()\n    for i, (input, target) in enumerate(train_loader):\n        # measure data loading time\n        data_time.update(time.time() - end)\n\n        target = target.cuda(non_blocking=True)\n\n        # compute output\n        output = model(input)\n        # measure accuracy and record loss\n        loss = []\n        prec1 = []\n        for j in range(len(output)):\n            loss.append(criterion(output[j], target[:, j]))\n            prec1.append(accuracy(output[j], target[:, j], topk=(1,)))\n\n            losses[j].update(loss[j].item(), input.size(0))\n            top1[j].update(prec1[j][0].item(), input.size(0))\n        losses_avg = [losses[k].avg for k in range(len(losses))]\n        top1_avg = [top1[k].avg for k in range(len(top1))]\n        loss_avg = sum(losses_avg) / len(losses_avg)\n        prec1_avg = sum(top1_avg) / len(top1_avg)\n\n        # compute gradient and do SGD step\n        optimizer.zero_grad()\n        loss_sum = sum(loss)\n        loss_sum.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}'.format(\n                    batch=i + 1,\n                    size=len(train_loader),\n                    data=data_time.avg,\n                    bt=batch_time.avg,\n                    total=bar.elapsed_td,\n                    eta=bar.eta_td,\n                    loss=loss_avg,\n                    top1=prec1_avg,\n                    )\n        bar.next()\n    bar.finish()\n    return (loss_avg, prec1_avg)\n\n\ndef validate(val_loader, model, criterion):\n    bar = Bar('Processing', max=len(val_loader))\n\n    batch_time = AverageMeter()\n    data_time = AverageMeter()\n    losses = [AverageMeter() for _ in range(40)]\n    top1 = [AverageMeter() for _ in range(40)]\n\n    # switch to evaluate mode\n    model.eval()\n\n    with torch.no_grad():\n        end = time.time()\n        for i, (input, target) in enumerate(val_loader):\n            # measure data loading time\n            data_time.update(time.time() - end)\n\n            target = target.cuda(non_blocking=True)\n\n            # compute output\n            output = model(input)\n            # measure accuracy and record loss\n            loss = []\n            prec1 = []\n            for j in range(len(output)):\n                loss.append(criterion(output[j], target[:, j]))\n                prec1.append(accuracy(output[j], target[:, j], topk=(1,)))\n\n                losses[j].update(loss[j].item(), input.size(0))\n                top1[j].update(prec1[j][0].item(), input.size(0))\n            losses_avg = [losses[k].avg for k in range(len(losses))]\n            top1_avg = [top1[k].avg for k in range(len(top1))]\n            loss_avg = sum(losses_avg) / len(losses_avg)\n            prec1_avg = sum(top1_avg) / len(top1_avg)\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}'.format(\n                    batch=i + 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=loss_avg,\n                    top1=prec1_avg,\n                    )\n        bar.next()\n    bar.finish()\n    return (loss_avg, prec1_avg)\n\n\ndef save_checkpoint(state, is_best, checkpoint='checkpoint', filename='checkpoint.pth.tar'):\n    filepath = os.path.join(checkpoint, filename)\n    torch.save(state, filepath)\n    if is_best:\n        shutil.copyfile(filepath, os.path.join(checkpoint, 'model_best.pth.tar'))\n\n\ndef adjust_learning_rate(optimizer, epoch):\n    lr = optimizer.param_groups[0]['lr']\n    \"\"\"Sets the learning rate to the initial LR decayed by 10 following schedule\"\"\"\n    if args.lr_decay == 'step':\n        lr = args.lr * (args.gamma ** (epoch // args.step))\n    elif args.lr_decay == 'cos':\n        lr = args.lr * (1 + cos(pi * epoch / args.epochs)) / 2\n    elif args.lr_decay == 'linear':\n        lr = args.lr * (1 - epoch / args.epochs)\n    elif args.lr_decay == 'linear2exp':\n        if epoch < args.turning_point + 1:\n            # learning rate decay as 95% at the turning point (1 / 95% = 1.0526)\n            lr = args.lr * (1 - epoch / int(args.turning_point * 1.0526))\n        else:\n            lr *= args.gamma\n    elif args.lr_decay == 'schedule':\n        if epoch in args.schedule:\n            lr *= args.gamma\n    else:\n        raise ValueError('Unknown lr mode {}'.format(args.lr_decay))\n\n    for param_group in optimizer.param_groups:\n        param_group['lr'] = lr\n    return lr\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "models/__init__.py",
    "content": "from __future__ import absolute_import\n\nfrom .resnet import *\nfrom .mobilenetv1 import *\nfrom .mobilenetv2 import *\n"
  },
  {
    "path": "models/mobilenetv1.py",
    "content": "\"\"\"\nCreates a MobileNet Model as defined in:\nAndrew G. H., Menglong Z., Bo C., Dmitry K., Weijun W., Tobias W., Marco A., Hartwig A. (2017). \nMobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications\narXiv preprint arXiv:1704.04861.\nimport from https://github.com/marvis/pytorch-mobilenet\n\"\"\"\n\nimport torch.nn as nn\n\n__all__ = ['mobilenetv1']\n\n\ndef conv_bn(inp, oup, stride):\n    return nn.Sequential(\n        nn.Conv2d(inp, oup, 3, stride, 1, bias=False),\n        nn.BatchNorm2d(oup),\n        nn.ReLU(inplace=True)\n    )\n\n\ndef conv_dw(inp, oup, stride):\n    return nn.Sequential(\n        nn.Conv2d(inp, inp, 3, stride, 1, groups=inp, bias=False),\n        nn.BatchNorm2d(inp),\n        nn.ReLU(inplace=True),\n    \n        nn.Conv2d(inp, oup, 1, 1, 0, bias=False),\n        nn.BatchNorm2d(oup),\n        nn.ReLU(inplace=True),\n    )\n\n\nclass MobileNet(nn.Module):\n    def __init__(self, num_classes=1000):\n        super(MobileNet, self).__init__()\n\n        self.features = nn.Sequential(\n            conv_bn(  3,  32, 2), \n            conv_dw( 32,  64, 1),\n            conv_dw( 64, 128, 2),\n            conv_dw(128, 128, 1),\n            conv_dw(128, 256, 2),\n            conv_dw(256, 256, 1),\n            conv_dw(256, 512, 2),\n            conv_dw(512, 512, 1),\n            conv_dw(512, 512, 1),\n            conv_dw(512, 512, 1),\n            conv_dw(512, 512, 1),\n            conv_dw(512, 512, 1),\n            conv_dw(512, 1024, 2),\n            conv_dw(1024, 1024, 1),\n            nn.AvgPool2d(7),\n        )\n        self.fc = nn.Linear(1024, num_classes)\n\n    def forward(self, x):\n        x = self.features(x)\n        x = x.view(-1, 1024)\n        x = self.fc(x)\n        return x\n\ndef mobilenetv1(**kwargs):\n    \"\"\"\n    Constructs a MobileNet V1 model\n    \"\"\"\n    return MobileNet(**kwargs)\n\n"
  },
  {
    "path": "models/mobilenetv2.py",
    "content": "\"\"\"\nCreates a MobileNetV2 Model as defined in:\nMark Sandler, Andrew Howard, Menglong Zhu, Andrey Zhmoginov, Liang-Chieh Chen. (2018). \nMobileNetV2: Inverted Residuals and Linear Bottlenecks\narXiv preprint arXiv:1801.04381.\nimport from https://github.com/tonylins/pytorch-mobilenet-v2\n\"\"\"\n\nimport torch\nimport torch.nn as nn\nimport math\nimport os.path\n\n__all__ = ['mobilenetv2']\n\n\ndef _make_divisible(v, divisor, min_value=None):\n    \"\"\"\n    This function is taken from the original tf repo.\n    It ensures that all layers have a channel number that is divisible by 8\n    It can be seen here:\n    https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py\n    :param v:\n    :param divisor:\n    :param min_value:\n    :return:\n    \"\"\"\n    if min_value is None:\n        min_value = divisor\n    new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)\n    # Make sure that round down does not go down by more than 10%.\n    if new_v < 0.9 * v:\n        new_v += divisor\n    return new_v\n\n\ndef conv_3x3_bn(inp, oup, stride):\n    return nn.Sequential(\n        nn.Conv2d(inp, oup, 3, stride, 1, bias=False),\n        nn.BatchNorm2d(oup),\n        nn.ReLU6(inplace=True)\n    )\n\n\ndef conv_1x1_bn(inp, oup):\n    return nn.Sequential(\n        nn.Conv2d(inp, oup, 1, 1, 0, bias=False),\n        nn.BatchNorm2d(oup),\n        nn.ReLU6(inplace=True)\n    )\n\n\nclass InvertedResidual(nn.Module):\n    def __init__(self, inp, oup, stride, expand_ratio):\n        super(InvertedResidual, self).__init__()\n        assert stride in [1, 2]\n\n        hidden_dim = round(inp * expand_ratio)\n        self.identity = stride == 1 and inp == oup\n\n        if expand_ratio == 1:\n            self.conv = nn.Sequential(\n                # dw\n                nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),\n                nn.BatchNorm2d(hidden_dim),\n                nn.ReLU6(inplace=True),\n                # pw-linear\n                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),\n                nn.BatchNorm2d(oup),\n            )\n        else:\n            self.conv = nn.Sequential(\n                # pw\n                nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),\n                nn.BatchNorm2d(hidden_dim),\n                nn.ReLU6(inplace=True),\n                # dw\n                nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),\n                nn.BatchNorm2d(hidden_dim),\n                nn.ReLU6(inplace=True),\n                # pw-linear\n                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),\n                nn.BatchNorm2d(oup),\n            )\n\n    def forward(self, x):\n        if self.identity:\n            return x + self.conv(x)\n        else:\n            return self.conv(x)\n\n\nclass fc_block(nn.Module):\n    def __init__(self, inplanes, planes, drop_rate=0.15):\n        super(fc_block, self).__init__()\n        self.fc = nn.Linear(inplanes, planes)\n        self.bn = nn.BatchNorm1d(planes)\n        if drop_rate > 0:\n            self.dropout = nn.Dropout(drop_rate)\n        self.relu = nn.ReLU(inplace=True)\n        self.drop_rate = drop_rate\n\n    def forward(self, x):\n        x = self.fc(x)\n        x = self.bn(x)\n        if self.drop_rate > 0:\n            x = self.dropout(x)\n        x = self.relu(x)\n        return x\n\n\nclass MobileNetV2(nn.Module):\n    def __init__(self, num_attributes=40, input_size=224, width_mult=1.):\n        super(MobileNetV2, self).__init__()\n        # setting of inverted residual blocks\n        self.cfgs = [\n            # t, c, n, s\n            [1,  16, 1, 1],\n            [6,  24, 2, 2],\n            [6,  32, 3, 2],\n            [6,  64, 4, 2],\n            [6,  96, 3, 1],\n            [6, 160, 3, 2],\n            [6, 320, 1, 1],\n        ]\n\n        # building first layer\n        input_channel = _make_divisible(32 * width_mult, 8)\n        layers = [conv_3x3_bn(3, input_channel, 2)]\n        # building inverted residual blocks\n        block = InvertedResidual\n        for t, c, n, s in self.cfgs:\n            output_channel = _make_divisible(c * width_mult, 8)\n            layers.append(block(input_channel, output_channel, s, t))\n            input_channel = output_channel\n            for i in range(1, n):\n                layers.append(block(input_channel, output_channel, 1, t))\n                input_channel = output_channel\n        self.features = nn.Sequential(*layers)\n        # building last several layers\n        output_channel = _make_divisible(1280 * width_mult, 8) if width_mult > 1.0 else 1280\n        self.conv = conv_1x1_bn(input_channel, output_channel)\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.stem = fc_block(output_channel, 512)\n        for i in range(num_attributes):\n            setattr(self, 'classifier' + str(i).zfill(2), nn.Sequential(fc_block(512, 256), nn.Linear(256, 2)))\n        self.num_attributes = num_attributes\n\n        self._initialize_weights()\n\n    def forward(self, x):\n        x = self.features(x)\n        x = self.conv(x)\n        x = self.avgpool(x)\n        x = x.view(x.size(0), -1)\n        x = self.stem(x)\n\n        y = []\n        for i in range(self.num_attributes):\n            classifier = getattr(self, 'classifier' + str(i).zfill(2))\n            y.append(classifier(x))\n\n        return y\n\n    def _initialize_weights(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels\n                m.weight.data.normal_(0, math.sqrt(2. / n))\n                if m.bias is not None:\n                    m.bias.data.zero_()\n            elif isinstance(m, nn.BatchNorm2d):\n                m.weight.data.fill_(1)\n                m.bias.data.zero_()\n            elif isinstance(m, nn.Linear):\n                n = m.weight.size(1)\n                m.weight.data.normal_(0, 0.01)\n                m.bias.data.zero_()\n\n\ndef init_pretrained_weights(model, path=os.path.expanduser('~/.torch/models/mobilenetv2-0c6065bc.pth')):\n    \"\"\"\n    Initialize model with pretrained weights.\n    Layers that don't match with pretrained layers in name or size are kept unchanged.\n    \"\"\"\n    #pretrain_dict = model_zoo.load_url(model_url)\n    pretrain_dict = torch.load(path)\n    model_dict = model.state_dict()\n    pretrain_dict = {k: v for k, v in pretrain_dict.items() if k in model_dict and model_dict[k].size() == v.size()}\n    model_dict.update(pretrain_dict)\n    model.load_state_dict(model_dict)\n    print(\"Initialized model with pretrained weights from {}\".format(path))\n\n\ndef mobilenetv2(pretrained=True, **kwargs):\n    \"\"\"\n    Constructs a MobileNet V2 model\n    \"\"\"\n    model = MobileNetV2(**kwargs)\n    if pretrained:\n        init_pretrained_weights(model)\n    return model\n\n"
  },
  {
    "path": "models/resnet.py",
    "content": "import torch.nn as nn\nimport torch.utils.model_zoo as model_zoo\n\n\n__all__ = ['ResNet', 'resnet50']\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}\n\n\ndef conv3x3(in_planes, out_planes, stride=1):\n    \"\"\"3x3 convolution with padding\"\"\"\n    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,\n                     padding=1, bias=False)\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):\n        super(BasicBlock, self).__init__()\n        self.conv1 = conv3x3(inplanes, planes, stride)\n        self.bn1 = nn.BatchNorm2d(planes)\n        self.relu = nn.ReLU(inplace=True)\n        self.conv2 = conv3x3(planes, planes)\n        self.bn2 = nn.BatchNorm2d(planes)\n        self.downsample = downsample\n        self.stride = stride\n\n    def forward(self, x):\n        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):\n        super(Bottleneck, self).__init__()\n        self.conv1 = conv1x1(inplanes, planes)\n        self.bn1 = nn.BatchNorm2d(planes)\n        self.conv2 = conv3x3(planes, planes, stride)\n        self.bn2 = nn.BatchNorm2d(planes)\n        self.conv3 = conv1x1(planes, planes * self.expansion)\n        self.bn3 = nn.BatchNorm2d(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 fc_block(nn.Module):\n    def __init__(self, inplanes, planes, drop_rate=0.15):\n        super(fc_block, self).__init__()\n        self.fc = nn.Linear(inplanes, planes)\n        self.bn = nn.BatchNorm1d(planes)\n        if drop_rate > 0:\n            self.dropout = nn.Dropout(drop_rate)\n        self.relu = nn.ReLU(inplace=True)\n        self.drop_rate = drop_rate\n\n    def forward(self, x):\n        x = self.fc(x)\n        x = self.bn(x)\n        if self.drop_rate > 0:\n            x = self.dropout(x)\n        x = self.relu(x)\n        return x\n\n\nclass ResNet(nn.Module):\n\n    def __init__(self, block, layers, num_attributes=40, zero_init_residual=False):\n        super(ResNet, self).__init__()\n        self.inplanes = 64\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,\n                               bias=False)\n        self.bn1 = nn.BatchNorm2d(64)\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        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)\n        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.stem = fc_block(512 * block.expansion, 512)\n        for i in range(num_attributes):\n            setattr(self, 'classifier' + str(i).zfill(2), nn.Sequential(fc_block(512, 256), nn.Linear(256, 2)))\n        self.num_attributes = num_attributes\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):\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):\n        downsample = None\n        if stride != 1 or self.inplanes != planes * block.expansion:\n            downsample = nn.Sequential(\n                conv1x1(self.inplanes, planes * block.expansion, stride),\n                nn.BatchNorm2d(planes * block.expansion),\n            )\n\n        layers = []\n        layers.append(block(self.inplanes, planes, stride, downsample))\n        self.inplanes = planes * block.expansion\n        for _ in range(1, blocks):\n            layers.append(block(self.inplanes, planes))\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.view(x.size(0), -1)\n        x = self.stem(x)\n\n        y = []\n        for i in range(self.num_attributes):\n            classifier = getattr(self, 'classifier' + str(i).zfill(2))\n            y.append(classifier(x))\n\n        return y\n\n\ndef resnet50(pretrained=True, **kwargs):\n    \"\"\"Constructs a ResNet-50 model.\n\n    Args:\n        pretrained (bool): If True, returns a model pre-trained on ImageNet\n    \"\"\"\n    model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs)\n    if pretrained:\n        init_pretrained_weights(model, model_urls['resnet50'])\n    return model\n\n\ndef init_pretrained_weights(model, model_url):\n    \"\"\"\n    Initialize model with pretrained weights.\n    Layers that don't match with pretrained layers in name or size are kept unchanged.\n    \"\"\"\n    pretrain_dict = model_zoo.load_url(model_url)\n    model_dict = model.state_dict()\n    pretrain_dict = {k: v for k, v in pretrain_dict.items() if k in model_dict and model_dict[k].size() == v.size()}\n    model_dict.update(pretrain_dict)\n    model.load_state_dict(model_dict)\n    print(\"Initialized model with pretrained weights from {}\".format(model_url))\n\n"
  },
  {
    "path": "utils/__init__.py",
    "content": "\"\"\"Useful utils\n\"\"\"\nfrom .misc import *\nfrom .logger import *\nfrom .visualize import *\nfrom .eval import *\n\n# progress bar\nimport os, sys\nsys.path.append(os.path.join(os.path.dirname(__file__), \"progress\"))\nfrom progress.bar import Bar as Bar"
  },
  {
    "path": "utils/eval.py",
    "content": "from __future__ import print_function, absolute_import\nimport torch\n\n__all__ = ['accuracy']\n\ndef accuracy(output, target, topk=(1,)):\n    \"\"\"Computes the precision@k for the specified values of k\"\"\"\n    with torch.no_grad():\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"
  },
  {
    "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')\n"
  },
  {
    "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\n\n__all__ = ['get_mean_and_std', 'init_params', 'mkdir_p', 'AverageMeter']\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"
  },
  {
    "path": "utils/progress/.gitignore",
    "content": "*.pyc\n*.egg-info\nbuild/\ndist/\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/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()"
  }
]