├── data
├── __init__.py
├── __pycache__
│ ├── cifar.cpython-36.pyc
│ ├── mnist.cpython-36.pyc
│ ├── utils.cpython-36.pyc
│ ├── __init__.cpython-36.pyc
│ └── datasets.cpython-36.pyc
├── datasets.py
├── utils.py
└── mnist.py
├── results
└── __init__.py
├── phase2
├── results
│ └── __init__.py
├── samplers
│ ├── __init__.py
│ └── stratified_sampler.py
├── .DS_Store
├── indices.npy
├── labels.npy
├── confs
│ ├── .DS_Store
│ ├── resnet34_ins_0.2.yaml
│ ├── resnet34_ins_0.4.yaml
│ └── resnet34_ins_0.6.yaml
├── warmup_scheduler
│ ├── __init__.py
│ ├── run.py
│ └── scheduler.py
├── pretrainedmodels
│ ├── .DS_Store
│ ├── version.py
│ ├── datasets
│ │ ├── __init__.py
│ │ ├── utils.py
│ │ └── voc.py
│ ├── models
│ │ ├── resnext_features
│ │ │ └── __init__.py
│ │ ├── utils.py
│ │ ├── __init__.py
│ │ ├── wideresnet.py
│ │ ├── resnext.py
│ │ ├── vggm.py
│ │ ├── cafferesnet.py
│ │ ├── fbresnet.py
│ │ ├── xception.py
│ │ ├── inceptionv4.py
│ │ └── inceptionresnetv2.py
│ ├── __init__.py
│ └── utils.py
├── .vscode
│ ├── settings.json
│ └── launch.json
├── requirements.txt
├── common.py
├── get_noise_preds.py
├── networks
│ ├── __init__.py
│ ├── wideresnet.py
│ ├── preact_resnet.py
│ └── resnet.py
├── .gitignore
├── metrics.py
├── augmentations.py
├── utils.py
├── data.py
├── LICENSE
├── phase2.py
└── noisy_cifar.py
├── .DS_Store
├── models
├── __init__.py
├── __pycache__
│ ├── resnet.cpython-36.pyc
│ ├── __init__.cpython-36.pyc
│ └── nine_layer_cnn.cpython-36.pyc
├── nine_layer_cnn.py
└── resnet.py
├── .gitignore
├── README.md
├── loss.py
└── phase1.py
/data/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/results/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/phase2/results/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/phase2/samplers/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/.DS_Store
--------------------------------------------------------------------------------
/models/__init__.py:
--------------------------------------------------------------------------------
1 | from .resnet import *
2 | from .nine_layer_cnn import *
--------------------------------------------------------------------------------
/phase2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/phase2/.DS_Store
--------------------------------------------------------------------------------
/phase2/indices.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/phase2/indices.npy
--------------------------------------------------------------------------------
/phase2/labels.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/phase2/labels.npy
--------------------------------------------------------------------------------
/phase2/confs/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/phase2/confs/.DS_Store
--------------------------------------------------------------------------------
/phase2/warmup_scheduler/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | from warmup_scheduler.scheduler import GradualWarmupScheduler
3 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/phase2/pretrainedmodels/.DS_Store
--------------------------------------------------------------------------------
/data/__pycache__/cifar.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/data/__pycache__/cifar.cpython-36.pyc
--------------------------------------------------------------------------------
/data/__pycache__/mnist.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/data/__pycache__/mnist.cpython-36.pyc
--------------------------------------------------------------------------------
/data/__pycache__/utils.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/data/__pycache__/utils.cpython-36.pyc
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/version.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | __version__ = '0.7.4'
3 |
--------------------------------------------------------------------------------
/data/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/data/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/data/__pycache__/datasets.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/data/__pycache__/datasets.cpython-36.pyc
--------------------------------------------------------------------------------
/models/__pycache__/resnet.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/models/__pycache__/resnet.cpython-36.pyc
--------------------------------------------------------------------------------
/models/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/models/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/models/__pycache__/nine_layer_cnn.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/haochenglouis/cores/HEAD/models/__pycache__/nine_layer_cnn.cpython-36.pyc
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/datasets/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | from .voc import Voc2007Classification
--------------------------------------------------------------------------------
/phase2/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.pythonPath": "/raid/home/public/anaconda3/bin/python",
3 | "python.linting.pylintEnabled": true,
4 | "python.linting.enabled": true,
5 | "python.linting.flake8Enabled": false
6 | }
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/resnext_features/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | from .resnext101_32x4d_features import resnext101_32x4d_features
3 | from .resnext101_64x4d_features import resnext101_64x4d_features
--------------------------------------------------------------------------------
/phase2/requirements.txt:
--------------------------------------------------------------------------------
1 | git+https://github.com/wbaek/theconf
2 | git+https://github.com/ildoonet/pytorch-gradual-warmup-lr.git@v0.2
3 | git+https://github.com/ildoonet/pystopwatch2.git
4 | pretrainedmodels
5 | tqdm
6 | tensorboardx
7 | sklearn
8 | matplotlib
9 | psutil
10 | requests
--------------------------------------------------------------------------------
/phase2/warmup_scheduler/run.py:
--------------------------------------------------------------------------------
1 | import torch
2 |
3 | from warmup_scheduler import GradualWarmupScheduler
4 |
5 |
6 | if __name__ == '__main__':
7 | v = torch.zeros(10)
8 | optim = torch.optim.SGD([v], lr=0.01)
9 | scheduler = GradualWarmupScheduler(optim, multiplier=8, total_epoch=10)
10 |
11 | for epoch in range(1, 20):
12 | scheduler.step(epoch)
13 |
14 | print(epoch, optim.param_groups[0]['lr'])
15 |
--------------------------------------------------------------------------------
/phase2/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // 使用 IntelliSense 了解相关属性。
3 | // 悬停以查看现有属性的描述。
4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Python: 当前文件",
9 | "type": "python",
10 | "request": "launch",
11 | "program": "${file}",
12 | "console": "integratedTerminal"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/phase2/common.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
4 |
5 |
6 | def get_logger(name, level=logging.DEBUG):
7 | logger = logging.getLogger(name)
8 | logger.handlers.clear()
9 | logger.setLevel(level)
10 | ch = logging.StreamHandler()
11 | ch.setLevel(level)
12 | ch.setFormatter(formatter)
13 | logger.addHandler(ch)
14 | return logger
15 |
16 |
17 | def add_filehandler(logger, filepath):
18 | fh = logging.FileHandler(filepath)
19 | fh.setLevel(logging.DEBUG)
20 | fh.setFormatter(formatter)
21 | logger.addHandler(fh)
22 |
--------------------------------------------------------------------------------
/phase2/confs/resnet34_ins_0.2.yaml:
--------------------------------------------------------------------------------
1 | model:
2 | type: resnet34
3 | dataset: cifar10
4 | aug: autoaug_cifar10 # autoaug_extend
5 | cutout: 16
6 | batch: 320
7 | batch_unsup: 80
8 | ratio_unsup: 0.2
9 | ratio_mode: 'constant'
10 | epoch: 1600
11 | lr: 0.001
12 | lr_schedule:
13 | type: 'cosine'
14 | warmup:
15 | multiplier: 300
16 | epoch: 120
17 | optimizer:
18 | type: sgd
19 | nesterov: True
20 | decay: 0.0005
21 |
22 | random_state: 0
23 | train_labels: '../results/cifar10/resnet/coresinstance0.2train_noisy_labels.npy'
24 | unsup_idx: '../results/cifar10/resnet/coresinstance0.2_noise_pred.npy'
25 | pretrain: ''
26 |
27 | tqdm_disable: False
28 |
--------------------------------------------------------------------------------
/phase2/confs/resnet34_ins_0.4.yaml:
--------------------------------------------------------------------------------
1 | model:
2 | type: resnet34
3 | dataset: cifar10
4 | aug: autoaug_cifar10 # autoaug_extend
5 | cutout: 16
6 | batch: 320
7 | batch_unsup: 160
8 | ratio_unsup: 0.4
9 | ratio_mode: 'constant'
10 | epoch: 1600
11 | lr: 0.001
12 | lr_schedule:
13 | type: 'cosine'
14 | warmup:
15 | multiplier: 300
16 | epoch: 120
17 | optimizer:
18 | type: sgd
19 | nesterov: True
20 | decay: 0.0005
21 |
22 | random_state: 0
23 | train_labels: '../results/cifar10/resnet/coresinstance0.4train_noisy_labels.npy'
24 | unsup_idx: '../results/cifar10/resnet/coresinstance0.4_noise_pred.npy'
25 | pretrain: ''
26 |
27 | tqdm_disable: False
28 |
--------------------------------------------------------------------------------
/phase2/confs/resnet34_ins_0.6.yaml:
--------------------------------------------------------------------------------
1 | model:
2 | type: resnet34
3 | dataset: cifar10
4 | aug: autoaug_cifar10 # autoaug_extend
5 | cutout: 16
6 | batch: 320
7 | batch_unsup: 240
8 | ratio_unsup: 0.9
9 | ratio_mode: 'constant'
10 | epoch: 1600
11 | lr: 0.001
12 | lr_schedule:
13 | type: 'cosine'
14 | warmup:
15 | multiplier: 300
16 | epoch: 120
17 | optimizer:
18 | type: sgd
19 | nesterov: True
20 | decay: 0.0005
21 |
22 | random_state: 0
23 | train_labels: '../results/cifar10/resnet/coresinstance0.6train_noisy_labels.npy'
24 | unsup_idx: '../results/cifar10/resnet/coresinstance0.6_noise_pred.npy'
25 | pretrain: ''
26 |
27 | tqdm_disable: False
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | results/cifar10/resnet/crispsymmetric0.6.txt
2 | results/cifar10/resnet/crispsymmetric0.6best.pth.tar
3 | results/cifar10/resnet/crispsymmetric0.6last_noise_pred.npy
4 | results/cifar10/resnet/crispsymmetric0.6loss_all.npy
5 | results/cifar10/resnet/crispsymmetric0.6loss_div_all.npy
6 | __pycache__/loss.cpython-38.pyc
7 | data/__pycache__/__init__.cpython-38.pyc
8 | data/__pycache__/cifar.cpython-38.pyc
9 | data/__pycache__/datasets.cpython-38.pyc
10 | data/__pycache__/mnist.cpython-38.pyc
11 | data/__pycache__/utils.cpython-38.pyc
12 | models/__pycache__/__init__.cpython-38.pyc
13 | models/__pycache__/nine_layer_cnn.cpython-38.pyc
14 | models/__pycache__/resnet.cpython-38.pyc
15 |
--------------------------------------------------------------------------------
/phase2/get_noise_preds.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | noise='symmetric'
3 | nr=0.2
4 | alpha=-4
5 |
6 | save_dir = '../results/cifar10/resnet'
7 | loss=np.load('../results/cifar10/resnet/uspl{}{}loss_div_all.npy'.format(noise,nr))
8 | results='../results/cifar10/resnet/uspl{}{}.txt'.format(noise,nr)
9 |
10 | lines = open(results, 'r').readlines()[1:]
11 | best = 0.
12 | best_epoch = -1
13 | for line in lines:
14 | epoch, _, testacc=line.strip().split()
15 | testacc = float(testacc)
16 | if testacc > best:
17 | best=testacc
18 | best_epoch = int(epoch[:-1])
19 | best_epoch = 21
20 | print('best_epoch ', best_epoch, best)
21 |
22 | lbest = loss[:,best_epoch]
23 | llast = loss[:,-1]
24 |
25 | idx_best = np.where(lbest>alpha)[0]
26 | print('best idx:', idx_best.shape)
27 |
28 | idx_last = np.where(llast>alpha)[0]
29 | print('last idx:', idx_last.shape)
30 |
31 | np.save(save_dir+'/usplpeer{}{}best_noise_pred.npy'.format(noise, nr), idx_best)
32 | np.save(save_dir+'/usplpeer{}{}last_noise_pred.npy'.format(noise, nr), idx_last)
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/phase2/networks/__init__.py:
--------------------------------------------------------------------------------
1 | import torch
2 | from pretrainedmodels import models
3 |
4 | from torch import nn
5 | from torch.nn import DataParallel
6 | import torch.backends.cudnn as cudnn
7 |
8 | from networks.wideresnet import WideResNet
9 | from .resnet import ResNet34
10 | from .preact_resnet import PreActResNet18
11 |
12 | import os
13 |
14 | def get_model(conf, num_class=10, data_parallel=True, devices=None): #None means using all devices
15 | name = conf['type']
16 |
17 | if name == 'wresnet40_2':
18 | model = WideResNet(40, 2, dropout_rate=0.0, num_classes=num_class)
19 | elif name == 'wresnet28_2':
20 | model = WideResNet(28, 2, dropout_rate=0.0, num_classes=num_class)
21 | elif name == 'wresnet28_10':
22 | model = WideResNet(28, 10, dropout_rate=0.0, num_classes=num_class)
23 | elif name == 'resnet34':
24 | model = ResNet34(num_class)
25 | elif name == 'preres18':
26 | model = PreActResNet18(num_class)
27 | else:
28 | raise NameError('no model named, %s' % name)
29 |
30 | if data_parallel:
31 | print('DEBUG: torch device count', torch.cuda.device_count())
32 | model = model.cuda()
33 | model = DataParallel(model, device_ids=devices)
34 | else:
35 | import horovod.torch as hvd
36 | device = torch.device('cuda', hvd.local_rank())
37 | model = model.to(device)
38 | cudnn.benchmark = True
39 | return model
40 |
41 |
42 | def num_class(dataset):
43 | return {
44 | 'cifar10': 10,
45 | 'reduced_cifar10': 10,
46 | 'cifar100': 100,
47 | 'imagenet': 1000,
48 | 'reduced_imagenet': 120,
49 | }[dataset]
50 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/utils.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | from .fbresnet import pretrained_settings as fbresnet_settings
3 | from .bninception import pretrained_settings as bninception_settings
4 | from .resnext import pretrained_settings as resnext_settings
5 | from .inceptionv4 import pretrained_settings as inceptionv4_settings
6 | from .inceptionresnetv2 import pretrained_settings as inceptionresnetv2_settings
7 | from .torchvision_models import pretrained_settings as torchvision_models_settings
8 | from .nasnet_mobile import pretrained_settings as nasnet_mobile_settings
9 | from .nasnet import pretrained_settings as nasnet_settings
10 | from .dpn import pretrained_settings as dpn_settings
11 | from .xception import pretrained_settings as xception_settings
12 | from .senet import pretrained_settings as senet_settings
13 | from .cafferesnet import pretrained_settings as cafferesnet_settings
14 | from .pnasnet import pretrained_settings as pnasnet_settings
15 | from .polynet import pretrained_settings as polynet_settings
16 |
17 | all_settings = [
18 | fbresnet_settings,
19 | bninception_settings,
20 | resnext_settings,
21 | inceptionv4_settings,
22 | inceptionresnetv2_settings,
23 | torchvision_models_settings,
24 | nasnet_mobile_settings,
25 | nasnet_settings,
26 | dpn_settings,
27 | xception_settings,
28 | senet_settings,
29 | cafferesnet_settings,
30 | pnasnet_settings,
31 | polynet_settings
32 | ]
33 |
34 | model_names = []
35 | pretrained_settings = {}
36 | for settings in all_settings:
37 | for model_name, model_settings in settings.items():
38 | pretrained_settings[model_name] = model_settings
39 | model_names.append(model_name)
40 |
--------------------------------------------------------------------------------
/phase2/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Learning with Instance-Dependent Label Noise: A Sample Sieve Approach
2 | This code is a PyTorch implementation of our paper "[Learning with Instance-Dependent Label Noise: A Sample Sieve Approach](https://arxiv.org/abs/2010.02347)" accepted by ICLR2021.
3 |
4 | The code is run on the Tesla V-100.
5 | ## Prerequisites
6 | Python 3.6.9
7 |
8 | PyTorch 1.2.0
9 |
10 | Torchvision 0.5.0
11 |
12 |
13 | ## Steps on Runing CORES on CIFAR 10
14 | ### Step 1:
15 |
16 | Download the datset from **http://www.cs.toronto.edu/~kriz/cifar.html** Put the dataset on **data/**
17 |
18 | Install theconf by **pip install git+https://github.com/wbaek/theconf.git**
19 |
20 |
21 | ### Step 2:
22 |
23 | Run CORES (Phase 1: Sample Sieve) on CIFAR-10 with instance 0.6 noise:
24 |
25 | ```
26 | CUDA_VISIBLE_DEVICES=0 python phase1.py --loss cores --dataset cifar10 --model resnet --noise_type instance --noise_rate 0.6
27 | ```
28 | ### Step 3:
29 | Run CORES (Phase 2: Consistency Training) on the CIFAR-10 with instance 0.6 noise:
30 |
31 | ```
32 | cd phase2
33 | CUDA_VISIBLE_DEVICES=0,1 python phase2.py -c confs/resnet34_ins_0.6.yaml --unsupervised
34 | ```
35 | **Both Phase 1 and Phase 2 do not need pre-trained model.**
36 |
37 |
38 | ## Citation
39 |
40 | If you find this code useful, please cite the following paper:
41 |
42 | ```
43 | @article{cheng2020learning,
44 | title={Learning with Instance-Dependent Label Noise: A Sample Sieve Approach},
45 | author={Cheng, Hao and Zhu, Zhaowei and Li, Xingyu and Gong, Yifei and Sun, Xing and Liu, Yang},
46 | journal={arXiv preprint arXiv:2010.02347},
47 | year={2020}
48 | }
49 | ```
50 |
51 |
52 | ## References
53 |
54 | The code of Phase 2 is based on **https://github.com/ildoonet/unsupervised-data-augmentation**
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | from .fbresnet import fbresnet152
3 |
4 | from .cafferesnet import cafferesnet101
5 |
6 | from .bninception import bninception
7 |
8 | from .resnext import resnext101_32x4d
9 | from .resnext import resnext101_64x4d
10 |
11 | from .inceptionv4 import inceptionv4
12 |
13 | from .inceptionresnetv2 import inceptionresnetv2
14 |
15 | from .nasnet import nasnetalarge
16 |
17 | from .nasnet_mobile import nasnetamobile
18 |
19 | from .torchvision_models import alexnet
20 | from .torchvision_models import densenet121
21 | from .torchvision_models import densenet169
22 | from .torchvision_models import densenet201
23 | from .torchvision_models import densenet161
24 | from .torchvision_models import resnet18
25 | from .torchvision_models import resnet34
26 | from .torchvision_models import resnet50
27 | from .torchvision_models import resnet101
28 | from .torchvision_models import resnet152
29 | from .torchvision_models import inceptionv3
30 | from .torchvision_models import squeezenet1_0
31 | from .torchvision_models import squeezenet1_1
32 | from .torchvision_models import vgg11
33 | from .torchvision_models import vgg11_bn
34 | from .torchvision_models import vgg13
35 | from .torchvision_models import vgg13_bn
36 | from .torchvision_models import vgg16
37 | from .torchvision_models import vgg16_bn
38 | from .torchvision_models import vgg19_bn
39 | from .torchvision_models import vgg19
40 |
41 | from .dpn import dpn68
42 | from .dpn import dpn68b
43 | from .dpn import dpn92
44 | from .dpn import dpn98
45 | from .dpn import dpn131
46 | from .dpn import dpn107
47 |
48 | from .xception import xception
49 |
50 | from .senet import senet154
51 | from .senet import se_resnet50
52 | from .senet import se_resnet101
53 | from .senet import se_resnet152
54 | from .senet import se_resnext50_32x4d
55 | from .senet import se_resnext101_32x4d
56 |
57 | from .pnasnet import pnasnet5large
58 | from .polynet import polynet
59 |
--------------------------------------------------------------------------------
/phase2/samplers/stratified_sampler.py:
--------------------------------------------------------------------------------
1 | import random
2 | from collections import defaultdict
3 |
4 | from torch.utils.data import Sampler
5 |
6 |
7 | class StratifiedSampler(Sampler):
8 | def __init__(self, labels):
9 | self.idx_by_lb = defaultdict(list)
10 | for idx, lb in enumerate(labels):
11 | self.idx_by_lb[lb].append(idx)
12 |
13 | self.size = len(labels)
14 |
15 | def __len__(self):
16 | return self.size
17 |
18 | def __iter__(self):
19 | songs_list = []
20 | artists_list = []
21 | for lb, v in self.idx_by_lb.items():
22 | for idx in v:
23 | songs_list.append(idx)
24 | artists_list.append(lb)
25 |
26 | shuffled = spotifyShuffle(songs_list, artists_list)
27 | return iter(shuffled)
28 |
29 |
30 | def fisherYatesShuffle(arr):
31 | """
32 | https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
33 | for i from n−1 downto 1 do
34 | j ← random integer such that 0 ≤ j ≤ i
35 | exchange a[j] and a[i]
36 | """
37 | for i in range(len(arr)-1, 0, -1):
38 | j = random.randint(0, i)
39 | arr[i], arr[j] = arr[j], arr[i]
40 | return arr
41 |
42 |
43 | def spotifyShuffle(songs_list, artists_list):
44 | artist2songs = defaultdict(list)
45 | for artist, song in zip(artists_list, songs_list):
46 | artist2songs[artist].append(song)
47 | songList = []
48 | songsLocs = []
49 | for artist, songs in artist2songs.items():
50 | songs = fisherYatesShuffle(songs)
51 | songList += songs
52 | songsLocs += get_locs(len(songs))
53 | return [songList[idx] for idx in argsort(songsLocs)]
54 |
55 |
56 | def argsort(seq):
57 | return [i for i, j in sorted(enumerate(seq), key=lambda x:x[1])]
58 |
59 |
60 | def get_locs(n):
61 | percent = 1. / n
62 | locs = [percent * random.random()]
63 | last = locs[0]
64 | for i in range(n - 1):
65 | value = last + percent * random.uniform(0.8, 1.2) # 25% : 20~30% = 1 : 0.8x~1.2x
66 | locs.append(value)
67 | last = value
68 | return locs
69 |
--------------------------------------------------------------------------------
/loss.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.nn.functional as F
4 | from torch.autograd import Variable
5 | import numpy as np
6 | import random
7 | import math
8 | # Loss functions
9 |
10 |
11 | def loss_cross_entropy(epoch, y, t,class_list, ind, noise_or_not,loss_all,loss_div_all):
12 | ##Record loss and loss_div for further analysis
13 | loss = F.cross_entropy(y, t, reduce = False)
14 | loss_numpy = loss.data.cpu().numpy()
15 | num_batch = len(loss_numpy)
16 | loss_all[ind,epoch] = loss_numpy
17 | return torch.sum(loss)/num_batch
18 |
19 |
20 |
21 |
22 |
23 | def loss_cores(epoch, y, t,class_list, ind, noise_or_not,loss_all,loss_div_all, noise_prior = None):
24 | beta = f_beta(epoch)
25 | # if epoch == 1:
26 | # print(f'current beta is {beta}')
27 | loss = F.cross_entropy(y, t, reduce = False)
28 | loss_numpy = loss.data.cpu().numpy()
29 | num_batch = len(loss_numpy)
30 | loss_v = np.zeros(num_batch)
31 | loss_div_numpy = float(np.array(0))
32 | loss_ = -torch.log(F.softmax(y) + 1e-8)
33 | # sel metric
34 | loss_sel = loss - torch.mean(loss_,1)
35 | if noise_prior is None:
36 | loss = loss - beta*torch.mean(loss_,1)
37 | else:
38 | loss = loss - beta*torch.sum(torch.mul(noise_prior, loss_),1)
39 |
40 | loss_div_numpy = loss_sel.data.cpu().numpy()
41 | loss_all[ind,epoch] = loss_numpy
42 | loss_div_all[ind,epoch] = loss_div_numpy
43 | for i in range(len(loss_numpy)):
44 | if epoch <=30:
45 | loss_v[i] = 1.0
46 | elif loss_div_numpy[i] <= 0:
47 | loss_v[i] = 1.0
48 | loss_v = loss_v.astype(np.float32)
49 | loss_v_var = Variable(torch.from_numpy(loss_v)).cuda()
50 | loss_ = loss_v_var * loss
51 | if sum(loss_v) == 0.0:
52 | return torch.mean(loss_)/100000000
53 | else:
54 | return torch.sum(loss_)/sum(loss_v), loss_v.astype(int)
55 |
56 | def f_beta(epoch):
57 | beta1 = np.linspace(0.0, 0.0, num=10)
58 | beta2 = np.linspace(0.0, 2, num=30)
59 | beta3 = np.linspace(2, 2, num=60)
60 |
61 | beta = np.concatenate((beta1,beta2,beta3),axis=0)
62 | return beta[epoch]
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/phase2/metrics.py:
--------------------------------------------------------------------------------
1 | import copy
2 |
3 | import torch
4 | from collections import defaultdict
5 |
6 | from torch import nn
7 |
8 |
9 | def accuracy(output, target, topk=(1,)):
10 | """Computes the precision@k for the specified values of k"""
11 | maxk = max(topk)
12 | batch_size = target.size(0)
13 |
14 | _, pred = output.topk(maxk, 1, True, True)
15 | pred = pred.t()
16 | correct = pred.eq(target.view(1, -1).expand_as(pred))
17 |
18 | res = []
19 | for k in topk:
20 | correct_k = correct[:k].view(-1).float().sum(0)
21 | res.append(correct_k.mul_(1. / batch_size))
22 | return res
23 |
24 |
25 | def cross_entropy_smooth(input, target, size_average=True, label_smoothing=0.1):
26 | y = torch.eye(10).cuda()
27 | lb_oh = y[target]
28 |
29 | target = lb_oh * (1 - label_smoothing) + 0.5 * label_smoothing
30 |
31 | logsoftmax = nn.LogSoftmax()
32 | if size_average:
33 | return torch.mean(torch.sum(-target * logsoftmax(input), dim=1))
34 | else:
35 | return torch.sum(torch.sum(-target * logsoftmax(input), dim=1))
36 |
37 |
38 | class Accumulator:
39 | def __init__(self):
40 | self.metrics = defaultdict(lambda: 0.)
41 |
42 | def add(self, key, value):
43 | self.metrics[key] += value
44 |
45 | def add_dict(self, dict):
46 | for key, value in dict.items():
47 | self.add(key, value)
48 |
49 | def __getitem__(self, item):
50 | return self.metrics[item]
51 |
52 | def __setitem__(self, key, value):
53 | self.metrics[key] = value
54 |
55 | def get_dict(self):
56 | return copy.deepcopy(dict(self.metrics))
57 |
58 | def items(self):
59 | return self.metrics.items()
60 |
61 | def __str__(self):
62 | return str(dict(self.metrics))
63 |
64 | def __truediv__(self, other):
65 | newone = Accumulator()
66 | for key, value in self.items():
67 | if isinstance(other, str):
68 | if other != key:
69 | newone[key] = value / self[other]
70 | else:
71 | newone[key] = value
72 | else:
73 | newone[key] = value / other
74 | return newone
75 |
76 |
77 | class SummaryWriterDummy:
78 | def __init__(self, logdir):
79 | pass
80 |
81 | def add_scalar(self, *args, **kwargs):
82 | pass
83 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/__init__.py:
--------------------------------------------------------------------------------
1 | from .version import __version__
2 |
3 | from . import models
4 | from . import datasets
5 |
6 | from .models.utils import pretrained_settings
7 | from .models.utils import model_names
8 |
9 | # to support pretrainedmodels.__dict__['nasnetalarge']
10 | # but depreciated
11 | from .models.fbresnet import fbresnet152
12 | from .models.cafferesnet import cafferesnet101
13 | from .models.bninception import bninception
14 | from .models.resnext import resnext101_32x4d
15 | from .models.resnext import resnext101_64x4d
16 | from .models.inceptionv4 import inceptionv4
17 | from .models.inceptionresnetv2 import inceptionresnetv2
18 | from .models.nasnet import nasnetalarge
19 | from .models.nasnet_mobile import nasnetamobile
20 | from .models.torchvision_models import alexnet
21 | from .models.torchvision_models import densenet121
22 | from .models.torchvision_models import densenet169
23 | from .models.torchvision_models import densenet201
24 | from .models.torchvision_models import densenet161
25 | from .models.torchvision_models import resnet18
26 | from .models.torchvision_models import resnet34
27 | from .models.torchvision_models import resnet50
28 | from .models.torchvision_models import resnet101
29 | from .models.torchvision_models import resnet152
30 | from .models.torchvision_models import inceptionv3
31 | from .models.torchvision_models import squeezenet1_0
32 | from .models.torchvision_models import squeezenet1_1
33 | from .models.torchvision_models import vgg11
34 | from .models.torchvision_models import vgg11_bn
35 | from .models.torchvision_models import vgg13
36 | from .models.torchvision_models import vgg13_bn
37 | from .models.torchvision_models import vgg16
38 | from .models.torchvision_models import vgg16_bn
39 | from .models.torchvision_models import vgg19_bn
40 | from .models.torchvision_models import vgg19
41 | from .models.dpn import dpn68
42 | from .models.dpn import dpn68b
43 | from .models.dpn import dpn92
44 | from .models.dpn import dpn98
45 | from .models.dpn import dpn131
46 | from .models.dpn import dpn107
47 | from .models.xception import xception
48 | from .models.senet import senet154
49 | from .models.senet import se_resnet50
50 | from .models.senet import se_resnet101
51 | from .models.senet import se_resnet152
52 | from .models.senet import se_resnext50_32x4d
53 | from .models.senet import se_resnext101_32x4d
54 | from .models.pnasnet import pnasnet5large
55 | from .models.polynet import polynet
56 |
--------------------------------------------------------------------------------
/data/datasets.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import torchvision.transforms as transforms
3 | from .cifar import CIFAR10, CIFAR100
4 |
5 |
6 |
7 | train_cifar10_transform = transforms.Compose([
8 | transforms.RandomCrop(32, padding=4),
9 | transforms.RandomHorizontalFlip(),
10 | transforms.ToTensor(),
11 | transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
12 | ])
13 |
14 | test_cifar10_transform = transforms.Compose([
15 | transforms.ToTensor(),
16 | transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
17 | ])
18 | train_cifar100_transform = transforms.Compose([
19 | transforms.RandomCrop(32, padding=4),
20 | transforms.RandomHorizontalFlip(),
21 | transforms.ToTensor(),
22 | transforms.Normalize((0.5071, 0.4867, 0.4408), (0.2675, 0.2565, 0.2761)),
23 | ])
24 |
25 | test_cifar100_transform = transforms.Compose([
26 | transforms.ToTensor(),
27 | transforms.Normalize((0.5071, 0.4867, 0.4408), (0.2675, 0.2565, 0.2761)),
28 | ])
29 | def input_dataset(dataset, noise_type, noise_ratio):
30 | if dataset == 'cifar10':
31 | train_dataset = CIFAR10(root='./data/',
32 | download=False,
33 | train=True,
34 | transform = train_cifar10_transform,
35 | noise_type=noise_type,
36 | noise_rate=noise_ratio
37 | )
38 | test_dataset = CIFAR10(root='./data/',
39 | download=False,
40 | train=False,
41 | transform = test_cifar10_transform,
42 | noise_type=noise_type,
43 | noise_rate=noise_ratio
44 | )
45 | num_classes = 10
46 | num_training_samples = 50000
47 | elif dataset == 'cifar100':
48 | train_dataset = CIFAR100(root='./data/',
49 | download=True,
50 | train=True,
51 | transform=train_cifar100_transform,
52 | noise_type=noise_type,
53 | noise_rate=noise_ratio
54 | )
55 | test_dataset = CIFAR100(root='./data/',
56 | download=True,
57 | train=False,
58 | transform=test_cifar100_transform,
59 | noise_type=noise_type,
60 | noise_rate=noise_ratio
61 | )
62 | num_classes = 100
63 | num_training_samples = 50000
64 | return train_dataset, test_dataset, num_classes, num_training_samples
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/models/nine_layer_cnn.py:
--------------------------------------------------------------------------------
1 | import math
2 | import torch
3 | import torch.nn as nn
4 | import torch.nn.init as init
5 | import torch.nn.functional as F
6 | import torch.optim as optim
7 |
8 | def call_bn(bn, x):
9 | return bn(x)
10 |
11 | class CNN(nn.Module):
12 | def __init__(self, input_channel=3, n_outputs=10, dropout_rate=0.25, top_bn=False):
13 | self.dropout_rate = dropout_rate
14 | self.top_bn = top_bn
15 | super(CNN, self).__init__()
16 | self.c1=nn.Conv2d(input_channel,128,kernel_size=3,stride=1, padding=1)
17 | self.c2=nn.Conv2d(128,128,kernel_size=3,stride=1, padding=1)
18 | self.c3=nn.Conv2d(128,128,kernel_size=3,stride=1, padding=1)
19 | self.c4=nn.Conv2d(128,256,kernel_size=3,stride=1, padding=1)
20 | self.c5=nn.Conv2d(256,256,kernel_size=3,stride=1, padding=1)
21 | self.c6=nn.Conv2d(256,256,kernel_size=3,stride=1, padding=1)
22 | self.c7=nn.Conv2d(256,512,kernel_size=3,stride=1, padding=0)
23 | self.c8=nn.Conv2d(512,256,kernel_size=3,stride=1, padding=0)
24 | self.c9=nn.Conv2d(256,128,kernel_size=3,stride=1, padding=0)
25 | self.l_c1=nn.Linear(128,n_outputs)
26 | self.bn1=nn.BatchNorm2d(128)
27 | self.bn2=nn.BatchNorm2d(128)
28 | self.bn3=nn.BatchNorm2d(128)
29 | self.bn4=nn.BatchNorm2d(256)
30 | self.bn5=nn.BatchNorm2d(256)
31 | self.bn6=nn.BatchNorm2d(256)
32 | self.bn7=nn.BatchNorm2d(512)
33 | self.bn8=nn.BatchNorm2d(256)
34 | self.bn9=nn.BatchNorm2d(128)
35 |
36 | def forward(self, x,):
37 | h=x
38 | h=self.c1(h)
39 | h=F.leaky_relu(call_bn(self.bn1, h), negative_slope=0.01)
40 | h=self.c2(h)
41 | h=F.leaky_relu(call_bn(self.bn2, h), negative_slope=0.01)
42 | h=self.c3(h)
43 | h=F.leaky_relu(call_bn(self.bn3, h), negative_slope=0.01)
44 | h=F.max_pool2d(h, kernel_size=2, stride=2)
45 | h=F.dropout2d(h, p=self.dropout_rate)
46 |
47 | h=self.c4(h)
48 | h=F.leaky_relu(call_bn(self.bn4, h), negative_slope=0.01)
49 | h=self.c5(h)
50 | h=F.leaky_relu(call_bn(self.bn5, h), negative_slope=0.01)
51 | h=self.c6(h)
52 | h=F.leaky_relu(call_bn(self.bn6, h), negative_slope=0.01)
53 | h=F.max_pool2d(h, kernel_size=2, stride=2)
54 | h=F.dropout2d(h, p=self.dropout_rate)
55 |
56 | h=self.c7(h)
57 | h=F.leaky_relu(call_bn(self.bn7, h), negative_slope=0.01)
58 | h=self.c8(h)
59 | h=F.leaky_relu(call_bn(self.bn8, h), negative_slope=0.01)
60 | h=self.c9(h)
61 | h=F.leaky_relu(call_bn(self.bn9, h), negative_slope=0.01)
62 | h=F.avg_pool2d(h, kernel_size=h.data.shape[2])
63 |
64 | h = h.view(h.size(0), h.size(1))
65 | logit=self.l_c1(h)
66 | if self.top_bn:
67 | logit=call_bn(self.bn_c1, logit)
68 | return logit
69 |
70 |
71 |
--------------------------------------------------------------------------------
/phase2/warmup_scheduler/scheduler.py:
--------------------------------------------------------------------------------
1 | from torch.optim.lr_scheduler import _LRScheduler
2 | from torch.optim.lr_scheduler import ReduceLROnPlateau
3 |
4 |
5 | class GradualWarmupScheduler(_LRScheduler):
6 | """ Gradually warm-up(increasing) learning rate in optimizer.
7 | Proposed in 'Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour'.
8 |
9 | Args:
10 | optimizer (Optimizer): Wrapped optimizer.
11 | multiplier: target learning rate = base lr * multiplier
12 | total_epoch: target learning rate is reached at total_epoch, gradually
13 | after_scheduler: after target_epoch, use this scheduler(eg. ReduceLROnPlateau)
14 | """
15 |
16 | def __init__(self, optimizer, multiplier, total_epoch, after_scheduler=None):
17 | self.multiplier = multiplier
18 | if self.multiplier <= 1.:
19 | raise ValueError('multiplier should be greater than 1.')
20 | self.total_epoch = total_epoch
21 | self.after_scheduler = after_scheduler
22 | self.finished = False
23 | super().__init__(optimizer)
24 |
25 | def get_lr(self):
26 | if self.last_epoch > self.total_epoch:
27 | if self.after_scheduler:
28 | if not self.finished:
29 | self.after_scheduler.base_lrs = [base_lr * self.multiplier for base_lr in self.base_lrs]
30 | self.finished = True
31 | return self.after_scheduler.get_lr()
32 | return [base_lr * self.multiplier for base_lr in self.base_lrs]
33 |
34 | return [base_lr * ((self.multiplier - 1.) * self.last_epoch / self.total_epoch + 1.) for base_lr in self.base_lrs]
35 |
36 | def step_ReduceLROnPlateau(self, metrics, epoch=None):
37 | if epoch is None:
38 | epoch = self.last_epoch + 1
39 | self.last_epoch = epoch if epoch != 0 else 1 # ReduceLROnPlateau is called at the end of epoch, whereas others are called at beginning
40 | if self.last_epoch <= self.total_epoch:
41 | warmup_lr = [base_lr * ((self.multiplier - 1.) * self.last_epoch / self.total_epoch + 1.) for base_lr in self.base_lrs]
42 | for param_group, lr in zip(self.optimizer.param_groups, warmup_lr):
43 | param_group['lr'] = lr
44 | else:
45 | if epoch is None:
46 | self.after_scheduler.step(metrics, None)
47 | else:
48 | self.after_scheduler.step(metrics, epoch - self.total_epoch)
49 |
50 | def step(self, epoch=None, metrics=None):
51 | if type(self.after_scheduler) != ReduceLROnPlateau:
52 | if self.finished and self.after_scheduler:
53 | if epoch is None:
54 | self.after_scheduler.step(None)
55 | else:
56 | self.after_scheduler.step(epoch - self.total_epoch)
57 | else:
58 | return super(GradualWarmupScheduler, self).step(epoch)
59 | else:
60 | self.step_ReduceLROnPlateau(metrics, epoch)
61 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/wideresnet.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import os
3 | from os.path import expanduser
4 | import hickle as hkl
5 | import torch
6 | import torch.nn.functional as F
7 | from torch.autograd import Variable
8 |
9 | __all__ = ['wideresnet50']
10 |
11 | model_urls = {
12 | 'wideresnet152': 'https://s3.amazonaws.com/pytorch/h5models/wide-resnet-50-2-export.hkl'
13 | }
14 |
15 | def define_model(params):
16 | def conv2d(input, params, base, stride=1, pad=0):
17 | return F.conv2d(input, params[base + '.weight'],
18 | params[base + '.bias'], stride, pad)
19 |
20 | def group(input, params, base, stride, n):
21 | o = input
22 | for i in range(0,n):
23 | b_base = ('%s.block%d.conv') % (base, i)
24 | x = o
25 | o = conv2d(x, params, b_base + '0')
26 | o = F.relu(o)
27 | o = conv2d(o, params, b_base + '1', stride=i==0 and stride or 1, pad=1)
28 | o = F.relu(o)
29 | o = conv2d(o, params, b_base + '2')
30 | if i == 0:
31 | o += conv2d(x, params, b_base + '_dim', stride=stride)
32 | else:
33 | o += x
34 | o = F.relu(o)
35 | return o
36 |
37 | # determine network size by parameters
38 | blocks = [sum([re.match('group%d.block\d+.conv0.weight'%j, k) is not None
39 | for k in params.keys()]) for j in range(4)]
40 |
41 | def f(input, params, pooling_classif=True):
42 | o = F.conv2d(input, params['conv0.weight'], params['conv0.bias'], 2, 3)
43 | o = F.relu(o)
44 | o = F.max_pool2d(o, 3, 2, 1)
45 | o_g0 = group(o, params, 'group0', 1, blocks[0])
46 | o_g1 = group(o_g0, params, 'group1', 2, blocks[1])
47 | o_g2 = group(o_g1, params, 'group2', 2, blocks[2])
48 | o_g3 = group(o_g2, params, 'group3', 2, blocks[3])
49 | if pooling_classif:
50 | o = F.avg_pool2d(o_g3, 7, 1, 0)
51 | o = o.view(o.size(0), -1)
52 | o = F.linear(o, params['fc.weight'], params['fc.bias'])
53 | return o
54 |
55 | return f
56 |
57 |
58 | class WideResNet(nn.Module):
59 |
60 | def __init__(self, pooling):
61 | super(WideResNet, self).__init__()
62 | self.pooling = pooling
63 | self.params = params
64 |
65 | def forward(self, x):
66 | x = f(x, self.params, self.pooling)
67 | return x
68 |
69 |
70 | def wideresnet50(pooling):
71 | dir_models = os.path.join(expanduser("~"), '.torch/wideresnet')
72 | path_hkl = os.path.join(dir_models, 'wideresnet50.hkl')
73 | if os.path.isfile(path_hkl):
74 | params = hkl.load(path_hkl)
75 | # convert numpy arrays to torch Variables
76 | for k,v in sorted(params.items()):
77 | print(k, v.shape)
78 | params[k] = Variable(torch.from_numpy(v), requires_grad=True)
79 | else:
80 | os.system('mkdir -p ' + dir_models)
81 | os.system('wget {} -O {}'.format(model_urls['wideresnet50'], path_hkl))
82 | f = define_model(params)
83 | model = WideResNet(pooling)
84 | return model
85 |
86 |
87 |
--------------------------------------------------------------------------------
/phase2/networks/wideresnet.py:
--------------------------------------------------------------------------------
1 | import torch.nn as nn
2 | import torch.nn.init as init
3 | import torch.nn.functional as F
4 | import numpy as np
5 |
6 |
7 | bn_momentum = 0.9
8 |
9 |
10 | def conv3x3(in_planes, out_planes, stride=1):
11 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias=True)
12 |
13 |
14 | def conv_init(m):
15 | classname = m.__class__.__name__
16 | if classname.find('Conv') != -1:
17 | init.xavier_uniform_(m.weight, gain=np.sqrt(2))
18 | init.constant_(m.bias, 0)
19 | elif classname.find('BatchNorm') != -1:
20 | init.constant_(m.weight, 1)
21 | init.constant_(m.bias, 0)
22 |
23 |
24 | class WideBasic(nn.Module):
25 | def __init__(self, in_planes, planes, dropout_rate, stride=1):
26 | super(WideBasic, self).__init__()
27 | self.bn1 = nn.BatchNorm2d(in_planes, momentum=bn_momentum)
28 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, padding=1, bias=True)
29 | self.dropout = nn.Dropout(p=dropout_rate)
30 | self.bn2 = nn.BatchNorm2d(planes, momentum=bn_momentum)
31 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=True)
32 |
33 | self.shortcut = nn.Sequential()
34 | if stride != 1 or in_planes != planes:
35 | self.shortcut = nn.Sequential(
36 | nn.Conv2d(in_planes, planes, kernel_size=1, stride=stride, bias=True),
37 | )
38 |
39 | def forward(self, x):
40 | out = self.dropout(self.conv1(F.relu(self.bn1(x))))
41 | out = self.conv2(F.relu(self.bn2(out)))
42 | out += self.shortcut(x)
43 |
44 | return out
45 |
46 |
47 | class WideResNet(nn.Module):
48 | def __init__(self, depth, widen_factor, dropout_rate, num_classes):
49 | super(WideResNet, self).__init__()
50 | self.in_planes = 16
51 |
52 | assert ((depth - 4) % 6 == 0), 'Wide-resnet depth should be 6n+4'
53 | n = int((depth - 4) / 6)
54 | k = widen_factor
55 |
56 | nStages = [16, 16*k, 32*k, 64*k]
57 |
58 | self.conv1 = conv3x3(3, nStages[0])
59 | self.layer1 = self._wide_layer(WideBasic, nStages[1], n, dropout_rate, stride=1)
60 | self.layer2 = self._wide_layer(WideBasic, nStages[2], n, dropout_rate, stride=2)
61 | self.layer3 = self._wide_layer(WideBasic, nStages[3], n, dropout_rate, stride=2)
62 | self.bn1 = nn.BatchNorm2d(nStages[3], momentum=bn_momentum)
63 | self.linear = nn.Linear(nStages[3], num_classes)
64 |
65 | # self.apply(conv_init)
66 |
67 | def _wide_layer(self, block, planes, num_blocks, dropout_rate, stride):
68 | strides = [stride] + [1]*(num_blocks-1)
69 | layers = []
70 |
71 | for stride in strides:
72 | layers.append(block(self.in_planes, planes, dropout_rate, stride))
73 | self.in_planes = planes
74 |
75 | return nn.Sequential(*layers)
76 |
77 | def forward(self, x):
78 | out = self.conv1(x)
79 | out = self.layer1(out)
80 | out = self.layer2(out)
81 | out = self.layer3(out)
82 | out = F.relu(self.bn1(out))
83 | # out = F.avg_pool2d(out, 8)
84 | out = F.adaptive_avg_pool2d(out, (1, 1))
85 | out = out.view(out.size(0), -1)
86 | out = self.linear(out)
87 |
88 | return out
89 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/utils.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import math
3 | import torch
4 | import torch.nn as nn
5 | import torchvision.transforms as transforms
6 | from PIL import Image
7 | from munch import munchify
8 |
9 | class ToSpaceBGR(object):
10 |
11 | def __init__(self, is_bgr):
12 | self.is_bgr = is_bgr
13 |
14 | def __call__(self, tensor):
15 | if self.is_bgr:
16 | new_tensor = tensor.clone()
17 | new_tensor[0] = tensor[2]
18 | new_tensor[2] = tensor[0]
19 | tensor = new_tensor
20 | return tensor
21 |
22 |
23 | class ToRange255(object):
24 |
25 | def __init__(self, is_255):
26 | self.is_255 = is_255
27 |
28 | def __call__(self, tensor):
29 | if self.is_255:
30 | tensor.mul_(255)
31 | return tensor
32 |
33 |
34 | class TransformImage(object):
35 |
36 | def __init__(self, opts, scale=0.875, random_crop=False,
37 | random_hflip=False, random_vflip=False,
38 | preserve_aspect_ratio=True):
39 | if type(opts) == dict:
40 | opts = munchify(opts)
41 | self.input_size = opts.input_size
42 | self.input_space = opts.input_space
43 | self.input_range = opts.input_range
44 | self.mean = opts.mean
45 | self.std = opts.std
46 |
47 | # https://github.com/tensorflow/models/blob/master/research/inception/inception/image_processing.py#L294
48 | self.scale = scale
49 | self.random_crop = random_crop
50 | self.random_hflip = random_hflip
51 | self.random_vflip = random_vflip
52 |
53 | tfs = []
54 | if preserve_aspect_ratio:
55 | tfs.append(transforms.Resize(int(math.floor(max(self.input_size)/self.scale))))
56 | else:
57 | height = int(self.input_size[1] / self.scale)
58 | width = int(self.input_size[2] / self.scale)
59 | tfs.append(transforms.Resize((height, width)))
60 |
61 | if random_crop:
62 | tfs.append(transforms.RandomCrop(max(self.input_size)))
63 | else:
64 | tfs.append(transforms.CenterCrop(max(self.input_size)))
65 |
66 | if random_hflip:
67 | tfs.append(transforms.RandomHorizontalFlip())
68 |
69 | if random_vflip:
70 | tfs.append(transforms.RandomVerticalFlip())
71 |
72 | tfs.append(transforms.ToTensor())
73 | tfs.append(ToSpaceBGR(self.input_space=='BGR'))
74 | tfs.append(ToRange255(max(self.input_range)==255))
75 | tfs.append(transforms.Normalize(mean=self.mean, std=self.std))
76 |
77 | self.tf = transforms.Compose(tfs)
78 |
79 | def __call__(self, img):
80 | tensor = self.tf(img)
81 | return tensor
82 |
83 |
84 | class LoadImage(object):
85 |
86 | def __init__(self, space='RGB'):
87 | self.space = space
88 |
89 | def __call__(self, path_img):
90 | with open(path_img, 'rb') as f:
91 | with Image.open(f) as img:
92 | img = img.convert(self.space)
93 | return img
94 |
95 |
96 | class LoadTransformImage(object):
97 |
98 | def __init__(self, model, scale=0.875):
99 | self.load = LoadImage()
100 | self.tf = TransformImage(model, scale=scale)
101 |
102 | def __call__(self, path_img):
103 | img = self.load(path_img)
104 | tensor = self.tf(img)
105 | return tensor
106 |
107 |
108 | class Identity(nn.Module):
109 |
110 | def __init__(self):
111 | super(Identity, self).__init__()
112 |
113 | def forward(self, x):
114 | return x
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/resnext.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import os
3 | import torch
4 | import torch.nn as nn
5 | import torch.utils.model_zoo as model_zoo
6 | from .resnext_features import resnext101_32x4d_features
7 | from .resnext_features import resnext101_64x4d_features
8 |
9 | __all__ = ['ResNeXt101_32x4d', 'resnext101_32x4d',
10 | 'ResNeXt101_64x4d', 'resnext101_64x4d']
11 |
12 | pretrained_settings = {
13 | 'resnext101_32x4d': {
14 | 'imagenet': {
15 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/resnext101_32x4d-29e315fa.pth',
16 | 'input_space': 'RGB',
17 | 'input_size': [3, 224, 224],
18 | 'input_range': [0, 1],
19 | 'mean': [0.485, 0.456, 0.406],
20 | 'std': [0.229, 0.224, 0.225],
21 | 'num_classes': 1000
22 | }
23 | },
24 | 'resnext101_64x4d': {
25 | 'imagenet': {
26 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/resnext101_64x4d-e77a0586.pth',
27 | 'input_space': 'RGB',
28 | 'input_size': [3, 224, 224],
29 | 'input_range': [0, 1],
30 | 'mean': [0.485, 0.456, 0.406],
31 | 'std': [0.229, 0.224, 0.225],
32 | 'num_classes': 1000
33 | }
34 | }
35 | }
36 |
37 | class ResNeXt101_32x4d(nn.Module):
38 |
39 | def __init__(self, num_classes=1000):
40 | super(ResNeXt101_32x4d, self).__init__()
41 | self.num_classes = num_classes
42 | self.features = resnext101_32x4d_features
43 | self.avg_pool = nn.AvgPool2d((7, 7), (1, 1))
44 | self.last_linear = nn.Linear(2048, num_classes)
45 |
46 | def logits(self, input):
47 | x = self.avg_pool(input)
48 | x = x.view(x.size(0), -1)
49 | x = self.last_linear(x)
50 | return x
51 |
52 | def forward(self, input):
53 | x = self.features(input)
54 | x = self.logits(x)
55 | return x
56 |
57 |
58 | class ResNeXt101_64x4d(nn.Module):
59 |
60 | def __init__(self, num_classes=1000):
61 | super(ResNeXt101_64x4d, self).__init__()
62 | self.num_classes = num_classes
63 | self.features = resnext101_64x4d_features
64 | self.avg_pool = nn.AvgPool2d((7, 7), (1, 1))
65 | self.last_linear = nn.Linear(2048, num_classes)
66 |
67 | def logits(self, input):
68 | x = self.avg_pool(input)
69 | x = x.view(x.size(0), -1)
70 | x = self.last_linear(x)
71 | return x
72 |
73 | def forward(self, input):
74 | x = self.features(input)
75 | x = self.logits(x)
76 | return x
77 |
78 |
79 | def resnext101_32x4d(num_classes=1000, pretrained='imagenet'):
80 | model = ResNeXt101_32x4d(num_classes=num_classes)
81 | if pretrained is not None:
82 | settings = pretrained_settings['resnext101_32x4d'][pretrained]
83 | assert num_classes == settings['num_classes'], \
84 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
85 | model.load_state_dict(model_zoo.load_url(settings['url']))
86 | model.input_space = settings['input_space']
87 | model.input_size = settings['input_size']
88 | model.input_range = settings['input_range']
89 | model.mean = settings['mean']
90 | model.std = settings['std']
91 | return model
92 |
93 | def resnext101_64x4d(num_classes=1000, pretrained='imagenet'):
94 | model = ResNeXt101_64x4d(num_classes=num_classes)
95 | if pretrained is not None:
96 | settings = pretrained_settings['resnext101_64x4d'][pretrained]
97 | assert num_classes == settings['num_classes'], \
98 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
99 | model.load_state_dict(model_zoo.load_url(settings['url']))
100 | model.input_space = settings['input_space']
101 | model.input_size = settings['input_size']
102 | model.input_range = settings['input_range']
103 | model.mean = settings['mean']
104 | model.std = settings['std']
105 | return model
106 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/vggm.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import torch
3 | import torch.nn as nn
4 | from torch.autograd import Variable
5 | #from torch.legacy import nn as nnl
6 | import torch.utils.model_zoo as model_zoo
7 |
8 | __all__ = ['vggm']
9 |
10 | pretrained_settings = {
11 | 'vggm': {
12 | 'imagenet': {
13 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/vggm-786f2434.pth',
14 | 'input_space': 'BGR',
15 | 'input_size': [3, 221, 221],
16 | 'input_range': [0, 255],
17 | 'mean': [123.68, 116.779, 103.939],
18 | 'std': [1, 1, 1],
19 | 'num_classes': 1000
20 | }
21 | }
22 | }
23 |
24 | class SpatialCrossMapLRN(nn.Module):
25 | def __init__(self, local_size=1, alpha=1.0, beta=0.75, k=1, ACROSS_CHANNELS=True):
26 | super(SpatialCrossMapLRN, self).__init__()
27 | self.ACROSS_CHANNELS = ACROSS_CHANNELS
28 | if ACROSS_CHANNELS:
29 | self.average=nn.AvgPool3d(kernel_size=(local_size, 1, 1),
30 | stride=1,
31 | padding=(int((local_size-1.0)/2), 0, 0))
32 | else:
33 | self.average=nn.AvgPool2d(kernel_size=local_size,
34 | stride=1,
35 | padding=int((local_size-1.0)/2))
36 | self.alpha = alpha
37 | self.beta = beta
38 | self.k = k
39 |
40 | def forward(self, x):
41 | if self.ACROSS_CHANNELS:
42 | div = x.pow(2).unsqueeze(1)
43 | div = self.average(div).squeeze(1)
44 | div = div.mul(self.alpha).add(self.k).pow(self.beta)
45 | else:
46 | div = x.pow(2)
47 | div = self.average(div)
48 | div = div.mul(self.alpha).add(self.k).pow(self.beta)
49 | x = x.div(div)
50 | return x
51 |
52 | class LambdaBase(nn.Sequential):
53 | def __init__(self, fn, *args):
54 | super(LambdaBase, self).__init__(*args)
55 | self.lambda_func = fn
56 |
57 | def forward_prepare(self, input):
58 | output = []
59 | for module in self._modules.values():
60 | output.append(module(input))
61 | return output if output else input
62 |
63 | class Lambda(LambdaBase):
64 | def forward(self, input):
65 | return self.lambda_func(self.forward_prepare(input))
66 |
67 | class VGGM(nn.Module):
68 |
69 | def __init__(self, num_classes=1000):
70 | super(VGGM, self).__init__()
71 | self.num_classes = num_classes
72 | self.features = nn.Sequential(
73 | nn.Conv2d(3,96,(7, 7),(2, 2)),
74 | nn.ReLU(),
75 | SpatialCrossMapLRN(5, 0.0005, 0.75, 2),
76 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True),
77 | nn.Conv2d(96,256,(5, 5),(2, 2),(1, 1)),
78 | nn.ReLU(),
79 | SpatialCrossMapLRN(5, 0.0005, 0.75, 2),
80 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True),
81 | nn.Conv2d(256,512,(3, 3),(1, 1),(1, 1)),
82 | nn.ReLU(),
83 | nn.Conv2d(512,512,(3, 3),(1, 1),(1, 1)),
84 | nn.ReLU(),
85 | nn.Conv2d(512,512,(3, 3),(1, 1),(1, 1)),
86 | nn.ReLU(),
87 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True)
88 | )
89 | self.classif = nn.Sequential(
90 | nn.Linear(18432,4096),
91 | nn.ReLU(),
92 | nn.Dropout(0.5),
93 | nn.Linear(4096,4096),
94 | nn.ReLU(),
95 | nn.Dropout(0.5),
96 | nn.Linear(4096,num_classes)
97 | )
98 |
99 | def forward(self, x):
100 | x = self.features(x)
101 | x = x.view(x.size(0), -1)
102 | x = self.classif(x)
103 | return x
104 |
105 | def vggm(num_classes=1000, pretrained='imagenet'):
106 | if pretrained:
107 | settings = pretrained_settings['vggm'][pretrained]
108 | assert num_classes == settings['num_classes'], \
109 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
110 |
111 | model = VGGM(num_classes=1000)
112 | model.load_state_dict(model_zoo.load_url(settings['url']))
113 |
114 | model.input_space = settings['input_space']
115 | model.input_size = settings['input_size']
116 | model.input_range = settings['input_range']
117 | model.mean = settings['mean']
118 | model.std = settings['std']
119 | else:
120 | model = VGGM(num_classes=num_classes)
121 | return model
--------------------------------------------------------------------------------
/phase2/networks/preact_resnet.py:
--------------------------------------------------------------------------------
1 | '''Pre-activation ResNet in PyTorch.
2 |
3 | Reference:
4 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
5 | Identity Mappings in Deep Residual Networks. arXiv:1603.05027
6 | '''
7 | import torch
8 | import torch.nn as nn
9 | import torch.nn.functional as F
10 |
11 |
12 | class PreActBlock(nn.Module):
13 | '''Pre-activation version of the BasicBlock.'''
14 | expansion = 1
15 |
16 | def __init__(self, in_planes, planes, stride=1):
17 | super(PreActBlock, self).__init__()
18 | self.bn1 = nn.BatchNorm2d(in_planes)
19 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
20 | self.bn2 = nn.BatchNorm2d(planes)
21 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
22 |
23 | if stride != 1 or in_planes != self.expansion*planes:
24 | self.shortcut = nn.Sequential(
25 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False)
26 | )
27 |
28 | def forward(self, x):
29 | out = F.relu(self.bn1(x))
30 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
31 | out = self.conv1(out)
32 | out = self.conv2(F.relu(self.bn2(out)))
33 | out += shortcut
34 | return out
35 |
36 |
37 | class PreActBottleneck(nn.Module):
38 | '''Pre-activation version of the original Bottleneck module.'''
39 | expansion = 4
40 |
41 | def __init__(self, in_planes, planes, stride=1):
42 | super(PreActBottleneck, self).__init__()
43 | self.bn1 = nn.BatchNorm2d(in_planes)
44 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
45 | self.bn2 = nn.BatchNorm2d(planes)
46 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
47 | self.bn3 = nn.BatchNorm2d(planes)
48 | self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)
49 |
50 | if stride != 1 or in_planes != self.expansion*planes:
51 | self.shortcut = nn.Sequential(
52 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False)
53 | )
54 |
55 | def forward(self, x):
56 | out = F.relu(self.bn1(x))
57 | shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
58 | out = self.conv1(out)
59 | out = self.conv2(F.relu(self.bn2(out)))
60 | out = self.conv3(F.relu(self.bn3(out)))
61 | out += shortcut
62 | return out
63 |
64 |
65 | class PreActResNet(nn.Module):
66 | def __init__(self, block, num_blocks, num_classes=10):
67 | super(PreActResNet, self).__init__()
68 | self.in_planes = 64
69 |
70 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
71 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
72 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
73 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
74 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
75 | self.linear = nn.Linear(512*block.expansion, num_classes)
76 |
77 | def _make_layer(self, block, planes, num_blocks, stride):
78 | strides = [stride] + [1]*(num_blocks-1)
79 | layers = []
80 | for stride in strides:
81 | layers.append(block(self.in_planes, planes, stride))
82 | self.in_planes = planes * block.expansion
83 | return nn.Sequential(*layers)
84 |
85 | def forward(self, x):
86 | out = self.conv1(x)
87 | out = self.layer1(out)
88 | out = self.layer2(out)
89 | out = self.layer3(out)
90 | out = self.layer4(out)
91 | out = F.avg_pool2d(out, 4)
92 | out = out.view(out.size(0), -1)
93 | out = self.linear(out)
94 | return out
95 |
96 |
97 | def PreActResNet18(num_classes):
98 | return PreActResNet(PreActBlock, [2,2,2,2],num_classes=num_classes)
99 |
100 | def PreActResNet34():
101 | return PreActResNet(PreActBlock, [3,4,6,3])
102 |
103 | def PreActResNet50():
104 | return PreActResNet(PreActBottleneck, [3,4,6,3])
105 |
106 | def PreActResNet101():
107 | return PreActResNet(PreActBottleneck, [3,4,23,3])
108 |
109 | def PreActResNet152():
110 | return PreActResNet(PreActBottleneck, [3,8,36,3])
111 |
112 | '''
113 | def test():
114 | net = PreActResNet18()
115 | y = net((torch.randn(1,3,32,32)))
116 | print(y.size())
117 | '''
118 | # test()
119 |
--------------------------------------------------------------------------------
/models/resnet.py:
--------------------------------------------------------------------------------
1 | '''ResNet in PyTorch.
2 |
3 | For Pre-activation ResNet, see 'preact_resnet.py'.
4 |
5 | Reference:
6 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
7 | Deep Residual Learning for Image Recognition. arXiv:1512.03385
8 | '''
9 | import torch
10 | import torch.nn as nn
11 | import torch.nn.functional as F
12 |
13 |
14 | class BasicBlock(nn.Module):
15 | expansion = 1
16 |
17 | def __init__(self, in_planes, planes, stride=1):
18 | super(BasicBlock, self).__init__()
19 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
20 | self.bn1 = nn.BatchNorm2d(planes)
21 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
22 | self.bn2 = nn.BatchNorm2d(planes)
23 |
24 | self.shortcut = nn.Sequential()
25 | if stride != 1 or in_planes != self.expansion*planes:
26 | self.shortcut = nn.Sequential(
27 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
28 | nn.BatchNorm2d(self.expansion*planes)
29 | )
30 |
31 | def forward(self, x):
32 | out = F.relu(self.bn1(self.conv1(x)))
33 | out = self.bn2(self.conv2(out))
34 | out += self.shortcut(x)
35 | out = F.relu(out)
36 | return out
37 |
38 |
39 | class Bottleneck(nn.Module):
40 | expansion = 4
41 |
42 | def __init__(self, in_planes, planes, stride=1):
43 | super(Bottleneck, self).__init__()
44 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
45 | self.bn1 = nn.BatchNorm2d(planes)
46 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
47 | self.bn2 = nn.BatchNorm2d(planes)
48 | self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)
49 | self.bn3 = nn.BatchNorm2d(self.expansion*planes)
50 |
51 | self.shortcut = nn.Sequential()
52 | if stride != 1 or in_planes != self.expansion*planes:
53 | self.shortcut = nn.Sequential(
54 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
55 | nn.BatchNorm2d(self.expansion*planes)
56 | )
57 |
58 | def forward(self, x):
59 | out = F.relu(self.bn1(self.conv1(x)))
60 | out = F.relu(self.bn2(self.conv2(out)))
61 | out = self.bn3(self.conv3(out))
62 | out += self.shortcut(x)
63 | out = F.relu(out)
64 | return out
65 |
66 |
67 | class ResNet(nn.Module):
68 | def __init__(self, block, num_blocks, num_classes=10):
69 | super(ResNet, self).__init__()
70 | self.in_planes = 64
71 |
72 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
73 | self.bn1 = nn.BatchNorm2d(64)
74 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
75 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
76 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
77 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
78 | self.linear = nn.Linear(512*block.expansion, num_classes)
79 |
80 | def _make_layer(self, block, planes, num_blocks, stride):
81 | strides = [stride] + [1]*(num_blocks-1)
82 | layers = []
83 | for stride in strides:
84 | layers.append(block(self.in_planes, planes, stride))
85 | self.in_planes = planes * block.expansion
86 | return nn.Sequential(*layers)
87 |
88 | def forward(self, x):
89 | out = F.relu(self.bn1(self.conv1(x)))
90 | out = self.layer1(out)
91 | out = self.layer2(out)
92 | out = self.layer3(out)
93 | out = self.layer4(out)
94 | out = F.avg_pool2d(out, 4)
95 | out = out.view(out.size(0), -1)
96 | out = self.linear(out)
97 | return out
98 |
99 |
100 | def ResNet18(num_classes):
101 | return ResNet(BasicBlock, [2,2,2,2],num_classes=num_classes)
102 |
103 | def ResNet34(num_classes):
104 | return ResNet(BasicBlock, [3,4,6,3],num_classes=num_classes)
105 |
106 | def ResNet50(num_classes):
107 | return ResNet(Bottleneck, [3,4,6,3],num_classes=num_classes)
108 |
109 | def ResNet101(num_classes):
110 | return ResNet(Bottleneck, [3,4,23,3],num_classes=num_classes)
111 |
112 | def ResNet152(num_classes):
113 | return ResNet(Bottleneck, [3,8,36,3],num_classes=num_classes)
114 |
115 |
116 | def test():
117 | net = ResNet18()
118 | y = net(torch.randn(1,3,32,32))
119 | print(y.size())
120 |
121 | # test()
122 |
--------------------------------------------------------------------------------
/phase2/networks/resnet.py:
--------------------------------------------------------------------------------
1 | '''ResNet in PyTorch.
2 |
3 | For Pre-activation ResNet, see 'preact_resnet.py'.
4 |
5 | Reference:
6 | [1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
7 | Deep Residual Learning for Image Recognition. arXiv:1512.03385
8 | '''
9 | import torch
10 | import torch.nn as nn
11 | import torch.nn.functional as F
12 |
13 |
14 | class BasicBlock(nn.Module):
15 | expansion = 1
16 |
17 | def __init__(self, in_planes, planes, stride=1):
18 | super(BasicBlock, self).__init__()
19 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
20 | self.bn1 = nn.BatchNorm2d(planes)
21 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
22 | self.bn2 = nn.BatchNorm2d(planes)
23 |
24 | self.shortcut = nn.Sequential()
25 | if stride != 1 or in_planes != self.expansion*planes:
26 | self.shortcut = nn.Sequential(
27 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
28 | nn.BatchNorm2d(self.expansion*planes)
29 | )
30 |
31 | def forward(self, x):
32 | out = F.relu(self.bn1(self.conv1(x)))
33 | out = self.bn2(self.conv2(out))
34 | out += self.shortcut(x)
35 | out = F.relu(out)
36 | return out
37 |
38 |
39 | class Bottleneck(nn.Module):
40 | expansion = 4
41 |
42 | def __init__(self, in_planes, planes, stride=1):
43 | super(Bottleneck, self).__init__()
44 | self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
45 | self.bn1 = nn.BatchNorm2d(planes)
46 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
47 | self.bn2 = nn.BatchNorm2d(planes)
48 | self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)
49 | self.bn3 = nn.BatchNorm2d(self.expansion*planes)
50 |
51 | self.shortcut = nn.Sequential()
52 | if stride != 1 or in_planes != self.expansion*planes:
53 | self.shortcut = nn.Sequential(
54 | nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False),
55 | nn.BatchNorm2d(self.expansion*planes)
56 | )
57 |
58 | def forward(self, x):
59 | out = F.relu(self.bn1(self.conv1(x)))
60 | out = F.relu(self.bn2(self.conv2(out)))
61 | out = self.bn3(self.conv3(out))
62 | out += self.shortcut(x)
63 | out = F.relu(out)
64 | return out
65 |
66 |
67 | class ResNet(nn.Module):
68 | def __init__(self, block, num_blocks, num_classes=10):
69 | super(ResNet, self).__init__()
70 | self.in_planes = 64
71 |
72 | self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
73 | self.bn1 = nn.BatchNorm2d(64)
74 | self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
75 | self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
76 | self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
77 | self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
78 | self.linear = nn.Linear(512*block.expansion, num_classes)
79 |
80 | def _make_layer(self, block, planes, num_blocks, stride):
81 | strides = [stride] + [1]*(num_blocks-1)
82 | layers = []
83 | for stride in strides:
84 | layers.append(block(self.in_planes, planes, stride))
85 | self.in_planes = planes * block.expansion
86 | return nn.Sequential(*layers)
87 |
88 | def forward(self, x):
89 | out = F.relu(self.bn1(self.conv1(x)))
90 | out = self.layer1(out)
91 | out = self.layer2(out)
92 | out = self.layer3(out)
93 | out = self.layer4(out)
94 | out = F.avg_pool2d(out, 4)
95 | out = out.view(out.size(0), -1)
96 | out = self.linear(out)
97 | return out
98 |
99 |
100 | def ResNet18(num_classes):
101 | return ResNet(BasicBlock, [2,2,2,2],num_classes=num_classes)
102 |
103 | def ResNet34(num_classes):
104 | return ResNet(BasicBlock, [3,4,6,3],num_classes=num_classes)
105 |
106 | def ResNet50(num_classes):
107 | return ResNet(Bottleneck, [3,4,6,3],num_classes=num_classes)
108 |
109 | def ResNet101(num_classes):
110 | return ResNet(Bottleneck, [3,4,23,3],num_classes=num_classes)
111 |
112 | def ResNet152(num_classes):
113 | return ResNet(Bottleneck, [3,8,36,3],num_classes=num_classes)
114 |
115 |
116 | def test():
117 | net = ResNet18()
118 | y = net(torch.randn(1,3,32,32))
119 | print(y.size())
120 |
121 | # test()
122 |
--------------------------------------------------------------------------------
/phase2/augmentations.py:
--------------------------------------------------------------------------------
1 | # code in this file is adpated from rpmcruz/autoaugment
2 | # https://github.com/rpmcruz/autoaugment/blob/master/transformations.py
3 | import random
4 |
5 | import PIL, PIL.ImageOps, PIL.ImageEnhance, PIL.ImageDraw
6 | import numpy as np
7 |
8 | random_mirror = True
9 |
10 |
11 | def ShearX(img, v): # [-0.3, 0.3]
12 | assert -0.3 <= v <= 0.3
13 | if random_mirror and random.random() > 0.5:
14 | v = -v
15 | return img.transform(img.size, PIL.Image.AFFINE, (1, v, 0, 0, 1, 0))
16 |
17 |
18 | def ShearY(img, v): # [-0.3, 0.3]
19 | assert -0.3 <= v <= 0.3
20 | if random_mirror and random.random() > 0.5:
21 | v = -v
22 | return img.transform(img.size, PIL.Image.AFFINE, (1, 0, 0, v, 1, 0))
23 |
24 |
25 | def TranslateX(img, v): # [-150, 150] => percentage: [-0.45, 0.45]
26 | assert -0.45 <= v <= 0.45
27 | if random_mirror and random.random() > 0.5:
28 | v = -v
29 | v = v * img.size[0]
30 | return img.transform(img.size, PIL.Image.AFFINE, (1, 0, v, 0, 1, 0))
31 |
32 |
33 | def TranslateY(img, v): # [-150, 150] => percentage: [-0.45, 0.45]
34 | assert -0.45 <= v <= 0.45
35 | if random_mirror and random.random() > 0.5:
36 | v = -v
37 | v = v * img.size[1]
38 | return img.transform(img.size, PIL.Image.AFFINE, (1, 0, 0, 0, 1, v))
39 |
40 |
41 | def TranslateXAbs(img, v): # [-150, 150] => percentage: [-0.45, 0.45]
42 | assert 0 <= v <= 10
43 | if random.random() > 0.5:
44 | v = -v
45 | return img.transform(img.size, PIL.Image.AFFINE, (1, 0, v, 0, 1, 0))
46 |
47 |
48 | def TranslateYAbs(img, v): # [-150, 150] => percentage: [-0.45, 0.45]
49 | assert 0 <= v <= 10
50 | if random.random() > 0.5:
51 | v = -v
52 | return img.transform(img.size, PIL.Image.AFFINE, (1, 0, 0, 0, 1, v))
53 |
54 |
55 | def Rotate(img, v): # [-30, 30]
56 | assert -30 <= v <= 30
57 | if random_mirror and random.random() > 0.5:
58 | v = -v
59 | return img.rotate(v)
60 |
61 |
62 | def AutoContrast(img, _):
63 | return PIL.ImageOps.autocontrast(img)
64 |
65 |
66 | def Invert(img, _):
67 | return PIL.ImageOps.invert(img)
68 |
69 |
70 | def Equalize(img, _):
71 | return PIL.ImageOps.equalize(img)
72 |
73 |
74 | def Flip(img, _): # not from the paper
75 | return PIL.ImageOps.mirror(img)
76 |
77 |
78 | def Solarize(img, v): # [0, 256]
79 | assert 0 <= v <= 256
80 | return PIL.ImageOps.solarize(img, v)
81 |
82 |
83 | def Posterize(img, v): # [4, 8]
84 | assert 4 <= v <= 8
85 | v = int(v)
86 | return PIL.ImageOps.posterize(img, v)
87 |
88 |
89 | def Posterize2(img, v): # [0, 4]
90 | assert 0 <= v <= 4
91 | v = int(v)
92 | return PIL.ImageOps.posterize(img, v)
93 |
94 |
95 | def Contrast(img, v): # [0.1,1.9]
96 | assert 0.1 <= v <= 1.9
97 | return PIL.ImageEnhance.Contrast(img).enhance(v)
98 |
99 |
100 | def Color(img, v): # [0.1,1.9]
101 | assert 0.1 <= v <= 1.9
102 | return PIL.ImageEnhance.Color(img).enhance(v)
103 |
104 |
105 | def Brightness(img, v): # [0.1,1.9]
106 | assert 0.1 <= v <= 1.9
107 | return PIL.ImageEnhance.Brightness(img).enhance(v)
108 |
109 |
110 | def Sharpness(img, v): # [0.1,1.9]
111 | assert 0.1 <= v <= 1.9
112 | return PIL.ImageEnhance.Sharpness(img).enhance(v)
113 |
114 |
115 | def Cutout(img, v): # [0, 60] => percentage: [0, 0.2]
116 | assert 0.0 <= v <= 0.2
117 | if v <= 0.:
118 | return img
119 |
120 | v = v * img.size[0]
121 |
122 | return CutoutAbs(img, v)
123 |
124 | # x0 = np.random.uniform(w - v)
125 | # y0 = np.random.uniform(h - v)
126 | # xy = (x0, y0, x0 + v, y0 + v)
127 | # color = (127, 127, 127)
128 | # img = img.copy()
129 | # PIL.ImageDraw.Draw(img).rectangle(xy, color)
130 | # return img
131 |
132 |
133 | def CutoutAbs(img, v): # [0, 60] => percentage: [0, 0.2]
134 | # assert 0 <= v <= 20
135 | if v < 0:
136 | return img
137 | w, h = img.size
138 | x0 = np.random.uniform(w)
139 | y0 = np.random.uniform(h)
140 |
141 | x0 = int(max(0, x0 - v / 2.))
142 | y0 = int(max(0, y0 - v / 2.))
143 | x1 = min(w, x0 + v)
144 | y1 = min(h, y0 + v)
145 |
146 | xy = (x0, y0, x1, y1)
147 | color = (125, 123, 114)
148 | # color = (0, 0, 0)
149 | img = img.copy()
150 | PIL.ImageDraw.Draw(img).rectangle(xy, color)
151 | return img
152 |
153 |
154 | def SamplePairing(imgs): # [0, 0.4]
155 | def f(img1, v):
156 | i = np.random.choice(len(imgs))
157 | img2 = PIL.Image.fromarray(imgs[i])
158 | return PIL.Image.blend(img1, img2, v)
159 |
160 | return f
161 |
162 |
163 | def augment_list(for_autoaug=True): # 16 operations and their ranges
164 | l = [
165 | (ShearX, -0.3, 0.3), # 0
166 | (ShearY, -0.3, 0.3), # 1
167 | (TranslateX, -0.45, 0.45), # 2
168 | (TranslateY, -0.45, 0.45), # 3
169 | (Rotate, -30, 30), # 4
170 | (AutoContrast, 0, 1), # 5
171 | (Invert, 0, 1), # 6
172 | (Equalize, 0, 1), # 7
173 | (Solarize, 0, 256), # 8
174 | (Posterize, 4, 8), # 9
175 | (Contrast, 0.1, 1.9), # 10
176 | (Color, 0.1, 1.9), # 11
177 | (Brightness, 0.1, 1.9), # 12
178 | (Sharpness, 0.1, 1.9), # 13
179 | (Cutout, 0, 0.2), # 14
180 | # (SamplePairing(imgs), 0, 0.4), # 15
181 | ]
182 | if for_autoaug:
183 | l += [
184 | (CutoutAbs, 0, 20), # compatible with auto-augment
185 | (Posterize2, 0, 4), # 9
186 | (TranslateXAbs, 0, 10), # 9
187 | (TranslateYAbs, 0, 10), # 9
188 | ]
189 | return l
190 |
191 |
192 | augment_dict = {fn.__name__: (fn, v1, v2) for fn, v1, v2 in augment_list()}
193 |
194 |
195 | def get_augment(name):
196 | return augment_dict[name]
197 |
198 |
199 | def apply_augment(img, name, level):
200 | augment_fn, low, high = get_augment(name)
201 | return augment_fn(img.copy(), level * (high - low) + low)
202 |
--------------------------------------------------------------------------------
/phase2/utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | import os.path
3 | import copy
4 | import hashlib
5 | import errno
6 | import numpy as np
7 | from numpy.testing import assert_array_almost_equal
8 |
9 |
10 | def check_integrity(fpath, md5):
11 | if not os.path.isfile(fpath):
12 | return False
13 | md5o = hashlib.md5()
14 | with open(fpath, 'rb') as f:
15 | # read in 1MB chunks
16 | for chunk in iter(lambda: f.read(1024 * 1024), b''):
17 | md5o.update(chunk)
18 | md5c = md5o.hexdigest()
19 | if md5c != md5:
20 | return False
21 | return True
22 |
23 |
24 | def download_url(url, root, filename, md5):
25 | from six.moves import urllib
26 |
27 | root = os.path.expanduser(root)
28 | fpath = os.path.join(root, filename)
29 |
30 | try:
31 | os.makedirs(root)
32 | except OSError as e:
33 | if e.errno == errno.EEXIST:
34 | pass
35 | else:
36 | raise
37 |
38 | # downloads file
39 | if os.path.isfile(fpath) and check_integrity(fpath, md5):
40 | print('Using downloaded and verified file: ' + fpath)
41 | else:
42 | try:
43 | print('Downloading ' + url + ' to ' + fpath)
44 | urllib.request.urlretrieve(url, fpath)
45 | except:
46 | if url[:5] == 'https':
47 | url = url.replace('https:', 'http:')
48 | print('Failed download. Trying https -> http instead.'
49 | ' Downloading ' + url + ' to ' + fpath)
50 | urllib.request.urlretrieve(url, fpath)
51 |
52 |
53 | def list_dir(root, prefix=False):
54 | """List all directories at a given root
55 |
56 | Args:
57 | root (str): Path to directory whose folders need to be listed
58 | prefix (bool, optional): If true, prepends the path to each result, otherwise
59 | only returns the name of the directories found
60 | """
61 | root = os.path.expanduser(root)
62 | directories = list(
63 | filter(
64 | lambda p: os.path.isdir(os.path.join(root, p)),
65 | os.listdir(root)
66 | )
67 | )
68 |
69 | if prefix is True:
70 | directories = [os.path.join(root, d) for d in directories]
71 |
72 | return directories
73 |
74 |
75 | def list_files(root, suffix, prefix=False):
76 | """List all files ending with a suffix at a given root
77 |
78 | Args:
79 | root (str): Path to directory whose folders need to be listed
80 | suffix (str or tuple): Suffix of the files to match, e.g. '.png' or ('.jpg', '.png').
81 | It uses the Python "str.endswith" method and is passed directly
82 | prefix (bool, optional): If true, prepends the path to each result, otherwise
83 | only returns the name of the files found
84 | """
85 | root = os.path.expanduser(root)
86 | files = list(
87 | filter(
88 | lambda p: os.path.isfile(os.path.join(root, p)) and p.endswith(suffix),
89 | os.listdir(root)
90 | )
91 | )
92 |
93 | if prefix is True:
94 | files = [os.path.join(root, d) for d in files]
95 |
96 | return files
97 |
98 | # basic function#
99 | def multiclass_noisify(y, P, random_state=0):
100 | """ Flip classes according to transition probability matrix T.
101 | It expects a number between 0 and the number of classes - 1.
102 | """
103 | #print np.max(y), P.shape[0]
104 | assert P.shape[0] == P.shape[1]
105 | assert np.max(y) < P.shape[0]
106 |
107 | # row stochastic matrix
108 | assert_array_almost_equal(P.sum(axis=1), np.ones(P.shape[1]))
109 | assert (P >= 0.0).all()
110 |
111 | m = y.shape[0]
112 | #print m
113 | new_y = y.copy()
114 | flipper = np.random.RandomState(random_state)
115 |
116 | for idx in np.arange(m):
117 | i = y[idx]
118 | # draw a vector with only an 1
119 | flipped = flipper.multinomial(1, P[i, :][0], 1)[0]
120 | new_y[idx] = np.where(flipped == 1)[0]
121 |
122 | return new_y
123 |
124 |
125 | # noisify_pairflip call the function "multiclass_noisify"
126 | def noisify_pairflip(y_train, noise, random_state=None, nb_classes=10):
127 | """mistakes:
128 | flip in the pair
129 | """
130 | P = np.eye(nb_classes)
131 | n = noise
132 |
133 | if n > 0.0:
134 | # 0 -> 1
135 | P[0, 0], P[0, 1] = 1. - n, n
136 | for i in range(1, nb_classes-1):
137 | P[i, i], P[i, i + 1] = 1. - n, n
138 | P[nb_classes-1, nb_classes-1], P[nb_classes-1, 0] = 1. - n, n
139 |
140 | y_train_noisy = multiclass_noisify(y_train, P=P,
141 | random_state=random_state)
142 | actual_noise = (y_train_noisy != y_train).mean()
143 | assert actual_noise > 0.0
144 | print('Actual noise %.2f' % actual_noise)
145 | y_train = y_train_noisy
146 | #print P
147 |
148 | return y_train, actual_noise
149 |
150 | def noisify_multiclass_symmetric(y_train, noise, random_state=None, nb_classes=10):
151 | """mistakes:
152 | flip in the symmetric way
153 | """
154 | P = np.ones((nb_classes, nb_classes))
155 | n = noise
156 | P = (n / (nb_classes - 1)) * P
157 |
158 | if n > 0.0:
159 | # 0 -> 1
160 | P[0, 0] = 1. - n
161 | for i in range(1, nb_classes-1):
162 | P[i, i] = 1. - n
163 | P[nb_classes-1, nb_classes-1] = 1. - n
164 |
165 | y_train_noisy = multiclass_noisify(y_train, P=P,
166 | random_state=random_state)
167 | actual_noise = (y_train_noisy != y_train).mean()
168 | assert actual_noise > 0.0
169 | print('Actual noise %.5f' % actual_noise)
170 | y_train = y_train_noisy
171 | #print P
172 |
173 | return y_train, actual_noise
174 |
175 | def noisify(nb_classes=10, train_labels=None, noise_type=None, noise_rate=0, random_state=0):
176 | if noise_type == 'pairflip':
177 | train_noisy_labels, actual_noise_rate = noisify_pairflip(train_labels, noise_rate, random_state=0, nb_classes=nb_classes)
178 | if noise_type == 'symmetric':
179 | train_noisy_labels, actual_noise_rate = noisify_multiclass_symmetric(train_labels, noise_rate, random_state=0, nb_classes=nb_classes)
180 | return train_noisy_labels, actual_noise_rate
181 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/cafferesnet.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import math
3 | import torch
4 | import torch.nn as nn
5 | import torch.nn.functional as F
6 | import torch.utils.model_zoo as model_zoo
7 |
8 | pretrained_settings = {
9 | 'cafferesnet101': {
10 | 'imagenet': {
11 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/cafferesnet101-9d633cc0.pth',
12 | 'input_space': 'BGR',
13 | 'input_size': [3, 224, 224],
14 | 'input_range': [0, 255],
15 | 'mean': [102.9801, 115.9465, 122.7717],
16 | 'std': [1, 1, 1],
17 | 'num_classes': 1000
18 | }
19 | }
20 | }
21 |
22 |
23 | def conv3x3(in_planes, out_planes, stride=1):
24 | "3x3 convolution with padding"
25 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
26 | padding=1, bias=False)
27 |
28 |
29 | class BasicBlock(nn.Module):
30 | expansion = 1
31 |
32 | def __init__(self, inplanes, planes, stride=1, downsample=None):
33 | super(BasicBlock, self).__init__()
34 | self.conv1 = conv3x3(inplanes, planes, stride)
35 | self.bn1 = nn.BatchNorm2d(planes)
36 | self.relu = nn.ReLU(inplace=True)
37 | self.conv2 = conv3x3(planes, planes)
38 | self.bn2 = nn.BatchNorm2d(planes)
39 | self.downsample = downsample
40 | self.stride = stride
41 |
42 | def forward(self, x):
43 | residual = x
44 |
45 | out = self.conv1(x)
46 | out = self.bn1(out)
47 | out = self.relu(out)
48 |
49 | out = self.conv2(out)
50 | out = self.bn2(out)
51 |
52 | if self.downsample is not None:
53 | residual = self.downsample(x)
54 |
55 | out += residual
56 | out = self.relu(out)
57 |
58 | return out
59 |
60 |
61 | class Bottleneck(nn.Module):
62 | expansion = 4
63 |
64 | def __init__(self, inplanes, planes, stride=1, downsample=None):
65 | super(Bottleneck, self).__init__()
66 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, stride=stride, bias=False) # change
67 | self.bn1 = nn.BatchNorm2d(planes)
68 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, # change
69 | padding=1, bias=False)
70 | self.bn2 = nn.BatchNorm2d(planes)
71 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
72 | self.bn3 = nn.BatchNorm2d(planes * 4)
73 | self.relu = nn.ReLU(inplace=True)
74 | self.downsample = downsample
75 | self.stride = stride
76 |
77 | def forward(self, x):
78 | residual = x
79 |
80 | out = self.conv1(x)
81 | out = self.bn1(out)
82 | out = self.relu(out)
83 |
84 | out = self.conv2(out)
85 | out = self.bn2(out)
86 | out = self.relu(out)
87 |
88 | out = self.conv3(out)
89 | out = self.bn3(out)
90 |
91 | if self.downsample is not None:
92 | residual = self.downsample(x)
93 |
94 | out += residual
95 | out = self.relu(out)
96 |
97 | return out
98 |
99 |
100 | class ResNet(nn.Module):
101 |
102 | def __init__(self, block, layers, num_classes=1000):
103 | self.inplanes = 64
104 | super(ResNet, self).__init__()
105 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
106 | bias=False)
107 | self.bn1 = nn.BatchNorm2d(64)
108 | self.relu = nn.ReLU(inplace=True)
109 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=True) # change
110 | self.layer1 = self._make_layer(block, 64, layers[0])
111 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
112 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
113 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
114 | # it is slightly better whereas slower to set stride = 1
115 | # self.layer4 = self._make_layer(block, 512, layers[3], stride=1)
116 | self.avgpool = nn.AvgPool2d(7)
117 | self.last_linear = nn.Linear(512 * block.expansion, num_classes)
118 |
119 | for m in self.modules():
120 | if isinstance(m, nn.Conv2d):
121 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
122 | m.weight.data.normal_(0, math.sqrt(2. / n))
123 | elif isinstance(m, nn.BatchNorm2d):
124 | m.weight.data.fill_(1)
125 | m.bias.data.zero_()
126 |
127 | def _make_layer(self, block, planes, blocks, stride=1):
128 | downsample = None
129 | if stride != 1 or self.inplanes != planes * block.expansion:
130 | downsample = nn.Sequential(
131 | nn.Conv2d(self.inplanes, planes * block.expansion,
132 | kernel_size=1, stride=stride, bias=False),
133 | nn.BatchNorm2d(planes * block.expansion),
134 | )
135 |
136 | layers = []
137 | layers.append(block(self.inplanes, planes, stride, downsample))
138 | self.inplanes = planes * block.expansion
139 | for i in range(1, blocks):
140 | layers.append(block(self.inplanes, planes))
141 |
142 | return nn.Sequential(*layers)
143 |
144 | def features(self, x):
145 | x = self.conv1(x)
146 | x = self.bn1(x)
147 | x = self.relu(x)
148 | x = self.maxpool(x)
149 |
150 | x = self.layer1(x)
151 | x = self.layer2(x)
152 | x = self.layer3(x)
153 | x = self.layer4(x)
154 | return x
155 |
156 | def logits(self, x):
157 | x = self.avgpool(x)
158 | x = x.view(x.size(0), -1)
159 | x = self.last_linear(x)
160 | return x
161 |
162 | def forward(self, x):
163 | x = self.features(x)
164 | x = self.logits(x)
165 | return x
166 |
167 |
168 | def cafferesnet101(num_classes=1000, pretrained='imagenet'):
169 | """Constructs a ResNet-101 model.
170 | Args:
171 | pretrained (bool): If True, returns a model pre-trained on ImageNet
172 | """
173 | model = ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes)
174 | if pretrained is not None:
175 | settings = pretrained_settings['cafferesnet101'][pretrained]
176 | assert num_classes == settings['num_classes'], \
177 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
178 | model.load_state_dict(model_zoo.load_url(settings['url']))
179 | model.input_space = settings['input_space']
180 | model.input_size = settings['input_size']
181 | model.input_range = settings['input_range']
182 | model.mean = settings['mean']
183 | model.std = settings['std']
184 | return model
--------------------------------------------------------------------------------
/data/utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | import os.path
3 | import copy
4 | import hashlib
5 | import errno
6 | import numpy as np
7 | from numpy.testing import assert_array_almost_equal
8 | import torch
9 | import torch.nn.functional as F
10 |
11 | def check_integrity(fpath, md5):
12 | if not os.path.isfile(fpath):
13 | return False
14 | md5o = hashlib.md5()
15 | with open(fpath, 'rb') as f:
16 | # read in 1MB chunks
17 | for chunk in iter(lambda: f.read(1024 * 1024), b''):
18 | md5o.update(chunk)
19 | md5c = md5o.hexdigest()
20 | if md5c != md5:
21 | return False
22 | return True
23 |
24 |
25 | def download_url(url, root, filename, md5):
26 | from six.moves import urllib
27 |
28 | root = os.path.expanduser(root)
29 | fpath = os.path.join(root, filename)
30 |
31 | try:
32 | os.makedirs(root)
33 | except OSError as e:
34 | if e.errno == errno.EEXIST:
35 | pass
36 | else:
37 | raise
38 |
39 | # downloads file
40 | if os.path.isfile(fpath) and check_integrity(fpath, md5):
41 | print('Using downloaded and verified file: ' + fpath)
42 | else:
43 | try:
44 | print('Downloading ' + url + ' to ' + fpath)
45 | urllib.request.urlretrieve(url, fpath)
46 | except:
47 | if url[:5] == 'https':
48 | url = url.replace('https:', 'http:')
49 | print('Failed download. Trying https -> http instead.'
50 | ' Downloading ' + url + ' to ' + fpath)
51 | urllib.request.urlretrieve(url, fpath)
52 |
53 |
54 | def list_dir(root, prefix=False):
55 | """List all directories at a given root
56 |
57 | Args:
58 | root (str): Path to directory whose folders need to be listed
59 | prefix (bool, optional): If true, prepends the path to each result, otherwise
60 | only returns the name of the directories found
61 | """
62 | root = os.path.expanduser(root)
63 | directories = list(
64 | filter(
65 | lambda p: os.path.isdir(os.path.join(root, p)),
66 | os.listdir(root)
67 | )
68 | )
69 |
70 | if prefix is True:
71 | directories = [os.path.join(root, d) for d in directories]
72 |
73 | return directories
74 |
75 |
76 | def list_files(root, suffix, prefix=False):
77 | """List all files ending with a suffix at a given root
78 |
79 | Args:
80 | root (str): Path to directory whose folders need to be listed
81 | suffix (str or tuple): Suffix of the files to match, e.g. '.png' or ('.jpg', '.png').
82 | It uses the Python "str.endswith" method and is passed directly
83 | prefix (bool, optional): If true, prepends the path to each result, otherwise
84 | only returns the name of the files found
85 | """
86 | root = os.path.expanduser(root)
87 | files = list(
88 | filter(
89 | lambda p: os.path.isfile(os.path.join(root, p)) and p.endswith(suffix),
90 | os.listdir(root)
91 | )
92 | )
93 |
94 | if prefix is True:
95 | files = [os.path.join(root, d) for d in files]
96 |
97 | return files
98 |
99 | # basic function#
100 | def multiclass_noisify(y, P, random_state=0):
101 | """ Flip classes according to transition probability matrix T.
102 | It expects a number between 0 and the number of classes - 1.
103 | """
104 | #print np.max(y), P.shape[0]
105 | assert P.shape[0] == P.shape[1]
106 | assert np.max(y) < P.shape[0]
107 |
108 | # row stochastic matrix
109 | assert_array_almost_equal(P.sum(axis=1), np.ones(P.shape[1]))
110 | assert (P >= 0.0).all()
111 |
112 | m = y.shape[0]
113 | #print m
114 | new_y = y.copy()
115 | flipper = np.random.RandomState(random_state)
116 |
117 | for idx in np.arange(m):
118 | i = y[idx]
119 | # draw a vector with only an 1
120 | flipped = flipper.multinomial(1, P[i, :][0], 1)[0]
121 | new_y[idx] = np.where(flipped == 1)[0]
122 |
123 | return new_y
124 |
125 |
126 | # noisify_pairflip call the function "multiclass_noisify"
127 | def noisify_pairflip(y_train, noise, random_state=None, nb_classes=10):
128 | """mistakes:
129 | flip in the pair
130 | """
131 | P = np.eye(nb_classes)
132 | n = noise
133 |
134 | if n > 0.0:
135 | # 0 -> 1
136 | P[0, 0], P[0, 1] = 1. - n, n
137 | for i in range(1, nb_classes-1):
138 | P[i, i], P[i, i + 1] = 1. - n, n
139 | P[nb_classes-1, nb_classes-1], P[nb_classes-1, 0] = 1. - n, n
140 |
141 | y_train_noisy = multiclass_noisify(y_train, P=P,
142 | random_state=random_state)
143 | actual_noise = (y_train_noisy != y_train).mean()
144 | assert actual_noise > 0.0
145 | print('Actual noise %.2f' % actual_noise)
146 | y_train = y_train_noisy
147 | #print P
148 |
149 | return y_train, actual_noise
150 |
151 | def noisify_multiclass_symmetric(y_train, noise, random_state=None, nb_classes=10):
152 | """mistakes:
153 | flip in the symmetric way
154 | """
155 | P = np.ones((nb_classes, nb_classes))
156 | n = noise
157 | P = (n / (nb_classes - 1)) * P
158 |
159 | if n > 0.0:
160 | # 0 -> 1
161 | P[0, 0] = 1. - n
162 | for i in range(1, nb_classes-1):
163 | P[i, i] = 1. - n
164 | P[nb_classes-1, nb_classes-1] = 1. - n
165 |
166 | y_train_noisy = multiclass_noisify(y_train, P=P,
167 | random_state=random_state)
168 | actual_noise = (y_train_noisy != y_train).mean()
169 | assert actual_noise > 0.0
170 | print('Actual noise %.2f' % actual_noise)
171 | y_train = y_train_noisy
172 | #print P
173 |
174 | return y_train, actual_noise
175 |
176 | def noisify(dataset='mnist', nb_classes=10, train_labels=None, noise_type=None, noise_rate=0, random_state=0):
177 | if noise_type == 'pairflip':
178 | train_noisy_labels, actual_noise_rate = noisify_pairflip(train_labels, noise_rate, random_state=0, nb_classes=nb_classes)
179 | if noise_type == 'symmetric':
180 | train_noisy_labels, actual_noise_rate = noisify_multiclass_symmetric(train_labels, noise_rate, random_state=0, nb_classes=nb_classes)
181 | return train_noisy_labels, actual_noise_rate
182 |
183 |
184 |
185 | def noisify_instance(train_data,train_labels,noise_rate):
186 | if max(train_labels)>10:
187 | num_class = 100
188 | else:
189 | num_class = 10
190 | np.random.seed(0)
191 |
192 | q_ = np.random.normal(loc=noise_rate,scale=0.1,size=1000000)
193 | q = []
194 | for pro in q_:
195 | if 0 < pro < 1:
196 | q.append(pro)
197 | if len(q)==50000:
198 | break
199 |
200 | w = np.random.normal(loc=0,scale=1,size=(32*32*3,num_class))
201 |
202 | noisy_labels = []
203 | for i, sample in enumerate(train_data):
204 | sample = sample.flatten()
205 | p_all = np.matmul(sample,w)
206 | p_all[train_labels[i]] = -1000000
207 | p_all = q[i]* F.softmax(torch.tensor(p_all),dim=0).numpy()
208 | p_all[train_labels[i]] = 1 - q[i]
209 | noisy_labels.append(np.random.choice(np.arange(num_class),p=p_all/sum(p_all)))
210 | over_all_noise_rate = 1 - float(torch.tensor(train_labels).eq(torch.tensor(noisy_labels)).sum())/50000
211 | return noisy_labels, over_all_noise_rate
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/datasets/utils.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import math
3 | from six.moves.urllib.request import urlretrieve
4 |
5 | import torch
6 | from PIL import Image
7 | from tqdm import tqdm
8 |
9 | def load_imagenet_classes(path_synsets='data/imagenet_synsets.txt',
10 | path_classes='data/imagenet_classes.txt'):
11 | with open(path_synsets, 'r') as f:
12 | synsets = f.readlines()
13 |
14 | synsets = [x.strip() for x in synsets]
15 | splits = [line.split(' ') for line in synsets]
16 | key_to_classname = {spl[0]:' '.join(spl[1:]) for spl in splits}
17 |
18 | with open(path_classes, 'r') as f:
19 | class_id_to_key = f.readlines()
20 |
21 | class_id_to_key = [x.strip() for x in class_id_to_key]
22 |
23 | cid_to_cname = []
24 | for i in range(len(class_id_to_key)):
25 | key = class_id_to_key[i]
26 | cname = key_to_classname[key]
27 | cid_to_cname.append(cname)
28 |
29 | return cid_to_cname
30 |
31 |
32 | class Warp(object):
33 | def __init__(self, size, interpolation=Image.BILINEAR):
34 | self.size = int(size)
35 | self.interpolation = interpolation
36 |
37 | def __call__(self, img):
38 | return img.resize((self.size, self.size), self.interpolation)
39 |
40 | def __str__(self):
41 | return self.__class__.__name__ + ' (size={size}, interpolation={interpolation})'.format(size=self.size,
42 | interpolation=self.interpolation)
43 |
44 |
45 | def download_url(url, destination=None, progress_bar=True):
46 | """Download a URL to a local file.
47 |
48 | Parameters
49 | ----------
50 | url : str
51 | The URL to download.
52 | destination : str, None
53 | The destination of the file. If None is given the file is saved to a temporary directory.
54 | progress_bar : bool
55 | Whether to show a command-line progress bar while downloading.
56 |
57 | Returns
58 | -------
59 | filename : str
60 | The location of the downloaded file.
61 |
62 | Notes
63 | -----
64 | Progress bar use/example adapted from tqdm documentation: https://github.com/tqdm/tqdm
65 | """
66 |
67 | def my_hook(t):
68 | last_b = [0]
69 |
70 | def inner(b=1, bsize=1, tsize=None):
71 | if tsize is not None:
72 | t.total = tsize
73 | if b > 0:
74 | t.update((b - last_b[0]) * bsize)
75 | last_b[0] = b
76 |
77 | return inner
78 |
79 | if progress_bar:
80 | with tqdm(unit='B', unit_scale=True, miniters=1, desc=url.split('/')[-1]) as t:
81 | filename, _ = urlretrieve(url, filename=destination, reporthook=my_hook(t))
82 | else:
83 | filename, _ = urlretrieve(url, filename=destination)
84 |
85 |
86 | class AveragePrecisionMeter(object):
87 | """
88 | The APMeter measures the average precision per class.
89 | The APMeter is designed to operate on `NxK` Tensors `output` and
90 | `target`, and optionally a `Nx1` Tensor weight where (1) the `output`
91 | contains model output scores for `N` examples and `K` classes that ought to
92 | be higher when the model is more convinced that the example should be
93 | positively labeled, and smaller when the model believes the example should
94 | be negatively labeled (for instance, the output of a sigmoid function); (2)
95 | the `target` contains only values 0 (for negative examples) and 1
96 | (for positive examples); and (3) the `weight` ( > 0) represents weight for
97 | each sample.
98 | """
99 |
100 | def __init__(self, difficult_examples=False):
101 | super(AveragePrecisionMeter, self).__init__()
102 | self.reset()
103 | self.difficult_examples = difficult_examples
104 |
105 | def reset(self):
106 | """Resets the meter with empty member variables"""
107 | self.scores = torch.FloatTensor(torch.FloatStorage())
108 | self.targets = torch.LongTensor(torch.LongStorage())
109 |
110 | def add(self, output, target):
111 | """
112 | Args:
113 | output (Tensor): NxK tensor that for each of the N examples
114 | indicates the probability of the example belonging to each of
115 | the K classes, according to the model. The probabilities should
116 | sum to one over all classes
117 | target (Tensor): binary NxK tensort that encodes which of the K
118 | classes are associated with the N-th input
119 | (eg: a row [0, 1, 0, 1] indicates that the example is
120 | associated with classes 2 and 4)
121 | weight (optional, Tensor): Nx1 tensor representing the weight for
122 | each example (each weight > 0)
123 | """
124 | if not torch.is_tensor(output):
125 | output = torch.from_numpy(output)
126 | if not torch.is_tensor(target):
127 | target = torch.from_numpy(target)
128 |
129 | if output.dim() == 1:
130 | output = output.view(-1, 1)
131 | else:
132 | assert output.dim() == 2, \
133 | 'wrong output size (should be 1D or 2D with one column \
134 | per class)'
135 | if target.dim() == 1:
136 | target = target.view(-1, 1)
137 | else:
138 | assert target.dim() == 2, \
139 | 'wrong target size (should be 1D or 2D with one column \
140 | per class)'
141 | if self.scores.numel() > 0:
142 | assert target.size(1) == self.targets.size(1), \
143 | 'dimensions for output should match previously added examples.'
144 |
145 | # make sure storage is of sufficient size
146 | if self.scores.storage().size() < self.scores.numel() + output.numel():
147 | new_size = math.ceil(self.scores.storage().size() * 1.5)
148 | self.scores.storage().resize_(int(new_size + output.numel()))
149 | self.targets.storage().resize_(int(new_size + output.numel()))
150 |
151 | # store scores and targets
152 | offset = self.scores.size(0) if self.scores.dim() > 0 else 0
153 | self.scores.resize_(offset + output.size(0), output.size(1))
154 | self.targets.resize_(offset + target.size(0), target.size(1))
155 | self.scores.narrow(0, offset, output.size(0)).copy_(output)
156 | self.targets.narrow(0, offset, target.size(0)).copy_(target)
157 |
158 | def value(self):
159 | """Returns the model's average precision for each class
160 | Return:
161 | ap (FloatTensor): 1xK tensor, with avg precision for each class k
162 | """
163 |
164 | if self.scores.numel() == 0:
165 | return 0
166 | ap = torch.zeros(self.scores.size(1))
167 | rg = torch.arange(1, self.scores.size(0)).float()
168 |
169 | # compute average precision for each class
170 | for k in range(self.scores.size(1)):
171 | # sort scores
172 | scores = self.scores[:, k]
173 | targets = self.targets[:, k]
174 |
175 | # compute average precision
176 | ap[k] = AveragePrecisionMeter.average_precision(scores, targets, self.difficult_examples)
177 | return ap
178 |
179 | @staticmethod
180 | def average_precision(output, target, difficult_examples=True):
181 |
182 | # sort examples
183 | sorted, indices = torch.sort(output, dim=0, descending=True)
184 |
185 | # Computes prec@i
186 | pos_count = 0.
187 | total_count = 0.
188 | precision_at_i = 0.
189 | for i in indices:
190 | label = target[i]
191 | if difficult_examples and label == 0:
192 | continue
193 | if label == 1:
194 | pos_count += 1
195 | total_count += 1
196 | if label == 1:
197 | precision_at_i += pos_count / total_count
198 | precision_at_i /= pos_count
199 | return precision_at_i
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/fbresnet.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import torch.nn as nn
3 | import math
4 | import torch.utils.model_zoo as model_zoo
5 |
6 |
7 | __all__ = ['FBResNet',
8 | #'fbresnet18', 'fbresnet34', 'fbresnet50', 'fbresnet101',
9 | 'fbresnet152']
10 |
11 | pretrained_settings = {
12 | 'fbresnet152': {
13 | 'imagenet': {
14 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/fbresnet152-2e20f6b4.pth',
15 | 'input_space': 'RGB',
16 | 'input_size': [3, 224, 224],
17 | 'input_range': [0, 1],
18 | 'mean': [0.485, 0.456, 0.406],
19 | 'std': [0.229, 0.224, 0.225],
20 | 'num_classes': 1000
21 | }
22 | }
23 | }
24 |
25 |
26 | def conv3x3(in_planes, out_planes, stride=1):
27 | "3x3 convolution with padding"
28 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
29 | padding=1, bias=True)
30 |
31 |
32 | class BasicBlock(nn.Module):
33 | expansion = 1
34 |
35 | def __init__(self, inplanes, planes, stride=1, downsample=None):
36 | super(BasicBlock, self).__init__()
37 | self.conv1 = conv3x3(inplanes, planes, stride)
38 | self.bn1 = nn.BatchNorm2d(planes)
39 | self.relu = nn.ReLU(inplace=True)
40 | self.conv2 = conv3x3(planes, planes)
41 | self.bn2 = nn.BatchNorm2d(planes)
42 | self.downsample = downsample
43 | self.stride = stride
44 |
45 | def forward(self, x):
46 | residual = x
47 |
48 | out = self.conv1(x)
49 | out = self.bn1(out)
50 | out = self.relu(out)
51 |
52 | out = self.conv2(out)
53 | out = self.bn2(out)
54 |
55 | if self.downsample is not None:
56 | residual = self.downsample(x)
57 |
58 | out += residual
59 | out = self.relu(out)
60 |
61 | return out
62 |
63 |
64 | class Bottleneck(nn.Module):
65 | expansion = 4
66 |
67 | def __init__(self, inplanes, planes, stride=1, downsample=None):
68 | super(Bottleneck, self).__init__()
69 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=True)
70 | self.bn1 = nn.BatchNorm2d(planes)
71 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
72 | padding=1, bias=True)
73 | self.bn2 = nn.BatchNorm2d(planes)
74 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=True)
75 | self.bn3 = nn.BatchNorm2d(planes * 4)
76 | self.relu = nn.ReLU(inplace=True)
77 | self.downsample = downsample
78 | self.stride = stride
79 |
80 | def forward(self, x):
81 | residual = x
82 |
83 | out = self.conv1(x)
84 | out = self.bn1(out)
85 | out = self.relu(out)
86 |
87 | out = self.conv2(out)
88 | out = self.bn2(out)
89 | out = self.relu(out)
90 |
91 | out = self.conv3(out)
92 | out = self.bn3(out)
93 |
94 | if self.downsample is not None:
95 | residual = self.downsample(x)
96 |
97 | out += residual
98 | out = self.relu(out)
99 |
100 | return out
101 |
102 | class FBResNet(nn.Module):
103 |
104 | def __init__(self, block, layers, num_classes=1000):
105 | self.inplanes = 64
106 | # Special attributs
107 | self.input_space = None
108 | self.input_size = (299, 299, 3)
109 | self.mean = None
110 | self.std = None
111 | super(FBResNet, self).__init__()
112 | # Modules
113 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
114 | bias=True)
115 | self.bn1 = nn.BatchNorm2d(64)
116 | self.relu = nn.ReLU(inplace=True)
117 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
118 | self.layer1 = self._make_layer(block, 64, layers[0])
119 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
120 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
121 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
122 | self.avgpool = nn.AvgPool2d(7)
123 | self.last_linear = nn.Linear(512 * block.expansion, num_classes)
124 |
125 | for m in self.modules():
126 | if isinstance(m, nn.Conv2d):
127 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
128 | m.weight.data.normal_(0, math.sqrt(2. / n))
129 | elif isinstance(m, nn.BatchNorm2d):
130 | m.weight.data.fill_(1)
131 | m.bias.data.zero_()
132 |
133 | def _make_layer(self, block, planes, blocks, stride=1):
134 | downsample = None
135 | if stride != 1 or self.inplanes != planes * block.expansion:
136 | downsample = nn.Sequential(
137 | nn.Conv2d(self.inplanes, planes * block.expansion,
138 | kernel_size=1, stride=stride, bias=True),
139 | nn.BatchNorm2d(planes * block.expansion),
140 | )
141 |
142 | layers = []
143 | layers.append(block(self.inplanes, planes, stride, downsample))
144 | self.inplanes = planes * block.expansion
145 | for i in range(1, blocks):
146 | layers.append(block(self.inplanes, planes))
147 |
148 | return nn.Sequential(*layers)
149 |
150 | def features(self, input):
151 | x = self.conv1(input)
152 | self.conv1_input = x.clone()
153 | x = self.bn1(x)
154 | x = self.relu(x)
155 | x = self.maxpool(x)
156 |
157 | x = self.layer1(x)
158 | x = self.layer2(x)
159 | x = self.layer3(x)
160 | x = self.layer4(x)
161 | return x
162 |
163 | def logits(self, features):
164 | x = self.avgpool(features)
165 | x = x.view(x.size(0), -1)
166 | x = self.last_linear(x)
167 | return x
168 |
169 | def forward(self, input):
170 | x = self.features(input)
171 | x = self.logits(x)
172 | return x
173 |
174 |
175 | def fbresnet18(num_classes=1000):
176 | """Constructs a ResNet-18 model.
177 |
178 | Args:
179 | pretrained (bool): If True, returns a model pre-trained on ImageNet
180 | """
181 | model = FBResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes)
182 | return model
183 |
184 |
185 | def fbresnet34(num_classes=1000):
186 | """Constructs a ResNet-34 model.
187 |
188 | Args:
189 | pretrained (bool): If True, returns a model pre-trained on ImageNet
190 | """
191 | model = FBResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes)
192 | return model
193 |
194 |
195 | def fbresnet50(num_classes=1000):
196 | """Constructs a ResNet-50 model.
197 |
198 | Args:
199 | pretrained (bool): If True, returns a model pre-trained on ImageNet
200 | """
201 | model = FBResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes)
202 | return model
203 |
204 |
205 | def fbresnet101(num_classes=1000):
206 | """Constructs a ResNet-101 model.
207 |
208 | Args:
209 | pretrained (bool): If True, returns a model pre-trained on ImageNet
210 | """
211 | model = FBResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes)
212 | return model
213 |
214 |
215 | def fbresnet152(num_classes=1000, pretrained='imagenet'):
216 | """Constructs a ResNet-152 model.
217 |
218 | Args:
219 | pretrained (bool): If True, returns a model pre-trained on ImageNet
220 | """
221 | model = FBResNet(Bottleneck, [3, 8, 36, 3], num_classes=num_classes)
222 | if pretrained is not None:
223 | settings = pretrained_settings['fbresnet152'][pretrained]
224 | assert num_classes == settings['num_classes'], \
225 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
226 | model.load_state_dict(model_zoo.load_url(settings['url']))
227 | model.input_space = settings['input_space']
228 | model.input_size = settings['input_size']
229 | model.input_range = settings['input_range']
230 | model.mean = settings['mean']
231 | model.std = settings['std']
232 | return model
233 |
234 |
235 |
--------------------------------------------------------------------------------
/data/mnist.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | import torch.utils.data as data
3 | from PIL import Image
4 | import os
5 | import os.path
6 | import errno
7 | import numpy as np
8 | import torch
9 | import codecs
10 | from .utils import noisify
11 |
12 |
13 | class MNIST(data.Dataset):
14 | """`MNIST `_ Dataset.
15 |
16 | Args:
17 | root (string): Root directory of dataset where ``processed/training.pt``
18 | and ``processed/test.pt`` exist.
19 | train (bool, optional): If True, creates dataset from ``training.pt``,
20 | otherwise from ``test.pt``.
21 | download (bool, optional): If true, downloads the dataset from the internet and
22 | puts it in root directory. If dataset is already downloaded, it is not
23 | downloaded again.
24 | transform (callable, optional): A function/transform that takes in an PIL image
25 | and returns a transformed version. E.g, ``transforms.RandomCrop``
26 | target_transform (callable, optional): A function/transform that takes in the
27 | target and transforms it.
28 | """
29 | urls = [
30 | 'http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz',
31 | 'http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz',
32 | 'http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz',
33 | 'http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz',
34 | ]
35 | raw_folder = 'raw'
36 | processed_folder = 'processed'
37 | training_file = 'training.pt'
38 | test_file = 'test.pt'
39 |
40 | def __init__(self, root, train=True, transform=None, target_transform=None, download=False,
41 | noise_type=None, noise_rate=0.2, random_state=0):
42 | self.root = os.path.expanduser(root)
43 | self.transform = transform
44 | self.target_transform = target_transform
45 | self.train = train # training set or test set
46 | self.dataset='mnist'
47 | self.noise_type=noise_type
48 |
49 | if download:
50 | self.download()
51 |
52 | if not self._check_exists():
53 | raise RuntimeError('Dataset not found.' +
54 | ' You can use download=True to download it')
55 |
56 | if self.train:
57 | self.train_data, self.train_labels = torch.load(
58 | os.path.join(self.root, self.processed_folder, self.training_file))
59 |
60 | if noise_type != 'clean':
61 | self.train_labels=np.asarray([[self.train_labels[i]] for i in range(len(self.train_labels))])
62 | self.train_noisy_labels, self.actual_noise_rate = noisify(dataset=self.dataset, train_labels=self.train_labels, noise_type=noise_type, noise_rate=noise_rate, random_state=random_state)
63 | self.train_noisy_labels=[i[0] for i in self.train_noisy_labels]
64 | _train_labels=[i[0] for i in self.train_labels]
65 | self.noise_or_not = np.transpose(self.train_noisy_labels)==np.transpose(_train_labels)
66 | else:
67 | self.test_data, self.test_labels = torch.load(
68 | os.path.join(self.root, self.processed_folder, self.test_file))
69 |
70 | def __getitem__(self, index):
71 | """
72 | Args:
73 | index (int): Index
74 |
75 | Returns:
76 | tuple: (image, target) where target is index of the target class.
77 | """
78 | if self.train:
79 | #if self.noise_type is not None:
80 | if self.noise_type != 'clean':
81 | img, target = self.train_data[index], self.train_noisy_labels[index]
82 | else:
83 | img, target = self.train_data[index], self.train_labels[index]
84 | else:
85 | img, target = self.test_data[index], self.test_labels[index]
86 |
87 | # doing this so that it is consistent with all other datasets
88 | # to return a PIL Image
89 | img = Image.fromarray(img.numpy(), mode='L')
90 |
91 | if self.transform is not None:
92 | img = self.transform(img)
93 |
94 | if self.target_transform is not None:
95 | target = self.target_transform(target)
96 |
97 | return img, target, index
98 |
99 | def __len__(self):
100 | if self.train:
101 | return len(self.train_data)
102 | else:
103 | return len(self.test_data)
104 |
105 | def _check_exists(self):
106 | return os.path.exists(os.path.join(self.root, self.processed_folder, self.training_file)) and \
107 | os.path.exists(os.path.join(self.root, self.processed_folder, self.test_file))
108 |
109 | def download(self):
110 | """Download the MNIST data if it doesn't exist in processed_folder already."""
111 | from six.moves import urllib
112 | import gzip
113 |
114 | if self._check_exists():
115 | return
116 |
117 | # download files
118 | try:
119 | os.makedirs(os.path.join(self.root, self.raw_folder))
120 | os.makedirs(os.path.join(self.root, self.processed_folder))
121 | except OSError as e:
122 | if e.errno == errno.EEXIST:
123 | pass
124 | else:
125 | raise
126 |
127 | for url in self.urls:
128 | print('Downloading ' + url)
129 | data = urllib.request.urlopen(url)
130 | filename = url.rpartition('/')[2]
131 | file_path = os.path.join(self.root, self.raw_folder, filename)
132 | with open(file_path, 'wb') as f:
133 | f.write(data.read())
134 | with open(file_path.replace('.gz', ''), 'wb') as out_f, \
135 | gzip.GzipFile(file_path) as zip_f:
136 | out_f.write(zip_f.read())
137 | os.unlink(file_path)
138 |
139 | # process and save as torch files
140 | print('Processing...')
141 |
142 | training_set = (
143 | read_image_file(os.path.join(self.root, self.raw_folder, 'train-images-idx3-ubyte')),
144 | read_label_file(os.path.join(self.root, self.raw_folder, 'train-labels-idx1-ubyte'))
145 | )
146 | test_set = (
147 | read_image_file(os.path.join(self.root, self.raw_folder, 't10k-images-idx3-ubyte')),
148 | read_label_file(os.path.join(self.root, self.raw_folder, 't10k-labels-idx1-ubyte'))
149 | )
150 | with open(os.path.join(self.root, self.processed_folder, self.training_file), 'wb') as f:
151 | torch.save(training_set, f)
152 | with open(os.path.join(self.root, self.processed_folder, self.test_file), 'wb') as f:
153 | torch.save(test_set, f)
154 |
155 | print('Done!')
156 |
157 | def __repr__(self):
158 | fmt_str = 'Dataset ' + self.__class__.__name__ + '\n'
159 | fmt_str += ' Number of datapoints: {}\n'.format(self.__len__())
160 | tmp = 'train' if self.train is True else 'test'
161 | fmt_str += ' Split: {}\n'.format(tmp)
162 | fmt_str += ' Root Location: {}\n'.format(self.root)
163 | tmp = ' Transforms (if any): '
164 | fmt_str += '{0}{1}\n'.format(tmp, self.transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
165 | tmp = ' Target Transforms (if any): '
166 | fmt_str += '{0}{1}'.format(tmp, self.target_transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
167 | return fmt_str
168 |
169 |
170 | def get_int(b):
171 | return int(codecs.encode(b, 'hex'), 16)
172 |
173 |
174 | def read_label_file(path):
175 | with open(path, 'rb') as f:
176 | data = f.read()
177 | assert get_int(data[:4]) == 2049
178 | length = get_int(data[4:8])
179 | parsed = np.frombuffer(data, dtype=np.uint8, offset=8)
180 | return torch.from_numpy(parsed).view(length).long()
181 |
182 |
183 | def read_image_file(path):
184 | with open(path, 'rb') as f:
185 | data = f.read()
186 | assert get_int(data[:4]) == 2051
187 | length = get_int(data[4:8])
188 | num_rows = get_int(data[8:12])
189 | num_cols = get_int(data[12:16])
190 | images = []
191 | parsed = np.frombuffer(data, dtype=np.uint8, offset=16)
192 | return torch.from_numpy(parsed).view(length, num_rows, num_cols)
193 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/xception.py:
--------------------------------------------------------------------------------
1 | """
2 | Ported to pytorch thanks to [tstandley](https://github.com/tstandley/Xception-PyTorch)
3 |
4 | @author: tstandley
5 | Adapted by cadene
6 |
7 | Creates an Xception Model as defined in:
8 |
9 | Francois Chollet
10 | Xception: Deep Learning with Depthwise Separable Convolutions
11 | https://arxiv.org/pdf/1610.02357.pdf
12 |
13 | This weights ported from the Keras implementation. Achieves the following performance on the validation set:
14 |
15 | Loss:0.9173 Prec@1:78.892 Prec@5:94.292
16 |
17 | REMEMBER to set your image size to 3x299x299 for both test and validation
18 |
19 | normalize = transforms.Normalize(mean=[0.5, 0.5, 0.5],
20 | std=[0.5, 0.5, 0.5])
21 |
22 | The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299
23 | """
24 | from __future__ import print_function, division, absolute_import
25 | import math
26 | import torch
27 | import torch.nn as nn
28 | import torch.nn.functional as F
29 | import torch.utils.model_zoo as model_zoo
30 | from torch.nn import init
31 |
32 | __all__ = ['xception']
33 |
34 | pretrained_settings = {
35 | 'xception': {
36 | 'imagenet': {
37 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/xception-43020ad28.pth',
38 | 'input_space': 'RGB',
39 | 'input_size': [3, 299, 299],
40 | 'input_range': [0, 1],
41 | 'mean': [0.5, 0.5, 0.5],
42 | 'std': [0.5, 0.5, 0.5],
43 | 'num_classes': 1000,
44 | 'scale': 0.8975 # The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299
45 | }
46 | }
47 | }
48 |
49 |
50 | class SeparableConv2d(nn.Module):
51 | def __init__(self,in_channels,out_channels,kernel_size=1,stride=1,padding=0,dilation=1,bias=False):
52 | super(SeparableConv2d,self).__init__()
53 |
54 | self.conv1 = nn.Conv2d(in_channels,in_channels,kernel_size,stride,padding,dilation,groups=in_channels,bias=bias)
55 | self.pointwise = nn.Conv2d(in_channels,out_channels,1,1,0,1,1,bias=bias)
56 |
57 | def forward(self,x):
58 | x = self.conv1(x)
59 | x = self.pointwise(x)
60 | return x
61 |
62 |
63 | class Block(nn.Module):
64 | def __init__(self,in_filters,out_filters,reps,strides=1,start_with_relu=True,grow_first=True):
65 | super(Block, self).__init__()
66 |
67 | if out_filters != in_filters or strides!=1:
68 | self.skip = nn.Conv2d(in_filters,out_filters,1,stride=strides, bias=False)
69 | self.skipbn = nn.BatchNorm2d(out_filters)
70 | else:
71 | self.skip=None
72 |
73 | self.relu = nn.ReLU(inplace=True)
74 | rep=[]
75 |
76 | filters=in_filters
77 | if grow_first:
78 | rep.append(self.relu)
79 | rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=1,bias=False))
80 | rep.append(nn.BatchNorm2d(out_filters))
81 | filters = out_filters
82 |
83 | for i in range(reps-1):
84 | rep.append(self.relu)
85 | rep.append(SeparableConv2d(filters,filters,3,stride=1,padding=1,bias=False))
86 | rep.append(nn.BatchNorm2d(filters))
87 |
88 | if not grow_first:
89 | rep.append(self.relu)
90 | rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=1,bias=False))
91 | rep.append(nn.BatchNorm2d(out_filters))
92 |
93 | if not start_with_relu:
94 | rep = rep[1:]
95 | else:
96 | rep[0] = nn.ReLU(inplace=False)
97 |
98 | if strides != 1:
99 | rep.append(nn.MaxPool2d(3,strides,1))
100 | self.rep = nn.Sequential(*rep)
101 |
102 | def forward(self,inp):
103 | x = self.rep(inp)
104 |
105 | if self.skip is not None:
106 | skip = self.skip(inp)
107 | skip = self.skipbn(skip)
108 | else:
109 | skip = inp
110 |
111 | x+=skip
112 | return x
113 |
114 |
115 | class Xception(nn.Module):
116 | """
117 | Xception optimized for the ImageNet dataset, as specified in
118 | https://arxiv.org/pdf/1610.02357.pdf
119 | """
120 | def __init__(self, num_classes=1000):
121 | """ Constructor
122 | Args:
123 | num_classes: number of classes
124 | """
125 | super(Xception, self).__init__()
126 | self.num_classes = num_classes
127 |
128 | self.conv1 = nn.Conv2d(3, 32, 3,2, 0, bias=False)
129 | self.bn1 = nn.BatchNorm2d(32)
130 | self.relu = nn.ReLU(inplace=True)
131 |
132 | self.conv2 = nn.Conv2d(32,64,3,bias=False)
133 | self.bn2 = nn.BatchNorm2d(64)
134 | #do relu here
135 |
136 | self.block1=Block(64,128,2,2,start_with_relu=False,grow_first=True)
137 | self.block2=Block(128,256,2,2,start_with_relu=True,grow_first=True)
138 | self.block3=Block(256,728,2,2,start_with_relu=True,grow_first=True)
139 |
140 | self.block4=Block(728,728,3,1,start_with_relu=True,grow_first=True)
141 | self.block5=Block(728,728,3,1,start_with_relu=True,grow_first=True)
142 | self.block6=Block(728,728,3,1,start_with_relu=True,grow_first=True)
143 | self.block7=Block(728,728,3,1,start_with_relu=True,grow_first=True)
144 |
145 | self.block8=Block(728,728,3,1,start_with_relu=True,grow_first=True)
146 | self.block9=Block(728,728,3,1,start_with_relu=True,grow_first=True)
147 | self.block10=Block(728,728,3,1,start_with_relu=True,grow_first=True)
148 | self.block11=Block(728,728,3,1,start_with_relu=True,grow_first=True)
149 |
150 | self.block12=Block(728,1024,2,2,start_with_relu=True,grow_first=False)
151 |
152 | self.conv3 = SeparableConv2d(1024,1536,3,1,1)
153 | self.bn3 = nn.BatchNorm2d(1536)
154 |
155 | #do relu here
156 | self.conv4 = SeparableConv2d(1536,2048,3,1,1)
157 | self.bn4 = nn.BatchNorm2d(2048)
158 |
159 | self.fc = nn.Linear(2048, num_classes)
160 |
161 | # #------- init weights --------
162 | # for m in self.modules():
163 | # if isinstance(m, nn.Conv2d):
164 | # n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
165 | # m.weight.data.normal_(0, math.sqrt(2. / n))
166 | # elif isinstance(m, nn.BatchNorm2d):
167 | # m.weight.data.fill_(1)
168 | # m.bias.data.zero_()
169 | # #-----------------------------
170 |
171 | def features(self, input):
172 | x = self.conv1(input)
173 | x = self.bn1(x)
174 | x = self.relu(x)
175 |
176 | x = self.conv2(x)
177 | x = self.bn2(x)
178 | x = self.relu(x)
179 |
180 | x = self.block1(x)
181 | x = self.block2(x)
182 | x = self.block3(x)
183 | x = self.block4(x)
184 | x = self.block5(x)
185 | x = self.block6(x)
186 | x = self.block7(x)
187 | x = self.block8(x)
188 | x = self.block9(x)
189 | x = self.block10(x)
190 | x = self.block11(x)
191 | x = self.block12(x)
192 |
193 | x = self.conv3(x)
194 | x = self.bn3(x)
195 | x = self.relu(x)
196 |
197 | x = self.conv4(x)
198 | x = self.bn4(x)
199 | return x
200 |
201 | def logits(self, features):
202 | x = self.relu(features)
203 |
204 | x = F.adaptive_avg_pool2d(x, (1, 1))
205 | x = x.view(x.size(0), -1)
206 | x = self.last_linear(x)
207 | return x
208 |
209 | def forward(self, input):
210 | x = self.features(input)
211 | x = self.logits(x)
212 | return x
213 |
214 |
215 | def xception(num_classes=1000, pretrained='imagenet'):
216 | model = Xception(num_classes=num_classes)
217 | if pretrained:
218 | settings = pretrained_settings['xception'][pretrained]
219 | assert num_classes == settings['num_classes'], \
220 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
221 |
222 | model = Xception(num_classes=num_classes)
223 | model.load_state_dict(model_zoo.load_url(settings['url']))
224 |
225 | model.input_space = settings['input_space']
226 | model.input_size = settings['input_size']
227 | model.input_range = settings['input_range']
228 | model.mean = settings['mean']
229 | model.std = settings['std']
230 |
231 | # TODO: ugly
232 | model.last_linear = model.fc
233 | del model.fc
234 | return model
235 |
--------------------------------------------------------------------------------
/phase2/data.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | import copy
4 | import numpy as np
5 | import torch
6 | import torchvision
7 | from PIL import Image
8 |
9 | from torch.utils.data import SubsetRandomSampler, Subset, Dataset
10 | from torchvision.transforms import transforms
11 | from sklearn.model_selection import StratifiedShuffleSplit
12 | from theconf import Config as C
13 |
14 | from archive import autoaug_policy, autoaug_paper_cifar10, fa_reduced_cifar10
15 | from augmentations import *
16 | from common import get_logger
17 | from samplers.stratified_sampler import StratifiedSampler
18 | from utils import noisify
19 |
20 | logger = get_logger('Unsupervised Data Augmentation')
21 | logger.setLevel(logging.INFO)
22 |
23 | class MyCIFAR10(torchvision.datasets.CIFAR10):
24 | def __getitem__(self, index):
25 | """
26 | Args:
27 | index (int): Index
28 |
29 | Returns:
30 | tuple: (image, target) where target is index of the target class.
31 | """
32 |
33 | img, target = self.data[index], self.targets[index]
34 |
35 | # doing this so that it is consistent with all other datasets
36 | # to return a PIL Image
37 | img = Image.fromarray(img)
38 |
39 | if self.transform is not None:
40 | img = self.transform(img)
41 |
42 | if self.target_transform is not None:
43 | target = self.target_transform(target)
44 |
45 | return img, target, index
46 |
47 |
48 |
49 | def get_dataloaders(dataset, batch, batch_unsup, dataroot, with_noise=True, random_state=0, unsup_idx=set()):
50 | if 'cifar' in dataset:
51 | transform_train = transforms.Compose([
52 | transforms.RandomCrop(32, padding=4),
53 | transforms.RandomHorizontalFlip(),
54 | transforms.ToTensor(),
55 | transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
56 | ])
57 | transform_valid = transforms.Compose([
58 | transforms.RandomCrop(32, padding=4),
59 | transforms.RandomHorizontalFlip(),
60 | transforms.ToTensor(),
61 | transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
62 | ])
63 | transform_test = transforms.Compose([
64 | transforms.ToTensor(),
65 | transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
66 | ])
67 | else:
68 | raise ValueError('dataset=%s' % dataset)
69 |
70 | autoaug = transforms.Compose([])
71 | if isinstance(C.get()['aug'], list):
72 | logger.debug('augmentation provided.')
73 | autoaug.transforms.insert(0, Augmentation(C.get()['aug']))
74 | else:
75 | logger.debug('augmentation: %s' % C.get()['aug'])
76 | if C.get()['aug'] == 'fa_reduced_cifar10':
77 | autoaug.transforms.insert(0, Augmentation(fa_reduced_cifar10()))
78 | elif C.get()['aug'] == 'autoaug_cifar10':
79 | autoaug.transforms.insert(0, Augmentation(autoaug_paper_cifar10()))
80 | elif C.get()['aug'] == 'autoaug_extend':
81 | autoaug.transforms.insert(0, Augmentation(autoaug_policy()))
82 | elif C.get()['aug'] == 'default':
83 | pass
84 | else:
85 | raise ValueError('not found augmentations. %s' % C.get()['aug'])
86 | transform_train.transforms.insert(0, autoaug)
87 |
88 | if C.get()['cutout'] > 0:
89 | transform_train.transforms.append(CutoutDefault(C.get()['cutout']))
90 |
91 | if dataset in ['cifar10', 'cifar100']:
92 | if dataset == 'cifar10':
93 | total_trainset = torchvision.datasets.CIFAR10(root=dataroot, train=True, download=True, transform=transform_train)
94 | unsup_trainset = torchvision.datasets.CIFAR10(root=dataroot, train=True, download=True, transform=None)
95 | testset = torchvision.datasets.CIFAR10(root=dataroot, train=False, download=True, transform=transform_test)
96 | #nb_classes = 10
97 | elif dataset == 'cifar100':
98 | total_trainset = torchvision.datasets.CIFAR100(root=dataroot, train=True, download=True, transform=transform_train)
99 | unsup_trainset = torchvision.datasets.CIFAR100(root=dataroot, train=True, download=True, transform=None)
100 | testset = torchvision.datasets.CIFAR100(root=dataroot, train=False, download=True, transform=transform_test)
101 | #nb_classes = 100
102 | else:
103 | raise ValueError
104 | print('DEBUG:', len(total_trainset.targets))
105 |
106 | if not with_noise:
107 | sss = StratifiedShuffleSplit(n_splits=1, test_size=46000, random_state=0) # 4000 trainset
108 | sss = sss.split(list(range(len(total_trainset))), total_trainset.targets)
109 | train_idx, valid_idx = next(sss)
110 | #train_labels = [total_trainset.targets[idx] for idx in train_idx]
111 |
112 | trainset = Subset(total_trainset, train_idx) # for supervised
113 | #trainset.targets = train_labels #THIS DOES NOTHING
114 |
115 | otherset = Subset(unsup_trainset, valid_idx) # for unsupervised
116 | # otherset = unsup_trainset
117 | otherset = UnsupervisedDataset(otherset, transform_valid, autoaug, cutout=C.get()['cutout'])
118 | else:
119 | #import ipdb
120 | #ipdb.set_trace()
121 |
122 | #print('Noisy data config: noise_rate={}, noise_type={}'.format(noise_rate, noise_type))
123 | print('unsup_idx:', len(unsup_idx))
124 |
125 | all_idx = list(range(len(total_trainset)))
126 | sup_idx = [idx for idx in all_idx if idx not in unsup_idx]
127 | print('sup_idx: ', len(sup_idx))
128 |
129 | #apply noise to supervised trainset
130 | train_labels_with_noise = np.load(C.get()['train_labels']).reshape(-1)
131 | noisy_trainset = copy.deepcopy(total_trainset)
132 | noisy_trainset.targets = train_labels_with_noise
133 |
134 | train_labels_clean = np.array(total_trainset.targets)
135 | sup_labels_clean = np.array([train_labels_clean[idx] for idx in sup_idx]) #for estimating actual noise rate
136 |
137 | est_noise = len(np.where(train_labels_clean!=train_labels_with_noise)[0])
138 | print('noise labels total: ', est_noise)
139 | print('estimated noise rate: ', est_noise / len(train_labels_clean))
140 |
141 | trainset = Subset(noisy_trainset, sup_idx)
142 | otherset = Subset(unsup_trainset, unsup_idx)
143 |
144 | sup_labels_with_noise = [trainset.dataset.targets[idx] for idx in sup_idx]
145 | est_noise = len(np.where(sup_labels_clean != np.array(sup_labels_with_noise))[0])
146 | print('noise labels in sup. data: ', est_noise)
147 | print('sup. data noise rate: ', est_noise / len(sup_labels_clean))
148 |
149 | trainset.targets = sup_labels_with_noise #only for sampler
150 | otherset = UnsupervisedDataset(otherset, transform_valid, autoaug, cutout=C.get()['cutout'])
151 | else:
152 | raise ValueError('invalid dataset name=%s' % dataset)
153 |
154 | trainloader = torch.utils.data.DataLoader(
155 | trainset, batch_size=batch, shuffle=False, num_workers=8, pin_memory=False,
156 | sampler=StratifiedSampler(trainset.targets), drop_last=True)
157 |
158 | unsuploader = torch.utils.data.DataLoader(
159 | otherset, batch_size=batch_unsup, shuffle=True, num_workers=8, pin_memory=False,
160 | sampler=None, drop_last=True)
161 |
162 | testloader = torch.utils.data.DataLoader(
163 | testset, batch_size=batch, shuffle=False, num_workers=32, pin_memory=False,
164 | drop_last=False
165 | )
166 | return trainloader, unsuploader, testloader
167 |
168 |
169 | class CutoutDefault(object):
170 | """
171 | Reference : https://github.com/quark0/darts/blob/master/cnn/utils.py
172 | """
173 | def __init__(self, length):
174 | self.length = length
175 |
176 | def __call__(self, img):
177 | if self.length <= 0:
178 | return img
179 | h, w = img.size(1), img.size(2)
180 | mask = np.ones((h, w), np.float32)
181 | y = np.random.randint(h)
182 | x = np.random.randint(w)
183 |
184 | y1 = np.clip(y - self.length // 2, 0, h)
185 | y2 = np.clip(y + self.length // 2, 0, h)
186 | x1 = np.clip(x - self.length // 2, 0, w)
187 | x2 = np.clip(x + self.length // 2, 0, w)
188 |
189 | mask[y1: y2, x1: x2] = 0.
190 | mask = torch.from_numpy(mask)
191 | mask = mask.expand_as(img)
192 | img *= mask
193 | return img
194 |
195 |
196 | class Augmentation(object):
197 | def __init__(self, policies):
198 | self.policies = policies
199 |
200 | def __call__(self, img):
201 | for _ in range(1):
202 | policy = random.choice(self.policies)
203 | for name, pr, level in policy:
204 | if random.random() > pr:
205 | continue
206 | img = apply_augment(img, name, level)
207 | return img
208 |
209 |
210 | class UnsupervisedDataset(Dataset):
211 | def __init__(self, dataset, transform_default, transform_aug, cutout=0):
212 | self.dataset = dataset
213 | self.transform_default = transform_default
214 | self.transform_aug = transform_aug
215 | self.transform_cutout = CutoutDefault(cutout) # issue 4 : https://github.com/ildoonet/unsupervised-data-augmentation/issues/4
216 |
217 | def __getitem__(self, index):
218 | img, _ = self.dataset[index]
219 |
220 | img1 = self.transform_default(img)
221 | img2 = self.transform_default(self.transform_aug(img))
222 | img2 = self.transform_cutout(img2)
223 |
224 | return img1, img2
225 |
226 | def __len__(self):
227 | return len(self.dataset)
228 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/datasets/voc.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import csv
3 | import os
4 | import os.path
5 | import tarfile
6 | from six.moves.urllib.parse import urlparse
7 |
8 | import numpy as np
9 | import torch
10 | import torch.utils.data as data
11 | from PIL import Image
12 |
13 | from . import utils
14 |
15 | object_categories = ['aeroplane', 'bicycle', 'bird', 'boat',
16 | 'bottle', 'bus', 'car', 'cat', 'chair',
17 | 'cow', 'diningtable', 'dog', 'horse',
18 | 'motorbike', 'person', 'pottedplant',
19 | 'sheep', 'sofa', 'train', 'tvmonitor']
20 |
21 | urls = {
22 | 'devkit': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCdevkit_18-May-2011.tar',
23 | 'trainval_2007': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar',
24 | 'test_images_2007': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar',
25 | 'test_anno_2007': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtestnoimgs_06-Nov-2007.tar',
26 | }
27 |
28 |
29 | def read_image_label(file):
30 | print('[dataset] read ' + file)
31 | data = dict()
32 | with open(file, 'r') as f:
33 | for line in f:
34 | tmp = line.split(' ')
35 | name = tmp[0]
36 | label = int(tmp[-1])
37 | data[name] = label
38 | # data.append([name, label])
39 | # print('%s %d' % (name, label))
40 | return data
41 |
42 |
43 | def read_object_labels(root, dataset, set):
44 | path_labels = os.path.join(root, 'VOCdevkit', dataset, 'ImageSets', 'Main')
45 | labeled_data = dict()
46 | num_classes = len(object_categories)
47 |
48 | for i in range(num_classes):
49 | file = os.path.join(path_labels, object_categories[i] + '_' + set + '.txt')
50 | data = read_image_label(file)
51 |
52 | if i == 0:
53 | for (name, label) in data.items():
54 | labels = np.zeros(num_classes)
55 | labels[i] = label
56 | labeled_data[name] = labels
57 | else:
58 | for (name, label) in data.items():
59 | labeled_data[name][i] = label
60 |
61 | return labeled_data
62 |
63 |
64 | def write_object_labels_csv(file, labeled_data):
65 | # write a csv file
66 | print('[dataset] write file %s' % file)
67 | with open(file, 'w') as csvfile:
68 | fieldnames = ['name']
69 | fieldnames.extend(object_categories)
70 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
71 |
72 | writer.writeheader()
73 | for (name, labels) in labeled_data.items():
74 | example = {'name': name}
75 | for i in range(20):
76 | example[fieldnames[i + 1]] = int(labels[i])
77 | writer.writerow(example)
78 |
79 | csvfile.close()
80 |
81 |
82 | def read_object_labels_csv(file, header=True):
83 | images = []
84 | num_categories = 0
85 | print('[dataset] read', file)
86 | with open(file, 'r') as f:
87 | reader = csv.reader(f)
88 | rownum = 0
89 | for row in reader:
90 | if header and rownum == 0:
91 | header = row
92 | else:
93 | if num_categories == 0:
94 | num_categories = len(row) - 1
95 | name = row[0]
96 | labels = (np.asarray(row[1:num_categories + 1])).astype(np.float32)
97 | labels = torch.from_numpy(labels)
98 | item = (name, labels)
99 | images.append(item)
100 | rownum += 1
101 | return images
102 |
103 |
104 | def find_images_classification(root, dataset, set):
105 | path_labels = os.path.join(root, 'VOCdevkit', dataset, 'ImageSets', 'Main')
106 | images = []
107 | file = os.path.join(path_labels, set + '.txt')
108 | with open(file, 'r') as f:
109 | for line in f:
110 | images.append(line)
111 | return images
112 |
113 |
114 | def download_voc2007(root):
115 | path_devkit = os.path.join(root, 'VOCdevkit')
116 | path_images = os.path.join(root, 'VOCdevkit', 'VOC2007', 'JPEGImages')
117 | tmpdir = os.path.join(root, 'tmp')
118 |
119 | # create directory
120 | if not os.path.exists(root):
121 | os.makedirs(root)
122 |
123 | if not os.path.exists(path_devkit):
124 |
125 | if not os.path.exists(tmpdir):
126 | os.makedirs(tmpdir)
127 |
128 | parts = urlparse(urls['devkit'])
129 | filename = os.path.basename(parts.path)
130 | cached_file = os.path.join(tmpdir, filename)
131 |
132 | if not os.path.exists(cached_file):
133 | print('Downloading: "{}" to {}\n'.format(urls['devkit'], cached_file))
134 | utils.download_url(urls['devkit'], cached_file)
135 |
136 | # extract file
137 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root))
138 | cwd = os.getcwd()
139 | tar = tarfile.open(cached_file, "r")
140 | os.chdir(root)
141 | tar.extractall()
142 | tar.close()
143 | os.chdir(cwd)
144 | print('[dataset] Done!')
145 |
146 | # train/val images/annotations
147 | if not os.path.exists(path_images):
148 |
149 | # download train/val images/annotations
150 | parts = urlparse(urls['trainval_2007'])
151 | filename = os.path.basename(parts.path)
152 | cached_file = os.path.join(tmpdir, filename)
153 |
154 | if not os.path.exists(cached_file):
155 | print('Downloading: "{}" to {}\n'.format(urls['trainval_2007'], cached_file))
156 | utils.download_url(urls['trainval_2007'], cached_file)
157 |
158 | # extract file
159 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root))
160 | cwd = os.getcwd()
161 | tar = tarfile.open(cached_file, "r")
162 | os.chdir(root)
163 | tar.extractall()
164 | tar.close()
165 | os.chdir(cwd)
166 | print('[dataset] Done!')
167 |
168 | # test annotations
169 | test_anno = os.path.join(path_devkit, 'VOC2007/ImageSets/Main/aeroplane_test.txt')
170 | if not os.path.exists(test_anno):
171 |
172 | # download test annotations
173 | parts = urlparse(urls['test_images_2007'])
174 | filename = os.path.basename(parts.path)
175 | cached_file = os.path.join(tmpdir, filename)
176 |
177 | if not os.path.exists(cached_file):
178 | print('Downloading: "{}" to {}\n'.format(urls['test_images_2007'], cached_file))
179 | utils.download_url(urls['test_images_2007'], cached_file)
180 |
181 | # extract file
182 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root))
183 | cwd = os.getcwd()
184 | tar = tarfile.open(cached_file, "r")
185 | os.chdir(root)
186 | tar.extractall()
187 | tar.close()
188 | os.chdir(cwd)
189 | print('[dataset] Done!')
190 |
191 | # test images
192 | test_image = os.path.join(path_devkit, 'VOC2007/JPEGImages/000001.jpg')
193 | if not os.path.exists(test_image):
194 |
195 | # download test images
196 | parts = urlparse(urls['test_anno_2007'])
197 | filename = os.path.basename(parts.path)
198 | cached_file = os.path.join(tmpdir, filename)
199 |
200 | if not os.path.exists(cached_file):
201 | print('Downloading: "{}" to {}\n'.format(urls['test_anno_2007'], cached_file))
202 | utils.download_url(urls['test_anno_2007'], cached_file)
203 |
204 | # extract file
205 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root))
206 | cwd = os.getcwd()
207 | tar = tarfile.open(cached_file, "r")
208 | os.chdir(root)
209 | tar.extractall()
210 | tar.close()
211 | os.chdir(cwd)
212 | print('[dataset] Done!')
213 |
214 |
215 | class Voc2007Classification(data.Dataset):
216 |
217 | def __init__(self, root, set, transform=None, target_transform=None):
218 | self.root = root
219 | self.path_devkit = os.path.join(root, 'VOCdevkit')
220 | self.path_images = os.path.join(root, 'VOCdevkit', 'VOC2007', 'JPEGImages')
221 | self.set = set
222 | self.transform = transform
223 | self.target_transform = target_transform
224 |
225 | # download dataset
226 | download_voc2007(self.root)
227 |
228 | # define path of csv file
229 | path_csv = os.path.join(self.root, 'files', 'VOC2007')
230 | # define filename of csv file
231 | file_csv = os.path.join(path_csv, 'classification_' + set + '.csv')
232 |
233 | # create the csv file if necessary
234 | if not os.path.exists(file_csv):
235 | if not os.path.exists(path_csv): # create dir if necessary
236 | os.makedirs(path_csv)
237 | # generate csv file
238 | labeled_data = read_object_labels(self.root, 'VOC2007', self.set)
239 | # write csv file
240 | write_object_labels_csv(file_csv, labeled_data)
241 |
242 | self.classes = object_categories
243 | self.images = read_object_labels_csv(file_csv)
244 |
245 | print('[dataset] VOC 2007 classification set=%s number of classes=%d number of images=%d' % (
246 | set, len(self.classes), len(self.images)))
247 |
248 | def __getitem__(self, index):
249 | path, target = self.images[index]
250 | img = Image.open(os.path.join(self.path_images, path + '.jpg')).convert('RGB')
251 | if self.transform is not None:
252 | img = self.transform(img)
253 | if self.target_transform is not None:
254 | target = self.target_transform(target)
255 | return img, path, target
256 |
257 | def __len__(self):
258 | return len(self.images)
259 |
260 | def get_number_classes(self):
261 | return len(self.classes)
262 |
--------------------------------------------------------------------------------
/phase1.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf-8 -*-
2 | import os
3 | import torch
4 | import torch.nn as nn
5 | import torch.nn.functional as F
6 | from torch.autograd import Variable
7 | import torchvision.transforms as transforms
8 | from data.cifar import CIFAR10, CIFAR100
9 | from data.mnist import MNIST
10 | from data.datasets import input_dataset
11 | from models import *
12 | import argparse, sys
13 | import numpy as np
14 | import datetime
15 | import shutil
16 | from random import sample
17 | from loss import loss_cross_entropy,loss_cores,f_beta
18 |
19 | parser = argparse.ArgumentParser()
20 | parser.add_argument('--lr', type = float, default = 0.05)
21 | parser.add_argument('--lr_plan', type = str, help = 'base, cyclic', default = 'cyclic')
22 | parser.add_argument('--loss', type = str, help = 'ce, cores', default = 'cores')
23 | parser.add_argument('--result_dir', type = str, help = 'dir to save result txt files', default = 'results')
24 | parser.add_argument('--noise_rate', type = float, help = 'corruption rate, should be less than 1', default = 0.2)
25 | parser.add_argument('--noise_type', type = str, help='[pairflip, symmetric,instance]', default='pairflip')
26 | parser.add_argument('--top_bn', action='store_true')
27 | parser.add_argument('--ideal', action='store_true')
28 | parser.add_argument('--dataset', type = str, help = 'mnist, cifar10, or cifar100', default = 'cifar10')
29 | parser.add_argument('--model', type = str, help = 'cnn,resnet', default = 'cnn')
30 | parser.add_argument('--n_epoch', type=int, default=100)
31 | parser.add_argument('--seed', type=int, default=0)
32 | parser.add_argument('--print_freq', type=int, default=50)
33 | parser.add_argument('--num_workers', type=int, default=4, help='how many subprocesses to use for data loading')
34 | parser.add_argument('--resume', '-r', action='store_true', help='resume from checkpoint')
35 |
36 | def get_noise_pred(loss_div, args, epoch=-1, alpha=0.):
37 | #Get noise prediction
38 | print('DEBUG, loss_div', loss_div.shape)
39 | llast = loss_div[:, epoch]
40 | idx_last = np.where(llast>alpha)[0]
41 | print('last idx:', idx_last.shape)
42 | return idx_last
43 |
44 | # Adjust learning rate and for SGD Optimizer
45 | def adjust_learning_rate(optimizer, epoch,alpha_plan):
46 | for param_group in optimizer.param_groups:
47 | param_group['lr']=alpha_plan[epoch]/(1+f_beta(epoch))
48 |
49 |
50 | def accuracy(logit, target, topk=(1,)):
51 | """Computes the precision@k for the specified values of k"""
52 | output = F.softmax(logit, dim=1)
53 | maxk = max(topk)
54 | batch_size = target.size(0)
55 |
56 | _, pred = output.topk(maxk, 1, True, True)
57 | pred = pred.t()
58 | correct = pred.eq(target.view(1, -1).expand_as(pred))
59 |
60 | res = []
61 | for k in topk:
62 | correct_k = correct[:k].view(-1).float().sum(0, keepdim=True)
63 | res.append(correct_k.mul_(100.0 / batch_size))
64 | return res
65 |
66 | # Train the Model
67 | def train(epoch, num_classes, train_loader,model, optimizer,loss_all,loss_div_all,loss_type, noise_prior = None):
68 | train_total=0
69 | train_correct=0
70 | print(f'current beta is {f_beta(epoch)}')
71 | v_list = np.zeros(num_training_samples)
72 | idx_each_class_noisy = [[] for i in range(num_classes)]
73 | if not isinstance(noise_prior, torch.Tensor):
74 | noise_prior = torch.tensor(noise_prior.astype('float32')).cuda().unsqueeze(0)
75 | for i, (images, labels, indexes) in enumerate(train_loader):
76 | ind=indexes.cpu().numpy().transpose()
77 | batch_size = len(ind)
78 | class_list = range(num_classes)
79 |
80 | images = Variable(images).cuda()
81 | labels = Variable(labels).cuda()
82 |
83 | # Forward + Backward + Optimize
84 | logits = model(images)
85 | prec, _ = accuracy(logits, labels, topk=(1, 5))
86 | train_total+=1
87 | train_correct+=prec
88 | if loss_type=='ce':
89 | loss = loss_cross_entropy(epoch,logits, labels,class_list,ind, noise_or_not, loss_all, loss_div_all)
90 | elif loss_type=='cores':
91 | loss, loss_v = loss_cores(epoch,logits, labels,class_list,ind, noise_or_not, loss_all, loss_div_all, noise_prior = noise_prior)
92 | v_list[ind] = loss_v
93 | for i in range(batch_size):
94 | if loss_v[i] == 0:
95 | idx_each_class_noisy[labels[i]].append(ind[i])
96 | else:
97 | print('loss type not supported')
98 | raise SystemExit
99 | optimizer.zero_grad()
100 | loss.backward()
101 | optimizer.step()
102 | if (i+1) % args.print_freq == 0:
103 | print ('Epoch [%d/%d], Iter [%d/%d] Training Accuracy: %.4F, Loss: %.4f'
104 | %(epoch+1, args.n_epoch, i+1, len(train_dataset)//batch_size, prec, loss.data))
105 |
106 | class_size_noisy = [len(idx_each_class_noisy[i]) for i in range(num_classes)]
107 | noise_prior_delta = np.array(class_size_noisy)
108 | print(noise_prior_delta)
109 |
110 | train_acc=float(train_correct)/float(train_total)
111 | return train_acc, noise_prior_delta
112 |
113 | # Evaluate the Model
114 | def evaluate(test_loader,model,save=False,epoch=0,best_acc_=0,args=None):
115 | model.eval() # Change model to 'eval' mode.
116 | print('previous_best', best_acc_)
117 | correct = 0
118 | total = 0
119 | for images, labels, _ in test_loader:
120 | images = Variable(images).cuda()
121 | logits = model(images)
122 | outputs = F.softmax(logits, dim=1)
123 | _, pred = torch.max(outputs.data, 1)
124 | total += labels.size(0)
125 | correct += (pred.cpu() == labels).sum()
126 | acc = 100*float(correct)/float(total)
127 |
128 | if save:
129 | if acc > best_acc_:
130 | state = {'state_dict': model.state_dict(),
131 | 'epoch':epoch,
132 | 'acc':acc,
133 | }
134 | torch.save(state,os.path.join(save_dir,args.loss + args.noise_type + str(args.noise_rate)+'best.pth.tar'))
135 | #np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'loss_div_all_best.npy',loss_div_all)
136 | #np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'loss_all_best.npy',loss_all)
137 | best_acc_ = acc
138 | if epoch == args.n_epoch -1:
139 | state = {'state_dict': model.state_dict(),
140 | 'epoch':epoch,
141 | 'acc':acc,
142 | }
143 | torch.save(state,os.path.join(save_dir,args.loss + args.noise_type + str(args.noise_rate)+'last.pth.tar'))
144 | #np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'loss_div_all_last.npy',loss_div_all)
145 | #np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'loss_all_best.npy',loss_all)
146 | return acc, best_acc_
147 |
148 |
149 |
150 | #####################################main code ################################################
151 | args = parser.parse_args()
152 | # Seed
153 | torch.manual_seed(args.seed)
154 | torch.cuda.manual_seed(args.seed)
155 |
156 | # Hyper Parameters
157 | batch_size = 64
158 | learning_rate = args.lr
159 |
160 | # load dataset
161 | train_dataset,test_dataset,num_classes,num_training_samples = input_dataset(args.dataset,args.noise_type,args.noise_rate)
162 | noise_prior = train_dataset.noise_prior
163 | noise_or_not = train_dataset.noise_or_not
164 | print('train_labels:', len(train_dataset.train_labels), train_dataset.train_labels[:10])
165 | # load model
166 | print('building model...')
167 | if args.model == 'cnn':
168 | model = CNN(input_channel=3, n_outputs=num_classes)
169 | else:
170 | model = ResNet34(num_classes)
171 | print('building model done')
172 | optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
173 | # Creat loss and loss_div for each sample at each epoch
174 | loss_all = np.zeros((num_training_samples,args.n_epoch))
175 | loss_div_all = np.zeros((num_training_samples,args.n_epoch))
176 | ### save result and model checkpoint #######
177 | save_dir = args.result_dir +'/' +args.dataset + '/' + args.model
178 | if not os.path.exists(save_dir):
179 | os.system('mkdir -p %s' % save_dir)
180 | train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
181 | batch_size = batch_size,
182 | num_workers=args.num_workers,
183 | shuffle=True)
184 |
185 | test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
186 | batch_size = 64,
187 | num_workers=args.num_workers,
188 | shuffle=False)
189 | alpha_plan = [0.1] * 50 + [0.01] * 50
190 | #alpha_plan = []
191 | #for ii in range(args.n_epoch):
192 | # alpha_plan.append(learning_rate*pow(0.95,ii))
193 | model.cuda()
194 | txtfile=save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate) + '.txt'
195 | if os.path.exists(txtfile):
196 | os.system('rm %s' % txtfile)
197 | with open(txtfile, "a") as myfile:
198 | myfile.write('epoch: train_acc test_acc \n')
199 |
200 | epoch=0
201 | train_acc = 0
202 | best_acc_ = 0.0
203 | #print(best_acc_)
204 | # training
205 | noise_prior_cur = noise_prior
206 | for epoch in range(args.n_epoch):
207 | # train models
208 | adjust_learning_rate(optimizer, epoch, alpha_plan)
209 | model.train()
210 | train_acc, noise_prior_delta = train(epoch,num_classes,train_loader, model, optimizer,loss_all,loss_div_all,args.loss,noise_prior = noise_prior_cur)
211 | noise_prior_cur = noise_prior*num_training_samples - noise_prior_delta
212 | noise_prior_cur = noise_prior_cur/sum(noise_prior_cur)
213 | # evaluate models
214 | test_acc, best_acc_ = evaluate(test_loader=test_loader, save=True, model=model,epoch=epoch,best_acc_=best_acc_,args=args)
215 | # save results
216 | #det_by_loss = det_acc(save_dir,best_ratio,args,loss_all,noise_or_not,epoch,sum_epoch = False)
217 | #det_by_loss_div = det_acc(save_dir,best_ratio,args,loss_div_all,noise_or_not,epoch,sum_epoch = False)
218 | print('train acc on train images is ', train_acc)
219 | print('test acc on test images is ', test_acc)
220 | #print('precision of labels by loss is', det_by_loss)
221 | #print('precision of labels by loss div is', det_by_loss_div)
222 | with open(txtfile, "a") as myfile:
223 | myfile.write(str(int(epoch)) + ': ' + str(train_acc) +' ' + str(test_acc) + "\n")
224 | np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'loss_all.npy',loss_all)
225 | np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'loss_div_all.npy',loss_div_all)
226 | np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'noise_or_not.npy',noise_or_not)
227 | np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'train_noisy_labels.npy',train_dataset.train_noisy_labels)
228 | if epoch ==40:
229 | idx_last = get_noise_pred(loss_div_all, args, epoch=epoch)
230 | np.save(save_dir + '/' + args.loss + args.noise_type + str(args.noise_rate)+'_noise_pred.npy',idx_last)
231 |
--------------------------------------------------------------------------------
/phase2/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/inceptionv4.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import torch
3 | import torch.nn as nn
4 | import torch.utils.model_zoo as model_zoo
5 | import os
6 | import sys
7 |
8 | __all__ = ['InceptionV4', 'inceptionv4']
9 |
10 | pretrained_settings = {
11 | 'inceptionv4': {
12 | 'imagenet': {
13 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionv4-8e4777a0.pth',
14 | 'input_space': 'RGB',
15 | 'input_size': [3, 299, 299],
16 | 'input_range': [0, 1],
17 | 'mean': [0.5, 0.5, 0.5],
18 | 'std': [0.5, 0.5, 0.5],
19 | 'num_classes': 1000
20 | },
21 | 'imagenet+background': {
22 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionv4-8e4777a0.pth',
23 | 'input_space': 'RGB',
24 | 'input_size': [3, 299, 299],
25 | 'input_range': [0, 1],
26 | 'mean': [0.5, 0.5, 0.5],
27 | 'std': [0.5, 0.5, 0.5],
28 | 'num_classes': 1001
29 | }
30 | }
31 | }
32 |
33 |
34 | class BasicConv2d(nn.Module):
35 |
36 | def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0):
37 | super(BasicConv2d, self).__init__()
38 | self.conv = nn.Conv2d(in_planes, out_planes,
39 | kernel_size=kernel_size, stride=stride,
40 | padding=padding, bias=False) # verify bias false
41 | self.bn = nn.BatchNorm2d(out_planes,
42 | eps=0.001, # value found in tensorflow
43 | momentum=0.1, # default pytorch value
44 | affine=True)
45 | self.relu = nn.ReLU(inplace=True)
46 |
47 | def forward(self, x):
48 | x = self.conv(x)
49 | x = self.bn(x)
50 | x = self.relu(x)
51 | return x
52 |
53 |
54 | class Mixed_3a(nn.Module):
55 |
56 | def __init__(self):
57 | super(Mixed_3a, self).__init__()
58 | self.maxpool = nn.MaxPool2d(3, stride=2)
59 | self.conv = BasicConv2d(64, 96, kernel_size=3, stride=2)
60 |
61 | def forward(self, x):
62 | x0 = self.maxpool(x)
63 | x1 = self.conv(x)
64 | out = torch.cat((x0, x1), 1)
65 | return out
66 |
67 |
68 | class Mixed_4a(nn.Module):
69 |
70 | def __init__(self):
71 | super(Mixed_4a, self).__init__()
72 |
73 | self.branch0 = nn.Sequential(
74 | BasicConv2d(160, 64, kernel_size=1, stride=1),
75 | BasicConv2d(64, 96, kernel_size=3, stride=1)
76 | )
77 |
78 | self.branch1 = nn.Sequential(
79 | BasicConv2d(160, 64, kernel_size=1, stride=1),
80 | BasicConv2d(64, 64, kernel_size=(1,7), stride=1, padding=(0,3)),
81 | BasicConv2d(64, 64, kernel_size=(7,1), stride=1, padding=(3,0)),
82 | BasicConv2d(64, 96, kernel_size=(3,3), stride=1)
83 | )
84 |
85 | def forward(self, x):
86 | x0 = self.branch0(x)
87 | x1 = self.branch1(x)
88 | out = torch.cat((x0, x1), 1)
89 | return out
90 |
91 |
92 | class Mixed_5a(nn.Module):
93 |
94 | def __init__(self):
95 | super(Mixed_5a, self).__init__()
96 | self.conv = BasicConv2d(192, 192, kernel_size=3, stride=2)
97 | self.maxpool = nn.MaxPool2d(3, stride=2)
98 |
99 | def forward(self, x):
100 | x0 = self.conv(x)
101 | x1 = self.maxpool(x)
102 | out = torch.cat((x0, x1), 1)
103 | return out
104 |
105 |
106 | class Inception_A(nn.Module):
107 |
108 | def __init__(self):
109 | super(Inception_A, self).__init__()
110 | self.branch0 = BasicConv2d(384, 96, kernel_size=1, stride=1)
111 |
112 | self.branch1 = nn.Sequential(
113 | BasicConv2d(384, 64, kernel_size=1, stride=1),
114 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1)
115 | )
116 |
117 | self.branch2 = nn.Sequential(
118 | BasicConv2d(384, 64, kernel_size=1, stride=1),
119 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1),
120 | BasicConv2d(96, 96, kernel_size=3, stride=1, padding=1)
121 | )
122 |
123 | self.branch3 = nn.Sequential(
124 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
125 | BasicConv2d(384, 96, kernel_size=1, stride=1)
126 | )
127 |
128 | def forward(self, x):
129 | x0 = self.branch0(x)
130 | x1 = self.branch1(x)
131 | x2 = self.branch2(x)
132 | x3 = self.branch3(x)
133 | out = torch.cat((x0, x1, x2, x3), 1)
134 | return out
135 |
136 |
137 | class Reduction_A(nn.Module):
138 |
139 | def __init__(self):
140 | super(Reduction_A, self).__init__()
141 | self.branch0 = BasicConv2d(384, 384, kernel_size=3, stride=2)
142 |
143 | self.branch1 = nn.Sequential(
144 | BasicConv2d(384, 192, kernel_size=1, stride=1),
145 | BasicConv2d(192, 224, kernel_size=3, stride=1, padding=1),
146 | BasicConv2d(224, 256, kernel_size=3, stride=2)
147 | )
148 |
149 | self.branch2 = nn.MaxPool2d(3, stride=2)
150 |
151 | def forward(self, x):
152 | x0 = self.branch0(x)
153 | x1 = self.branch1(x)
154 | x2 = self.branch2(x)
155 | out = torch.cat((x0, x1, x2), 1)
156 | return out
157 |
158 |
159 | class Inception_B(nn.Module):
160 |
161 | def __init__(self):
162 | super(Inception_B, self).__init__()
163 | self.branch0 = BasicConv2d(1024, 384, kernel_size=1, stride=1)
164 |
165 | self.branch1 = nn.Sequential(
166 | BasicConv2d(1024, 192, kernel_size=1, stride=1),
167 | BasicConv2d(192, 224, kernel_size=(1,7), stride=1, padding=(0,3)),
168 | BasicConv2d(224, 256, kernel_size=(7,1), stride=1, padding=(3,0))
169 | )
170 |
171 | self.branch2 = nn.Sequential(
172 | BasicConv2d(1024, 192, kernel_size=1, stride=1),
173 | BasicConv2d(192, 192, kernel_size=(7,1), stride=1, padding=(3,0)),
174 | BasicConv2d(192, 224, kernel_size=(1,7), stride=1, padding=(0,3)),
175 | BasicConv2d(224, 224, kernel_size=(7,1), stride=1, padding=(3,0)),
176 | BasicConv2d(224, 256, kernel_size=(1,7), stride=1, padding=(0,3))
177 | )
178 |
179 | self.branch3 = nn.Sequential(
180 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
181 | BasicConv2d(1024, 128, kernel_size=1, stride=1)
182 | )
183 |
184 | def forward(self, x):
185 | x0 = self.branch0(x)
186 | x1 = self.branch1(x)
187 | x2 = self.branch2(x)
188 | x3 = self.branch3(x)
189 | out = torch.cat((x0, x1, x2, x3), 1)
190 | return out
191 |
192 |
193 | class Reduction_B(nn.Module):
194 |
195 | def __init__(self):
196 | super(Reduction_B, self).__init__()
197 |
198 | self.branch0 = nn.Sequential(
199 | BasicConv2d(1024, 192, kernel_size=1, stride=1),
200 | BasicConv2d(192, 192, kernel_size=3, stride=2)
201 | )
202 |
203 | self.branch1 = nn.Sequential(
204 | BasicConv2d(1024, 256, kernel_size=1, stride=1),
205 | BasicConv2d(256, 256, kernel_size=(1,7), stride=1, padding=(0,3)),
206 | BasicConv2d(256, 320, kernel_size=(7,1), stride=1, padding=(3,0)),
207 | BasicConv2d(320, 320, kernel_size=3, stride=2)
208 | )
209 |
210 | self.branch2 = nn.MaxPool2d(3, stride=2)
211 |
212 | def forward(self, x):
213 | x0 = self.branch0(x)
214 | x1 = self.branch1(x)
215 | x2 = self.branch2(x)
216 | out = torch.cat((x0, x1, x2), 1)
217 | return out
218 |
219 |
220 | class Inception_C(nn.Module):
221 |
222 | def __init__(self):
223 | super(Inception_C, self).__init__()
224 |
225 | self.branch0 = BasicConv2d(1536, 256, kernel_size=1, stride=1)
226 |
227 | self.branch1_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1)
228 | self.branch1_1a = BasicConv2d(384, 256, kernel_size=(1,3), stride=1, padding=(0,1))
229 | self.branch1_1b = BasicConv2d(384, 256, kernel_size=(3,1), stride=1, padding=(1,0))
230 |
231 | self.branch2_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1)
232 | self.branch2_1 = BasicConv2d(384, 448, kernel_size=(3,1), stride=1, padding=(1,0))
233 | self.branch2_2 = BasicConv2d(448, 512, kernel_size=(1,3), stride=1, padding=(0,1))
234 | self.branch2_3a = BasicConv2d(512, 256, kernel_size=(1,3), stride=1, padding=(0,1))
235 | self.branch2_3b = BasicConv2d(512, 256, kernel_size=(3,1), stride=1, padding=(1,0))
236 |
237 | self.branch3 = nn.Sequential(
238 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
239 | BasicConv2d(1536, 256, kernel_size=1, stride=1)
240 | )
241 |
242 | def forward(self, x):
243 | x0 = self.branch0(x)
244 |
245 | x1_0 = self.branch1_0(x)
246 | x1_1a = self.branch1_1a(x1_0)
247 | x1_1b = self.branch1_1b(x1_0)
248 | x1 = torch.cat((x1_1a, x1_1b), 1)
249 |
250 | x2_0 = self.branch2_0(x)
251 | x2_1 = self.branch2_1(x2_0)
252 | x2_2 = self.branch2_2(x2_1)
253 | x2_3a = self.branch2_3a(x2_2)
254 | x2_3b = self.branch2_3b(x2_2)
255 | x2 = torch.cat((x2_3a, x2_3b), 1)
256 |
257 | x3 = self.branch3(x)
258 |
259 | out = torch.cat((x0, x1, x2, x3), 1)
260 | return out
261 |
262 |
263 | class InceptionV4(nn.Module):
264 |
265 | def __init__(self, num_classes=1001):
266 | super(InceptionV4, self).__init__()
267 | # Special attributs
268 | self.input_space = None
269 | self.input_size = (299, 299, 3)
270 | self.mean = None
271 | self.std = None
272 | # Modules
273 | self.features = nn.Sequential(
274 | BasicConv2d(3, 32, kernel_size=3, stride=2),
275 | BasicConv2d(32, 32, kernel_size=3, stride=1),
276 | BasicConv2d(32, 64, kernel_size=3, stride=1, padding=1),
277 | Mixed_3a(),
278 | Mixed_4a(),
279 | Mixed_5a(),
280 | Inception_A(),
281 | Inception_A(),
282 | Inception_A(),
283 | Inception_A(),
284 | Reduction_A(), # Mixed_6a
285 | Inception_B(),
286 | Inception_B(),
287 | Inception_B(),
288 | Inception_B(),
289 | Inception_B(),
290 | Inception_B(),
291 | Inception_B(),
292 | Reduction_B(), # Mixed_7a
293 | Inception_C(),
294 | Inception_C(),
295 | Inception_C()
296 | )
297 | self.avg_pool = nn.AvgPool2d(8, count_include_pad=False)
298 | self.last_linear = nn.Linear(1536, num_classes)
299 |
300 | def logits(self, features):
301 | x = self.avg_pool(features)
302 | x = x.view(x.size(0), -1)
303 | x = self.last_linear(x)
304 | return x
305 |
306 | def forward(self, input):
307 | x = self.features(input)
308 | x = self.logits(x)
309 | return x
310 |
311 |
312 | def inceptionv4(num_classes=1000, pretrained='imagenet'):
313 | if pretrained:
314 | settings = pretrained_settings['inceptionv4'][pretrained]
315 | assert num_classes == settings['num_classes'], \
316 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
317 |
318 | # both 'imagenet'&'imagenet+background' are loaded from same parameters
319 | model = InceptionV4(num_classes=1001)
320 | model.load_state_dict(model_zoo.load_url(settings['url']))
321 |
322 | if pretrained == 'imagenet':
323 | new_last_linear = nn.Linear(1536, 1000)
324 | new_last_linear.weight.data = model.last_linear.weight.data[1:]
325 | new_last_linear.bias.data = model.last_linear.bias.data[1:]
326 | model.last_linear = new_last_linear
327 |
328 | model.input_space = settings['input_space']
329 | model.input_size = settings['input_size']
330 | model.input_range = settings['input_range']
331 | model.mean = settings['mean']
332 | model.std = settings['std']
333 | else:
334 | model = InceptionV4(num_classes=num_classes)
335 | return model
336 |
337 |
338 | '''
339 | TEST
340 | Run this code with:
341 | ```
342 | cd $HOME/pretrained-models.pytorch
343 | python -m pretrainedmodels.inceptionv4
344 | ```
345 | '''
346 | if __name__ == '__main__':
347 |
348 | assert inceptionv4(num_classes=10, pretrained=None)
349 | print('success')
350 | assert inceptionv4(num_classes=1000, pretrained='imagenet')
351 | print('success')
352 | assert inceptionv4(num_classes=1001, pretrained='imagenet+background')
353 | print('success')
354 |
355 | # fail
356 | assert inceptionv4(num_classes=1001, pretrained='imagenet')
--------------------------------------------------------------------------------
/phase2/phase2.py:
--------------------------------------------------------------------------------
1 | import itertools
2 | import logging
3 | import math
4 | import os
5 | from collections import OrderedDict
6 | import numpy as np
7 |
8 | import torch
9 | from torch import nn, optim
10 | from torch.nn.functional import kl_div, softmax, log_softmax
11 |
12 | from tqdm import tqdm
13 | from theconf import Config as C, ConfigArgumentParser
14 |
15 | from common import get_logger
16 | from data import get_dataloaders
17 | from metrics import accuracy, Accumulator
18 | from networks import get_model, num_class
19 |
20 | from warmup_scheduler import GradualWarmupScheduler
21 |
22 |
23 | logger = get_logger('Unsupervised Data Augmentation')
24 | logger.setLevel(logging.INFO)
25 |
26 | best_valid_top1 = 0
27 |
28 |
29 | def run_epoch(model, loader_s, loader_u, loss_fn, optimizer, desc_default='', epoch=0, writer=None, verbose=1, unsupervised=False, scheduler=None):
30 | #tqdm_disable = bool(os.environ.get('TASK_NAME', ''))
31 | tqdm_disable = C.get()['tqdm_disable']
32 | if verbose:
33 | loader_s = tqdm(loader_s, disable=tqdm_disable)
34 | loader_s.set_description('[%s %04d/%04d]' % (desc_default, epoch, C.get()['epoch']))
35 |
36 | iter_u = iter(loader_u)
37 |
38 | metrics = Accumulator()
39 | cnt = 0
40 | total_steps = len(loader_s)
41 | steps = 0
42 | #for data, label, indices in loader_s:
43 | for data, label in loader_s:
44 | steps += 1
45 | '''
46 | print('labels',label)
47 | np.save('labels', label)
48 | np.save('indices', indices)
49 | print('indices', indices)
50 | raise SystemExit
51 | '''
52 | if not unsupervised:
53 | data, label = data.cuda(), label.cuda()
54 | preds = model(data)
55 | loss = loss_fn(preds, label) # loss for supervised learning
56 | else:
57 | label = label.cuda()
58 | try:
59 | unlabel1, unlabel2 = next(iter_u)
60 | except StopIteration:
61 | iter_u = iter(loader_u)
62 | unlabel1, unlabel2 = next(iter_u)
63 | data_all = torch.cat([data, unlabel1, unlabel2]).cuda()
64 | #print('DEBUG: data', len(data))
65 |
66 | preds_all = model(data_all)
67 | preds = preds_all[:len(data)]
68 |
69 | loss = loss_fn(preds, label) # loss for supervised learning
70 | metrics.add_dict({'sup_loss': loss.item() * len(data)})
71 |
72 |
73 | preds_unsup = preds_all[len(data):]
74 | preds1, preds2 = torch.chunk(preds_unsup, 2)
75 | preds1 = softmax(preds1, dim=1).detach()
76 | preds2 = log_softmax(preds2, dim=1)
77 | assert len(preds1) == len(preds2) == C.get()['batch_unsup']
78 |
79 | loss_kldiv = kl_div(preds2, preds1, reduction='none') # loss for unsupervised
80 | loss_kldiv = torch.sum(loss_kldiv, dim=1)
81 | assert len(loss_kldiv) == len(unlabel1)
82 | # loss += (epoch / 200. * C.get()['ratio_unsup']) * torch.mean(loss_kldiv)
83 | if C.get()['ratio_mode'] == 'constant':
84 | loss += C.get()['ratio_unsup'] * torch.mean(loss_kldiv)
85 | elif C.get()['ratio_mode'] == 'gradual':
86 | loss += (epoch / float(C.get()['epoch'])) * C.get()['ratio_unsup'] * torch.mean(loss_kldiv)
87 | else:
88 | raise ValueError
89 |
90 |
91 | if optimizer:
92 | loss.backward()
93 | if C.get()['optimizer'].get('clip', 5) > 0:
94 | nn.utils.clip_grad_norm_(model.parameters(), C.get()['optimizer'].get('clip', 5))
95 |
96 | optimizer.step()
97 | optimizer.zero_grad()
98 |
99 | top1, top5 = accuracy(preds, label, (1, 5))
100 |
101 | metrics.add_dict({
102 | 'loss': loss.item() * len(data),
103 | 'top1': top1.item() * len(data),
104 | 'top5': top5.item() * len(data),
105 | })
106 | cnt += len(data)
107 | if verbose:
108 | postfix = metrics / cnt
109 | if optimizer:
110 | postfix['lr'] = optimizer.param_groups[0]['lr']
111 | loader_s.set_postfix(postfix)
112 |
113 | if scheduler is not None:
114 | scheduler.step(epoch - 1 + float(steps) / total_steps)
115 |
116 | del preds, loss, top1, top5, data, label
117 |
118 | if tqdm_disable:
119 | logger.info('[%s %03d/%03d] %s', desc_default, epoch, C.get()['epoch'], metrics / cnt)
120 |
121 | metrics /= cnt
122 | if optimizer:
123 | metrics.metrics['lr'] = optimizer.param_groups[0]['lr']
124 | if verbose:
125 | for key, value in metrics.items():
126 | writer.add_scalar(key, value, epoch)
127 | return metrics
128 |
129 |
130 | def train_and_eval(tag, dataroot, metric='last', resume=False, save_path=None, only_eval=False, unsupervised=False, devices=None):
131 | max_epoch = C.get()['epoch']
132 | unsup_idx = C.get()['unsup_idx']
133 | if os.path.exists(unsup_idx):
134 | unsup_idx = np.load(unsup_idx).tolist()
135 | print('Unsup idx:', len(unsup_idx))
136 | trainloader, unsuploader, testloader = get_dataloaders(C.get()['dataset'], C.get()['batch'], C.get()['batch_unsup'],
137 | dataroot, with_noise=True,
138 | random_state=C.get()['random_state'], unsup_idx=unsup_idx)
139 | else:
140 | trainloader, unsuploader, testloader = get_dataloaders(C.get()['dataset'], C.get()['batch'], C.get()['batch_unsup'],
141 | dataroot, with_noise=False,
142 | random_state=C.get()['random_state'])
143 |
144 | # create a model & an optimizer
145 | model = get_model(C.get()['model'], num_class(C.get()['dataset']), data_parallel=True, devices=devices)
146 |
147 | criterion = nn.CrossEntropyLoss()
148 | if C.get()['optimizer']['type'] == 'sgd':
149 | optimizer = optim.SGD(
150 | model.parameters(),
151 | lr=C.get()['lr'],
152 | momentum=C.get()['optimizer'].get('momentum', 0.9),
153 | weight_decay=C.get()['optimizer']['decay'],
154 | nesterov=C.get()['optimizer']['nesterov']
155 | )
156 | else:
157 | raise ValueError('invalid optimizer type=%s' % C.get()['optimizer']['type'])
158 |
159 | lr_scheduler_type = C.get()['lr_schedule'].get('type', 'cosine')
160 | if lr_scheduler_type == 'cosine':
161 | #t_max = 600
162 | #print('Temp Fix for AnnealingCosine, Tmax=',t_max)
163 | t_max = C.get()['epoch']
164 | if C.get()['lr_schedule'].get('warmup', None):
165 | t_max -= C.get()['lr_schedule']['warmup']['epoch']
166 | scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=t_max, eta_min=0.)
167 | else:
168 | raise ValueError('invalid lr_schduler=%s' % lr_scheduler_type)
169 |
170 | if C.get()['lr_schedule'].get('warmup', None):
171 | scheduler = GradualWarmupScheduler(
172 | optimizer,
173 | multiplier=C.get()['lr_schedule']['warmup']['multiplier'],
174 | total_epoch=C.get()['lr_schedule']['warmup']['epoch'],
175 | after_scheduler=scheduler
176 | )
177 |
178 | if not tag.strip():
179 | from metrics import SummaryWriterDummy as SummaryWriter
180 | logger.warning('tag not provided, no tensorboard log.')
181 | else:
182 | from tensorboardX import SummaryWriter
183 | writers = [SummaryWriter(logdir='./logs/%s/%s' % (tag, x)) for x in ['train', 'test']]
184 |
185 | result = OrderedDict()
186 | epoch_start = 1
187 |
188 | if (resume or only_eval) and save_path and os.path.exists(save_path):
189 | print('Resuming from last epoch:', save_path)
190 | ckpt = torch.load(save_path)
191 | model.load_state_dict(ckpt['state_dict'])
192 | optimizer.load_state_dict(ckpt['optimizer'])
193 | epoch_start = ckpt['epoch']
194 |
195 | elif os.path.exists(C.get()['pretrain']):
196 | print('Loading pretrain from:', C.get()['pretrain'])
197 | ckpt = torch.load(C.get()['pretrain'])
198 | try:
199 | model.load_state_dict(ckpt['state_dict'])
200 | except RuntimeError:
201 | new_state_dict = {'module.'+k: v for k, v in ckpt['state_dict'].items()}
202 | model.load_state_dict(new_state_dict)
203 | else:
204 | print('DEBUG: No pretrain available')
205 |
206 | if only_eval:
207 | logger.info('evaluation only+')
208 | model.eval()
209 | rs = dict()
210 | rs['test'] = run_epoch(model, testloader, unsuploader, criterion, None, desc_default='*test', epoch=epoch_start, writer=writers[1])
211 | for key, setname in itertools.product(['loss', 'top1', 'top5'], ['train', 'test']):
212 | result['%s_%s' % (key, setname)] = rs[setname][key]
213 | result['epoch'] = 0
214 | return result
215 |
216 | # train loop
217 | global best_valid_top1
218 | best_valid_loss = 10e10
219 | for epoch in range(epoch_start, max_epoch + 1):
220 | model.train()
221 | rs = dict()
222 | rs['train'] = run_epoch(model, trainloader, unsuploader, criterion, optimizer, desc_default='train', epoch=epoch, writer=writers[0], verbose=False, unsupervised=unsupervised, scheduler=scheduler)
223 | print('Train At Epoch {}'.format(epoch), rs['train'])
224 | if math.isnan(rs['train']['loss']):
225 | raise Exception('train loss is NaN.')
226 |
227 | model.eval()
228 | if epoch % (10 if 'cifar' in C.get()['dataset'] else 30) == 0 or epoch == max_epoch:
229 | rs['test'] = run_epoch(model, testloader, unsuploader, criterion, None, desc_default='*test', epoch=epoch, writer=writers[1], verbose=False)
230 | print('Test At Epoch {}'.format(epoch), rs['test'])
231 | if best_valid_top1 < rs['test']['top1']:
232 | best_valid_top1 = rs['test']['top1']
233 |
234 | if metric == 'last' or rs[metric]['loss'] < best_valid_loss: # TODO
235 | if metric != 'last':
236 | best_valid_loss = rs[metric]['loss']
237 | for key, setname in itertools.product(['loss', 'top1', 'top5'], ['train', 'test']):
238 | result['%s_%s' % (key, setname)] = rs[setname][key]
239 | result['epoch'] = epoch
240 |
241 | writers[1].add_scalar('test_top1/best', rs['test']['top1'], epoch)
242 |
243 | # save checkpoint
244 | if save_path:
245 | logger.info('save model@%d to %s' % (epoch, save_path))
246 | torch.save({
247 | 'epoch': epoch,
248 | 'log': {
249 | 'train': rs['train'].get_dict(),
250 | 'test': rs['test'].get_dict(),
251 | },
252 | 'optimizer': optimizer.state_dict(),
253 | 'state_dict': model.state_dict()
254 | }, save_path)
255 |
256 | del model
257 |
258 | return result
259 |
260 |
261 | if __name__ == '__main__':
262 | parser = ConfigArgumentParser(conflict_handler='resolve')
263 | parser.add_argument('--tag', type=str, default='')
264 | parser.add_argument('--dataroot', type=str, default='../data/', help='torchvision data folder')
265 | parser.add_argument('--save', type=str, default='')
266 | parser.add_argument('--decay', type=float, default=-1)
267 | parser.add_argument('--unsupervised', action='store_true')
268 | parser.add_argument('--only-eval', action='store_true')
269 | parser.add_argument('--gpu', type=int, nargs='+', default=None)
270 | parser.add_argument('--resume', action='store_true')
271 |
272 | args = parser.parse_args()
273 | print('Unsupervised', args.unsupervised)
274 | assert (args.only_eval and not args.save) or not args.only_eval, 'checkpoint path not provided in evaluation mode.'
275 |
276 | if args.decay > 0:
277 | logger.info('decay reset=%.8f' % args.decay)
278 | C.get()['optimizer']['decay'] = args.decay
279 | if args.save:
280 | logger.info('checkpoint will be saved at %s', args.save)
281 | print('ratio_unsup', C.get()['ratio_unsup'])
282 | print('lr', C.get()['lr'])
283 | print('batch ', C.get()['batch'], 'batch_unsup', C.get()['batch_unsup'])
284 |
285 | import time
286 | t = time.time()
287 | result = train_and_eval(args.tag, args.dataroot, resume=args.resume, save_path=args.save, only_eval=args.only_eval, unsupervised=args.unsupervised, devices=args.gpu)
288 | elapsed = time.time() - t
289 |
290 | logger.info('training done.')
291 | logger.info('model: %s' % C.get()['model'])
292 | logger.info('augmentation: %s' % C.get()['aug'])
293 | logger.info(result)
294 | logger.info('elapsed time: %.3f Hours' % (elapsed / 3600.))
295 | logger.info('top1 error in testset: %.4f' % (1. - result['top1_test']))
296 | logger.info('best top1 error in testset: %.4f' % (1. - best_valid_top1))
297 |
--------------------------------------------------------------------------------
/phase2/pretrainedmodels/models/inceptionresnetv2.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function, division, absolute_import
2 | import torch
3 | import torch.nn as nn
4 | import torch.utils.model_zoo as model_zoo
5 | import torch.nn.functional as F
6 | import os
7 | import sys
8 |
9 | __all__ = ['InceptionResNetV2', 'inceptionresnetv2']
10 |
11 | pretrained_settings = {
12 | 'inceptionresnetv2': {
13 | 'imagenet': {
14 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionresnetv2-520b38e4.pth',
15 | 'input_space': 'RGB',
16 | 'input_size': [3, 299, 299],
17 | 'input_range': [0, 1],
18 | 'mean': [0.5, 0.5, 0.5],
19 | 'std': [0.5, 0.5, 0.5],
20 | 'num_classes': 1000
21 | },
22 | 'imagenet+background': {
23 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionresnetv2-520b38e4.pth',
24 | 'input_space': 'RGB',
25 | 'input_size': [3, 299, 299],
26 | 'input_range': [0, 1],
27 | 'mean': [0.5, 0.5, 0.5],
28 | 'std': [0.5, 0.5, 0.5],
29 | 'num_classes': 1001
30 | }
31 | }
32 | }
33 |
34 |
35 | class BasicConv2d(nn.Module):
36 |
37 | def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0):
38 | super(BasicConv2d, self).__init__()
39 | self.conv = nn.Conv2d(in_planes, out_planes,
40 | kernel_size=kernel_size, stride=stride,
41 | padding=padding, bias=False) # verify bias false
42 | self.bn = nn.BatchNorm2d(out_planes,
43 | eps=0.001, # value found in tensorflow
44 | momentum=0.1, # default pytorch value
45 | affine=True)
46 | self.relu = nn.ReLU(inplace=False)
47 |
48 | def forward(self, x):
49 | x = self.conv(x)
50 | x = self.bn(x)
51 | x = self.relu(x)
52 | return x
53 |
54 |
55 | class Mixed_5b(nn.Module):
56 |
57 | def __init__(self):
58 | super(Mixed_5b, self).__init__()
59 |
60 | self.branch0 = BasicConv2d(192, 96, kernel_size=1, stride=1)
61 |
62 | self.branch1 = nn.Sequential(
63 | BasicConv2d(192, 48, kernel_size=1, stride=1),
64 | BasicConv2d(48, 64, kernel_size=5, stride=1, padding=2)
65 | )
66 |
67 | self.branch2 = nn.Sequential(
68 | BasicConv2d(192, 64, kernel_size=1, stride=1),
69 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1),
70 | BasicConv2d(96, 96, kernel_size=3, stride=1, padding=1)
71 | )
72 |
73 | self.branch3 = nn.Sequential(
74 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
75 | BasicConv2d(192, 64, kernel_size=1, stride=1)
76 | )
77 |
78 | def forward(self, x):
79 | x0 = self.branch0(x)
80 | x1 = self.branch1(x)
81 | x2 = self.branch2(x)
82 | x3 = self.branch3(x)
83 | out = torch.cat((x0, x1, x2, x3), 1)
84 | return out
85 |
86 |
87 | class Block35(nn.Module):
88 |
89 | def __init__(self, scale=1.0):
90 | super(Block35, self).__init__()
91 |
92 | self.scale = scale
93 |
94 | self.branch0 = BasicConv2d(320, 32, kernel_size=1, stride=1)
95 |
96 | self.branch1 = nn.Sequential(
97 | BasicConv2d(320, 32, kernel_size=1, stride=1),
98 | BasicConv2d(32, 32, kernel_size=3, stride=1, padding=1)
99 | )
100 |
101 | self.branch2 = nn.Sequential(
102 | BasicConv2d(320, 32, kernel_size=1, stride=1),
103 | BasicConv2d(32, 48, kernel_size=3, stride=1, padding=1),
104 | BasicConv2d(48, 64, kernel_size=3, stride=1, padding=1)
105 | )
106 |
107 | self.conv2d = nn.Conv2d(128, 320, kernel_size=1, stride=1)
108 | self.relu = nn.ReLU(inplace=False)
109 |
110 | def forward(self, x):
111 | x0 = self.branch0(x)
112 | x1 = self.branch1(x)
113 | x2 = self.branch2(x)
114 | out = torch.cat((x0, x1, x2), 1)
115 | out = self.conv2d(out)
116 | out = out * self.scale + x
117 | out = self.relu(out)
118 | return out
119 |
120 |
121 | class Mixed_6a(nn.Module):
122 |
123 | def __init__(self):
124 | super(Mixed_6a, self).__init__()
125 |
126 | self.branch0 = BasicConv2d(320, 384, kernel_size=3, stride=2)
127 |
128 | self.branch1 = nn.Sequential(
129 | BasicConv2d(320, 256, kernel_size=1, stride=1),
130 | BasicConv2d(256, 256, kernel_size=3, stride=1, padding=1),
131 | BasicConv2d(256, 384, kernel_size=3, stride=2)
132 | )
133 |
134 | self.branch2 = nn.MaxPool2d(3, stride=2)
135 |
136 | def forward(self, x):
137 | x0 = self.branch0(x)
138 | x1 = self.branch1(x)
139 | x2 = self.branch2(x)
140 | out = torch.cat((x0, x1, x2), 1)
141 | return out
142 |
143 |
144 | class Block17(nn.Module):
145 |
146 | def __init__(self, scale=1.0):
147 | super(Block17, self).__init__()
148 |
149 | self.scale = scale
150 |
151 | self.branch0 = BasicConv2d(1088, 192, kernel_size=1, stride=1)
152 |
153 | self.branch1 = nn.Sequential(
154 | BasicConv2d(1088, 128, kernel_size=1, stride=1),
155 | BasicConv2d(128, 160, kernel_size=(1,7), stride=1, padding=(0,3)),
156 | BasicConv2d(160, 192, kernel_size=(7,1), stride=1, padding=(3,0))
157 | )
158 |
159 | self.conv2d = nn.Conv2d(384, 1088, kernel_size=1, stride=1)
160 | self.relu = nn.ReLU(inplace=False)
161 |
162 | def forward(self, x):
163 | x0 = self.branch0(x)
164 | x1 = self.branch1(x)
165 | out = torch.cat((x0, x1), 1)
166 | out = self.conv2d(out)
167 | out = out * self.scale + x
168 | out = self.relu(out)
169 | return out
170 |
171 |
172 | class Mixed_7a(nn.Module):
173 |
174 | def __init__(self):
175 | super(Mixed_7a, self).__init__()
176 |
177 | self.branch0 = nn.Sequential(
178 | BasicConv2d(1088, 256, kernel_size=1, stride=1),
179 | BasicConv2d(256, 384, kernel_size=3, stride=2)
180 | )
181 |
182 | self.branch1 = nn.Sequential(
183 | BasicConv2d(1088, 256, kernel_size=1, stride=1),
184 | BasicConv2d(256, 288, kernel_size=3, stride=2)
185 | )
186 |
187 | self.branch2 = nn.Sequential(
188 | BasicConv2d(1088, 256, kernel_size=1, stride=1),
189 | BasicConv2d(256, 288, kernel_size=3, stride=1, padding=1),
190 | BasicConv2d(288, 320, kernel_size=3, stride=2)
191 | )
192 |
193 | self.branch3 = nn.MaxPool2d(3, stride=2)
194 |
195 | def forward(self, x):
196 | x0 = self.branch0(x)
197 | x1 = self.branch1(x)
198 | x2 = self.branch2(x)
199 | x3 = self.branch3(x)
200 | out = torch.cat((x0, x1, x2, x3), 1)
201 | return out
202 |
203 |
204 | class Block8(nn.Module):
205 |
206 | def __init__(self, scale=1.0, noReLU=False):
207 | super(Block8, self).__init__()
208 |
209 | self.scale = scale
210 | self.noReLU = noReLU
211 |
212 | self.branch0 = BasicConv2d(2080, 192, kernel_size=1, stride=1)
213 |
214 | self.branch1 = nn.Sequential(
215 | BasicConv2d(2080, 192, kernel_size=1, stride=1),
216 | BasicConv2d(192, 224, kernel_size=(1,3), stride=1, padding=(0,1)),
217 | BasicConv2d(224, 256, kernel_size=(3,1), stride=1, padding=(1,0))
218 | )
219 |
220 | self.conv2d = nn.Conv2d(448, 2080, kernel_size=1, stride=1)
221 | if not self.noReLU:
222 | self.relu = nn.ReLU(inplace=False)
223 |
224 | def forward(self, x):
225 | x0 = self.branch0(x)
226 | x1 = self.branch1(x)
227 | out = torch.cat((x0, x1), 1)
228 | out = self.conv2d(out)
229 | out = out * self.scale + x
230 | if not self.noReLU:
231 | out = self.relu(out)
232 | return out
233 |
234 |
235 | class InceptionResNetV2(nn.Module):
236 |
237 | def __init__(self, num_classes=1001):
238 | super(InceptionResNetV2, self).__init__()
239 | # Special attributs
240 | self.input_space = None
241 | self.input_size = (299, 299, 3)
242 | self.mean = None
243 | self.std = None
244 | # Modules
245 | self.conv2d_1a = BasicConv2d(3, 32, kernel_size=3, stride=2)
246 | self.conv2d_2a = BasicConv2d(32, 32, kernel_size=3, stride=1)
247 | self.conv2d_2b = BasicConv2d(32, 64, kernel_size=3, stride=1, padding=1)
248 | self.maxpool_3a = nn.MaxPool2d(3, stride=2)
249 | self.conv2d_3b = BasicConv2d(64, 80, kernel_size=1, stride=1)
250 | self.conv2d_4a = BasicConv2d(80, 192, kernel_size=3, stride=1)
251 | self.maxpool_5a = nn.MaxPool2d(3, stride=2)
252 | self.mixed_5b = Mixed_5b()
253 | self.repeat = nn.Sequential(
254 | Block35(scale=0.17),
255 | Block35(scale=0.17),
256 | Block35(scale=0.17),
257 | Block35(scale=0.17),
258 | Block35(scale=0.17),
259 | Block35(scale=0.17),
260 | Block35(scale=0.17),
261 | Block35(scale=0.17),
262 | Block35(scale=0.17),
263 | Block35(scale=0.17)
264 | )
265 | self.mixed_6a = Mixed_6a()
266 | self.repeat_1 = nn.Sequential(
267 | Block17(scale=0.10),
268 | Block17(scale=0.10),
269 | Block17(scale=0.10),
270 | Block17(scale=0.10),
271 | Block17(scale=0.10),
272 | Block17(scale=0.10),
273 | Block17(scale=0.10),
274 | Block17(scale=0.10),
275 | Block17(scale=0.10),
276 | Block17(scale=0.10),
277 | Block17(scale=0.10),
278 | Block17(scale=0.10),
279 | Block17(scale=0.10),
280 | Block17(scale=0.10),
281 | Block17(scale=0.10),
282 | Block17(scale=0.10),
283 | Block17(scale=0.10),
284 | Block17(scale=0.10),
285 | Block17(scale=0.10),
286 | Block17(scale=0.10)
287 | )
288 | self.mixed_7a = Mixed_7a()
289 | self.repeat_2 = nn.Sequential(
290 | Block8(scale=0.20),
291 | Block8(scale=0.20),
292 | Block8(scale=0.20),
293 | Block8(scale=0.20),
294 | Block8(scale=0.20),
295 | Block8(scale=0.20),
296 | Block8(scale=0.20),
297 | Block8(scale=0.20),
298 | Block8(scale=0.20)
299 | )
300 | self.block8 = Block8(noReLU=True)
301 | self.conv2d_7b = BasicConv2d(2080, 1536, kernel_size=1, stride=1)
302 | self.avgpool_1a = nn.AvgPool2d(8, count_include_pad=False)
303 | self.last_linear = nn.Linear(1536, num_classes)
304 |
305 | def features(self, input):
306 | x = self.conv2d_1a(input)
307 | x = self.conv2d_2a(x)
308 | x = self.conv2d_2b(x)
309 | x = self.maxpool_3a(x)
310 | x = self.conv2d_3b(x)
311 | x = self.conv2d_4a(x)
312 | x = self.maxpool_5a(x)
313 | x = self.mixed_5b(x)
314 | x = self.repeat(x)
315 | x = self.mixed_6a(x)
316 | x = self.repeat_1(x)
317 | x = self.mixed_7a(x)
318 | x = self.repeat_2(x)
319 | x = self.block8(x)
320 | x = self.conv2d_7b(x)
321 | return x
322 |
323 | def logits(self, features):
324 | x = self.avgpool_1a(features)
325 | x = x.view(x.size(0), -1)
326 | x = F.dropout(x, training=self.training)
327 | x = self.last_linear(x)
328 | return x
329 |
330 | def forward(self, input):
331 | x = self.features(input)
332 | x = self.logits(x)
333 | return x
334 |
335 | def inceptionresnetv2(num_classes=1000, pretrained='imagenet'):
336 | r"""InceptionResNetV2 model architecture from the
337 | `"InceptionV4, Inception-ResNet..." `_ paper.
338 | """
339 | if pretrained:
340 | settings = pretrained_settings['inceptionresnetv2'][pretrained]
341 | assert num_classes == settings['num_classes'], \
342 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
343 |
344 | # both 'imagenet'&'imagenet+background' are loaded from same parameters
345 | model = InceptionResNetV2(num_classes=1001)
346 | model.load_state_dict(model_zoo.load_url(settings['url']))
347 |
348 | if pretrained == 'imagenet':
349 | new_last_linear = nn.Linear(1536, 1000)
350 | new_last_linear.weight.data = model.last_linear.weight.data[1:]
351 | new_last_linear.bias.data = model.last_linear.bias.data[1:]
352 | model.last_linear = new_last_linear
353 |
354 | model.input_space = settings['input_space']
355 | model.input_size = settings['input_size']
356 | model.input_range = settings['input_range']
357 |
358 | model.mean = settings['mean']
359 | model.std = settings['std']
360 | else:
361 | model = InceptionResNetV2(num_classes=num_classes)
362 | return model
363 |
364 | '''
365 | TEST
366 | Run this code with:
367 | ```
368 | cd $HOME/pretrained-models.pytorch
369 | python -m pretrainedmodels.inceptionresnetv2
370 | ```
371 | '''
372 | if __name__ == '__main__':
373 |
374 | assert inceptionresnetv2(num_classes=10, pretrained=None)
375 | print('success')
376 | assert inceptionresnetv2(num_classes=1000, pretrained='imagenet')
377 | print('success')
378 | assert inceptionresnetv2(num_classes=1001, pretrained='imagenet+background')
379 | print('success')
380 |
381 | # fail
382 | assert inceptionresnetv2(num_classes=1001, pretrained='imagenet')
--------------------------------------------------------------------------------
/phase2/noisy_cifar.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | from PIL import Image
3 | import os
4 | import os.path
5 | import numpy as np
6 | import sys
7 | if sys.version_info[0] == 2:
8 | import cPickle as pickle
9 | else:
10 | import pickle
11 |
12 | import torch.utils.data as data
13 | from .utils import download_url, check_integrity, noisify
14 |
15 | class Noisy_CIFAR10(data.Dataset):
16 | """`CIFAR10 `_ Dataset.
17 |
18 | Args:
19 | root (string): Root directory of dataset where directory
20 | ``cifar-10-batches-py`` exists or will be saved to if download is set to True.
21 | train (bool, optional): If True, creates dataset from training set, otherwise
22 | creates from test set.
23 | transform (callable, optional): A function/transform that takes in an PIL image
24 | and returns a transformed version. E.g, ``transforms.RandomCrop``
25 | target_transform (callable, optional): A function/transform that takes in the
26 | target and transforms it.
27 | download (bool, optional): If true, downloads the dataset from the internet and
28 | puts it in root directory. If dataset is already downloaded, it is not
29 | downloaded again.
30 |
31 | """
32 | base_folder = 'cifar-10-batches-py'
33 | url = "https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz"
34 | filename = "cifar-10-python.tar.gz"
35 | tgz_md5 = 'c58f30108f718f92721af3b95e74349a'
36 | train_list = [
37 | ['data_batch_1', 'c99cafc152244af753f735de768cd75f'],
38 | ['data_batch_2', 'd4bba439e000b95fd0a9bffe97cbabec'],
39 | ['data_batch_3', '54ebc095f3ab1f0389bbae665268c751'],
40 | ['data_batch_4', '634d18415352ddfa80567beed471001a'],
41 | ['data_batch_5', '482c414d41f54cd18b22e5b47cb7c3cb'],
42 | ]
43 |
44 | test_list = [
45 | ['test_batch', '40351d587109b95175f43aff81a1287e'],
46 | ]
47 |
48 | def __init__(self, root, train=True,
49 | transform=None, target_transform=None,
50 | download=False,
51 | noise_type=None, noise_rate=0.2, random_state=0):
52 | self.root = os.path.expanduser(root)
53 | self.transform = transform
54 | self.target_transform = target_transform
55 | self.train = train # training set or test set
56 | self.dataset='cifar10'
57 | self.noise_type=noise_type
58 | self.nb_classes=10
59 |
60 | #if download:
61 | # self.download()
62 |
63 | #if not self._check_integrity():
64 | # raise RuntimeError('Dataset not found or corrupted.' +
65 | # ' You can use download=True to download it')
66 |
67 | # now load the picked numpy arrays
68 | if self.train:
69 | self.train_data = []
70 | self.train_labels = []
71 | for fentry in self.train_list:
72 | f = fentry[0]
73 | file = os.path.join(self.root, self.base_folder, f)
74 | fo = open(file, 'rb')
75 | if sys.version_info[0] == 2:
76 | entry = pickle.load(fo)
77 | else:
78 | entry = pickle.load(fo, encoding='latin1')
79 | self.train_data.append(entry['data'])
80 | if 'labels' in entry:
81 | self.train_labels += entry['labels']
82 | else:
83 | self.train_labels += entry['fine_labels']
84 | fo.close()
85 |
86 | self.train_data = np.concatenate(self.train_data)
87 | self.train_data = self.train_data.reshape((50000, 3, 32, 32))
88 | self.train_data = self.train_data.transpose((0, 2, 3, 1)) # convert to HWC
89 | #if noise_type is not None:
90 | if noise_type !='clean':
91 | # noisify train data
92 | self.train_labels=np.asarray([[self.train_labels[i]] for i in range(len(self.train_labels))])
93 | self.train_noisy_labels, self.actual_noise_rate = noisify(dataset=self.dataset, train_labels=self.train_labels, noise_type=noise_type, noise_rate=noise_rate, random_state=random_state, nb_classes=self.nb_classes)
94 | self.train_noisy_labels=[i[0] for i in self.train_noisy_labels]
95 | _train_labels=[i[0] for i in self.train_labels]
96 | self.noise_or_not = np.transpose(self.train_noisy_labels)!=np.transpose(_train_labels)
97 | else:
98 | f = self.test_list[0][0]
99 | file = os.path.join(self.root, self.base_folder, f)
100 | fo = open(file, 'rb')
101 | if sys.version_info[0] == 2:
102 | entry = pickle.load(fo)
103 | else:
104 | entry = pickle.load(fo, encoding='latin1')
105 | self.test_data = entry['data']
106 | if 'labels' in entry:
107 | self.test_labels = entry['labels']
108 | else:
109 | self.test_labels = entry['fine_labels']
110 | fo.close()
111 | self.test_data = self.test_data.reshape((10000, 3, 32, 32))
112 | self.test_data = self.test_data.transpose((0, 2, 3, 1)) # convert to HWC
113 |
114 | def __getitem__(self, index):
115 | """
116 | Args:
117 | index (int): Index
118 |
119 | Returns:
120 | tuple: (image, target) where target is index of the target class.
121 | """
122 | if self.train:
123 | if self.noise_type !='clean':
124 | img, target = self.train_data[index], self.train_noisy_labels[index]
125 | else:
126 | img, target = self.train_data[index], self.train_labels[index]
127 | else:
128 | img, target = self.test_data[index], self.test_labels[index]
129 |
130 | # doing this so that it is consistent with all other datasets
131 | # to return a PIL Image
132 | img = Image.fromarray(img)
133 |
134 | if self.transform is not None:
135 | img = self.transform(img)
136 |
137 | if self.target_transform is not None:
138 | target = self.target_transform(target)
139 |
140 | return img, target, index
141 |
142 | def __len__(self):
143 | if self.train:
144 | return len(self.train_data)
145 | else:
146 | return len(self.test_data)
147 |
148 | def _check_integrity(self):
149 | root = self.root
150 | for fentry in (self.train_list + self.test_list):
151 | filename, md5 = fentry[0], fentry[1]
152 | fpath = os.path.join(root, self.base_folder, filename)
153 | if not check_integrity(fpath, md5):
154 | return False
155 | return True
156 |
157 | def download(self):
158 | import tarfile
159 |
160 | if self._check_integrity():
161 | print('Files already downloaded and verified')
162 | return
163 |
164 | root = self.root
165 | download_url(self.url, root, self.filename, self.tgz_md5)
166 |
167 | # extract file
168 | cwd = os.getcwd()
169 | tar = tarfile.open(os.path.join(root, self.filename), "r:gz")
170 | os.chdir(root)
171 | tar.extractall()
172 | tar.close()
173 | os.chdir(cwd)
174 |
175 | def __repr__(self):
176 | fmt_str = 'Dataset ' + self.__class__.__name__ + '\n'
177 | fmt_str += ' Number of datapoints: {}\n'.format(self.__len__())
178 | tmp = 'train' if self.train is True else 'test'
179 | fmt_str += ' Split: {}\n'.format(tmp)
180 | fmt_str += ' Root Location: {}\n'.format(self.root)
181 | tmp = ' Transforms (if any): '
182 | fmt_str += '{0}{1}\n'.format(tmp, self.transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
183 | tmp = ' Target Transforms (if any): '
184 | fmt_str += '{0}{1}'.format(tmp, self.target_transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
185 | return fmt_str
186 |
187 | class CIFAR100(data.Dataset):
188 | """`CIFAR100 `_ Dataset.
189 |
190 | Args:
191 | root (string): Root directory of dataset where directory
192 | ``cifar-10-batches-py`` exists or will be saved to if download is set to True.
193 | train (bool, optional): If True, creates dataset from training set, otherwise
194 | creates from test set.
195 | transform (callable, optional): A function/transform that takes in an PIL image
196 | and returns a transformed version. E.g, ``transforms.RandomCrop``
197 | target_transform (callable, optional): A function/transform that takes in the
198 | target and transforms it.
199 | download (bool, optional): If true, downloads the dataset from the internet and
200 | puts it in root directory. If dataset is already downloaded, it is not
201 | downloaded again.
202 |
203 | """
204 | base_folder = 'cifar-100-python'
205 | url = "https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz"
206 | filename = "cifar-100-python.tar.gz"
207 | tgz_md5 = 'eb9058c3a382ffc7106e4002c42a8d85'
208 | train_list = [
209 | ['train', '16019d7e3df5f24257cddd939b257f8d'],
210 | ]
211 |
212 | test_list = [
213 | ['test', 'f0ef6b0ae62326f3e7ffdfab6717acfc'],
214 | ]
215 |
216 |
217 | def __init__(self, root, train=True,
218 | transform=None, target_transform=None,
219 | download=False,
220 | noise_type=None, noise_rate=0.2, random_state=0):
221 | self.root = os.path.expanduser(root)
222 | self.transform = transform
223 | self.target_transform = target_transform
224 | self.train = train # training set or test set
225 | self.dataset='cifar100'
226 | self.noise_type=noise_type
227 | self.nb_classes=100
228 |
229 | if download:
230 | self.download()
231 |
232 | if not self._check_integrity():
233 | raise RuntimeError('Dataset not found or corrupted.' +
234 | ' You can use download=True to download it')
235 |
236 | # now load the picked numpy arrays
237 | if self.train:
238 | self.train_data = []
239 | self.train_labels = []
240 | for fentry in self.train_list:
241 | f = fentry[0]
242 | file = os.path.join(self.root, self.base_folder, f)
243 | fo = open(file, 'rb')
244 | if sys.version_info[0] == 2:
245 | entry = pickle.load(fo)
246 | else:
247 | entry = pickle.load(fo, encoding='latin1')
248 | self.train_data.append(entry['data'])
249 | if 'labels' in entry:
250 | self.train_labels += entry['labels']
251 | else:
252 | self.train_labels += entry['fine_labels']
253 | fo.close()
254 |
255 | self.train_data = np.concatenate(self.train_data)
256 | self.train_data = self.train_data.reshape((50000, 3, 32, 32))
257 | self.train_data = self.train_data.transpose((0, 2, 3, 1)) # convert to HWC
258 | if noise_type is not None:
259 | # noisify train data
260 | self.train_labels=np.asarray([[self.train_labels[i]] for i in range(len(self.train_labels))])
261 | self.train_noisy_labels, self.actual_noise_rate = noisify(dataset=self.dataset, train_labels=self.train_labels, noise_type=noise_type, noise_rate=noise_rate, random_state=random_state, nb_classes=self.nb_classes)
262 | self.train_noisy_labels=[i[0] for i in self.train_noisy_labels]
263 | _train_labels=[i[0] for i in self.train_labels]
264 | self.noise_or_not = np.transpose(self.train_noisy_labels)!=np.transpose(_train_labels)
265 | else:
266 | f = self.test_list[0][0]
267 | file = os.path.join(self.root, self.base_folder, f)
268 | fo = open(file, 'rb')
269 | if sys.version_info[0] == 2:
270 | entry = pickle.load(fo)
271 | else:
272 | entry = pickle.load(fo, encoding='latin1')
273 | self.test_data = entry['data']
274 | if 'labels' in entry:
275 | self.test_labels = entry['labels']
276 | else:
277 | self.test_labels = entry['fine_labels']
278 | fo.close()
279 | self.test_data = self.test_data.reshape((10000, 3, 32, 32))
280 | self.test_data = self.test_data.transpose((0, 2, 3, 1)) # convert to HWC
281 |
282 | def __getitem__(self, index):
283 | """
284 | Args:
285 | index (int): Index
286 |
287 | Returns:
288 | tuple: (image, target) where target is index of the target class.
289 | """
290 | if self.train:
291 | if self.noise_type is not None:
292 | img, target = self.train_data[index], self.train_noisy_labels[index]
293 | else:
294 | img, target = self.train_data[index], self.train_labels[index]
295 | else:
296 | img, target = self.test_data[index], self.test_labels[index]
297 |
298 | # doing this so that it is consistent with all other datasets
299 | # to return a PIL Image
300 | img = Image.fromarray(img)
301 |
302 | if self.transform is not None:
303 | img = self.transform(img)
304 |
305 | if self.target_transform is not None:
306 | target = self.target_transform(target)
307 |
308 | return img, target, index
309 |
310 | def __len__(self):
311 | if self.train:
312 | return len(self.train_data)
313 | else:
314 | return len(self.test_data)
315 |
316 | def _check_integrity(self):
317 | root = self.root
318 | for fentry in (self.train_list + self.test_list):
319 | filename, md5 = fentry[0], fentry[1]
320 | fpath = os.path.join(root, self.base_folder, filename)
321 | if not check_integrity(fpath, md5):
322 | return False
323 | return True
324 |
325 | def download(self):
326 | import tarfile
327 |
328 | if self._check_integrity():
329 | print('Files already downloaded and verified')
330 | return
331 |
332 | root = self.root
333 | download_url(self.url, root, self.filename, self.tgz_md5)
334 |
335 | # extract file
336 | cwd = os.getcwd()
337 | tar = tarfile.open(os.path.join(root, self.filename), "r:gz")
338 | os.chdir(root)
339 | tar.extractall()
340 | tar.close()
341 | os.chdir(cwd)
342 |
343 | def __repr__(self):
344 | fmt_str = 'Dataset ' + self.__class__.__name__ + '\n'
345 | fmt_str += ' Number of datapoints: {}\n'.format(self.__len__())
346 | tmp = 'train' if self.train is True else 'test'
347 | fmt_str += ' Split: {}\n'.format(tmp)
348 | fmt_str += ' Root Location: {}\n'.format(self.root)
349 | tmp = ' Transforms (if any): '
350 | fmt_str += '{0}{1}\n'.format(tmp, self.transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
351 | tmp = ' Target Transforms (if any): '
352 | fmt_str += '{0}{1}'.format(tmp, self.target_transform.__repr__().replace('\n', '\n' + ' ' * len(tmp)))
353 | return fmt_str
354 |
355 |
356 |
--------------------------------------------------------------------------------