Repository: d-li14/face-attribute-prediction
Branch: master
Commit: 840e59aee39d
Files: 25
Total size: 64.4 KB
Directory structure:
gitextract_wilfivay/
├── .gitignore
├── LICENSE
├── README.md
├── celeba.py
├── main.py
├── models/
│ ├── __init__.py
│ ├── mobilenetv1.py
│ ├── mobilenetv2.py
│ └── resnet.py
└── utils/
├── __init__.py
├── eval.py
├── logger.py
├── misc.py
├── progress/
│ ├── .gitignore
│ ├── LICENSE
│ ├── MANIFEST.in
│ ├── README.rst
│ ├── progress/
│ │ ├── __init__.py
│ │ ├── bar.py
│ │ ├── counter.py
│ │ ├── helpers.py
│ │ └── spinner.py
│ ├── setup.py
│ └── test_progress.py
└── visualize.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# checkpoints
checkpoints/
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Duo LI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# face-attribute-prediction
Face 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).
## Dependencies
* Anaconda3 (Python 3.6+, with Numpy etc.)
* PyTorch 0.4+
* tensorboard, tensorboardX
## Dataset
[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>
## Features
* Both ResNet and MobileNet as the backbone for scalability
* Each of the 40 annotated attributes predicted with multi-head networks
* Achieve ~92% average accuracy, comparative to state-of-the-art
* Fast convergence (5~10 epochs) through finetuning the ImageNet pre-trained models
================================================
FILE: celeba.py
================================================
import torch
import torch.utils.data as data
from PIL import Image
import os
import os.path
def pil_loader(path):
# open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835)
with open(path, 'rb') as f:
img = Image.open(f)
return img.convert('RGB')
def accimage_loader(path):
import accimage
try:
return accimage.Image(path)
except IOError:
# Potentially a decoding problem, fall back to PIL.Image
return pil_loader(path)
def default_loader(path):
from torchvision import get_image_backend
if get_image_backend() == 'accimage':
return accimage_loader(path)
else:
return pil_loader(path)
class CelebA(data.Dataset):
def __init__(self, root, ann_file, transform=None, target_transform=None, loader=default_loader):
images = []
targets = []
for line in open(os.path.join(root, ann_file), 'r'):
sample = line.split()
if len(sample) != 41:
raise(RuntimeError("# Annotated face attributes of CelebA dataset should not be different from 40"))
images.append(sample[0])
targets.append([int(i) for i in sample[1:]])
self.images = [os.path.join(root, 'img_align_celeba_png', img) for img in images]
self.targets = targets
self.transform = transform
self.target_transform = target_transform
self.loader = loader
def __getitem__(self, index):
path = self.images[index]
sample = self.loader(path)
target = self.targets[index]
target = torch.LongTensor(target)
if self.transform is not None:
sample = self.transform(sample)
if self.target_transform is not None:
target = self.target_transform(target)
return sample, target
def __len__(self):
return len(self.images)
================================================
FILE: main.py
================================================
'''
Training script for ImageNet
Copyright (c) Wei YANG, 2017
'''
from __future__ import print_function
import argparse
import os
import shutil
import time
import random
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.backends.cudnn as cudnn
import torch.distributed as dist
import torch.optim
import torch.utils.data
import torch.utils.data.distributed
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import models
from math import cos, pi
from celeba import CelebA
from utils import Bar, Logger, AverageMeter, accuracy, mkdir_p, savefig
from tensorboardX import SummaryWriter
model_names = sorted(name for name in models.__dict__
if name.islower() and not name.startswith("__")
and callable(models.__dict__[name]))
# Parse arguments
parser = argparse.ArgumentParser(description='PyTorch ImageNet Training')
parser.add_argument('-d', '--data', default='path to dataset', type=str)
parser.add_argument('--arch', '-a', metavar='ARCH', default='resnet18',
choices=model_names,
help='model architecture: ' +
' | '.join(model_names) +
' (default: resnet18)')
parser.add_argument('-j', '--workers', default=4, type=int, metavar='N',
help='number of data loading workers (default: 4)')
# Optimization options
parser.add_argument('--epochs', default=90, type=int, metavar='N',
help='number of total epochs to run')
parser.add_argument('--start-epoch', default=0, type=int, metavar='N',
help='manual epoch number (useful on restarts)')
parser.add_argument('--train-batch', default=256, type=int, metavar='N',
help='train batchsize (default: 256)')
parser.add_argument('--test-batch', default=200, type=int, metavar='N',
help='test batchsize (default: 200)')
parser.add_argument('--lr', '--learning-rate', default=0.1, type=float,
metavar='LR', help='initial learning rate')
parser.add_argument('--lr-decay', type=str, default='step',
help='mode for learning rate decay')
parser.add_argument('--step', type=int, default=30,
help='interval for learning rate decay in step mode')
parser.add_argument('--schedule', type=int, nargs='+', default=[150, 225],
help='decrease learning rate at these epochs.')
parser.add_argument('--turning-point', type=int, default=100,
help='epoch number from linear to exponential decay mode')
parser.add_argument('--gamma', type=float, default=0.1,
help='LR is multiplied by gamma on schedule.')
parser.add_argument('--momentum', default=0.9, type=float, metavar='M',
help='momentum')
parser.add_argument('--weight-decay', '--wd', default=1e-4, type=float,
metavar='W', help='weight decay (default: 1e-4)')
# Checkpoints
parser.add_argument('-c', '--checkpoint', default='checkpoints', type=str, metavar='PATH',
help='path to save checkpoint (default: checkpoints)')
parser.add_argument('--resume', default='', type=str, metavar='PATH',
help='path to latest checkpoint (default: none)')
# Architecture
parser.add_argument('--cardinality', type=int, default=32, help='ResNeXt model cardinality (group).')
parser.add_argument('--base-width', type=int, default=4, help='ResNeXt model base width (number of channels in each group).')
parser.add_argument('--groups', type=int, default=3, help='ShuffleNet model groups')
# Miscs
parser.add_argument('--manual-seed', type=int, help='manual seed')
parser.add_argument('-e', '--evaluate', dest='evaluate', action='store_true',
help='evaluate model on validation set')
parser.add_argument('--pretrained', dest='pretrained', action='store_true',
help='use pre-trained model')
parser.add_argument('--world-size', default=1, type=int,
help='number of distributed processes')
parser.add_argument('--dist-url', default='tcp://224.66.41.62:23456', type=str,
help='url used to set up distributed training')
parser.add_argument('--dist-backend', default='gloo', type=str,
help='distributed backend')
# Device options
parser.add_argument('--gpu-id', default='0', type=str,
help='id(s) for CUDA_VISIBLE_DEVICES')
best_prec1 = 0
def main():
global args, best_prec1
args = parser.parse_args()
args.distributed = args.world_size > 1
if args.distributed:
dist.init_process_group(backend=args.dist_backend, init_method=args.dist_url,
world_size=args.world_size)
# Use CUDA
os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id
use_cuda = torch.cuda.is_available()
# Random seed
if args.manual_seed is None:
args.manual_seed = random.randint(1, 10000)
random.seed(args.manual_seed)
torch.manual_seed(args.manual_seed)
if use_cuda:
torch.cuda.manual_seed_all(args.manual_seed)
# create model
if args.pretrained:
print("=> using pre-trained model '{}'".format(args.arch))
model = models.__dict__[args.arch](pretrained=True)
elif args.arch.startswith('resnext'):
model = models.__dict__[args.arch](
baseWidth=args.base_width,
cardinality=args.cardinality,
)
elif args.arch.startswith('shufflenet'):
model = models.__dict__[args.arch](
groups=args.groups
)
else:
print("=> creating model '{}'".format(args.arch))
model = models.__dict__[args.arch]()
if not args.distributed:
if args.arch.startswith('alexnet') or args.arch.startswith('vgg'):
model.features = torch.nn.DataParallel(model.features)
model.cuda()
else:
model = torch.nn.DataParallel(model).cuda()
else:
model.cuda()
model = torch.nn.parallel.DistributedDataParallel(model)
# define loss function (criterion) and optimizer
criterion = nn.CrossEntropyLoss().cuda()
optimizer = torch.optim.SGD(model.parameters(), args.lr,
momentum=args.momentum,
weight_decay=args.weight_decay)
# optionally resume from a checkpoint
title = 'CelebA-' + args.arch
if not os.path.isdir(args.checkpoint):
mkdir_p(args.checkpoint)
if args.resume:
if os.path.isfile(args.resume):
print("=> loading checkpoint '{}'".format(args.resume))
checkpoint = torch.load(args.resume)
args.start_epoch = checkpoint['epoch']
best_prec1 = checkpoint['best_prec1']
model.load_state_dict(checkpoint['state_dict'])
optimizer.load_state_dict(checkpoint['optimizer'])
print("=> loaded checkpoint '{}' (epoch {})"
.format(args.resume, checkpoint['epoch']))
args.checkpoint = os.path.dirname(args.resume)
logger = Logger(os.path.join(args.checkpoint, 'log.txt'), title=title, resume=True)
else:
print("=> no checkpoint found at '{}'".format(args.resume))
else:
logger = Logger(os.path.join(args.checkpoint, 'log.txt'), title=title)
logger.set_names(['Learning Rate', 'Train Loss', 'Valid Loss', 'Train Acc.', 'Valid Acc.'])
cudnn.benchmark = True
# Data loading code
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
train_dataset = CelebA(
args.data,
'train_40_att_list.txt',
transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize,
]))
if args.distributed:
train_sampler = torch.utils.data.distributed.DistributedSampler(train_dataset)
else:
train_sampler = None
train_loader = torch.utils.data.DataLoader(
train_dataset, batch_size=args.train_batch, shuffle=(train_sampler is None),
num_workers=args.workers, pin_memory=True, sampler=train_sampler)
val_loader = torch.utils.data.DataLoader(
CelebA(args.data, 'val_40_att_list.txt', transforms.Compose([
transforms.ToTensor(),
normalize,
])),
batch_size=args.test_batch, shuffle=False,
num_workers=args.workers, pin_memory=True)
test_loader = torch.utils.data.DataLoader(
CelebA(args.data, 'test_40_att_list.txt', transforms.Compose([
transforms.ToTensor(),
normalize,
])),
batch_size=args.test_batch, shuffle=False,
num_workers=args.workers, pin_memory=True)
if args.evaluate:
validate(test_loader, model, criterion)
return
# visualization
writer = SummaryWriter(os.path.join(args.checkpoint, 'logs'))
for epoch in range(args.start_epoch, args.epochs):
if args.distributed:
train_sampler.set_epoch(epoch)
lr = adjust_learning_rate(optimizer, epoch)
print('\nEpoch: [%d | %d] LR: %f' % (epoch + 1, args.epochs, lr))
# train for one epoch
train_loss, train_acc = train(train_loader, model, criterion, optimizer, epoch)
# evaluate on validation set
val_loss, prec1 = validate(val_loader, model, criterion)
# append logger file
logger.append([lr, train_loss, val_loss, train_acc, prec1])
# tensorboardX
writer.add_scalar('learning rate', lr, epoch + 1)
writer.add_scalars('loss', {'train loss': train_loss, 'validation loss': val_loss}, epoch + 1)
writer.add_scalars('accuracy', {'train accuracy': train_acc, 'validation accuracy': prec1}, epoch + 1)
#for name, param in model.named_parameters():
# writer.add_histogram(name, param.clone().cpu().data.numpy(), epoch + 1)
is_best = prec1 > best_prec1
best_prec1 = max(prec1, best_prec1)
save_checkpoint({
'epoch': epoch + 1,
'arch': args.arch,
'state_dict': model.state_dict(),
'best_prec1': best_prec1,
'optimizer' : optimizer.state_dict(),
}, is_best, checkpoint=args.checkpoint)
logger.close()
logger.plot()
savefig(os.path.join(args.checkpoint, 'log.eps'))
writer.close()
print('Best accuracy:')
print(best_prec1)
def train(train_loader, model, criterion, optimizer, epoch):
bar = Bar('Processing', max=len(train_loader))
batch_time = AverageMeter()
data_time = AverageMeter()
losses = [AverageMeter() for _ in range(40)]
top1 = [AverageMeter() for _ in range(40)]
# switch to train mode
model.train()
end = time.time()
for i, (input, target) in enumerate(train_loader):
# measure data loading time
data_time.update(time.time() - end)
target = target.cuda(non_blocking=True)
# compute output
output = model(input)
# measure accuracy and record loss
loss = []
prec1 = []
for j in range(len(output)):
loss.append(criterion(output[j], target[:, j]))
prec1.append(accuracy(output[j], target[:, j], topk=(1,)))
losses[j].update(loss[j].item(), input.size(0))
top1[j].update(prec1[j][0].item(), input.size(0))
losses_avg = [losses[k].avg for k in range(len(losses))]
top1_avg = [top1[k].avg for k in range(len(top1))]
loss_avg = sum(losses_avg) / len(losses_avg)
prec1_avg = sum(top1_avg) / len(top1_avg)
# compute gradient and do SGD step
optimizer.zero_grad()
loss_sum = sum(loss)
loss_sum.backward()
optimizer.step()
# measure elapsed time
batch_time.update(time.time() - end)
end = time.time()
# plot progress
bar.suffix = '({batch}/{size}) Data: {data:.3f}s | Batch: {bt:.3f}s | Total: {total:} | ETA: {eta:} | Loss: {loss:.4f} | top1: {top1: .4f}'.format(
batch=i + 1,
size=len(train_loader),
data=data_time.avg,
bt=batch_time.avg,
total=bar.elapsed_td,
eta=bar.eta_td,
loss=loss_avg,
top1=prec1_avg,
)
bar.next()
bar.finish()
return (loss_avg, prec1_avg)
def validate(val_loader, model, criterion):
bar = Bar('Processing', max=len(val_loader))
batch_time = AverageMeter()
data_time = AverageMeter()
losses = [AverageMeter() for _ in range(40)]
top1 = [AverageMeter() for _ in range(40)]
# switch to evaluate mode
model.eval()
with torch.no_grad():
end = time.time()
for i, (input, target) in enumerate(val_loader):
# measure data loading time
data_time.update(time.time() - end)
target = target.cuda(non_blocking=True)
# compute output
output = model(input)
# measure accuracy and record loss
loss = []
prec1 = []
for j in range(len(output)):
loss.append(criterion(output[j], target[:, j]))
prec1.append(accuracy(output[j], target[:, j], topk=(1,)))
losses[j].update(loss[j].item(), input.size(0))
top1[j].update(prec1[j][0].item(), input.size(0))
losses_avg = [losses[k].avg for k in range(len(losses))]
top1_avg = [top1[k].avg for k in range(len(top1))]
loss_avg = sum(losses_avg) / len(losses_avg)
prec1_avg = sum(top1_avg) / len(top1_avg)
# measure elapsed time
batch_time.update(time.time() - end)
end = time.time()
# plot progress
bar.suffix = '({batch}/{size}) Data: {data:.3f}s | Batch: {bt:.3f}s | Total: {total:} | ETA: {eta:} | Loss: {loss:.4f} | top1: {top1: .4f}'.format(
batch=i + 1,
size=len(val_loader),
data=data_time.avg,
bt=batch_time.avg,
total=bar.elapsed_td,
eta=bar.eta_td,
loss=loss_avg,
top1=prec1_avg,
)
bar.next()
bar.finish()
return (loss_avg, prec1_avg)
def save_checkpoint(state, is_best, checkpoint='checkpoint', filename='checkpoint.pth.tar'):
filepath = os.path.join(checkpoint, filename)
torch.save(state, filepath)
if is_best:
shutil.copyfile(filepath, os.path.join(checkpoint, 'model_best.pth.tar'))
def adjust_learning_rate(optimizer, epoch):
lr = optimizer.param_groups[0]['lr']
"""Sets the learning rate to the initial LR decayed by 10 following schedule"""
if args.lr_decay == 'step':
lr = args.lr * (args.gamma ** (epoch // args.step))
elif args.lr_decay == 'cos':
lr = args.lr * (1 + cos(pi * epoch / args.epochs)) / 2
elif args.lr_decay == 'linear':
lr = args.lr * (1 - epoch / args.epochs)
elif args.lr_decay == 'linear2exp':
if epoch < args.turning_point + 1:
# learning rate decay as 95% at the turning point (1 / 95% = 1.0526)
lr = args.lr * (1 - epoch / int(args.turning_point * 1.0526))
else:
lr *= args.gamma
elif args.lr_decay == 'schedule':
if epoch in args.schedule:
lr *= args.gamma
else:
raise ValueError('Unknown lr mode {}'.format(args.lr_decay))
for param_group in optimizer.param_groups:
param_group['lr'] = lr
return lr
if __name__ == '__main__':
main()
================================================
FILE: models/__init__.py
================================================
from __future__ import absolute_import
from .resnet import *
from .mobilenetv1 import *
from .mobilenetv2 import *
================================================
FILE: models/mobilenetv1.py
================================================
"""
Creates a MobileNet Model as defined in:
Andrew G. H., Menglong Z., Bo C., Dmitry K., Weijun W., Tobias W., Marco A., Hartwig A. (2017).
MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
arXiv preprint arXiv:1704.04861.
import from https://github.com/marvis/pytorch-mobilenet
"""
import torch.nn as nn
__all__ = ['mobilenetv1']
def conv_bn(inp, oup, stride):
return nn.Sequential(
nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
nn.BatchNorm2d(oup),
nn.ReLU(inplace=True)
)
def conv_dw(inp, oup, stride):
return nn.Sequential(
nn.Conv2d(inp, inp, 3, stride, 1, groups=inp, bias=False),
nn.BatchNorm2d(inp),
nn.ReLU(inplace=True),
nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
nn.ReLU(inplace=True),
)
class MobileNet(nn.Module):
def __init__(self, num_classes=1000):
super(MobileNet, self).__init__()
self.features = nn.Sequential(
conv_bn( 3, 32, 2),
conv_dw( 32, 64, 1),
conv_dw( 64, 128, 2),
conv_dw(128, 128, 1),
conv_dw(128, 256, 2),
conv_dw(256, 256, 1),
conv_dw(256, 512, 2),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 512, 1),
conv_dw(512, 1024, 2),
conv_dw(1024, 1024, 1),
nn.AvgPool2d(7),
)
self.fc = nn.Linear(1024, num_classes)
def forward(self, x):
x = self.features(x)
x = x.view(-1, 1024)
x = self.fc(x)
return x
def mobilenetv1(**kwargs):
"""
Constructs a MobileNet V1 model
"""
return MobileNet(**kwargs)
================================================
FILE: models/mobilenetv2.py
================================================
"""
Creates a MobileNetV2 Model as defined in:
Mark Sandler, Andrew Howard, Menglong Zhu, Andrey Zhmoginov, Liang-Chieh Chen. (2018).
MobileNetV2: Inverted Residuals and Linear Bottlenecks
arXiv preprint arXiv:1801.04381.
import from https://github.com/tonylins/pytorch-mobilenet-v2
"""
import torch
import torch.nn as nn
import math
import os.path
__all__ = ['mobilenetv2']
def _make_divisible(v, divisor, min_value=None):
"""
This function is taken from the original tf repo.
It ensures that all layers have a channel number that is divisible by 8
It can be seen here:
https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
:param v:
:param divisor:
:param min_value:
:return:
"""
if min_value is None:
min_value = divisor
new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
# Make sure that round down does not go down by more than 10%.
if new_v < 0.9 * v:
new_v += divisor
return new_v
def conv_3x3_bn(inp, oup, stride):
return nn.Sequential(
nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
nn.BatchNorm2d(oup),
nn.ReLU6(inplace=True)
)
def conv_1x1_bn(inp, oup):
return nn.Sequential(
nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
nn.ReLU6(inplace=True)
)
class InvertedResidual(nn.Module):
def __init__(self, inp, oup, stride, expand_ratio):
super(InvertedResidual, self).__init__()
assert stride in [1, 2]
hidden_dim = round(inp * expand_ratio)
self.identity = stride == 1 and inp == oup
if expand_ratio == 1:
self.conv = nn.Sequential(
# dw
nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
nn.BatchNorm2d(hidden_dim),
nn.ReLU6(inplace=True),
# pw-linear
nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)
else:
self.conv = nn.Sequential(
# pw
nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),
nn.BatchNorm2d(hidden_dim),
nn.ReLU6(inplace=True),
# dw
nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
nn.BatchNorm2d(hidden_dim),
nn.ReLU6(inplace=True),
# pw-linear
nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
nn.BatchNorm2d(oup),
)
def forward(self, x):
if self.identity:
return x + self.conv(x)
else:
return self.conv(x)
class fc_block(nn.Module):
def __init__(self, inplanes, planes, drop_rate=0.15):
super(fc_block, self).__init__()
self.fc = nn.Linear(inplanes, planes)
self.bn = nn.BatchNorm1d(planes)
if drop_rate > 0:
self.dropout = nn.Dropout(drop_rate)
self.relu = nn.ReLU(inplace=True)
self.drop_rate = drop_rate
def forward(self, x):
x = self.fc(x)
x = self.bn(x)
if self.drop_rate > 0:
x = self.dropout(x)
x = self.relu(x)
return x
class MobileNetV2(nn.Module):
def __init__(self, num_attributes=40, input_size=224, width_mult=1.):
super(MobileNetV2, self).__init__()
# setting of inverted residual blocks
self.cfgs = [
# t, c, n, s
[1, 16, 1, 1],
[6, 24, 2, 2],
[6, 32, 3, 2],
[6, 64, 4, 2],
[6, 96, 3, 1],
[6, 160, 3, 2],
[6, 320, 1, 1],
]
# building first layer
input_channel = _make_divisible(32 * width_mult, 8)
layers = [conv_3x3_bn(3, input_channel, 2)]
# building inverted residual blocks
block = InvertedResidual
for t, c, n, s in self.cfgs:
output_channel = _make_divisible(c * width_mult, 8)
layers.append(block(input_channel, output_channel, s, t))
input_channel = output_channel
for i in range(1, n):
layers.append(block(input_channel, output_channel, 1, t))
input_channel = output_channel
self.features = nn.Sequential(*layers)
# building last several layers
output_channel = _make_divisible(1280 * width_mult, 8) if width_mult > 1.0 else 1280
self.conv = conv_1x1_bn(input_channel, output_channel)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.stem = fc_block(output_channel, 512)
for i in range(num_attributes):
setattr(self, 'classifier' + str(i).zfill(2), nn.Sequential(fc_block(512, 256), nn.Linear(256, 2)))
self.num_attributes = num_attributes
self._initialize_weights()
def forward(self, x):
x = self.features(x)
x = self.conv(x)
x = self.avgpool(x)
x = x.view(x.size(0), -1)
x = self.stem(x)
y = []
for i in range(self.num_attributes):
classifier = getattr(self, 'classifier' + str(i).zfill(2))
y.append(classifier(x))
return y
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2. / n))
if m.bias is not None:
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
n = m.weight.size(1)
m.weight.data.normal_(0, 0.01)
m.bias.data.zero_()
def init_pretrained_weights(model, path=os.path.expanduser('~/.torch/models/mobilenetv2-0c6065bc.pth')):
"""
Initialize model with pretrained weights.
Layers that don't match with pretrained layers in name or size are kept unchanged.
"""
#pretrain_dict = model_zoo.load_url(model_url)
pretrain_dict = torch.load(path)
model_dict = model.state_dict()
pretrain_dict = {k: v for k, v in pretrain_dict.items() if k in model_dict and model_dict[k].size() == v.size()}
model_dict.update(pretrain_dict)
model.load_state_dict(model_dict)
print("Initialized model with pretrained weights from {}".format(path))
def mobilenetv2(pretrained=True, **kwargs):
"""
Constructs a MobileNet V2 model
"""
model = MobileNetV2(**kwargs)
if pretrained:
init_pretrained_weights(model)
return model
================================================
FILE: models/resnet.py
================================================
import torch.nn as nn
import torch.utils.model_zoo as model_zoo
__all__ = ['ResNet', 'resnet50']
model_urls = {
'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
}
def conv3x3(in_planes, out_planes, stride=1):
"""3x3 convolution with padding"""
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
padding=1, bias=False)
def conv1x1(in_planes, out_planes, stride=1):
"""1x1 convolution"""
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None):
super(BasicBlock, self).__init__()
self.conv1 = conv3x3(inplanes, planes, stride)
self.bn1 = nn.BatchNorm2d(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = conv3x3(planes, planes)
self.bn2 = nn.BatchNorm2d(planes)
self.downsample = downsample
self.stride = stride
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
identity = self.downsample(x)
out += identity
out = self.relu(out)
return out
class Bottleneck(nn.Module):
expansion = 4
def __init__(self, inplanes, planes, stride=1, downsample=None):
super(Bottleneck, self).__init__()
self.conv1 = conv1x1(inplanes, planes)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = conv3x3(planes, planes, stride)
self.bn2 = nn.BatchNorm2d(planes)
self.conv3 = conv1x1(planes, planes * self.expansion)
self.bn3 = nn.BatchNorm2d(planes * self.expansion)
self.relu = nn.ReLU(inplace=True)
self.downsample = downsample
self.stride = stride
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out = self.relu(out)
out = self.conv3(out)
out = self.bn3(out)
if self.downsample is not None:
identity = self.downsample(x)
out += identity
out = self.relu(out)
return out
class fc_block(nn.Module):
def __init__(self, inplanes, planes, drop_rate=0.15):
super(fc_block, self).__init__()
self.fc = nn.Linear(inplanes, planes)
self.bn = nn.BatchNorm1d(planes)
if drop_rate > 0:
self.dropout = nn.Dropout(drop_rate)
self.relu = nn.ReLU(inplace=True)
self.drop_rate = drop_rate
def forward(self, x):
x = self.fc(x)
x = self.bn(x)
if self.drop_rate > 0:
x = self.dropout(x)
x = self.relu(x)
return x
class ResNet(nn.Module):
def __init__(self, block, layers, num_attributes=40, zero_init_residual=False):
super(ResNet, self).__init__()
self.inplanes = 64
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = self._make_layer(block, 64, layers[0])
self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.stem = fc_block(512 * block.expansion, 512)
for i in range(num_attributes):
setattr(self, 'classifier' + str(i).zfill(2), nn.Sequential(fc_block(512, 256), nn.Linear(256, 2)))
self.num_attributes = num_attributes
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
# Zero-initialize the last BN in each residual branch,
# so that the residual branch starts with zeros, and each residual block behaves like an identity.
# This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
if zero_init_residual:
for m in self.modules():
if isinstance(m, Bottleneck):
nn.init.constant_(m.bn3.weight, 0)
elif isinstance(m, BasicBlock):
nn.init.constant_(m.bn2.weight, 0)
def _make_layer(self, block, planes, blocks, stride=1):
downsample = None
if stride != 1 or self.inplanes != planes * block.expansion:
downsample = nn.Sequential(
conv1x1(self.inplanes, planes * block.expansion, stride),
nn.BatchNorm2d(planes * block.expansion),
)
layers = []
layers.append(block(self.inplanes, planes, stride, downsample))
self.inplanes = planes * block.expansion
for _ in range(1, blocks):
layers.append(block(self.inplanes, planes))
return nn.Sequential(*layers)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(x.size(0), -1)
x = self.stem(x)
y = []
for i in range(self.num_attributes):
classifier = getattr(self, 'classifier' + str(i).zfill(2))
y.append(classifier(x))
return y
def resnet50(pretrained=True, **kwargs):
"""Constructs a ResNet-50 model.
Args:
pretrained (bool): If True, returns a model pre-trained on ImageNet
"""
model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs)
if pretrained:
init_pretrained_weights(model, model_urls['resnet50'])
return model
def init_pretrained_weights(model, model_url):
"""
Initialize model with pretrained weights.
Layers that don't match with pretrained layers in name or size are kept unchanged.
"""
pretrain_dict = model_zoo.load_url(model_url)
model_dict = model.state_dict()
pretrain_dict = {k: v for k, v in pretrain_dict.items() if k in model_dict and model_dict[k].size() == v.size()}
model_dict.update(pretrain_dict)
model.load_state_dict(model_dict)
print("Initialized model with pretrained weights from {}".format(model_url))
================================================
FILE: utils/__init__.py
================================================
"""Useful utils
"""
from .misc import *
from .logger import *
from .visualize import *
from .eval import *
# progress bar
import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), "progress"))
from progress.bar import Bar as Bar
================================================
FILE: utils/eval.py
================================================
from __future__ import print_function, absolute_import
import torch
__all__ = ['accuracy']
def accuracy(output, target, topk=(1,)):
"""Computes the precision@k for the specified values of k"""
with torch.no_grad():
maxk = max(topk)
batch_size = target.size(0)
_, pred = output.topk(maxk, 1, True, True)
pred = pred.t()
correct = pred.eq(target.view(1, -1).expand_as(pred))
res = []
for k in topk:
correct_k = correct[:k].view(-1).float().sum(0)
res.append(correct_k.mul_(100.0 / batch_size))
return res
================================================
FILE: utils/logger.py
================================================
# A simple torch style logger
# (C) Wei YANG 2017
from __future__ import absolute_import
import matplotlib.pyplot as plt
import os
import sys
import numpy as np
__all__ = ['Logger', 'LoggerMonitor', 'savefig']
def savefig(fname, dpi=None):
dpi = 150 if dpi == None else dpi
plt.savefig(fname, dpi=dpi)
def plot_overlap(logger, names=None):
names = logger.names if names == None else names
numbers = logger.numbers
for _, name in enumerate(names):
x = np.arange(len(numbers[name]))
plt.plot(x, np.asarray(numbers[name]))
return [logger.title + '(' + name + ')' for name in names]
class Logger(object):
'''Save training process to log file with simple plot function.'''
def __init__(self, fpath, title=None, resume=False):
self.file = None
self.resume = resume
self.title = '' if title == None else title
if fpath is not None:
if resume:
self.file = open(fpath, 'r')
name = self.file.readline()
self.names = name.rstrip().split('\t')
self.numbers = {}
for _, name in enumerate(self.names):
self.numbers[name] = []
for numbers in self.file:
numbers = numbers.rstrip().split('\t')
for i in range(0, len(numbers)):
self.numbers[self.names[i]].append(numbers[i])
self.file.close()
self.file = open(fpath, 'a')
else:
self.file = open(fpath, 'w')
def set_names(self, names):
if self.resume:
pass
# initialize numbers as empty list
self.numbers = {}
self.names = names
for _, name in enumerate(self.names):
self.file.write(name)
self.file.write('\t')
self.numbers[name] = []
self.file.write('\n')
self.file.flush()
def append(self, numbers):
assert len(self.names) == len(numbers), 'Numbers do not match names'
for index, num in enumerate(numbers):
self.file.write("{0:.6f}".format(num))
self.file.write('\t')
self.numbers[self.names[index]].append(num)
self.file.write('\n')
self.file.flush()
def plot(self, names=None):
names = self.names if names == None else names
numbers = self.numbers
for _, name in enumerate(names):
x = np.arange(len(numbers[name]))
plt.plot(x, np.asarray(numbers[name]))
plt.legend([self.title + '(' + name + ')' for name in names])
plt.grid(True)
def close(self):
if self.file is not None:
self.file.close()
class LoggerMonitor(object):
'''Load and visualize multiple logs.'''
def __init__ (self, paths):
'''paths is a distionary with {name:filepath} pair'''
self.loggers = []
for title, path in paths.items():
logger = Logger(path, title=title, resume=True)
self.loggers.append(logger)
def plot(self, names=None):
plt.figure()
plt.subplot(121)
legend_text = []
for logger in self.loggers:
legend_text += plot_overlap(logger, names)
plt.legend(legend_text, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.grid(True)
if __name__ == '__main__':
# # Example
# logger = Logger('test.txt')
# logger.set_names(['Train loss', 'Valid loss','Test loss'])
# length = 100
# t = np.arange(length)
# train_loss = np.exp(-t / 10.0) + np.random.rand(length) * 0.1
# valid_loss = np.exp(-t / 10.0) + np.random.rand(length) * 0.1
# test_loss = np.exp(-t / 10.0) + np.random.rand(length) * 0.1
# for i in range(0, length):
# logger.append([train_loss[i], valid_loss[i], test_loss[i]])
# logger.plot()
# Example: logger monitor
paths = {
'resadvnet20':'/home/wyang/code/pytorch-classification/checkpoint/cifar10/resadvnet20/log.txt',
'resadvnet32':'/home/wyang/code/pytorch-classification/checkpoint/cifar10/resadvnet32/log.txt',
'resadvnet44':'/home/wyang/code/pytorch-classification/checkpoint/cifar10/resadvnet44/log.txt',
}
field = ['Valid Acc.']
monitor = LoggerMonitor(paths)
monitor.plot(names=field)
savefig('test.eps')
================================================
FILE: utils/misc.py
================================================
'''Some helper functions for PyTorch, including:
- get_mean_and_std: calculate the mean and std value of dataset.
- msr_init: net parameter initialization.
- progress_bar: progress bar mimic xlua.progress.
'''
import errno
import os
import sys
import time
import math
import torch.nn as nn
import torch.nn.init as init
from torch.autograd import Variable
__all__ = ['get_mean_and_std', 'init_params', 'mkdir_p', 'AverageMeter']
def get_mean_and_std(dataset):
'''Compute the mean and std value of dataset.'''
dataloader = trainloader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True, num_workers=2)
mean = torch.zeros(3)
std = torch.zeros(3)
print('==> Computing mean and std..')
for inputs, targets in dataloader:
for i in range(3):
mean[i] += inputs[:,i,:,:].mean()
std[i] += inputs[:,i,:,:].std()
mean.div_(len(dataset))
std.div_(len(dataset))
return mean, std
def init_params(net):
'''Init layer parameters.'''
for m in net.modules():
if isinstance(m, nn.Conv2d):
init.kaiming_normal(m.weight, mode='fan_out')
if m.bias:
init.constant(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
init.constant(m.weight, 1)
init.constant(m.bias, 0)
elif isinstance(m, nn.Linear):
init.normal(m.weight, std=1e-3)
if m.bias:
init.constant(m.bias, 0)
def mkdir_p(path):
'''make dir if not exist'''
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise
class AverageMeter(object):
"""Computes and stores the average and current value
Imported from https://github.com/pytorch/examples/blob/master/imagenet/main.py#L247-L262
"""
def __init__(self):
self.reset()
def reset(self):
self.val = 0
self.avg = 0
self.sum = 0
self.count = 0
def update(self, val, n=1):
self.val = val
self.sum += val * n
self.count += n
self.avg = self.sum / self.count
================================================
FILE: utils/progress/.gitignore
================================================
*.pyc
*.egg-info
build/
dist/
================================================
FILE: utils/progress/LICENSE
================================================
# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
================================================
FILE: utils/progress/MANIFEST.in
================================================
include README.rst LICENSE
================================================
FILE: utils/progress/README.rst
================================================
Easy progress reporting for Python
==================================
|pypi|
|demo|
.. |pypi| image:: https://img.shields.io/pypi/v/progress.svg
.. |demo| image:: https://raw.github.com/verigak/progress/master/demo.gif
:alt: Demo
Bars
----
There are 7 progress bars to choose from:
- ``Bar``
- ``ChargingBar``
- ``FillingSquaresBar``
- ``FillingCirclesBar``
- ``IncrementalBar``
- ``PixelBar``
- ``ShadyBar``
To use them, just call ``next`` to advance and ``finish`` to finish:
.. code-block:: python
from progress.bar import Bar
bar = Bar('Processing', max=20)
for i in range(20):
# Do some work
bar.next()
bar.finish()
The result will be a bar like the following: ::
Processing |############# | 42/100
To simplify the common case where the work is done in an iterator, you can
use the ``iter`` method:
.. code-block:: python
for i in Bar('Processing').iter(it):
# Do some work
Progress bars are very customizable, you can change their width, their fill
character, their suffix and more:
.. code-block:: python
bar = Bar('Loading', fill='@', suffix='%(percent)d%%')
This will produce a bar like the following: ::
Loading |@@@@@@@@@@@@@ | 42%
You can use a number of template arguments in ``message`` and ``suffix``:
========== ================================
Name Value
========== ================================
index current value
max maximum value
remaining max - index
progress index / max
percent progress * 100
avg simple moving average time per item (in seconds)
elapsed elapsed time in seconds
elapsed_td elapsed as a timedelta (useful for printing as a string)
eta avg * remaining
eta_td eta as a timedelta (useful for printing as a string)
========== ================================
Instead of passing all configuration options on instatiation, you can create
your custom subclass:
.. code-block:: python
class FancyBar(Bar):
message = 'Loading'
fill = '*'
suffix = '%(percent).1f%% - %(eta)ds'
You can also override any of the arguments or create your own:
.. code-block:: python
class SlowBar(Bar):
suffix = '%(remaining_hours)d hours remaining'
@property
def remaining_hours(self):
return self.eta // 3600
Spinners
========
For actions with an unknown number of steps you can use a spinner:
.. code-block:: python
from progress.spinner import Spinner
spinner = Spinner('Loading ')
while state != 'FINISHED':
# Do some work
spinner.next()
There are 5 predefined spinners:
- ``Spinner``
- ``PieSpinner``
- ``MoonSpinner``
- ``LineSpinner``
- ``PixelSpinner``
Other
=====
There are a number of other classes available too, please check the source or
subclass one of them to create your own.
License
=======
progress is licensed under ISC
================================================
FILE: utils/progress/progress/__init__.py
================================================
# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from __future__ import division
from collections import deque
from datetime import timedelta
from math import ceil
from sys import stderr
from time import time
__version__ = '1.3'
class Infinite(object):
file = stderr
sma_window = 10 # Simple Moving Average window
def __init__(self, *args, **kwargs):
self.index = 0
self.start_ts = time()
self.avg = 0
self._ts = self.start_ts
self._xput = deque(maxlen=self.sma_window)
for key, val in kwargs.items():
setattr(self, key, val)
def __getitem__(self, key):
if key.startswith('_'):
return None
return getattr(self, key, None)
@property
def elapsed(self):
return int(time() - self.start_ts)
@property
def elapsed_td(self):
return timedelta(seconds=self.elapsed)
def update_avg(self, n, dt):
if n > 0:
self._xput.append(dt / n)
self.avg = sum(self._xput) / len(self._xput)
def update(self):
pass
def start(self):
pass
def finish(self):
pass
def next(self, n=1):
now = time()
dt = now - self._ts
self.update_avg(n, dt)
self._ts = now
self.index = self.index + n
self.update()
def iter(self, it):
try:
for x in it:
yield x
self.next()
finally:
self.finish()
class Progress(Infinite):
def __init__(self, *args, **kwargs):
super(Progress, self).__init__(*args, **kwargs)
self.max = kwargs.get('max', 100)
@property
def eta(self):
return int(ceil(self.avg * self.remaining))
@property
def eta_td(self):
return timedelta(seconds=self.eta)
@property
def percent(self):
return self.progress * 100
@property
def progress(self):
return min(1, self.index / self.max)
@property
def remaining(self):
return max(self.max - self.index, 0)
def start(self):
self.update()
def goto(self, index):
incr = index - self.index
self.next(incr)
def iter(self, it):
try:
self.max = len(it)
except TypeError:
pass
try:
for x in it:
yield x
self.next()
finally:
self.finish()
================================================
FILE: utils/progress/progress/bar.py
================================================
# -*- coding: utf-8 -*-
# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from __future__ import unicode_literals
from . import Progress
from .helpers import WritelnMixin
class Bar(WritelnMixin, Progress):
width = 32
message = ''
suffix = '%(index)d/%(max)d'
bar_prefix = ' |'
bar_suffix = '| '
empty_fill = ' '
fill = '#'
hide_cursor = True
def update(self):
filled_length = int(self.width * self.progress)
empty_length = self.width - filled_length
message = self.message % self
bar = self.fill * filled_length
empty = self.empty_fill * empty_length
suffix = self.suffix % self
line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix,
suffix])
self.writeln(line)
class ChargingBar(Bar):
suffix = '%(percent)d%%'
bar_prefix = ' '
bar_suffix = ' '
empty_fill = '∙'
fill = '█'
class FillingSquaresBar(ChargingBar):
empty_fill = '▢'
fill = '▣'
class FillingCirclesBar(ChargingBar):
empty_fill = '◯'
fill = '◉'
class IncrementalBar(Bar):
phases = (' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█')
def update(self):
nphases = len(self.phases)
filled_len = self.width * self.progress
nfull = int(filled_len) # Number of full chars
phase = int((filled_len - nfull) * nphases) # Phase of last char
nempty = self.width - nfull # Number of empty chars
message = self.message % self
bar = self.phases[-1] * nfull
current = self.phases[phase] if phase > 0 else ''
empty = self.empty_fill * max(0, nempty - len(current))
suffix = self.suffix % self
line = ''.join([message, self.bar_prefix, bar, current, empty,
self.bar_suffix, suffix])
self.writeln(line)
class PixelBar(IncrementalBar):
phases = ('⡀', '⡄', '⡆', '⡇', '⣇', '⣧', '⣷', '⣿')
class ShadyBar(IncrementalBar):
phases = (' ', '░', '▒', '▓', '█')
================================================
FILE: utils/progress/progress/counter.py
================================================
# -*- coding: utf-8 -*-
# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from __future__ import unicode_literals
from . import Infinite, Progress
from .helpers import WriteMixin
class Counter(WriteMixin, Infinite):
message = ''
hide_cursor = True
def update(self):
self.write(str(self.index))
class Countdown(WriteMixin, Progress):
hide_cursor = True
def update(self):
self.write(str(self.remaining))
class Stack(WriteMixin, Progress):
phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█')
hide_cursor = True
def update(self):
nphases = len(self.phases)
i = min(nphases - 1, int(self.progress * nphases))
self.write(self.phases[i])
class Pie(Stack):
phases = ('○', '◔', '◑', '◕', '●')
================================================
FILE: utils/progress/progress/helpers.py
================================================
# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from __future__ import print_function
HIDE_CURSOR = '\x1b[?25l'
SHOW_CURSOR = '\x1b[?25h'
class WriteMixin(object):
hide_cursor = False
def __init__(self, message=None, **kwargs):
super(WriteMixin, self).__init__(**kwargs)
self._width = 0
if message:
self.message = message
if self.file.isatty():
if self.hide_cursor:
print(HIDE_CURSOR, end='', file=self.file)
print(self.message, end='', file=self.file)
self.file.flush()
def write(self, s):
if self.file.isatty():
b = '\b' * self._width
c = s.ljust(self._width)
print(b + c, end='', file=self.file)
self._width = max(self._width, len(s))
self.file.flush()
def finish(self):
if self.file.isatty() and self.hide_cursor:
print(SHOW_CURSOR, end='', file=self.file)
class WritelnMixin(object):
hide_cursor = False
def __init__(self, message=None, **kwargs):
super(WritelnMixin, self).__init__(**kwargs)
if message:
self.message = message
if self.file.isatty() and self.hide_cursor:
print(HIDE_CURSOR, end='', file=self.file)
def clearln(self):
if self.file.isatty():
print('\r\x1b[K', end='', file=self.file)
def writeln(self, line):
if self.file.isatty():
self.clearln()
print(line, end='', file=self.file)
self.file.flush()
def finish(self):
if self.file.isatty():
print(file=self.file)
if self.hide_cursor:
print(SHOW_CURSOR, end='', file=self.file)
from signal import signal, SIGINT
from sys import exit
class SigIntMixin(object):
"""Registers a signal handler that calls finish on SIGINT"""
def __init__(self, *args, **kwargs):
super(SigIntMixin, self).__init__(*args, **kwargs)
signal(SIGINT, self._sigint_handler)
def _sigint_handler(self, signum, frame):
self.finish()
exit(0)
================================================
FILE: utils/progress/progress/spinner.py
================================================
# -*- coding: utf-8 -*-
# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from __future__ import unicode_literals
from . import Infinite
from .helpers import WriteMixin
class Spinner(WriteMixin, Infinite):
message = ''
phases = ('-', '\\', '|', '/')
hide_cursor = True
def update(self):
i = self.index % len(self.phases)
self.write(self.phases[i])
class PieSpinner(Spinner):
phases = ['◷', '◶', '◵', '◴']
class MoonSpinner(Spinner):
phases = ['◑', '◒', '◐', '◓']
class LineSpinner(Spinner):
phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻']
class PixelSpinner(Spinner):
phases = ['⣾','⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽']
================================================
FILE: utils/progress/setup.py
================================================
#!/usr/bin/env python
from setuptools import setup
import progress
setup(
name='progress',
version=progress.__version__,
description='Easy to use progress bars',
long_description=open('README.rst').read(),
author='Giorgos Verigakis',
author_email='verigak@gmail.com',
url='http://github.com/verigak/progress/',
license='ISC',
packages=['progress'],
classifiers=[
'Environment :: Console',
'Intended Audience :: Developers',
'License :: OSI Approved :: ISC License (ISCL)',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
]
)
================================================
FILE: utils/progress/test_progress.py
================================================
#!/usr/bin/env python
from __future__ import print_function
import random
import time
from progress.bar import (Bar, ChargingBar, FillingSquaresBar,
FillingCirclesBar, IncrementalBar, PixelBar,
ShadyBar)
from progress.spinner import (Spinner, PieSpinner, MoonSpinner, LineSpinner,
PixelSpinner)
from progress.counter import Counter, Countdown, Stack, Pie
def sleep():
t = 0.01
t += t * random.uniform(-0.1, 0.1) # Add some variance
time.sleep(t)
for bar_cls in (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar):
suffix = '%(index)d/%(max)d [%(elapsed)d / %(eta)d / %(eta_td)s]'
bar = bar_cls(bar_cls.__name__, suffix=suffix)
for i in bar.iter(range(200)):
sleep()
for bar_cls in (IncrementalBar, PixelBar, ShadyBar):
suffix = '%(percent)d%% [%(elapsed_td)s / %(eta)d / %(eta_td)s]'
bar = bar_cls(bar_cls.__name__, suffix=suffix)
for i in bar.iter(range(200)):
sleep()
for spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner, PixelSpinner):
for i in spin(spin.__name__ + ' ').iter(range(100)):
sleep()
print()
for singleton in (Counter, Countdown, Stack, Pie):
for i in singleton(singleton.__name__ + ' ').iter(range(100)):
sleep()
print()
bar = IncrementalBar('Random', suffix='%(index)d')
for i in range(100):
bar.goto(random.randint(0, 100))
sleep()
bar.finish()
================================================
FILE: utils/visualize.py
================================================
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import numpy as np
from .misc import *
__all__ = ['make_image', 'show_batch', 'show_mask', 'show_mask_single']
# functions to show an image
def make_image(img, mean=(0,0,0), std=(1,1,1)):
for i in range(0, 3):
img[i] = img[i] * std[i] + mean[i] # unnormalize
npimg = img.numpy()
return np.transpose(npimg, (1, 2, 0))
def gauss(x,a,b,c):
return torch.exp(-torch.pow(torch.add(x,-b),2).div(2*c*c)).mul(a)
def colorize(x):
''' Converts a one-channel grayscale image to a color heatmap image '''
if x.dim() == 2:
torch.unsqueeze(x, 0, out=x)
if x.dim() == 3:
cl = torch.zeros([3, x.size(1), x.size(2)])
cl[0] = gauss(x,.5,.6,.2) + gauss(x,1,.8,.3)
cl[1] = gauss(x,1,.5,.3)
cl[2] = gauss(x,1,.2,.3)
cl[cl.gt(1)] = 1
elif x.dim() == 4:
cl = torch.zeros([x.size(0), 3, x.size(2), x.size(3)])
cl[:,0,:,:] = gauss(x,.5,.6,.2) + gauss(x,1,.8,.3)
cl[:,1,:,:] = gauss(x,1,.5,.3)
cl[:,2,:,:] = gauss(x,1,.2,.3)
return cl
def show_batch(images, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):
images = make_image(torchvision.utils.make_grid(images), Mean, Std)
plt.imshow(images)
plt.show()
def show_mask_single(images, mask, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):
im_size = images.size(2)
# save for adding mask
im_data = images.clone()
for i in range(0, 3):
im_data[:,i,:,:] = im_data[:,i,:,:] * Std[i] + Mean[i] # unnormalize
images = make_image(torchvision.utils.make_grid(images), Mean, Std)
plt.subplot(2, 1, 1)
plt.imshow(images)
plt.axis('off')
# for b in range(mask.size(0)):
# mask[b] = (mask[b] - mask[b].min())/(mask[b].max() - mask[b].min())
mask_size = mask.size(2)
# print('Max %f Min %f' % (mask.max(), mask.min()))
mask = (upsampling(mask, scale_factor=im_size/mask_size))
# mask = colorize(upsampling(mask, scale_factor=im_size/mask_size))
# for c in range(3):
# mask[:,c,:,:] = (mask[:,c,:,:] - Mean[c])/Std[c]
# print(mask.size())
mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask.expand_as(im_data)))
# mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask), Mean, Std)
plt.subplot(2, 1, 2)
plt.imshow(mask)
plt.axis('off')
def show_mask(images, masklist, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):
im_size = images.size(2)
# save for adding mask
im_data = images.clone()
for i in range(0, 3):
im_data[:,i,:,:] = im_data[:,i,:,:] * Std[i] + Mean[i] # unnormalize
images = make_image(torchvision.utils.make_grid(images), Mean, Std)
plt.subplot(1+len(masklist), 1, 1)
plt.imshow(images)
plt.axis('off')
for i in range(len(masklist)):
mask = masklist[i].data.cpu()
# for b in range(mask.size(0)):
# mask[b] = (mask[b] - mask[b].min())/(mask[b].max() - mask[b].min())
mask_size = mask.size(2)
# print('Max %f Min %f' % (mask.max(), mask.min()))
mask = (upsampling(mask, scale_factor=im_size/mask_size))
# mask = colorize(upsampling(mask, scale_factor=im_size/mask_size))
# for c in range(3):
# mask[:,c,:,:] = (mask[:,c,:,:] - Mean[c])/Std[c]
# print(mask.size())
mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask.expand_as(im_data)))
# mask = make_image(torchvision.utils.make_grid(0.3*im_data+0.7*mask), Mean, Std)
plt.subplot(1+len(masklist), 1, i+2)
plt.imshow(mask)
plt.axis('off')
# x = torch.zeros(1, 3, 3)
# out = colorize(x)
# out_im = make_image(out)
# plt.imshow(out_im)
# plt.show()
gitextract_wilfivay/
├── .gitignore
├── LICENSE
├── README.md
├── celeba.py
├── main.py
├── models/
│ ├── __init__.py
│ ├── mobilenetv1.py
│ ├── mobilenetv2.py
│ └── resnet.py
└── utils/
├── __init__.py
├── eval.py
├── logger.py
├── misc.py
├── progress/
│ ├── .gitignore
│ ├── LICENSE
│ ├── MANIFEST.in
│ ├── README.rst
│ ├── progress/
│ │ ├── __init__.py
│ │ ├── bar.py
│ │ ├── counter.py
│ │ ├── helpers.py
│ │ └── spinner.py
│ ├── setup.py
│ └── test_progress.py
└── visualize.py
SYMBOL INDEX (131 symbols across 15 files)
FILE: celeba.py
function pil_loader (line 9) | def pil_loader(path):
function accimage_loader (line 16) | def accimage_loader(path):
function default_loader (line 25) | def default_loader(path):
class CelebA (line 33) | class CelebA(data.Dataset):
method __init__ (line 34) | def __init__(self, root, ann_file, transform=None, target_transform=No...
method __getitem__ (line 50) | def __getitem__(self, index):
method __len__ (line 62) | def __len__(self):
FILE: main.py
function main (line 99) | def main():
function train (line 268) | def train(train_loader, model, criterion, optimizer, epoch):
function validate (line 328) | def validate(val_loader, model, criterion):
function save_checkpoint (line 383) | def save_checkpoint(state, is_best, checkpoint='checkpoint', filename='c...
function adjust_learning_rate (line 390) | def adjust_learning_rate(optimizer, epoch):
FILE: models/mobilenetv1.py
function conv_bn (line 14) | def conv_bn(inp, oup, stride):
function conv_dw (line 22) | def conv_dw(inp, oup, stride):
class MobileNet (line 34) | class MobileNet(nn.Module):
method __init__ (line 35) | def __init__(self, num_classes=1000):
method forward (line 57) | def forward(self, x):
function mobilenetv1 (line 63) | def mobilenetv1(**kwargs):
FILE: models/mobilenetv2.py
function _make_divisible (line 17) | def _make_divisible(v, divisor, min_value=None):
function conv_3x3_bn (line 37) | def conv_3x3_bn(inp, oup, stride):
function conv_1x1_bn (line 45) | def conv_1x1_bn(inp, oup):
class InvertedResidual (line 53) | class InvertedResidual(nn.Module):
method __init__ (line 54) | def __init__(self, inp, oup, stride, expand_ratio):
method forward (line 86) | def forward(self, x):
class fc_block (line 93) | class fc_block(nn.Module):
method __init__ (line 94) | def __init__(self, inplanes, planes, drop_rate=0.15):
method forward (line 103) | def forward(self, x):
class MobileNetV2 (line 112) | class MobileNetV2(nn.Module):
method __init__ (line 113) | def __init__(self, num_attributes=40, input_size=224, width_mult=1.):
method forward (line 151) | def forward(self, x):
method _initialize_weights (line 165) | def _initialize_weights(self):
function init_pretrained_weights (line 181) | def init_pretrained_weights(model, path=os.path.expanduser('~/.torch/mod...
function mobilenetv2 (line 195) | def mobilenetv2(pretrained=True, **kwargs):
FILE: models/resnet.py
function conv3x3 (line 17) | def conv3x3(in_planes, out_planes, stride=1):
function conv1x1 (line 23) | def conv1x1(in_planes, out_planes, stride=1):
class BasicBlock (line 28) | class BasicBlock(nn.Module):
method __init__ (line 31) | def __init__(self, inplanes, planes, stride=1, downsample=None):
method forward (line 41) | def forward(self, x):
class Bottleneck (line 60) | class Bottleneck(nn.Module):
method __init__ (line 63) | def __init__(self, inplanes, planes, stride=1, downsample=None):
method forward (line 75) | def forward(self, x):
class fc_block (line 98) | class fc_block(nn.Module):
method __init__ (line 99) | def __init__(self, inplanes, planes, drop_rate=0.15):
method forward (line 108) | def forward(self, x):
class ResNet (line 117) | class ResNet(nn.Module):
method __init__ (line 119) | def __init__(self, block, layers, num_attributes=40, zero_init_residua...
method _make_layer (line 154) | def _make_layer(self, block, planes, blocks, stride=1):
method forward (line 170) | def forward(self, x):
function resnet50 (line 193) | def resnet50(pretrained=True, **kwargs):
function init_pretrained_weights (line 205) | def init_pretrained_weights(model, model_url):
FILE: utils/eval.py
function accuracy (line 6) | def accuracy(output, target, topk=(1,)):
FILE: utils/logger.py
function savefig (line 11) | def savefig(fname, dpi=None):
function plot_overlap (line 15) | def plot_overlap(logger, names=None):
class Logger (line 23) | class Logger(object):
method __init__ (line 25) | def __init__(self, fpath, title=None, resume=False):
method set_names (line 47) | def set_names(self, names):
method append (line 61) | def append(self, numbers):
method plot (line 70) | def plot(self, names=None):
method close (line 79) | def close(self):
class LoggerMonitor (line 83) | class LoggerMonitor(object):
method __init__ (line 85) | def __init__ (self, paths):
method plot (line 92) | def plot(self, names=None):
FILE: utils/misc.py
function get_mean_and_std (line 19) | def get_mean_and_std(dataset):
function init_params (line 34) | def init_params(net):
function mkdir_p (line 49) | def mkdir_p(path):
class AverageMeter (line 59) | class AverageMeter(object):
method __init__ (line 63) | def __init__(self):
method reset (line 66) | def reset(self):
method update (line 72) | def update(self, val, n=1):
FILE: utils/progress/progress/__init__.py
class Infinite (line 27) | class Infinite(object):
method __init__ (line 31) | def __init__(self, *args, **kwargs):
method __getitem__ (line 40) | def __getitem__(self, key):
method elapsed (line 46) | def elapsed(self):
method elapsed_td (line 50) | def elapsed_td(self):
method update_avg (line 53) | def update_avg(self, n, dt):
method update (line 58) | def update(self):
method start (line 61) | def start(self):
method finish (line 64) | def finish(self):
method next (line 67) | def next(self, n=1):
method iter (line 75) | def iter(self, it):
class Progress (line 84) | class Progress(Infinite):
method __init__ (line 85) | def __init__(self, *args, **kwargs):
method eta (line 90) | def eta(self):
method eta_td (line 94) | def eta_td(self):
method percent (line 98) | def percent(self):
method progress (line 102) | def progress(self):
method remaining (line 106) | def remaining(self):
method start (line 109) | def start(self):
method goto (line 112) | def goto(self, index):
method iter (line 116) | def iter(self, it):
FILE: utils/progress/progress/bar.py
class Bar (line 22) | class Bar(WritelnMixin, Progress):
method update (line 32) | def update(self):
class ChargingBar (line 45) | class ChargingBar(Bar):
class FillingSquaresBar (line 53) | class FillingSquaresBar(ChargingBar):
class FillingCirclesBar (line 58) | class FillingCirclesBar(ChargingBar):
class IncrementalBar (line 63) | class IncrementalBar(Bar):
method update (line 66) | def update(self):
class PixelBar (line 83) | class PixelBar(IncrementalBar):
class ShadyBar (line 87) | class ShadyBar(IncrementalBar):
FILE: utils/progress/progress/counter.py
class Counter (line 22) | class Counter(WriteMixin, Infinite):
method update (line 26) | def update(self):
class Countdown (line 30) | class Countdown(WriteMixin, Progress):
method update (line 33) | def update(self):
class Stack (line 37) | class Stack(WriteMixin, Progress):
method update (line 41) | def update(self):
class Pie (line 47) | class Pie(Stack):
FILE: utils/progress/progress/helpers.py
class WriteMixin (line 22) | class WriteMixin(object):
method __init__ (line 25) | def __init__(self, message=None, **kwargs):
method write (line 37) | def write(self, s):
method finish (line 45) | def finish(self):
class WritelnMixin (line 50) | class WritelnMixin(object):
method __init__ (line 53) | def __init__(self, message=None, **kwargs):
method clearln (line 61) | def clearln(self):
method writeln (line 65) | def writeln(self, line):
method finish (line 71) | def finish(self):
class SigIntMixin (line 82) | class SigIntMixin(object):
method __init__ (line 85) | def __init__(self, *args, **kwargs):
method _sigint_handler (line 89) | def _sigint_handler(self, signum, frame):
FILE: utils/progress/progress/spinner.py
class Spinner (line 22) | class Spinner(WriteMixin, Infinite):
method update (line 27) | def update(self):
class PieSpinner (line 32) | class PieSpinner(Spinner):
class MoonSpinner (line 36) | class MoonSpinner(Spinner):
class LineSpinner (line 40) | class LineSpinner(Spinner):
class PixelSpinner (line 43) | class PixelSpinner(Spinner):
FILE: utils/progress/test_progress.py
function sleep (line 16) | def sleep():
FILE: utils/visualize.py
function make_image (line 12) | def make_image(img, mean=(0,0,0), std=(1,1,1)):
function gauss (line 18) | def gauss(x,a,b,c):
function colorize (line 21) | def colorize(x):
function show_batch (line 38) | def show_batch(images, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):
function show_mask_single (line 44) | def show_mask_single(images, mask, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):
function show_mask (line 73) | def show_mask(images, masklist, Mean=(2, 2, 2), Std=(0.5,0.5,0.5)):
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (70K chars).
[
{
"path": ".gitignore",
"chars": 1231,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": "LICENSE",
"chars": 1063,
"preview": "MIT License\n\nCopyright (c) 2019 Duo LI\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
},
{
"path": "README.md",
"chars": 980,
"preview": "# face-attribute-prediction\nFace Attribute Prediction on [CelebA](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html) benc"
},
{
"path": "celeba.py",
"chars": 1992,
"preview": "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(pa"
},
{
"path": "main.py",
"chars": 15825,
"preview": "'''\nTraining script for ImageNet\nCopyright (c) Wei YANG, 2017\n'''\nfrom __future__ import print_function\n\nimport argparse"
},
{
"path": "models/__init__.py",
"chars": 116,
"preview": "from __future__ import absolute_import\n\nfrom .resnet import *\nfrom .mobilenetv1 import *\nfrom .mobilenetv2 import *\n"
},
{
"path": "models/mobilenetv1.py",
"chars": 1811,
"preview": "\"\"\"\nCreates a MobileNet Model as defined in:\nAndrew G. H., Menglong Z., Bo C., Dmitry K., Weijun W., Tobias W., Marco A."
},
{
"path": "models/mobilenetv2.py",
"chars": 6746,
"preview": "\"\"\"\nCreates a MobileNetV2 Model as defined in:\nMark Sandler, Andrew Howard, Menglong Zhu, Andrey Zhmoginov, Liang-Chieh "
},
{
"path": "models/resnet.py",
"chars": 7115,
"preview": "import torch.nn as nn\nimport torch.utils.model_zoo as model_zoo\n\n\n__all__ = ['ResNet', 'resnet50']\n\n\nmodel_urls = {\n "
},
{
"path": "utils/__init__.py",
"chars": 242,
"preview": "\"\"\"Useful utils\n\"\"\"\nfrom .misc import *\nfrom .logger import *\nfrom .visualize import *\nfrom .eval import *\n\n# progress b"
},
{
"path": "utils/eval.py",
"chars": 603,
"preview": "from __future__ import print_function, absolute_import\nimport torch\n\n__all__ = ['accuracy']\n\ndef accuracy(output, target"
},
{
"path": "utils/logger.py",
"chars": 4399,
"preview": "# A simple torch style logger\n# (C) Wei YANG 2017\nfrom __future__ import absolute_import\nimport matplotlib.pyplot as plt"
},
{
"path": "utils/misc.py",
"chars": 2206,
"preview": "'''Some helper functions for PyTorch, including:\n - get_mean_and_std: calculate the mean and std value of dataset.\n "
},
{
"path": "utils/progress/.gitignore",
"chars": 30,
"preview": "*.pyc\n*.egg-info\nbuild/\ndist/\n"
},
{
"path": "utils/progress/LICENSE",
"chars": 776,
"preview": "# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this soft"
},
{
"path": "utils/progress/MANIFEST.in",
"chars": 27,
"preview": "include README.rst LICENSE\n"
},
{
"path": "utils/progress/README.rst",
"chars": 2944,
"preview": "Easy progress reporting for Python\n==================================\n\n|pypi|\n\n|demo|\n\n.. |pypi| image:: https://img.shi"
},
{
"path": "utils/progress/progress/__init__.py",
"chars": 3188,
"preview": "# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this soft"
},
{
"path": "utils/progress/progress/bar.py",
"chars": 2784,
"preview": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify,"
},
{
"path": "utils/progress/progress/counter.py",
"chars": 1502,
"preview": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify,"
},
{
"path": "utils/progress/progress/helpers.py",
"chars": 2854,
"preview": "# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify, and distribute this soft"
},
{
"path": "utils/progress/progress/spinner.py",
"chars": 1395,
"preview": "# -*- coding: utf-8 -*-\n\n# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com>\n#\n# Permission to use, copy, modify,"
},
{
"path": "utils/progress/setup.py",
"chars": 843,
"preview": "#!/usr/bin/env python\n\nfrom setuptools import setup\n\nimport progress\n\n\nsetup(\n name='progress',\n version=progress."
},
{
"path": "utils/progress/test_progress.py",
"chars": 1461,
"preview": "#!/usr/bin/env python\n\nfrom __future__ import print_function\n\nimport random\nimport time\n\nfrom progress.bar import (Bar, "
},
{
"path": "utils/visualize.py",
"chars": 3795,
"preview": "import matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torchvision\nimport torchvision.transforms as t"
}
]
About this extraction
This page contains the full source code of the d-li14/face-attribute-prediction GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (64.4 KB), approximately 17.1k tokens, and a symbol index with 131 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.