├── .gitignore
├── 2018_AL_defect_train.py
├── 2018_bd_tiangong_train.py
├── 2018_bd_xjtu_train.py
├── 2018_pdr_train.py
├── README.md
├── dataset
├── AL_defect_dataset.py
├── __init__.py
├── bd_tiangong_dataset.py
├── bd_xjtu_dataset.py
├── data_aug.py
└── pdr_dataset.py
├── models
├── __init__.py
├── inception_resnet_v2.py
├── inception_v4.py
├── multiscale_resnet.py
└── xception.py
├── predict
├── bd_tiangong_model_merge.py
├── bd_tiangong_pred.py
├── bd_tiangong_pred_unknow.py
└── bd_xjtu_pred.py
└── utils
├── __init__.py
├── losses.py
└── train_util.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.txt
3 | *.pth
4 | predict/Baidu/
5 | .idea
--------------------------------------------------------------------------------
/2018_AL_defect_train.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import os
3 | import pandas as pd
4 | from sklearn.model_selection import train_test_split
5 | from dataset.AL_defect_dataset import collate_fn, dataset,get_image_pd
6 | import torch
7 | import torch.utils.data as torchdata
8 | from torchvision import datasets, models, transforms
9 | from torchvision.models import resnet50,resnet101
10 | from models.multiscale_resnet import multiscale_resnet
11 | import torch.optim as optim
12 | from torch.optim import lr_scheduler
13 | from utils.train_util import train, trainlog
14 | from torch.nn import CrossEntropyLoss
15 | import logging
16 | from dataset.data_aug import *
17 | import sys
18 | import argparse
19 | from dataset.AL_defect_dataset import defect_label
20 |
21 | reload(sys)
22 | sys.setdefaultencoding('utf8')
23 | '''
24 | https://tianchi.aliyun.com/competition/information.htm?spm=5176.11165268.5678.2.7d4910c5YfrwzY&raceId=231682
25 | '''
26 | parser = argparse.ArgumentParser()
27 | parser.add_argument('--batch_size', type=int, default=8, help='size of each image batch')
28 |
29 | parser.add_argument('--learning_rate', type=float, default=0.001, help='learning rate')
30 | parser.add_argument('--checkpoint_dir', type=str, default='/media/hszc/model/detao/models/AL/resnet50', help='directory where model checkpoints are saved')
31 | parser.add_argument('--cuda_device', type=str, default="2,3", help='whether to use cuda if available')
32 | parser.add_argument('--net', dest='net',type=str, default='resnet50',help='resnet101,resnet50')
33 | parser.add_argument('--resume', type=str, default=None, help='path to resume weights file')
34 | parser.add_argument('--epochs', type=int, default=30, help='number of epochs')
35 | parser.add_argument('--start_epoch', type=int, default=0, help='number of start epoch')
36 |
37 | parser.add_argument('--save_checkpoint_val_interval', type=int, default=300, help='interval between saving model weights')
38 | parser.add_argument('--print_interval', type=int, default=100, help='interval between print log')
39 | parser.add_argument('--img_root_train', type=str, default= "/media/hszc/model/detao/data/guangdong/guangdong_round1_train2_2018091622/瑕疵样本", help='whether to img root')
40 |
41 | parser.add_argument('--n_cpu', type=int, default=4, help='number of cpu threads to use during batch generation')
42 | opt = parser.parse_args()
43 | os.environ["CUDA_VISIBLE_DEVICES"] = opt.cuda_device
44 | if __name__ == '__main__':
45 |
46 | # # saving dir
47 | save_dir = opt.checkpoint_dir
48 | if not os.path.exists(save_dir):
49 | os.makedirs(save_dir)
50 |
51 | logfile = '%s/trainlog.log' % save_dir
52 | trainlog(logfile)
53 |
54 | all_pd= get_image_pd(opt.img_root_train)
55 | train_pd,val_pd = train_test_split(all_pd, test_size=0.1, random_state=53,stratify=all_pd["label"])
56 |
57 | print(val_pd.shape)
58 |
59 | '''数据扩增'''
60 | data_transforms = {
61 | 'train': Compose([
62 | Resize(size=(640, 640)),
63 | FixRandomRotate(bound='Random'),
64 | RandomHflip(),
65 | RandomVflip(),
66 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
67 | ]),
68 | 'val': Compose([
69 | Resize(size=(640, 640)),
70 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
71 | ]),
72 | }
73 |
74 | data_set = {}
75 | data_set['train'] = dataset( anno_pd=train_pd, transforms=data_transforms["train"])
76 | data_set['val'] = dataset( anno_pd=val_pd, transforms=data_transforms["val"])
77 |
78 | dataloader = {}
79 | dataloader['train']=torch.utils.data.DataLoader(data_set['train'], batch_size=opt.batch_size,
80 | shuffle=True, num_workers=2*opt.n_cpu,collate_fn=collate_fn)
81 | dataloader['val']=torch.utils.data.DataLoader(data_set['val'], batch_size=4,
82 | shuffle=True, num_workers=opt.n_cpu,collate_fn=collate_fn)
83 | '''model'''
84 | if opt.net == "resnet50":
85 | model =resnet50(pretrained=True)
86 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
87 | model.fc = torch.nn.Linear(model.fc.in_features,61)
88 | elif opt.net == "resnet101":
89 | model =resnet101(pretrained=True)
90 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
91 | model.fc = torch.nn.Linear(model.fc.in_features,61)
92 |
93 | if opt.resume:
94 | model.eval()
95 | logging.info('resuming finetune from %s' % opt.resume)
96 | try:
97 | model.load_state_dict(torch.load(opt.resume))
98 | model = torch.nn.DataParallel(model)
99 | except KeyError:
100 | model = torch.nn.DataParallel(model)
101 | model.load_state_dict(torch.load(opt.resume))
102 | else:
103 | model = torch.nn.DataParallel(model)
104 | model = model.cuda()
105 |
106 | optimizer = optim.SGD(model.parameters(), lr=opt.learning_rate, momentum=0.9, weight_decay=1e-5)
107 | criterion = CrossEntropyLoss()
108 | exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)
109 |
110 | train(model,
111 | epoch_num=opt.epochs,
112 | start_epoch=opt.start_epoch,
113 | optimizer=optimizer,
114 | criterion=criterion,
115 | exp_lr_scheduler=exp_lr_scheduler,
116 | data_set=data_set,
117 | data_loader=dataloader,
118 | save_dir=save_dir,
119 | print_inter=opt.print_interval,
120 | val_inter=opt.save_checkpoint_val_interval)
--------------------------------------------------------------------------------
/2018_bd_tiangong_train.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import os
3 | import pandas as pd
4 | from sklearn.model_selection import train_test_split
5 | from dataset.bd_tiangong_dataset import collate_fn, dataset
6 | import torch
7 | import torch.utils.data as torchdata
8 | from torchvision import datasets, models, transforms
9 | from torchvision.models import resnet50,resnet101
10 | from models.multiscale_resnet import multiscale_resnet
11 | import torch.optim as optim
12 | from torch.optim import lr_scheduler
13 | from utils.train_util import train, trainlog
14 | from torch.nn import CrossEntropyLoss
15 | import logging
16 | from dataset.data_aug import *
17 | import sys
18 | import argparse
19 | from dataset.bd_tiangong_dataset import class2label
20 |
21 | reload(sys)
22 | sys.setdefaultencoding('utf8')
23 | '''
24 | http://dianshi.baidu.com/dianshi/pc/competition/22/rank'''
25 | parser = argparse.ArgumentParser()
26 | parser.add_argument('--batch_size', type=int, default=8, help='size of each image batch')
27 |
28 | parser.add_argument('--learning_rate', type=float, default=0.001, help='learning rate')
29 | parser.add_argument('--checkpoint_dir', type=str, default='/media/hszc/model/detao/models/bd_tiangong/resnet50', help='directory where model checkpoints are saved')
30 | parser.add_argument('--cuda_device', type=str, default="0", help='whether to use cuda if available')
31 | parser.add_argument('--net', dest='net',type=str, default='resnet50',help='resnet101,resnet50')
32 | parser.add_argument('--resume', type=str, default=None, help='path to resume weights file')
33 | parser.add_argument('--epochs', type=int, default=100, help='number of epochs')
34 | parser.add_argument('--start_epoch', type=int, default=0, help='number of start epoch')
35 |
36 | parser.add_argument('--save_checkpoint_val_interval', type=int, default=200, help='interval between saving model weights')
37 | parser.add_argument('--print_interval', type=int, default=100, help='interval between print log')
38 | # parser.add_argument('--img_root_train', type=str, default= "/media/hszc/model/detao/data/guangdong/guangdong_round1_train2_2018091622/瑕疵样本", help='whether to img root')
39 |
40 | parser.add_argument('--n_cpu', type=int, default=4, help='number of cpu threads to use during batch generation')
41 | opt = parser.parse_args()
42 | os.environ["CUDA_VISIBLE_DEVICES"] = opt.cuda_device
43 | if __name__ == '__main__':
44 |
45 | # # saving dir
46 | save_dir = opt.checkpoint_dir
47 | if not os.path.exists(save_dir):
48 | os.makedirs(save_dir)
49 |
50 | logfile = '%s/trainlog.log' % save_dir
51 | trainlog(logfile)
52 |
53 | label_csv ="/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛训练集2000/光学数据集-预赛训练集-2000-有标签.csv"
54 | imgroot="/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛训练集2000/预赛训练集-2000"
55 | label = pd.read_csv(label_csv,names=["ImageName","class"])
56 | label["label"]=label["class"].apply(lambda x:class2label[x])
57 | train_pd,val_pd = train_test_split(label, test_size=0.12, random_state=43,stratify=label["label"])
58 |
59 | print(val_pd.shape)
60 |
61 | '''数据扩增'''
62 | data_transforms = {
63 | 'train': Compose([
64 | Resize(size=(256, 256)),
65 | FixRandomRotate(bound='Random'),
66 | RandomHflip(),
67 | RandomVflip(),
68 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
69 | ]),
70 | 'val': Compose([
71 | Resize(size=(256, 256)),
72 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
73 | ]),
74 | }
75 |
76 | data_set = {}
77 | data_set['train'] = dataset(imgroot, anno_pd=train_pd, transforms=data_transforms["train"])
78 | data_set['val'] = dataset(imgroot, anno_pd=val_pd, transforms=data_transforms["val"])
79 |
80 | dataloader = {}
81 | dataloader['train']=torch.utils.data.DataLoader(data_set['train'], batch_size=opt.batch_size,
82 | shuffle=True, num_workers=2*opt.n_cpu,collate_fn=collate_fn)
83 | dataloader['val']=torch.utils.data.DataLoader(data_set['val'], batch_size=4,
84 | shuffle=True, num_workers=opt.n_cpu,collate_fn=collate_fn)
85 | '''model'''
86 | if opt.net == "resnet50":
87 | model =resnet50(pretrained=True)
88 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
89 | model.fc = torch.nn.Linear(model.fc.in_features,6)
90 | elif opt.net == "resnet101":
91 | model =resnet101(pretrained=True)
92 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
93 | model.fc = torch.nn.Linear(model.fc.in_features,6)
94 |
95 | if opt.resume:
96 | model.eval()
97 | logging.info('resuming finetune from %s' % opt.resume)
98 | try:
99 | model.load_state_dict(torch.load(opt.resume))
100 | except KeyError:
101 | model = torch.nn.DataParallel(model)
102 | model.load_state_dict(torch.load(opt.resume))
103 | model = model.cuda()
104 |
105 | optimizer = optim.SGD(model.parameters(), lr=opt.learning_rate, momentum=0.9, weight_decay=1e-5)
106 | criterion = CrossEntropyLoss()
107 | exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=15, gamma=0.1)
108 |
109 | train(model,
110 | epoch_num=opt.epochs,
111 | start_epoch=opt.start_epoch,
112 | optimizer=optimizer,
113 | criterion=criterion,
114 | exp_lr_scheduler=exp_lr_scheduler,
115 | data_set=data_set,
116 | data_loader=dataloader,
117 | save_dir=save_dir,
118 | print_inter=opt.print_interval,
119 | val_inter=opt.save_checkpoint_val_interval)
--------------------------------------------------------------------------------
/2018_bd_xjtu_train.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import os
3 | import pandas as pd
4 | from sklearn.model_selection import train_test_split
5 | from dataset.bd_xjtu_dataset import collate_fn, dataset
6 | import torch
7 | import torch.utils.data as torchdata
8 | from torchvision import datasets, models, transforms
9 | from torchvision.models import resnet50
10 | import torch.optim as optim
11 | from torch.optim import lr_scheduler
12 | from utils.train_util import train, trainlog
13 | from torch.nn import CrossEntropyLoss
14 | import logging
15 | from dataset.data_aug import *
16 | os.environ["CUDA_VISIBLE_DEVICES"] = "0"
17 | '''
18 | http://dianshi.baidu.com/gemstone/competitions/detail?raceId=17
19 | '''
20 | save_dir = '/media/hszc/model/detao/baidu_model/resnet50'
21 | if not os.path.exists(save_dir):
22 | os.makedirs(save_dir)
23 | logfile = '%s/trainlog.log'%save_dir
24 | trainlog(logfile)
25 |
26 | rawdata_root = '/media/hszc/data/detao/data/baidu/datasets/train'
27 | all_pd = pd.read_csv("/media/hszc/data/detao/data/baidu/datasets/train.txt",sep=" ",
28 | header=None, names=['ImageName', 'label'])
29 | train_pd, val_pd = train_test_split(all_pd, test_size=0.15, random_state=43,
30 | stratify=all_pd['label'])
31 | print(val_pd.shape)
32 |
33 | '''数据扩增'''
34 | data_transforms = {
35 | 'train': Compose([
36 | RandomRotate(angles=(-15,15)),
37 | ExpandBorder(size=(368,368),resize=True),
38 | RandomResizedCrop(size=(336, 336)),
39 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
40 | ]),
41 | 'val': Compose([
42 | ExpandBorder(size=(336,336),resize=True),
43 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
44 | ]),
45 | }
46 |
47 | data_set = {}
48 | data_set['train'] = dataset(imgroot=rawdata_root,anno_pd=train_pd,
49 | transforms=data_transforms["train"],
50 | )
51 | data_set['val'] = dataset(imgroot=rawdata_root,anno_pd=val_pd,
52 | transforms=data_transforms["val"],
53 | )
54 | dataloader = {}
55 | dataloader['train']=torch.utils.data.DataLoader(data_set['train'], batch_size=4,
56 | shuffle=True, num_workers=4,collate_fn=collate_fn)
57 | dataloader['val']=torch.utils.data.DataLoader(data_set['val'], batch_size=4,
58 | shuffle=True, num_workers=4,collate_fn=collate_fn)
59 | '''model'''
60 | model =resnet50(pretrained=True)
61 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
62 | model.fc = torch.nn.Linear(model.fc.in_features,100)
63 |
64 | base_lr =0.001
65 | resume =None
66 | if resume:
67 | logging.info('resuming finetune from %s'%resume)
68 | model.load_state_dict(torch.load(resume))
69 | model = model.cuda()
70 |
71 | optimizer = optim.SGD(model.parameters(), lr=base_lr, momentum=0.9, weight_decay=1e-5)
72 | criterion = CrossEntropyLoss()
73 | exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=6, gamma=0.1)
74 |
75 | train(model,
76 | epoch_num=50,
77 | start_epoch=0,
78 | optimizer=optimizer,
79 | criterion=criterion,
80 | exp_lr_scheduler=exp_lr_scheduler,
81 | data_set=data_set,
82 | data_loader=dataloader,
83 | save_dir=save_dir,
84 | print_inter=50,
85 | val_inter=400)
--------------------------------------------------------------------------------
/2018_pdr_train.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import os
3 | import pandas as pd
4 | from sklearn.model_selection import train_test_split
5 | from dataset.pdr_dataset import collate_fn, dataset
6 | import torch
7 | import torch.utils.data as torchdata
8 | from torchvision import datasets, models, transforms
9 | from torchvision.models import resnet50,resnet101
10 | from models.xception import pdr_xception
11 | from models.inception_v4 import inceptionv4
12 | from models.multiscale_resnet import multiscale_resnet
13 | import torch.optim as optim
14 | from torch.optim import lr_scheduler
15 | from utils.train_util import train, trainlog
16 | from torch.nn import CrossEntropyLoss
17 | from utils.losses import FocalLoss
18 | import logging
19 | from dataset.data_aug import *
20 | import sys
21 | import argparse
22 | reload(sys)
23 | sys.setdefaultencoding('utf8')
24 | '''
25 | https://challenger.ai/competition/pdr2018
26 | '''
27 | parser = argparse.ArgumentParser()
28 | parser.add_argument('--batch_size', type=int, default=32, help='size of each image batch')
29 |
30 | parser.add_argument('--learning_rate', type=float, default=0.0001, help='learning rate')
31 | parser.add_argument('--checkpoint_dir', type=str, default='/media/hszc/model/detao/models/pdr/resnet101_32', help='directory where model checkpoints are saved')
32 | parser.add_argument('--cuda_device', type=str, default="0,3", help='whether to use cuda if available')
33 | parser.add_argument('--net', dest='net',type=str, default='resnet101',help='resnet101,resnet50,xception,inceptionv4')
34 | parser.add_argument('--loss', dest='loss',type=str, default='CrossEntropyLoss',help='focal_loss,CrossEntropyLoss')
35 | parser.add_argument('--optim', dest='optim',type=str, default='sgd',help='adam,sgd')
36 | parser.add_argument('--resume', type=str, default="/media/hszc/model/detao/models/pdr/resnet101/weights-6-1718-[0.8310].pth", help='path to resume weights file')
37 | # parser.add_argument('--resume', type=str, default="/media/hszc/model/detao/models/pdr/inceptionv4/weights-9-1577-[0.8312].pth", help='path to resume weights file')
38 | parser.add_argument('--epochs', type=int, default=30, help='number of epochs')
39 | parser.add_argument('--start_epoch', type=int, default=0, help='number of start epoch')
40 |
41 | parser.add_argument('--save_checkpoint_val_interval', type=int, default=500, help='interval between saving model weights')
42 | parser.add_argument('--print_interval', type=int, default=100, help='interval between print log')
43 | parser.add_argument('--img_root_train', type=str, default= "/media/hszc/model/detao/data/pdr2/ai_challenger_pdr2018_trainingset_20180905/AgriculturalDisease_trainingset", help='whether to img root')
44 | parser.add_argument('--img_root_val', type=str, default= "/media/hszc/model/detao/data/pdr2/ai_challenger_pdr2018_validationset_20180905/AgriculturalDisease_validationset", help='whether to img root')
45 |
46 | parser.add_argument('--n_cpu', type=int, default=4, help='number of cpu threads to use during batch generation')
47 | opt = parser.parse_args()
48 | os.environ["CUDA_VISIBLE_DEVICES"] = opt.cuda_device
49 | if __name__ == '__main__':
50 |
51 | # # saving dir
52 | save_dir = opt.checkpoint_dir
53 | if not os.path.exists(save_dir):
54 | os.makedirs(save_dir)
55 |
56 | logfile = '%s/trainlog.log' % save_dir
57 | trainlog(logfile)
58 | logging.info(opt)
59 |
60 | train_info = open(os.path.join(opt.img_root_train, "AgriculturalDisease_train_annotations.json"))
61 | val_info = open(os.path.join(opt.img_root_val, "AgriculturalDisease_validation_annotations.json"))
62 |
63 | train_pd = pd.read_json(train_info)
64 | val_pd = pd.read_json(val_info)
65 | train_pd["label"] = train_pd['disease_class']
66 | val_pd["label"] = val_pd['disease_class']
67 |
68 | train_pd["ImageName"]=train_pd["image_id"].apply(lambda x:os.path.join(opt.img_root_train,"images",x))
69 | val_pd["ImageName"]=val_pd["image_id"].apply(lambda x:os.path.join(opt.img_root_val,"images",x))
70 |
71 | print(val_pd.shape)
72 |
73 | '''数据扩增'''
74 | if opt.net == "resnet50" :
75 |
76 | data_transforms = {
77 | 'train': Compose([
78 | RandomRotate(angles=(-15,15)),
79 | ExpandBorder(size=(368,368),resize=True),
80 | RandomResizedCrop(size=(336, 336)),
81 | RandomHflip(),
82 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
83 | ]),
84 | 'val': Compose([
85 | ExpandBorder(size=(336,336),resize=True),
86 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
87 | ]),
88 | }
89 | elif opt.net == "resnet101":
90 | data_transforms = {
91 | 'train': Compose([
92 | RandomRotate(angles=(-15,15)),
93 | ExpandBorder(size=(396,396),resize=True),
94 | RandomResizedCrop(size=(368, 368)),
95 | RandomHflip(),
96 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
97 | ]),
98 | 'val': Compose([
99 | ExpandBorder(size=(368,368),resize=True),
100 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
101 | ]),
102 | }
103 | elif opt.net == "inceptionv4" or opt.net == "xception" :
104 | data_transforms = {
105 | 'train': Compose([
106 | RandomRotate(angles=(-15,15)),
107 | ExpandBorder(size=(428,428),resize=True),
108 | RandomResizedCrop(size=(396, 396)),
109 | RandomHflip(),
110 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
111 | ]),
112 | 'val': Compose([
113 | ExpandBorder(size=(396,396),resize=True),
114 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
115 | ]),
116 | }
117 |
118 | data_set = {}
119 | data_set['train'] = dataset(anno_pd=train_pd,
120 | transforms=data_transforms["train"],
121 | )
122 | data_set['val'] = dataset(anno_pd=val_pd,
123 | transforms=data_transforms["val"],
124 | )
125 | dataloader = {}
126 | dataloader['train']=torch.utils.data.DataLoader(data_set['train'], batch_size=opt.batch_size,
127 | shuffle=True, num_workers=2*opt.n_cpu,collate_fn=collate_fn)
128 | dataloader['val']=torch.utils.data.DataLoader(data_set['val'], batch_size=8,
129 | shuffle=True, num_workers=opt.n_cpu,collate_fn=collate_fn)
130 | '''model'''
131 | if opt.net == "resnet50":
132 | model =resnet50(pretrained=True)
133 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
134 | model.fc = torch.nn.Linear(model.fc.in_features,61)
135 | elif opt.net == "resnet101":
136 | model =resnet101(pretrained=True)
137 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
138 | model.fc = torch.nn.Linear(model.fc.in_features,61)
139 | elif opt.net == "xception":
140 | model =pdr_xception(61)
141 | elif opt.net == "inceptionv4":
142 | model =inceptionv4(61)
143 | if opt.resume:
144 | logging.info('resuming finetune from %s'%opt.resume)
145 | model.load_state_dict(torch.load(opt.resume))
146 | model= torch.nn.DataParallel(model)
147 | model = model.cuda()
148 | if opt.optim =="sgd":
149 | optimizer = optim.SGD(model.parameters(), lr=opt.learning_rate, momentum=0.9, weight_decay=1e-5)
150 | elif opt.optim =="adam":
151 | optimizer = optim.Adam(model.parameters(), lr=opt.learning_rate, weight_decay=1e-5)
152 |
153 | if opt.loss =="CrossEntropyLoss":
154 | criterion = CrossEntropyLoss()
155 | else:
156 | criterion = FocalLoss(class_num=61)
157 |
158 | exp_lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=6, gamma=0.1)
159 |
160 | train(model,
161 | epoch_num=opt.epochs,
162 | start_epoch=opt.start_epoch,
163 | optimizer=optimizer,
164 | criterion=criterion,
165 | exp_lr_scheduler=exp_lr_scheduler,
166 | data_set=data_set,
167 | data_loader=dataloader,
168 | save_dir=save_dir,
169 | print_inter=opt.print_interval,
170 | val_inter=opt.save_checkpoint_val_interval)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 基于pytorch框架的分类baseline
2 | =========================================
3 | [百度-西交大·大数据竞赛2018——商家招牌的分类与检测](http://dianshi.baidu.com/gemstone/competitions/detail?raceId=17):单模型线上0.99+
4 |
5 | [天池 > 广东工业智造大数据创新大赛:铝型材表面瑕疵识别](https://tianchi.aliyun.com/competition/information.htm?spm=5176.11165268.5678.2.7d4910c5YfrwzY&raceId=231682):单模型线上0.91+
6 |
7 | [农作物病害检测](https://challenger.ai/competition/pdr2018):单模型线上0.845+
8 |
9 | [“探寻地球密码”天宫数据利用大赛](http://dianshi.baidu.com/dianshi/pc/competition/22/rank):单模型未调参线上0.99+
10 |
11 | --------------------------------------------------------
12 | 运行环境:Ubuntu系统 Python2 pytorch0.3
13 | --------------------------------------------------------
14 |
--------------------------------------------------------------------------------
/dataset/AL_defect_dataset.py:
--------------------------------------------------------------------------------
1 | # coding=utf8
2 | from __future__ import division
3 | import os
4 | import torch
5 | import torch.utils.data as data
6 | import PIL.Image as Image
7 | from data_aug import *
8 | import cv2
9 | import numpy as np
10 | import random
11 | import glob
12 | import pandas as pd
13 | defect_label_order = ['norm', 'defect1', 'defect2', 'defect3', 'defect4', 'defect5', 'defect6', 'defect7',
14 | 'defect8', 'defect9', 'defect10', 'defect11']
15 | defect_code = {
16 | '正常': 'norm',
17 | '不导电': 'defect1',
18 | '擦花': 'defect2',
19 | '横条压凹': 'defect3',
20 | '桔皮': 'defect4',
21 | '漏底': 'defect5',
22 | '碰伤': 'defect6',
23 | '起坑': 'defect7',
24 | '凸粉': 'defect8',
25 | '涂层开裂': 'defect9',
26 | '脏点': 'defect10',
27 | '其他': 'defect11'
28 | }
29 | defect_label = {
30 | '正常': '0',
31 | '不导电': '1',
32 | '擦花': '2',
33 | '横条压凹': '3',
34 | '桔皮': '4',
35 | '漏底': '5',
36 | '碰伤': '6',
37 | '起坑': '7',
38 | '凸粉': '8',
39 | '涂层开裂':'9',
40 | '脏点': '10',
41 | '其他': '11'
42 | }
43 | label2defect_map = dict(zip(defect_label.values(), defect_label.keys()))
44 |
45 | def get_image_pd(img_root):
46 | img_list = glob.glob(img_root + "/*/*.jpg")
47 | img_list2 = glob.glob(img_root+ "/*/*/*.jpg")
48 |
49 | image_pd1 = pd.DataFrame(img_list, columns=["ImageName"])
50 |
51 | image_pd2 = pd.DataFrame(img_list2, columns=["ImageName"])
52 | image_pd1["label_name"]=image_pd1["ImageName"].apply(lambda x:x.split("/")[-2])
53 | image_pd2["label_name"]=image_pd2["ImageName"].apply(lambda x:x.split("/")[-3])
54 | all_pd=image_pd1.append(image_pd2)
55 | all_pd["label"]=all_pd["label_name"].apply(lambda x:defect_label[x])
56 | print(all_pd["label"].value_counts())
57 | return all_pd
58 |
59 | class dataset(data.Dataset):
60 | def __init__(self, anno_pd, transforms=None,debug=False,test=False):
61 | self.paths = anno_pd['ImageName'].tolist()
62 | self.labels = anno_pd['label'].tolist()
63 | self.transforms = transforms
64 | self.debug=debug
65 | self.test=test
66 |
67 | def __len__(self):
68 | return len(self.paths)
69 |
70 | def __getitem__(self, item):
71 | img_path =self.paths[item]
72 | img_id =img_path.split("/")[-1]
73 | img =cv2.imread(img_path) #BGR
74 |
75 | img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # [h,w,3] RGB
76 |
77 | if self.transforms is not None:
78 | img = self.transforms(img)
79 | label = self.labels[item]
80 | if self.debug:
81 | print(label)
82 | plt.imshow(img)
83 | plt.show()
84 | if self.test:
85 | return torch.from_numpy(img).float(), int(label)
86 | else:
87 | return torch.from_numpy(img).float(), int(label)
88 |
89 |
90 | def collate_fn(batch):
91 | imgs = []
92 | label = []
93 |
94 | for sample in batch:
95 | imgs.append(sample[0])
96 | label.append(sample[1])
97 |
98 | return torch.stack(imgs, 0), \
99 | label
100 |
101 | if __name__ == '__main__':
102 | import matplotlib.pyplot as plt
103 | import pandas as pd
104 | import sys
105 | from sklearn.model_selection import train_test_split
106 | reload(sys)
107 | sys.setdefaultencoding('utf8')
108 | rawdata_root = '/media/hszc/model/detao/data/guangdong/guangdong_round1_train2_2018091622/瑕疵样本'
109 | all_pd= get_image_pd(rawdata_root)
110 | train_pd,val_pd = train_test_split(all_pd, test_size=0.15, random_state=43,stratify=all_pd["label"])
111 |
112 | print(val_pd["label"].value_counts())
113 |
114 | class train_Aug(object):
115 | def __init__(self):
116 | self.augment = Compose([
117 | Resize(size=(640, 640)),
118 | FixRandomRotate(bound='Random'),
119 | RandomHflip(),
120 | RandomVflip(),
121 | # Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
122 | ])
123 |
124 | def __call__(self, *args):
125 | return self.augment(*args)
126 | data_set = {}
127 | data_set['val'] = dataset(anno_pd=train_pd,transforms=train_Aug(),debug=True)
128 | for data in data_set["val"]:
129 | image, label =data
130 | print(label)
--------------------------------------------------------------------------------
/dataset/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OdingdongO/pytorch_classification/0b66c6f6aabf66eda0591712525ec036ee9a94e5/dataset/__init__.py
--------------------------------------------------------------------------------
/dataset/bd_tiangong_dataset.py:
--------------------------------------------------------------------------------
1 | # coding=utf8
2 | from __future__ import division
3 | import os
4 | import torch
5 | import torch.utils.data as data
6 | import PIL.Image as Image
7 | from data_aug import *
8 | import cv2
9 | class2label={"DESERT":0,"MOUNTAIN":1,"OCEAN":2,"FARMLAND":3,"LAKE":4,"CITY":5}
10 | label2class=["DESERT","MOUNTAIN","OCEAN","FARMLAND","LAKE","CITY"]
11 |
12 | class dataset(data.Dataset):
13 | def __init__(self, imgroot, anno_pd, transforms=None):
14 | self.root_path = imgroot
15 | self.paths = anno_pd['ImageName'].tolist()
16 | self.labels = anno_pd['label'].tolist()
17 | self.transforms = transforms
18 |
19 | def __len__(self):
20 | return len(self.paths)
21 |
22 | def __getitem__(self, item):
23 | img_path = os.path.join(self.root_path, self.paths[item])
24 |
25 | img =cv2.imread(img_path)
26 | img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # [h,w,3] RGB
27 |
28 | if self.transforms is not None:
29 | img = self.transforms(img)
30 | label = self.labels[item]
31 | # plt.imshow(img)
32 | # plt.show()
33 | return torch.from_numpy(img).float(), label
34 |
35 | def pil_loader(self,imgpath):
36 | with open(imgpath, 'rb') as f:
37 | with Image.open(f) as img:
38 | return img.convert('RGB')
39 | def collate_fn(batch):
40 | imgs = []
41 | label = []
42 |
43 | for sample in batch:
44 | imgs.append(sample[0])
45 | label.append(sample[1])
46 |
47 | return torch.stack(imgs, 0), \
48 | label
49 |
50 | if __name__ == '__main__':
51 | import matplotlib.pyplot as plt
52 | import pandas as pd
53 | import sys
54 | from sklearn.model_selection import train_test_split
55 | reload(sys)
56 | sys.setdefaultencoding('utf8')
57 | label_csv ="/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛训练集2000/光学数据集-预赛训练集-2000-有标签.csv"
58 | imgroot="/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛训练集2000/预赛训练集-2000"
59 | label = pd.read_csv(label_csv,names=["ImageName","class"])
60 | label["label"]=label["class"].apply(lambda x:class2label[x])
61 | print(label["label"].value_counts())
62 | train_pd,val_pd = train_test_split(label, test_size=0.15, random_state=43,stratify=label["label"])
63 | data_set = {}
64 | data_set['val'] = dataset(imgroot,anno_pd=train_pd,transforms=None)
65 | for data in data_set["val"]:
66 | image, label =data
67 | print(label)
68 |
--------------------------------------------------------------------------------
/dataset/bd_xjtu_dataset.py:
--------------------------------------------------------------------------------
1 | # coding=utf8
2 | from __future__ import division
3 | import os
4 | import torch
5 | import torch.utils.data as data
6 | import PIL.Image as Image
7 | from data_aug import *
8 | import cv2
9 | class dataset(data.Dataset):
10 | def __init__(self, imgroot, anno_pd, transforms=None):
11 | self.root_path = imgroot
12 | self.paths = anno_pd['ImageName'].tolist()
13 | self.labels = anno_pd['label'].tolist()
14 | self.transforms = transforms
15 |
16 | def __len__(self):
17 | return len(self.paths)
18 |
19 | def __getitem__(self, item):
20 | img_path = os.path.join(self.root_path, self.paths[item])
21 |
22 | img =cv2.imread(img_path)
23 | img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # [h,w,3] RGB
24 |
25 | if self.transforms is not None:
26 | img = self.transforms(img)
27 | label = self.labels[item]-1
28 |
29 | return torch.from_numpy(img).float(), label
30 |
31 | def pil_loader(self,imgpath):
32 | with open(imgpath, 'rb') as f:
33 | with Image.open(f) as img:
34 | return img.convert('RGB')
35 | def collate_fn(batch):
36 | imgs = []
37 | label = []
38 |
39 | for sample in batch:
40 | imgs.append(sample[0])
41 | label.append(sample[1])
42 |
43 | return torch.stack(imgs, 0), \
44 | label
--------------------------------------------------------------------------------
/dataset/data_aug.py:
--------------------------------------------------------------------------------
1 | from __future__ import division
2 | import cv2
3 | import numpy as np
4 | from numpy import random
5 | import math
6 | from sklearn.utils import shuffle
7 |
8 | __all__ = ['Compose','RandomHflip', 'RandomUpperCrop', 'Resize', 'UpperCrop', 'RandomBottomCrop',"RandomErasing",
9 | 'BottomCrop', 'Normalize', 'RandomSwapChannels', 'RandomRotate', 'RandomHShift',"CenterCrop","RandomVflip",
10 | 'ExpandBorder', 'RandomResizedCrop','RandomDownCrop', 'DownCrop', 'ResizedCrop',"FixRandomRotate"]
11 |
12 | def rotate_nobound(image, angle, center=None, scale=1.):
13 | (h, w) = image.shape[:2]
14 |
15 |
16 | # if the center is None, initialize it as the center of
17 | # the image
18 | if center is None:
19 | center = (w // 2, h // 2)
20 |
21 | # perform the rotation
22 | M = cv2.getRotationMatrix2D(center, angle, scale)
23 | rotated = cv2.warpAffine(image, M, (w, h))
24 |
25 | return rotated
26 |
27 | def scale_down(src_size, size):
28 | w, h = size
29 | sw, sh = src_size
30 | if sh < h:
31 | w, h = float(w * sh) / h, sh
32 | if sw < w:
33 | w, h = sw, float(h * sw) / w
34 | return int(w), int(h)
35 |
36 |
37 | def fixed_crop(src, x0, y0, w, h, size=None):
38 | out = src[y0:y0 + h, x0:x0 + w]
39 | if size is not None and (w, h) != size:
40 | out = cv2.resize(out, (size[0], size[1]), interpolation=cv2.INTER_CUBIC)
41 | return out
42 | class FixRandomRotate(object):
43 | def __init__(self, angles=[0,90,180,270], bound=False):
44 | self.angles = angles
45 | self.bound = bound
46 |
47 | def __call__(self,img):
48 | do_rotate = random.randint(0, 4)
49 | angle=self.angles[do_rotate]
50 | if self.bound:
51 | img = rotate_bound(img, angle)
52 | else:
53 | img = rotate_nobound(img, angle)
54 | return img
55 |
56 | def center_crop(src, size):
57 | h, w = src.shape[0:2]
58 | new_w, new_h = scale_down((w, h), size)
59 |
60 | x0 = int((w - new_w) / 2)
61 | y0 = int((h - new_h) / 2)
62 |
63 | out = fixed_crop(src, x0, y0, new_w, new_h, size)
64 | return out
65 |
66 |
67 | def bottom_crop(src, size):
68 | h, w = src.shape[0:2]
69 | new_w, new_h = scale_down((w, h), size)
70 |
71 | x0 = int((w - new_w) / 2)
72 | y0 = int((h - new_h) * 0.75)
73 |
74 | out = fixed_crop(src, x0, y0, new_w, new_h, size)
75 | return out
76 |
77 | def rotate_bound(image, angle):
78 | # grab the dimensions of the image and then determine the
79 | # center
80 | h, w = image.shape[:2]
81 |
82 | (cX, cY) = (w // 2, h // 2)
83 |
84 | M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)
85 | cos = np.abs(M[0, 0])
86 | sin = np.abs(M[0, 1])
87 |
88 | # compute the new bounding dimensions of the image
89 | nW = int((h * sin) + (w * cos))
90 | nH = int((h * cos) + (w * sin))
91 |
92 | # adjust the rotation matrix to take into account translation
93 | M[0, 2] += (nW / 2) - cX
94 | M[1, 2] += (nH / 2) - cY
95 |
96 | rotated = cv2.warpAffine(image, M, (nW, nH))
97 |
98 | return rotated
99 |
100 |
101 | class Compose(object):
102 | def __init__(self, transforms):
103 | self.transforms = transforms
104 | def __call__(self, img):
105 | for t in self.transforms:
106 | img = t(img)
107 | return img
108 | class RandomRotate(object):
109 | def __init__(self, angles, bound=False):
110 | self.angles = angles
111 | self.bound = bound
112 |
113 | def __call__(self,img):
114 | do_rotate = random.randint(0, 2)
115 | if do_rotate:
116 | angle = np.random.uniform(self.angles[0], self.angles[1])
117 | if self.bound:
118 | img = rotate_bound(img, angle)
119 | else:
120 | img = rotate_nobound(img, angle)
121 | return img
122 | class RandomBrightness(object):
123 | def __init__(self, delta=10):
124 | assert delta >= 0
125 | assert delta <= 255
126 | self.delta = delta
127 |
128 | def __call__(self, image):
129 | if random.randint(2):
130 | delta = random.uniform(-self.delta, self.delta)
131 | image = (image + delta).clip(0.0, 255.0)
132 | # print('RandomBrightness,delta ',delta)
133 | return image
134 |
135 |
136 | class RandomContrast(object):
137 | def __init__(self, lower=0.9, upper=1.05):
138 | self.lower = lower
139 | self.upper = upper
140 | assert self.upper >= self.lower, "contrast upper must be >= lower."
141 | assert self.lower >= 0, "contrast lower must be non-negative."
142 |
143 | # expects float image
144 | def __call__(self, image):
145 | if random.randint(2):
146 | alpha = random.uniform(self.lower, self.upper)
147 | # print('contrast:', alpha)
148 | image = (image * alpha).clip(0.0,255.0)
149 | return image
150 |
151 |
152 | class RandomSaturation(object):
153 | def __init__(self, lower=0.8, upper=1.2):
154 | self.lower = lower
155 | self.upper = upper
156 | assert self.upper >= self.lower, "contrast upper must be >= lower."
157 | assert self.lower >= 0, "contrast lower must be non-negative."
158 |
159 | def __call__(self, image):
160 | if random.randint(2):
161 | alpha = random.uniform(self.lower, self.upper)
162 | image[:, :, 1] *= alpha
163 | # print('RandomSaturation,alpha',alpha)
164 | return image
165 |
166 |
167 | class RandomHue(object):
168 | def __init__(self, delta=18.0):
169 | assert delta >= 0.0 and delta <= 360.0
170 | self.delta = delta
171 |
172 | def __call__(self, image):
173 | if random.randint(2):
174 | alpha = random.uniform(-self.delta, self.delta)
175 | image[:, :, 0] += alpha
176 | image[:, :, 0][image[:, :, 0] > 360.0] -= 360.0
177 | image[:, :, 0][image[:, :, 0] < 0.0] += 360.0
178 | # print('RandomHue,alpha:', alpha)
179 | return image
180 |
181 |
182 | class ConvertColor(object):
183 | def __init__(self, current='BGR', transform='HSV'):
184 | self.transform = transform
185 | self.current = current
186 |
187 | def __call__(self, image):
188 | if self.current == 'BGR' and self.transform == 'HSV':
189 | image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
190 | elif self.current == 'HSV' and self.transform == 'BGR':
191 | image = cv2.cvtColor(image, cv2.COLOR_HSV2BGR)
192 | else:
193 | raise NotImplementedError
194 | return image
195 |
196 | class RandomSwapChannels(object):
197 | def __call__(self, img):
198 | if np.random.randint(2):
199 | order = np.random.permutation(3)
200 | return img[:,:,order]
201 | return img
202 |
203 | class RandomCrop(object):
204 | def __init__(self, size):
205 | self.size = size
206 | def __call__(self, image):
207 | h, w, _ = image.shape
208 | new_w, new_h = scale_down((w, h), self.size)
209 |
210 | if w == new_w:
211 | x0 = 0
212 | else:
213 | x0 = random.randint(0, w - new_w)
214 |
215 | if h == new_h:
216 | y0 = 0
217 | else:
218 | y0 = random.randint(0, h - new_h)
219 |
220 | out = fixed_crop(image, x0, y0, new_w, new_h, self.size)
221 | return out
222 |
223 |
224 |
225 | class RandomResizedCrop(object):
226 | def __init__(self, size,scale=(0.49, 1.0), ratio=(1., 1.)):
227 | self.size = size
228 | self.scale = scale
229 | self.ratio = ratio
230 |
231 | def __call__(self,img):
232 | if random.random() < 0.2:
233 | return cv2.resize(img,self.size)
234 | h, w, _ = img.shape
235 | area = h * w
236 | d=1
237 | for attempt in range(10):
238 | target_area = random.uniform(self.scale[0], self.scale[1]) * area
239 | aspect_ratio = random.uniform(self.ratio[0], self.ratio[1])
240 |
241 |
242 | new_w = int(round(math.sqrt(target_area * aspect_ratio)))
243 | new_h = int(round(math.sqrt(target_area / aspect_ratio)))
244 |
245 | if random.random() < 0.5:
246 | new_h, new_w = new_w, new_h
247 |
248 | if new_w < w and new_h < h:
249 | x0 = random.randint(0, w - new_w)
250 | y0 = (random.randint(0, h - new_h))//d
251 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
252 |
253 | return out
254 |
255 | # Fallback
256 | return center_crop(img, self.size)
257 |
258 |
259 | class DownCrop():
260 | def __init__(self, size, select, scale=(0.36,0.81)):
261 | self.size = size
262 | self.scale = scale
263 | self.select = select
264 |
265 | def __call__(self,img, attr_idx):
266 | if attr_idx not in self.select:
267 | return img, attr_idx
268 | if attr_idx == 0:
269 | self.scale=(0.64,1.0)
270 | h, w, _ = img.shape
271 | area = h * w
272 |
273 | s = (self.scale[0]+self.scale[1])/2.0
274 |
275 | target_area = s * area
276 |
277 | new_w = int(round(math.sqrt(target_area)))
278 | new_h = int(round(math.sqrt(target_area)))
279 |
280 | if new_w < w and new_h < h:
281 | dw = w-new_w
282 | x0 = int(0.5*dw)
283 | y0 = h-new_h
284 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
285 | return out, attr_idx
286 |
287 | # Fallback
288 | return center_crop(img, self.size), attr_idx
289 |
290 |
291 | class ResizedCrop(object):
292 | def __init__(self, size, select,scale=(0.64, 1.0), ratio=(3. / 4., 4. / 3.)):
293 | self.size = size
294 | self.scale = scale
295 | self.ratio = ratio
296 | self.select = select
297 |
298 | def __call__(self,img, attr_idx):
299 | if attr_idx not in self.select:
300 | return img, attr_idx
301 | h, w, _ = img.shape
302 | area = h * w
303 | d=1
304 | if attr_idx == 2:
305 | self.scale=(0.36,0.81)
306 | d=2
307 | if attr_idx == 0:
308 | self.scale=(0.81,1.0)
309 |
310 | target_area = (self.scale[0]+self.scale[1])/2.0 * area
311 | # aspect_ratio = random.uniform(self.ratio[0], self.ratio[1])
312 |
313 |
314 | new_w = int(round(math.sqrt(target_area)))
315 | new_h = int(round(math.sqrt(target_area)))
316 |
317 | # if random.random() < 0.5:
318 | # new_h, new_w = new_w, new_h
319 |
320 | if new_w < w and new_h < h:
321 | x0 = (w - new_w)//2
322 | y0 = (h - new_h)//d//2
323 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
324 | # cv2.imshow('{}_img'.format(idx2attr_map[attr_idx]), img)
325 | # cv2.imshow('{}_crop'.format(idx2attr_map[attr_idx]), out)
326 | #
327 | # cv2.waitKey(0)
328 | return out, attr_idx
329 |
330 | # Fallback
331 | return center_crop(img, self.size), attr_idx
332 |
333 | class RandomHflip(object):
334 | def __call__(self, image):
335 | if random.randint(2):
336 | return cv2.flip(image, 1)
337 | else:
338 | return image
339 | class RandomVflip(object):
340 | def __call__(self, image):
341 | if random.randint(2):
342 | return cv2.flip(image, 0)
343 | else:
344 | return image
345 |
346 |
347 | class Hflip(object):
348 | def __init__(self,doHflip):
349 | self.doHflip = doHflip
350 |
351 | def __call__(self, image):
352 | if self.doHflip:
353 | return cv2.flip(image, 1)
354 | else:
355 | return image
356 |
357 |
358 | class CenterCrop(object):
359 | def __init__(self, size):
360 | self.size = size
361 |
362 | def __call__(self, image):
363 | return center_crop(image, self.size)
364 |
365 | class UpperCrop():
366 | def __init__(self, size, scale=(0.09, 0.64)):
367 | self.size = size
368 | self.scale = scale
369 |
370 | def __call__(self,img):
371 | h, w, _ = img.shape
372 | area = h * w
373 |
374 | s = (self.scale[0]+self.scale[1])/2.0
375 |
376 | target_area = s * area
377 |
378 | new_w = int(round(math.sqrt(target_area)))
379 | new_h = int(round(math.sqrt(target_area)))
380 |
381 | if new_w < w and new_h < h:
382 | dw = w-new_w
383 | x0 = int(0.5*dw)
384 | y0 = 0
385 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
386 | return out
387 |
388 | # Fallback
389 | return center_crop(img, self.size)
390 |
391 |
392 |
393 | class RandomUpperCrop(object):
394 | def __init__(self, size, select, scale=(0.09, 0.64), ratio=(3. / 4., 4. / 3.)):
395 | self.size = size
396 | self.scale = scale
397 | self.ratio = ratio
398 | self.select = select
399 |
400 | def __call__(self,img, attr_idx):
401 | if random.random() < 0.2:
402 | return img, attr_idx
403 | if attr_idx not in self.select:
404 | return img, attr_idx
405 |
406 | h, w, _ = img.shape
407 | area = h * w
408 | for attempt in range(10):
409 | s = random.uniform(self.scale[0], self.scale[1])
410 | d = 0.1 + (0.3 - 0.1) / (self.scale[1] - self.scale[0]) * (s - self.scale[0])
411 | target_area = s * area
412 | aspect_ratio = random.uniform(self.ratio[0], self.ratio[1])
413 | new_w = int(round(math.sqrt(target_area * aspect_ratio)))
414 | new_h = int(round(math.sqrt(target_area / aspect_ratio)))
415 |
416 |
417 | # new_w = int(round(math.sqrt(target_area)))
418 | # new_h = int(round(math.sqrt(target_area)))
419 |
420 | if new_w < w and new_h < h:
421 | dw = w-new_w
422 | x0 = random.randint(int((0.5-d)*dw), int((0.5+d)*dw)+1)
423 | y0 = (random.randint(0, h - new_h))//10
424 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
425 | return out, attr_idx
426 |
427 | # Fallback
428 | return center_crop(img, self.size), attr_idx
429 | class RandomDownCrop(object):
430 | def __init__(self, size, select, scale=(0.36, 0.81), ratio=(3. / 4., 4. / 3.)):
431 | self.size = size
432 | self.scale = scale
433 | self.ratio = ratio
434 | self.select = select
435 |
436 | def __call__(self,img, attr_idx):
437 | if random.random() < 0.2:
438 | return img, attr_idx
439 | if attr_idx not in self.select:
440 | return img, attr_idx
441 | if attr_idx == 0:
442 | self.scale=(0.64,1.0)
443 |
444 | h, w, _ = img.shape
445 | area = h * w
446 | for attempt in range(10):
447 | s = random.uniform(self.scale[0], self.scale[1])
448 | d = 0.1 + (0.3 - 0.1) / (self.scale[1] - self.scale[0]) * (s - self.scale[0])
449 | target_area = s * area
450 | aspect_ratio = random.uniform(self.ratio[0], self.ratio[1])
451 | new_w = int(round(math.sqrt(target_area * aspect_ratio)))
452 | new_h = int(round(math.sqrt(target_area / aspect_ratio)))
453 | #
454 | # new_w = int(round(math.sqrt(target_area)))
455 | # new_h = int(round(math.sqrt(target_area)))
456 |
457 | if new_w < w and new_h < h:
458 | dw = w-new_w
459 | x0 = random.randint(int((0.5-d)*dw), int((0.5+d)*dw)+1)
460 | y0 = (random.randint((h - new_h)*9//10, h - new_h))
461 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
462 |
463 | # cv2.imshow('{}_img'.format(idx2attr_map[attr_idx]), img)
464 | # cv2.imshow('{}_crop'.format(idx2attr_map[attr_idx]), out)
465 | #
466 | # cv2.waitKey(0)
467 |
468 | return out, attr_idx
469 |
470 | # Fallback
471 | return center_crop(img, self.size), attr_idx
472 |
473 | class RandomHShift(object):
474 | def __init__(self, select, scale=(0.0, 0.2)):
475 | self.scale = scale
476 | self.select = select
477 |
478 | def __call__(self,img, attr_idx):
479 | if attr_idx not in self.select:
480 | return img, attr_idx
481 | do_shift_crop = random.randint(0, 2)
482 | if do_shift_crop:
483 | h, w, _ = img.shape
484 | min_shift = int(w*self.scale[0])
485 | max_shift = int(w*self.scale[1])
486 | shift_idx = random.randint(min_shift, max_shift)
487 | direction = random.randint(0,2)
488 | if direction:
489 | right_part = img[:, -shift_idx:, :]
490 | left_part = img[:, :-shift_idx, :]
491 | else:
492 | left_part = img[:, :shift_idx, :]
493 | right_part = img[:, shift_idx:, :]
494 | img = np.concatenate((right_part, left_part), axis=1)
495 |
496 | # Fallback
497 | return img, attr_idx
498 |
499 |
500 | class RandomBottomCrop(object):
501 | def __init__(self, size, select, scale=(0.4, 0.8)):
502 | self.size = size
503 | self.scale = scale
504 | self.select = select
505 |
506 | def __call__(self,img, attr_idx):
507 | if attr_idx not in self.select:
508 | return img, attr_idx
509 |
510 | h, w, _ = img.shape
511 | area = h * w
512 | for attempt in range(10):
513 | s = random.uniform(self.scale[0], self.scale[1])
514 | d = 0.25 + (0.45 - 0.25) / (self.scale[1] - self.scale[0]) * (s - self.scale[0])
515 | target_area = s * area
516 |
517 | new_w = int(round(math.sqrt(target_area)))
518 | new_h = int(round(math.sqrt(target_area)))
519 |
520 | if new_w < w and new_h < h:
521 | dw = w-new_w
522 | dh = h - new_h
523 | x0 = random.randint(int((0.5-d)*dw), min(int((0.5+d)*dw)+1,dw))
524 | y0 = (random.randint(max(0,int(0.8*dh)-1), dh))
525 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
526 | return out, attr_idx
527 |
528 | # Fallback
529 | return bottom_crop(img, self.size), attr_idx
530 |
531 |
532 | class BottomCrop():
533 | def __init__(self, size, select, scale=(0.4, 0.8)):
534 | self.size = size
535 | self.scale = scale
536 | self.select = select
537 |
538 | def __call__(self,img, attr_idx):
539 | if attr_idx not in self.select:
540 | return img, attr_idx
541 |
542 | h, w, _ = img.shape
543 | area = h * w
544 |
545 | s = (self.scale[0]+self.scale[1])/3.*2.
546 |
547 | target_area = s * area
548 |
549 | new_w = int(round(math.sqrt(target_area)))
550 | new_h = int(round(math.sqrt(target_area)))
551 |
552 | if new_w < w and new_h < h:
553 | dw = w-new_w
554 | dh = h-new_h
555 | x0 = int(0.5*dw)
556 | y0 = int(0.9*dh)
557 | out = fixed_crop(img, x0, y0, new_w, new_h, self.size)
558 | return out, attr_idx
559 |
560 | # Fallback
561 | return bottom_crop(img, self.size), attr_idx
562 |
563 |
564 |
565 | class Resize(object):
566 | def __init__(self, size, inter=cv2.INTER_CUBIC):
567 | self.size = size
568 | self.inter = inter
569 |
570 | def __call__(self, image):
571 | return cv2.resize(image, (self.size[0], self.size[0]), interpolation=self.inter)
572 |
573 | class ExpandBorder(object):
574 | def __init__(self, mode='constant', value=255, size=(336,336), resize=False):
575 | self.mode = mode
576 | self.value = value
577 | self.resize = resize
578 | self.size = size
579 |
580 | def __call__(self, image):
581 | h, w, _ = image.shape
582 | if h > w:
583 | pad1 = (h-w)//2
584 | pad2 = h - w - pad1
585 | if self.mode == 'constant':
586 | image = np.pad(image, ((0, 0), (pad1, pad2), (0, 0)),
587 | self.mode, constant_values=self.value)
588 | else:
589 | image = np.pad(image,((0,0), (pad1, pad2),(0,0)), self.mode)
590 | elif h < w:
591 | pad1 = (w-h)//2
592 | pad2 = w-h - pad1
593 | if self.mode == 'constant':
594 | image = np.pad(image, ((pad1, pad2),(0, 0), (0, 0)),
595 | self.mode,constant_values=self.value)
596 | else:
597 | image = np.pad(image, ((pad1, pad2), (0, 0), (0, 0)),self.mode)
598 | if self.resize:
599 | image = cv2.resize(image, (self.size[0], self.size[0]),interpolation=cv2.INTER_LINEAR)
600 | return image
601 | class AstypeToInt():
602 | def __call__(self, image, attr_idx):
603 | return image.clip(0,255.0).astype(np.uint8), attr_idx
604 |
605 | class AstypeToFloat():
606 | def __call__(self, image, attr_idx):
607 | return image.astype(np.float32), attr_idx
608 |
609 | import matplotlib.pyplot as plt
610 | class Normalize(object):
611 | def __init__(self,mean, std):
612 | '''
613 | :param mean: RGB order
614 | :param std: RGB order
615 | '''
616 | self.mean = np.array(mean).reshape(3,1,1)
617 | self.std = np.array(std).reshape(3,1,1)
618 | def __call__(self, image):
619 | '''
620 | :param image: (H,W,3) RGB
621 | :return:
622 | '''
623 | # plt.figure(1)
624 | # plt.imshow(image)
625 | # plt.show()
626 | return (image.transpose((2, 0, 1)) / 255. - self.mean) / self.std
627 |
628 | class RandomErasing(object):
629 | def __init__(self, select,EPSILON=0.5,sl=0.02, sh=0.09, r1=0.3, mean=[0.485, 0.456, 0.406]):
630 | self.EPSILON = EPSILON
631 | self.mean = mean
632 | self.sl = sl
633 | self.sh = sh
634 | self.r1 = r1
635 | self.select = select
636 |
637 | def __call__(self, img,attr_idx):
638 | if attr_idx not in self.select:
639 | return img,attr_idx
640 |
641 | if random.uniform(0, 1) > self.EPSILON:
642 | return img,attr_idx
643 |
644 | for attempt in range(100):
645 | area = img.shape[1] * img.shape[2]
646 |
647 | target_area = random.uniform(self.sl, self.sh) * area
648 | aspect_ratio = random.uniform(self.r1, 1 / self.r1)
649 |
650 | h = int(round(math.sqrt(target_area * aspect_ratio)))
651 | w = int(round(math.sqrt(target_area / aspect_ratio)))
652 |
653 | if w <= img.shape[2] and h <= img.shape[1]:
654 | x1 = random.randint(0, img.shape[1] - h)
655 | y1 = random.randint(0, img.shape[2] - w)
656 | if img.shape[0] == 3:
657 | # img[0, x1:x1+h, y1:y1+w] = random.uniform(0, 1)
658 | # img[1, x1:x1+h, y1:y1+w] = random.uniform(0, 1)
659 | # img[2, x1:x1+h, y1:y1+w] = random.uniform(0, 1)
660 | img[0, x1:x1 + h, y1:y1 + w] = self.mean[0]
661 | img[1, x1:x1 + h, y1:y1 + w] = self.mean[1]
662 | img[2, x1:x1 + h, y1:y1 + w] = self.mean[2]
663 | # img[:, x1:x1+h, y1:y1+w] = torch.from_numpy(np.random.rand(3, h, w))
664 | else:
665 | img[0, x1:x1 + h, y1:y1 + w] = self.mean[1]
666 | # img[0, x1:x1+h, y1:y1+w] = torch.from_numpy(np.random.rand(1, h, w))
667 | return img,attr_idx
668 |
669 | return img,attr_idx
670 |
671 | if __name__ == '__main__':
672 | import matplotlib.pyplot as plt
673 |
674 |
675 | class FSAug(object):
676 | def __init__(self):
677 | self.augment = Compose([
678 | AstypeToFloat(),
679 | # RandomHShift(scale=(0.,0.2),select=range(8)),
680 | # RandomRotate(angles=(-20., 20.), bound=True),
681 | ExpandBorder(select=range(8), mode='symmetric'),# symmetric
682 | # Resize(size=(336, 336), select=[ 2, 7]),
683 | AstypeToInt()
684 | ])
685 |
686 | def __call__(self, spct,attr_idx):
687 | return self.augment(spct,attr_idx)
688 |
689 |
690 | trans = FSAug()
691 |
692 | img_path = '/media/gserver/data/FashionAI/round2/train/Images/coat_length_labels/0b6b4a2146fc8616a19fcf2026d61d50.jpg'
693 | img = cv2.cvtColor(cv2.imread(img_path),cv2.COLOR_BGR2RGB)
694 | img_trans,_ = trans(img,5)
695 | # img_trans2,_ = trans(img,6)
696 | print img_trans.max(), img_trans.min()
697 | print img_trans.dtype
698 |
699 | plt.figure()
700 | plt.subplot(221)
701 | plt.imshow(img)
702 |
703 | plt.subplot(222)
704 | plt.imshow(img_trans)
705 |
706 | # plt.subplot(223)
707 | # plt.imshow(img_trans2)
708 | # plt.imshow(img_trans2)
709 | plt.show()
710 |
--------------------------------------------------------------------------------
/dataset/pdr_dataset.py:
--------------------------------------------------------------------------------
1 | # coding=utf8
2 | from __future__ import division
3 | import os
4 | import torch
5 | import torch.utils.data as data
6 | import PIL.Image as Image
7 | from data_aug import *
8 | import cv2
9 | class dataset(data.Dataset):
10 | def __init__(self, imgroot, anno_pd, transforms=None):
11 | self.root_path = imgroot
12 | self.paths = anno_pd['ImageName'].tolist()
13 | self.labels = anno_pd['label'].tolist()
14 | self.transforms = transforms
15 |
16 | def __len__(self):
17 | return len(self.paths)
18 |
19 | def __getitem__(self, item):
20 | img_path =self.paths[item]
21 | img =cv2.imread(img_path)
22 | img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # [h,w,3] RGB
23 |
24 | if self.transforms is not None:
25 | img = self.transforms(img)
26 | label = self.labels[item]
27 |
28 | return torch.from_numpy(img).float(), label
29 |
30 | def pil_loader(self,imgpath):
31 | with open(imgpath, 'rb') as f:
32 | with Image.open(f) as img:
33 | return img.convert('RGB')
34 |
35 | def collate_fn(batch):
36 | imgs = []
37 | label = []
38 |
39 | for sample in batch:
40 | imgs.append(sample[0])
41 | label.append(sample[1])
42 |
43 | return torch.stack(imgs, 0), \
44 | label
--------------------------------------------------------------------------------
/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OdingdongO/pytorch_classification/0b66c6f6aabf66eda0591712525ec036ee9a94e5/models/__init__.py
--------------------------------------------------------------------------------
/models/inception_resnet_v2.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.utils.model_zoo as model_zoo
4 | import os
5 | import sys
6 | '''
7 | https://github.com/Cadene/pretrained-models.pytorch
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.AdaptiveAvgPool2d(output_size=1)
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 = self.last_linear(x)
327 | return x
328 |
329 | def forward(self, input):
330 | x = self.features(input)
331 | x = self.logits(x)
332 | return x
333 |
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 | def pdr_inceptionresnetv2(num_classes=1000):
364 | settings = pretrained_settings['inceptionresnetv2']['imagenet']
365 |
366 | model = InceptionResNetV2(num_classes=1001)
367 | model.load_state_dict(model_zoo.load_url(settings['url']))
368 | model.last_linear=nn.Linear(1536, num_classes)
369 | return model
370 |
371 | '''
372 | TEST
373 | Run this code with:
374 | ```
375 | cd $HOME/pretrained-models.pytorch
376 | python -m pretrainedmodels.inceptionresnetv2
377 | ```
378 | '''
379 | if __name__ == '__main__':
380 | assert inceptionresnetv2(num_classes=10, pretrained=None)
381 | print('success')
382 | assert inceptionresnetv2(num_classes=1000, pretrained='imagenet')
383 | print('success')
384 | assert inceptionresnetv2(num_classes=1001, pretrained='imagenet+background')
385 | print('success')
386 |
387 | # fail
388 | assert pdr_inceptionresnetv2(num_classes=10)
--------------------------------------------------------------------------------
/models/inception_v4.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.utils.model_zoo as model_zoo
4 | import os
5 | import sys
6 | '''
7 | https://github.com/Cadene/pretrained-models.pytorch
8 | '''
9 | __all__ = ['InceptionV4', 'inceptionv4']
10 |
11 | pretrained_settings = {
12 | 'inceptionv4': {
13 | 'imagenet': {
14 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionv4-8e4777a0.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/inceptionv4-8e4777a0.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=True)
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_3a(nn.Module):
56 |
57 | def __init__(self):
58 | super(Mixed_3a, self).__init__()
59 | self.maxpool = nn.MaxPool2d(3, stride=2)
60 | self.conv = BasicConv2d(64, 96, kernel_size=3, stride=2)
61 |
62 | def forward(self, x):
63 | x0 = self.maxpool(x)
64 | x1 = self.conv(x)
65 | out = torch.cat((x0, x1), 1)
66 | return out
67 |
68 |
69 | class Mixed_4a(nn.Module):
70 |
71 | def __init__(self):
72 | super(Mixed_4a, self).__init__()
73 |
74 | self.branch0 = nn.Sequential(
75 | BasicConv2d(160, 64, kernel_size=1, stride=1),
76 | BasicConv2d(64, 96, kernel_size=3, stride=1)
77 | )
78 |
79 | self.branch1 = nn.Sequential(
80 | BasicConv2d(160, 64, kernel_size=1, stride=1),
81 | BasicConv2d(64, 64, kernel_size=(1, 7), stride=1, padding=(0, 3)),
82 | BasicConv2d(64, 64, kernel_size=(7, 1), stride=1, padding=(3, 0)),
83 | BasicConv2d(64, 96, kernel_size=(3, 3), stride=1)
84 | )
85 |
86 | def forward(self, x):
87 | x0 = self.branch0(x)
88 | x1 = self.branch1(x)
89 | out = torch.cat((x0, x1), 1)
90 | return out
91 |
92 |
93 | class Mixed_5a(nn.Module):
94 |
95 | def __init__(self):
96 | super(Mixed_5a, self).__init__()
97 | self.conv = BasicConv2d(192, 192, kernel_size=3, stride=2)
98 | self.maxpool = nn.MaxPool2d(3, stride=2)
99 |
100 | def forward(self, x):
101 | x0 = self.conv(x)
102 | x1 = self.maxpool(x)
103 | out = torch.cat((x0, x1), 1)
104 | return out
105 |
106 |
107 | class Inception_A(nn.Module):
108 |
109 | def __init__(self):
110 | super(Inception_A, self).__init__()
111 | self.branch0 = BasicConv2d(384, 96, kernel_size=1, stride=1)
112 |
113 | self.branch1 = nn.Sequential(
114 | BasicConv2d(384, 64, kernel_size=1, stride=1),
115 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1)
116 | )
117 |
118 | self.branch2 = nn.Sequential(
119 | BasicConv2d(384, 64, kernel_size=1, stride=1),
120 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1),
121 | BasicConv2d(96, 96, kernel_size=3, stride=1, padding=1)
122 | )
123 |
124 | self.branch3 = nn.Sequential(
125 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
126 | BasicConv2d(384, 96, kernel_size=1, stride=1)
127 | )
128 |
129 | def forward(self, x):
130 | x0 = self.branch0(x)
131 | x1 = self.branch1(x)
132 | x2 = self.branch2(x)
133 | x3 = self.branch3(x)
134 | out = torch.cat((x0, x1, x2, x3), 1)
135 | return out
136 |
137 |
138 | class Reduction_A(nn.Module):
139 |
140 | def __init__(self):
141 | super(Reduction_A, self).__init__()
142 | self.branch0 = BasicConv2d(384, 384, kernel_size=3, stride=2)
143 |
144 | self.branch1 = nn.Sequential(
145 | BasicConv2d(384, 192, kernel_size=1, stride=1),
146 | BasicConv2d(192, 224, kernel_size=3, stride=1, padding=1),
147 | BasicConv2d(224, 256, kernel_size=3, stride=2)
148 | )
149 |
150 | self.branch2 = nn.MaxPool2d(3, stride=2)
151 |
152 | def forward(self, x):
153 | x0 = self.branch0(x)
154 | x1 = self.branch1(x)
155 | x2 = self.branch2(x)
156 | out = torch.cat((x0, x1, x2), 1)
157 | return out
158 |
159 |
160 | class Inception_B(nn.Module):
161 |
162 | def __init__(self):
163 | super(Inception_B, self).__init__()
164 | self.branch0 = BasicConv2d(1024, 384, kernel_size=1, stride=1)
165 |
166 | self.branch1 = nn.Sequential(
167 | BasicConv2d(1024, 192, kernel_size=1, stride=1),
168 | BasicConv2d(192, 224, kernel_size=(1, 7), stride=1, padding=(0, 3)),
169 | BasicConv2d(224, 256, kernel_size=(7, 1), stride=1, padding=(3, 0))
170 | )
171 |
172 | self.branch2 = nn.Sequential(
173 | BasicConv2d(1024, 192, kernel_size=1, stride=1),
174 | BasicConv2d(192, 192, kernel_size=(7, 1), stride=1, padding=(3, 0)),
175 | BasicConv2d(192, 224, kernel_size=(1, 7), stride=1, padding=(0, 3)),
176 | BasicConv2d(224, 224, kernel_size=(7, 1), stride=1, padding=(3, 0)),
177 | BasicConv2d(224, 256, kernel_size=(1, 7), stride=1, padding=(0, 3))
178 | )
179 |
180 | self.branch3 = nn.Sequential(
181 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
182 | BasicConv2d(1024, 128, kernel_size=1, stride=1)
183 | )
184 |
185 | def forward(self, x):
186 | x0 = self.branch0(x)
187 | x1 = self.branch1(x)
188 | x2 = self.branch2(x)
189 | x3 = self.branch3(x)
190 | out = torch.cat((x0, x1, x2, x3), 1)
191 | return out
192 |
193 |
194 | class Reduction_B(nn.Module):
195 |
196 | def __init__(self):
197 | super(Reduction_B, self).__init__()
198 |
199 | self.branch0 = nn.Sequential(
200 | BasicConv2d(1024, 192, kernel_size=1, stride=1),
201 | BasicConv2d(192, 192, kernel_size=3, stride=2)
202 | )
203 |
204 | self.branch1 = nn.Sequential(
205 | BasicConv2d(1024, 256, kernel_size=1, stride=1),
206 | BasicConv2d(256, 256, kernel_size=(1, 7), stride=1, padding=(0, 3)),
207 | BasicConv2d(256, 320, kernel_size=(7, 1), stride=1, padding=(3, 0)),
208 | BasicConv2d(320, 320, kernel_size=3, stride=2)
209 | )
210 |
211 | self.branch2 = nn.MaxPool2d(3, stride=2)
212 |
213 | def forward(self, x):
214 | x0 = self.branch0(x)
215 | x1 = self.branch1(x)
216 | x2 = self.branch2(x)
217 | out = torch.cat((x0, x1, x2), 1)
218 | return out
219 |
220 |
221 | class Inception_C(nn.Module):
222 |
223 | def __init__(self):
224 | super(Inception_C, self).__init__()
225 |
226 | self.branch0 = BasicConv2d(1536, 256, kernel_size=1, stride=1)
227 |
228 | self.branch1_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1)
229 | self.branch1_1a = BasicConv2d(384, 256, kernel_size=(1, 3), stride=1, padding=(0, 1))
230 | self.branch1_1b = BasicConv2d(384, 256, kernel_size=(3, 1), stride=1, padding=(1, 0))
231 |
232 | self.branch2_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1)
233 | self.branch2_1 = BasicConv2d(384, 448, kernel_size=(3, 1), stride=1, padding=(1, 0))
234 | self.branch2_2 = BasicConv2d(448, 512, kernel_size=(1, 3), stride=1, padding=(0, 1))
235 | self.branch2_3a = BasicConv2d(512, 256, kernel_size=(1, 3), stride=1, padding=(0, 1))
236 | self.branch2_3b = BasicConv2d(512, 256, kernel_size=(3, 1), stride=1, padding=(1, 0))
237 |
238 | self.branch3 = nn.Sequential(
239 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
240 | BasicConv2d(1536, 256, kernel_size=1, stride=1)
241 | )
242 |
243 | def forward(self, x):
244 | x0 = self.branch0(x)
245 |
246 | x1_0 = self.branch1_0(x)
247 | x1_1a = self.branch1_1a(x1_0)
248 | x1_1b = self.branch1_1b(x1_0)
249 | x1 = torch.cat((x1_1a, x1_1b), 1)
250 |
251 | x2_0 = self.branch2_0(x)
252 | x2_1 = self.branch2_1(x2_0)
253 | x2_2 = self.branch2_2(x2_1)
254 | x2_3a = self.branch2_3a(x2_2)
255 | x2_3b = self.branch2_3b(x2_2)
256 | x2 = torch.cat((x2_3a, x2_3b), 1)
257 |
258 | x3 = self.branch3(x)
259 |
260 | out = torch.cat((x0, x1, x2, x3), 1)
261 | return out
262 |
263 |
264 | class InceptionV4(nn.Module):
265 |
266 | def __init__(self, num_classes=1001):
267 | super(InceptionV4, self).__init__()
268 | # Special attributs
269 | self.input_space = None
270 | self.input_size = (299, 299, 3)
271 | self.mean = None
272 | self.std = None
273 | # Modules
274 | self.features = nn.Sequential(
275 | BasicConv2d(3, 32, kernel_size=3, stride=2),
276 | BasicConv2d(32, 32, kernel_size=3, stride=1),
277 | BasicConv2d(32, 64, kernel_size=3, stride=1, padding=1),
278 | Mixed_3a(),
279 | Mixed_4a(),
280 | Mixed_5a(),
281 | Inception_A(),
282 | Inception_A(),
283 | Inception_A(),
284 | Inception_A(),
285 | Reduction_A(), # Mixed_6a
286 | Inception_B(),
287 | Inception_B(),
288 | Inception_B(),
289 | Inception_B(),
290 | Inception_B(),
291 | Inception_B(),
292 | Inception_B(),
293 | Reduction_B(), # Mixed_7a
294 | Inception_C(),
295 | Inception_C(),
296 | Inception_C()
297 | )
298 | self.avg_pool = nn.AdaptiveAvgPool2d(output_size=1)
299 | self.last_linear = nn.Linear(1536, num_classes)
300 |
301 | def logits(self, features):
302 | x = self.avg_pool(features)
303 | x = x.view(x.size(0), -1)
304 | x = self.last_linear(x)
305 | return x
306 |
307 | def forward(self, input):
308 | x = self.features(input)
309 | # print(x.size())
310 | x = self.logits(x)
311 | return x
312 |
313 |
314 | def inceptionv4(num_classes=11,pretrained=True):
315 | """Constructs a ResNet-101 model.
316 |
317 | Args:
318 | pretrained (bool): If True, returns a model pre-trained on ImageNet
319 | """
320 | model = InceptionV4(num_classes=1001)
321 | if pretrained:
322 | settings = pretrained_settings['inceptionv4']["imagenet"]
323 | model.load_state_dict(model_zoo.load_url(settings['url']))
324 | model.last_linear = nn.Linear(model.last_linear.in_features, num_classes)
325 | return model
326 |
327 | '''
328 | TEST
329 | Run this code with:
330 | ```
331 | cd $HOME/pretrained-models.pytorch
332 | python -m pretrainedmodels.inceptionv4
333 | ```
334 | '''
335 | if __name__ == '__main__':
336 | import torch
337 | model = inceptionv4(num_classes=11)
338 | input = torch.autograd.Variable(torch.randn(2, 3, 299, 299))
339 | y = model(input)
340 | print y.size()
341 | # #
--------------------------------------------------------------------------------
/models/multiscale_resnet.py:
--------------------------------------------------------------------------------
1 | from torch import nn
2 | import torch
3 | from torchvision import models,transforms,datasets
4 | import torch.nn.functional as F
5 | class multiscale_resnet(nn.Module):
6 | def __init__(self,num_class):
7 | super(multiscale_resnet,self).__init__()
8 | resnet50 =models.resnet50(pretrained=True)
9 | self.base_model =nn.Sequential(*list(resnet50.children())[:-2])
10 | self.avgpool = nn.AdaptiveAvgPool2d(output_size=1)
11 | self.classifier = nn.Linear(resnet50.fc.in_features,num_class)
12 |
13 | def forward(self, x):
14 | input_size = x.size()[2]
15 | self.interp = nn.UpsamplingBilinear2d(size = (int(input_size*0.75)+1, int(input_size*0.75)+1))
16 |
17 | x2 = self.interp(x)
18 | x = self.base_model(x)
19 | x = self.avgpool(x)
20 | x = x.view(x.size(0), -1)
21 |
22 | x2 = self.base_model(x2)
23 | x2 = self.avgpool(x2)
24 | x2 = x2.view(x2.size(0), -1)
25 |
26 | out =[]
27 | out.append(self.classifier(x))
28 | out.append(self.classifier(x2))
29 | return out
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/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 | import math
25 | import torch
26 | import torch.nn as nn
27 | import torch.nn.functional as F
28 | import torch.utils.model_zoo as model_zoo
29 | from torch.nn import init
30 |
31 | __all__ = ['xception']
32 | '''
33 | https://github.com/Cadene/pretrained-models.pytorch
34 | '''
35 | pretrained_settings = {
36 | 'xception': {
37 | 'imagenet': {
38 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/xception-b5690688.pth',
39 | 'input_space': 'RGB',
40 | 'input_size': [3, 299, 299],
41 | 'input_range': [0, 1],
42 | 'mean': [0.5, 0.5, 0.5],
43 | 'std': [0.5, 0.5, 0.5],
44 | 'num_classes': 1000,
45 | 'scale': 0.8975
46 | # The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299
47 | }
48 | }
49 | }
50 |
51 |
52 | class SeparableConv2d(nn.Module):
53 | def __init__(self, in_channels, out_channels, kernel_size=1, stride=1, padding=0, dilation=1, bias=False):
54 | super(SeparableConv2d, self).__init__()
55 |
56 | self.conv1 = nn.Conv2d(in_channels, in_channels, kernel_size, stride, padding, dilation, groups=in_channels,
57 | bias=bias)
58 | self.pointwise = nn.Conv2d(in_channels, out_channels, 1, 1, 0, 1, 1, bias=bias)
59 |
60 | def forward(self, x):
61 | x = self.conv1(x)
62 | x = self.pointwise(x)
63 | return x
64 |
65 |
66 | class Block(nn.Module):
67 | def __init__(self, in_filters, out_filters, reps, strides=1, start_with_relu=True, grow_first=True):
68 | super(Block, self).__init__()
69 |
70 | if out_filters != in_filters or strides != 1:
71 | self.skip = nn.Conv2d(in_filters, out_filters, 1, stride=strides, bias=False)
72 | self.skipbn = nn.BatchNorm2d(out_filters)
73 | else:
74 | self.skip = None
75 |
76 | self.relu = nn.ReLU(inplace=True)
77 | rep = []
78 |
79 | filters = in_filters
80 | if grow_first:
81 | rep.append(self.relu)
82 | rep.append(SeparableConv2d(in_filters, out_filters, 3, stride=1, padding=1, bias=False))
83 | rep.append(nn.BatchNorm2d(out_filters))
84 | filters = out_filters
85 |
86 | for i in range(reps - 1):
87 | rep.append(self.relu)
88 | rep.append(SeparableConv2d(filters, filters, 3, stride=1, padding=1, bias=False))
89 | rep.append(nn.BatchNorm2d(filters))
90 |
91 | if not grow_first:
92 | rep.append(self.relu)
93 | rep.append(SeparableConv2d(in_filters, out_filters, 3, stride=1, padding=1, bias=False))
94 | rep.append(nn.BatchNorm2d(out_filters))
95 |
96 | if not start_with_relu:
97 | rep = rep[1:]
98 | else:
99 | rep[0] = nn.ReLU(inplace=False)
100 |
101 | if strides != 1:
102 | rep.append(nn.MaxPool2d(3, strides, 1))
103 | self.rep = nn.Sequential(*rep)
104 |
105 | def forward(self, inp):
106 | x = self.rep(inp)
107 |
108 | if self.skip is not None:
109 | skip = self.skip(inp)
110 | skip = self.skipbn(skip)
111 | else:
112 | skip = inp
113 |
114 | x += skip
115 | return x
116 |
117 |
118 | class Xception(nn.Module):
119 | """
120 | Xception optimized for the ImageNet dataset, as specified in
121 | https://arxiv.org/pdf/1610.02357.pdf
122 | """
123 |
124 | def __init__(self, num_classes=1000):
125 | """ Constructor
126 | Args:
127 | num_classes: number of classes
128 | """
129 | super(Xception, self).__init__()
130 | self.num_classes = num_classes
131 |
132 | self.conv1 = nn.Conv2d(3, 32, 3, 2, 0, bias=False)
133 | self.bn1 = nn.BatchNorm2d(32)
134 | self.relu = nn.ReLU(inplace=True)
135 |
136 | self.conv2 = nn.Conv2d(32, 64, 3, bias=False)
137 | self.bn2 = nn.BatchNorm2d(64)
138 | # do relu here
139 |
140 | self.block1 = Block(64, 128, 2, 2, start_with_relu=False, grow_first=True)
141 | self.block2 = Block(128, 256, 2, 2, start_with_relu=True, grow_first=True)
142 | self.block3 = Block(256, 728, 2, 2, start_with_relu=True, grow_first=True)
143 |
144 | self.block4 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
145 | self.block5 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
146 | self.block6 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
147 | self.block7 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
148 |
149 | self.block8 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
150 | self.block9 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
151 | self.block10 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
152 | self.block11 = Block(728, 728, 3, 1, start_with_relu=True, grow_first=True)
153 |
154 | self.block12 = Block(728, 1024, 2, 2, start_with_relu=True, grow_first=False)
155 |
156 | self.conv3 = SeparableConv2d(1024, 1536, 3, 1, 1)
157 | self.bn3 = nn.BatchNorm2d(1536)
158 |
159 | # do relu here
160 | self.conv4 = SeparableConv2d(1536, 2048, 3, 1, 1)
161 | self.bn4 = nn.BatchNorm2d(2048)
162 |
163 | self.fc = nn.Linear(2048, num_classes)
164 |
165 | # #------- init weights --------
166 | # for m in self.modules():
167 | # if isinstance(m, nn.Conv2d):
168 | # n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
169 | # m.weight.data.normal_(0, math.sqrt(2. / n))
170 | # elif isinstance(m, nn.BatchNorm2d):
171 | # m.weight.data.fill_(1)
172 | # m.bias.data.zero_()
173 | # #-----------------------------
174 |
175 | def features(self, input):
176 | x = self.conv1(input)
177 | x = self.bn1(x)
178 | x = self.relu(x)
179 |
180 | x = self.conv2(x)
181 | x = self.bn2(x)
182 | x = self.relu(x)
183 |
184 | x = self.block1(x)
185 | x = self.block2(x)
186 | x = self.block3(x)
187 | x = self.block4(x)
188 | x = self.block5(x)
189 | x = self.block6(x)
190 | x = self.block7(x)
191 | x = self.block8(x)
192 | x = self.block9(x)
193 | x = self.block10(x)
194 | x = self.block11(x)
195 | x = self.block12(x)
196 |
197 | x = self.conv3(x)
198 | x = self.bn3(x)
199 | x = self.relu(x)
200 |
201 | x = self.conv4(x)
202 | x = self.bn4(x)
203 | return x
204 |
205 | def logits(self, features):
206 | x = self.relu(features)
207 |
208 | x = F.adaptive_avg_pool2d(x, (1, 1))
209 | x = x.view(x.size(0), -1)
210 | x = self.fc(x)
211 | return x
212 |
213 | def forward(self, input):
214 | x = self.features(input)
215 | x = self.logits(x)
216 | return x
217 |
218 |
219 | def xception(num_classes=1000, pretrained='imagenet'):
220 | model = Xception(num_classes=num_classes)
221 | if pretrained:
222 | settings = pretrained_settings['xception'][pretrained]
223 | assert num_classes == settings['num_classes'], \
224 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
225 |
226 | model = Xception(num_classes=num_classes)
227 | model.load_state_dict(model_zoo.load_url(settings['url']))
228 |
229 | model.input_space = settings['input_space']
230 | model.input_size = settings['input_size']
231 | model.input_range = settings['input_range']
232 | model.mean = settings['mean']
233 | model.std = settings['std']
234 |
235 | # TODO: ugly
236 | model.last_linear = model.fc
237 | del model.fc
238 | return model
239 | def pdr_xception(num_classes):
240 | model = Xception(num_classes=1000)
241 | settings = pretrained_settings['xception']['imagenet']
242 | model.load_state_dict(model_zoo.load_url(settings['url']))
243 | model.fc = nn.Linear(2048, num_classes)
244 | return model
245 |
246 | if __name__ == '__main__':
247 | import torch
248 | model = pdr_xception(num_classes=11)
249 | input = torch.autograd.Variable(torch.randn(2, 3, 299, 299))
250 | y = model(input)
251 | print (y.size())
--------------------------------------------------------------------------------
/predict/bd_tiangong_model_merge.py:
--------------------------------------------------------------------------------
1 | import time
2 | import copy
3 | import pandas as pd
4 | from collections import defaultdict
5 | import numpy as np
6 | class2label={"DESERT":0,"MOUNTAIN":1,"OCEAN":2,"FARMLAND":3,"LAKE":4,"CITY":5,"UNKNOW":6}
7 | label2class=["DESERT","MOUNTAIN","OCEAN","FARMLAND","LAKE","CITY","UNKNOW"]
8 |
9 | result_ratios = defaultdict(lambda: 0)
10 | mode="val"
11 | result_ratios['resnet50'] = 0.5
12 | # result_ratios['resnet101'] = 0.5
13 | result_ratios['densent121'] = 0.5
14 | # result_ratios['densent169'] = 0.25
15 |
16 | assert sum(result_ratios.values()) == 1
17 | def str2np(str):
18 | return np.array([float(x) for x in str.split(";")])
19 | def np2str(arr):
20 | return ";".join(["%.16f" % x for x in arr])
21 | for index, model in enumerate(result_ratios.keys()):
22 | print('ratio: %.3f, model: %s' % (result_ratios[model], model))
23 | result = pd.read_csv('tiangong/csv/{}_{}_prob.csv'.format(model,mode),names=["filename","label","probability"])
24 | # result = result.sort_values(by='filename').reset_index(drop=True)
25 | result['probability'] = result['probability'].apply(lambda x: str2np(x))
26 | print(result.head())
27 |
28 | if index == 0:
29 | ensembled_result = copy.deepcopy(result)
30 | ensembled_result['probability'] =0
31 |
32 | ensembled_result['probability'] = ensembled_result['probability'] + result['probability']*result_ratios[model]
33 | print(ensembled_result.head())
34 | def parase_prob(x):
35 | if np.max(x)<0.33:
36 | label=label2class[6]
37 | else:
38 | label = label2class[int(np.argmax(x))]
39 | return label
40 | def get_class_pro(x,class_name):
41 | # sum =np.sum(x)
42 | # prob=x[class2label[class_name]]*1.0/sum
43 | prob=x[class2label[class_name]]
44 | prob =np.round(prob,8)
45 | # return str("({},{})".format(class_name,str("%.8f" % prob)))
46 | return "("+class_name+","+str(prob)+")"
47 |
48 | ensembled_result['label'] = ensembled_result['probability'].apply(lambda x: parase_prob(x))
49 | for class_name in label2class[:-1]:
50 | ensembled_result[class_name] = ensembled_result['probability'].map(lambda x: get_class_pro(x,class_name))
51 | # ensembled_result['probability'] = ensembled_result['probability'].map(lambda x: np2str(x))
52 | # ensembled_result[["filename","label","OCEAN","MOUNTAIN","LAKE","FARMLAND","DESERT","CITY"]].to_csv('%s_ensembled_result.csv' % time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime(time.time())), header=None,index=False)
53 | # ensembled_result[["filename","label","OCEAN","MOUNTAIN","LAKE","FARMLAND","DESERT","CITY"]].to_csv('ensembled_result2.csv', header=None,index=False)
54 | with open('ensembled_result.csv',"w") as f:
55 | for filename,label,OCEAN,MOUNTAIN,LAKE,FARMLAND,DESERT,CITY in zip(ensembled_result["filename"],
56 | ensembled_result["label"],
57 | ensembled_result["OCEAN"],
58 | ensembled_result["MOUNTAIN"],
59 | ensembled_result["LAKE"],
60 | ensembled_result["FARMLAND"],
61 | ensembled_result["DESERT"],
62 | ensembled_result["CITY"]):
63 | output_str=",".join([x for x in [filename,label,OCEAN,MOUNTAIN,LAKE,FARMLAND,DESERT,CITY]])
64 | f.write(output_str)
65 | f.write("\n")
66 |
--------------------------------------------------------------------------------
/predict/bd_tiangong_pred.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import os
3 | import numpy as np
4 | import pandas as pd
5 | from dataset.bd_tiangong_dataset import dataset, collate_fn,class2label,label2class
6 | import torch
7 | from torch.nn import CrossEntropyLoss
8 | import torch.utils.data as torchdata
9 | from torchvision import datasets, models, transforms
10 | from torchvision.models import resnet50
11 | from sklearn.model_selection import train_test_split
12 | from torch.autograd import Variable
13 | from math import ceil
14 | from torch.nn.functional import softmax
15 | from dataset.data_aug import *
16 | import glob
17 | test_transforms= Compose([
18 | Resize(size=(256, 256)),
19 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
20 | ])
21 |
22 | os.environ["CUDA_VISIBLE_DEVICES"] = "0"
23 | mode ="test"
24 |
25 | label_csv = "/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛训练集2000/光学数据集-预赛训练集-2000-有标签.csv"
26 | train_root = "/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛训练集2000/预赛训练集-2000"
27 | test_root = "/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛测试集A1000/预赛测试集A-1000"
28 | label = pd.read_csv(label_csv, names=["ImageName", "class"])
29 | label["label"] = label["class"].apply(lambda x: class2label[x])
30 | train_pd, val_pd = train_test_split(label, test_size=0.12, random_state=43, stratify=label["label"])
31 | test_list = glob.glob(test_root+"/*.jpg")
32 | true_test_pb=pd.DataFrame(test_list,columns=["path"])
33 | true_test_pb["ImageName"]=true_test_pb["path"].apply(lambda x:os.path.basename(x))
34 | "addFakeLabel"
35 | true_test_pb['label'] =1
36 |
37 | test_pd =true_test_pb if mode=="test" else val_pd
38 | rawdata_root =test_root if mode=="test" else train_root
39 |
40 | print(test_pd.head())
41 |
42 | data_set = {}
43 | data_set['test'] = dataset(imgroot=rawdata_root, anno_pd=test_pd,
44 | transforms=test_transforms,
45 | )
46 | data_loader = {}
47 | data_loader['test'] = torchdata.DataLoader(data_set['test'], batch_size=4, num_workers=4,
48 | shuffle=False, pin_memory=True, collate_fn=collate_fn)
49 |
50 | model_name = 'resnet50-out'
51 | resume = '/media/hszc/model/detao/models/bd_tiangong/resnet50/weights-26-80-[0.9917].pth'
52 |
53 | model =resnet50(pretrained=True)
54 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
55 | model.fc = torch.nn.Linear(model.fc.in_features,6)
56 | model = torch.nn.DataParallel(model)
57 |
58 | print('resuming finetune from %s'%resume)
59 | model.load_state_dict(torch.load(resume))
60 |
61 | model = model.cuda()
62 | model.eval()
63 |
64 | criterion = CrossEntropyLoss()
65 |
66 | if not os.path.exists('./Baidu/csv'):
67 | os.makedirs('./Baidu/csv')
68 |
69 | test_size = ceil(len(data_set['test']) / data_loader['test'].batch_size)
70 | test_preds = np.zeros((len(data_set['test'])), dtype=np.float32)
71 | true_label = np.zeros((len(data_set['test'])), dtype=np.int)
72 | idx = 0
73 | test_loss = 0
74 | test_corrects = 0
75 | for batch_cnt_test, data_test in enumerate(data_loader['test']):
76 | # print data
77 | print("{0}/{1}".format(batch_cnt_test, int(test_size)))
78 | inputs, labels = data_test
79 | inputs = Variable(inputs.cuda())
80 | labels = Variable(torch.from_numpy(np.array(labels)).long().cuda())
81 | # forward
82 | outputs = model(inputs)
83 |
84 | # statistics
85 | if isinstance(outputs, list):
86 | loss = criterion(outputs[0], labels)
87 | loss += criterion(outputs[1], labels)
88 | outputs = (outputs[0]+outputs[1])/2
89 | else:
90 | loss = criterion(outputs, labels)
91 | _, preds = torch.max(outputs, 1)
92 |
93 | test_loss += loss.data[0]
94 | batch_corrects = torch.sum((preds == labels)).data[0]
95 | test_corrects += batch_corrects
96 | test_preds[idx:(idx + labels.size(0))] = preds
97 | true_label[idx:(idx + labels.size(0))] = labels.data.cpu().numpy()
98 | # statistics
99 | idx += labels.size(0)
100 | test_loss = test_loss / test_size
101 | test_acc = 1.0 * test_corrects / len(data_set['test'])
102 | print('test-loss: %.4f ||test-acc@1: %.4f'
103 | % (test_loss, test_acc))
104 |
105 | test_pred = test_pd[['ImageName']].copy()
106 | test_pred['label'] = list(test_preds)
107 | test_pred['label'] = test_pred['label'].apply(lambda x: label2class[int(x)])
108 | test_pred[['ImageName',"label"]].to_csv('Baidu/csv/{0}_{1}.csv'.format(model_name,mode) ,sep=",",
109 | header=None, index=False)
110 | print (test_pred.info())
111 |
--------------------------------------------------------------------------------
/predict/bd_tiangong_pred_unknow.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 | import os
3 | import numpy as np
4 | import pandas as pd
5 | from dataset.bd_tiangong_dataset import dataset, collate_fn,class2label,label2class
6 | import torch
7 | from torch.nn import CrossEntropyLoss
8 | import torch.utils.data as torchdata
9 | from torchvision import datasets, models, transforms
10 | from torchvision.models import resnet50
11 | from sklearn.model_selection import train_test_split
12 | from torch.autograd import Variable
13 | from math import ceil
14 | from torch.nn.functional import softmax
15 | from dataset.data_aug import *
16 | import glob
17 | from models.resnet import resnet50,resnet101
18 | from models.inception_resnet_v2 import inceptionresnetv2
19 | from models.densenet import densenet169,densenet121
20 | import argparse
21 | from dataset.bd_tiangong_dataset import class2label
22 | from torch import nn
23 | '''
24 | http://dianshi.baidu.com/dianshi/pc/competition/22/rank'''
25 | parser = argparse.ArgumentParser()
26 | os.environ["CUDA_VISIBLE_DEVICES"] = "0"
27 | parser.add_argument('--net', dest='net',type=str, default='resnet50',help='densent121,resnet101,resnet50,inceptionv4,densent169,inceptionresnetv2')
28 | parser.add_argument('--resume', type=str, default="/home/detao/Videos/detao/code/pytorch_classification/predict/"
29 | "model_weights/resnet50_unknow/best_weigths_[1.0000000000000002e-06].pth")
30 | # parser.add_argument('--resume', type=str, default="/home/detao/Videos/detao/code/pytorch_classification/predict/"
31 | # "model_weights/densent169_unknow/best_weigths_[1.0000000000000002e-06].pth")
32 | # parser.add_argument('--resume', type=str, default="/home/detao/Videos/detao/code/pytorch_classification/predict/"
33 | # "model_weights/densenet121_unknow/best_weigths_[0.0001].pth")
34 | # parser.add_argument('--resume', type=str, default="/home/detao/Videos/detao/code/pytorch_classification/predict/"
35 | # "model_weights/resnet101_unknow/best_weigths_[0.001].pth")
36 | parser.add_argument('--mode', type=str, default="val", help='val,test')
37 | parser.add_argument('--start_epoch', type=int, default=0, help='number of start epoch')
38 |
39 | parser.add_argument('--save_checkpoint_val_interval', type=int, default=200, help='interval between saving model weights')
40 | parser.add_argument('--n_cpu', type=int, default=4, help='number of cpu threads to use during batch generation')
41 | opt = parser.parse_args()
42 | test_transforms= Compose([
43 | Resize(size=(256, 256)),
44 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
45 | ])
46 | def np2str(arr):
47 | return ";".join(["%.16f" % x for x in arr])
48 | def str2np(str):
49 | return np.array([x for x in str.split(";")])
50 | if __name__ == '__main__':
51 | if opt.mode=="val":
52 | label_csv = "/home/detao/Videos/detao/data/all/label/9970_b.csv"
53 | train_root = "/home/detao/Videos/detao/data/all/data/testb"
54 | else:
55 | label_csv = "/home/detao/Videos/detao/data/all/label/9990_a.csv"
56 | train_root = "/home/detao/Videos/detao/data/all/data/testa/testa"
57 | test_root = "/media/hszc/model/detao/data/dianshi/宽波段数据集-预赛测试集A1000/预赛测试集A-1000"
58 | val_pd = pd.read_csv(label_csv, names=["ImageName", "class"])
59 | val_pd["label"] = val_pd["class"].apply(lambda x: class2label[x])
60 | val_pd["img_path"]=val_pd["ImageName"].apply(lambda x:os.path.join(train_root,x))
61 |
62 | test_list = glob.glob(test_root+"/*.jpg")
63 | true_test_pb=pd.DataFrame(test_list,columns=["path"])
64 | true_test_pb["ImageName"]=true_test_pb["path"].apply(lambda x:os.path.basename(x))
65 | "addFakeLabel"
66 | true_test_pb['label'] =1
67 |
68 | test_pd =true_test_pb if opt.mode=="test" else val_pd
69 | rawdata_root =test_root if opt.mode=="test" else train_root
70 |
71 | print(test_pd.head())
72 | '''data_set&data_loader'''
73 | data_set = {}
74 | data_set['test'] = dataset(imgroot=rawdata_root, anno_pd=test_pd,
75 | transforms=test_transforms,
76 | )
77 | data_loader = {}
78 | data_loader['test'] = torchdata.DataLoader(data_set['test'], batch_size=4, num_workers=4,
79 | shuffle=False, pin_memory=True, collate_fn=collate_fn)
80 |
81 | '''model'''
82 | if opt.net == "resnet50":
83 | model =resnet50(pretrained=True)
84 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
85 | model.fc = torch.nn.Linear(model.fc.in_features,6)
86 | elif opt.net == "resnet101":
87 | model =resnet101(pretrained=True)
88 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
89 | model.fc = torch.nn.Linear(model.fc.in_features,6)
90 | elif opt.net == "inceptionresnetv2":
91 | model =inceptionresnetv2(num_classes=6)
92 | elif opt.net == "densent169":
93 | model =densenet169(pretrained=True)
94 | model.classifier = nn.Linear(model.classifier.in_features, 6)
95 | elif opt.net == "densent121":
96 | model =densenet121(pretrained=True)
97 | model.classifier = nn.Linear(model.classifier.in_features, 6)
98 | if opt.resume:
99 | model.eval()
100 | print('resuming finetune from %s' % opt.resume)
101 | try:
102 | model.load_state_dict(torch.load(opt.resume))
103 | except KeyError:
104 | model = torch.nn.DataParallel(model)
105 | model.load_state_dict(torch.load(opt.resume))
106 | model = model.cuda()
107 | model.eval()
108 |
109 | criterion = CrossEntropyLoss()
110 |
111 | if not os.path.exists('./tiangong/csv'):
112 | os.makedirs('./tiangong/csv')
113 |
114 | test_size = ceil(len(data_set['test']) / data_loader['test'].batch_size)
115 | test_preds = np.zeros((len(data_set['test'])), dtype=np.float32)
116 | true_label = np.zeros((len(data_set['test'])), dtype=np.int)
117 | test_scores = np.zeros((len(data_set['test']),6), dtype=np.float32)
118 |
119 | idx = 0
120 | test_loss = 0
121 | test_corrects = 0
122 | for batch_cnt_test, data_test in enumerate(data_loader['test']):
123 | # print data
124 | print("{0}/{1}".format(batch_cnt_test, int(test_size)))
125 | inputs, labels = data_test
126 | inputs = Variable(inputs.cuda())
127 | labels = Variable(torch.from_numpy(np.array(labels)).long().cuda())
128 | # forward
129 | outputs = model(inputs)
130 | # print(torch.sum(outputs.sigmoid()>0.5).cpu().float())
131 | # num =torch.sum(outputs.sigmoid()>0.288).cpu().float()
132 | scores=outputs.sigmoid()
133 | print(scores)
134 | if isinstance(outputs, list):
135 | loss = criterion(outputs[0], labels)
136 | loss += criterion(outputs[1], labels)
137 | outputs = (outputs[0]+outputs[1])/2
138 | else:
139 | loss = criterion(outputs, labels)
140 | _, preds = torch.max(outputs, 1)
141 |
142 | test_loss += loss.data[0]
143 | batch_corrects = torch.sum((preds == labels)).data[0]
144 | test_corrects += batch_corrects
145 | test_preds[idx:(idx + labels.size(0))] = preds
146 | test_scores[idx:(idx + labels.size(0))] = scores.data.cpu().numpy()
147 | true_label[idx:(idx + labels.size(0))] = labels.data.cpu().numpy()
148 | # statistics
149 | idx += labels.size(0)
150 | test_loss = test_loss / test_size
151 | test_acc = 1.0 * test_corrects / len(data_set['test'])
152 | print('test-loss: %.4f ||test-acc@1: %.4f'
153 | % (test_loss, test_acc))
154 |
155 | test_pred = test_pd[['ImageName']].copy()
156 | test_pred['label'] = list(test_preds)
157 | test_pred['label'] = test_pred['label'].apply(lambda x: label2class[int(x)])
158 | test_pred['prob'] = list(test_scores)
159 | test_pred['prob'] = test_pred['prob'].apply(lambda x: np2str(x))
160 | test_pred[['ImageName',"label","prob"]].to_csv('tiangong/csv/{0}_{1}_prob.csv'.format(opt.net,opt.mode) ,sep=",",
161 | header=None, index=False)
162 | test_pred[['ImageName',"label"]].to_csv('tiangong/csv/{0}_{1}_result.csv'.format(opt.net,opt.mode) ,sep=",",
163 | header=None, index=False)
--------------------------------------------------------------------------------
/predict/bd_xjtu_pred.py:
--------------------------------------------------------------------------------
1 | import os
2 | import numpy as np
3 | import pandas as pd
4 | from dataset.bd_xjtu_dataset import dataset, collate_fn
5 | import torch
6 | from torch.nn import CrossEntropyLoss
7 | import torch.utils.data as torchdata
8 | from torchvision import datasets, models, transforms
9 | from torchvision.models import resnet50
10 | from sklearn.model_selection import train_test_split
11 | from torch.autograd import Variable
12 | from math import ceil
13 | from torch.nn.functional import softmax
14 | from dataset.data_aug import *
15 | test_transforms= Compose([
16 | ExpandBorder(size=(336,336),resize=True),
17 | Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
18 | ])
19 |
20 | os.environ["CUDA_VISIBLE_DEVICES"] = "0"
21 | mode ="train"
22 |
23 | rawdata_root = '/media/hszc/data/detao/data/baidu/datasets/'
24 | all_pd = pd.read_csv("/media/hszc/data/detao/data/baidu/datasets/train.txt",sep=" ",
25 | header=None, names=['ImageName', 'label'])
26 | train_pd, val_pd = train_test_split(all_pd, test_size=0.15, random_state=43,
27 | stratify=all_pd['label'])
28 | true_test_pb = pd.read_csv("/media/hszc/data/detao/data/baidu/datasets/test.txt",sep=" ",
29 | header=None, names=['ImageName'])
30 | "addFakeLabel"
31 | true_test_pb['label'] =1
32 |
33 | test_pd =true_test_pb if mode=="test" else val_pd
34 | print(test_pd.head())
35 |
36 | data_set = {}
37 | data_set['test'] = dataset(imgroot=os.path.join(rawdata_root, mode), anno_pd=test_pd,
38 | transforms=test_transforms,
39 | )
40 | data_loader = {}
41 | data_loader['test'] = torchdata.DataLoader(data_set['test'], batch_size=4, num_workers=4,
42 | shuffle=False, pin_memory=True, collate_fn=collate_fn)
43 |
44 | model_name = 'resnet50-out'
45 | resume = '/media/hszc/model/detao/baidu_model/resnet/weights-20-360-[0.9870].pth'
46 |
47 | model =resnet50(pretrained=True)
48 | model.avgpool = torch.nn.AdaptiveAvgPool2d(output_size=1)
49 | model.fc = torch.nn.Linear(model.fc.in_features,100)
50 |
51 | print('resuming finetune from %s'%resume)
52 | model.load_state_dict(torch.load(resume))
53 | model = model.cuda()
54 | model.eval()
55 |
56 | criterion = CrossEntropyLoss()
57 |
58 | if not os.path.exists('./Baidu/csv'):
59 | os.makedirs('./Baidu/csv')
60 |
61 | test_size = ceil(len(data_set['test']) / data_loader['test'].batch_size)
62 | test_preds = np.zeros((len(data_set['test'])), dtype=np.float32)
63 | true_label = np.zeros((len(data_set['test'])), dtype=np.int)
64 | idx = 0
65 | test_loss = 0
66 | test_corrects = 0
67 | for batch_cnt_test, data_test in enumerate(data_loader['test']):
68 | # print data
69 | print("{0}/{1}".format(batch_cnt_test, int(test_size)))
70 | inputs, labels = data_test
71 | inputs = Variable(inputs.cuda())
72 | labels = Variable(torch.from_numpy(np.array(labels)).long().cuda())
73 | # forward
74 | outputs = model(inputs)
75 |
76 | # statistics
77 | if isinstance(outputs, list):
78 | loss = criterion(outputs[0], labels)
79 | loss += criterion(outputs[1], labels)
80 | outputs = (outputs[0]+outputs[1])/2
81 | else:
82 | loss = criterion(outputs, labels)
83 | _, preds = torch.max(outputs, 1)
84 |
85 | test_loss += loss.data[0]
86 | batch_corrects = torch.sum((preds == labels)).data[0]
87 | test_corrects += batch_corrects
88 | test_preds[idx:(idx + labels.size(0))] = preds
89 | true_label[idx:(idx + labels.size(0))] = labels.data.cpu().numpy()
90 | # statistics
91 | idx += labels.size(0)
92 | test_loss = test_loss / test_size
93 | test_acc = 1.0 * test_corrects / len(data_set['test'])
94 | print('test-loss: %.4f ||test-acc@1: %.4f'
95 | % (test_loss, test_acc))
96 |
97 | test_pred = test_pd[['ImageName']].copy()
98 | test_pred['label'] = list(test_preds)
99 | test_pred['label'] = test_pred['label'].apply(lambda x: int(x)+1)
100 | test_pred[['ImageName',"label"]].to_csv('Baidu/csv/{0}_{1}.csv'.format(model_name,mode) ,sep=" ",
101 | header=None, index=False)
102 | print (test_pred.info())
103 |
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OdingdongO/pytorch_classification/0b66c6f6aabf66eda0591712525ec036ee9a94e5/utils/__init__.py
--------------------------------------------------------------------------------
/utils/losses.py:
--------------------------------------------------------------------------------
1 | import torch
2 | from torch import nn
3 | import torch.nn.functional as F
4 | from torch.autograd import Variable
5 |
6 | class FocalLoss(nn.Module):
7 | """
8 |
9 | This criterion is a implemenation of Focal Loss, which is proposed in
10 | Focal Loss for Dense Object Detection.
11 |
12 | Loss(x, class) = - \alpha (1-softmax(x)[class])^gamma \log(softmax(x)[class])
13 |
14 | The losses are averaged across observations for each minibatch.
15 |
16 | Args:
17 | alpha(1D Tensor, Variable) : the scalar factor for this criterion
18 | gamma(float, double) : gamma > 0; reduces the relative loss for well-classi?ed examples (p > .5),
19 | putting more focus on hard, misclassi?ed examples
20 | size_average(bool): By default, the losses are averaged over observations for each minibatch.
21 | However, if the field size_average is set to False, the losses are
22 | instead summed for each minibatch.
23 | """
24 | def __init__(self, class_num, alpha=None, gamma=2, size_average=True):
25 | super(FocalLoss, self).__init__()
26 | if alpha is None:
27 | self.alpha = Variable(torch.ones(class_num, 1))
28 | else:
29 | if isinstance(alpha, Variable):
30 | self.alpha = alpha
31 | else:
32 | self.alpha = Variable(alpha)
33 | self.gamma = gamma
34 | self.class_num = class_num
35 | self.size_average = size_average
36 |
37 | def forward(self, inputs, targets):
38 | N = inputs.size(0)
39 | C = inputs.size(1)
40 | P = F.softmax(inputs)
41 |
42 | class_mask = inputs.data.new(N, C).fill_(0)
43 | class_mask = Variable(class_mask)
44 |
45 | ids = targets.view(-1, 1)
46 | class_mask.scatter_(1, Variable(ids.data), 1.0)
47 |
48 | if inputs.is_cuda and not self.alpha.is_cuda:
49 | self.alpha = self.alpha.cuda()
50 | alpha = self.alpha[ids.data.view(-1)]
51 |
52 | probs = (P*class_mask).sum(1).view(-1,1)
53 |
54 | log_p = probs.log()
55 |
56 | batch_loss = -alpha*(torch.pow((1-probs), self.gamma))*log_p
57 |
58 | if self.size_average:
59 | loss = batch_loss.mean()
60 | else:
61 | loss = batch_loss.sum()
62 | return loss
63 |
64 | class SoftmaxCrossEntropy(nn.Module):
65 | def __init__(self):
66 | super(SoftmaxCrossEntropy, self).__init__()
67 |
68 |
69 | def forward(self, y_preds, y_true,y_mask):
70 | '''
71 | :param y_preds: (N, C), Variable of FloatTensor
72 | :param y_true: (N, C), Variable of FloatTensor
73 | :return:
74 | '''
75 | # logp = F.log_softmax(y_preds)
76 | logp = y_preds.log() # (N, C)
77 | ylogp = y_true * logp
78 | ylogp =ylogp*y_mask
79 | return -ylogp.sum() / (y_true.sum()+0.000001)
--------------------------------------------------------------------------------
/utils/train_util.py:
--------------------------------------------------------------------------------
1 | #coding=utf8
2 | from __future__ import division
3 | import torch
4 | import os,time,datetime
5 | from torch.autograd import Variable
6 | import logging
7 | import numpy as np
8 | from math import ceil
9 |
10 | def dt():
11 | return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
12 |
13 | def trainlog(logfilepath, head='%(message)s'):
14 | logger = logging.getLogger('mylogger')
15 | logging.basicConfig(filename=logfilepath, level=logging.INFO, format=head)
16 | console = logging.StreamHandler()
17 | console.setLevel(logging.INFO)
18 | formatter = logging.Formatter(head)
19 | console.setFormatter(formatter)
20 | logging.getLogger('').addHandler(console)
21 |
22 | def train(model,
23 | epoch_num,
24 | start_epoch,
25 | optimizer,
26 | criterion,
27 | exp_lr_scheduler,
28 | data_set,
29 | data_loader,
30 | save_dir,
31 | print_inter=200,
32 | val_inter=3500
33 | ):
34 |
35 | step = -1
36 | for epoch in range(start_epoch,epoch_num):
37 | # train phase
38 | exp_lr_scheduler.step(epoch)
39 | model.train(True) # Set model to training mode
40 |
41 | for batch_cnt, data in enumerate(data_loader['train']):
42 |
43 | step+=1
44 | model.train(True)
45 | # print data
46 | inputs, labels = data
47 |
48 | inputs = Variable(inputs.cuda())
49 | labels = Variable(torch.from_numpy(np.array(labels)).long().cuda())
50 |
51 | # zero the parameter gradients
52 | optimizer.zero_grad()
53 |
54 | outputs = model(inputs)
55 | if isinstance(outputs, list):
56 | loss = criterion(outputs[0], labels)
57 | loss += criterion(outputs[1], labels)
58 | outputs=outputs[0]
59 | else:
60 | loss = criterion(outputs, labels)
61 |
62 | _, preds = torch.max(outputs, 1)
63 | loss.backward()
64 | optimizer.step()
65 |
66 | # batch loss
67 | if step % print_inter == 0:
68 | _, preds = torch.max(outputs, 1)
69 |
70 | batch_corrects = torch.sum((preds == labels)).data[0]
71 | batch_acc = batch_corrects / (labels.size(0))
72 |
73 | logging.info('%s [%d-%d] | batch-loss: %.3f | acc@1: %.3f'
74 | % (dt(), epoch, batch_cnt, loss.data[0], batch_acc))
75 |
76 |
77 | if step % val_inter == 0:
78 | logging.info('current lr:%s' % exp_lr_scheduler.get_lr())
79 | # val phase
80 | model.train(False) # Set model to evaluate mode
81 |
82 | val_loss = 0
83 | val_corrects = 0
84 | val_size = ceil(len(data_set['val']) / data_loader['val'].batch_size)
85 |
86 | t0 = time.time()
87 |
88 | for batch_cnt_val, data_val in enumerate(data_loader['val']):
89 | # print data
90 | inputs, labels = data_val
91 |
92 | inputs = Variable(inputs.cuda())
93 | labels = Variable(torch.from_numpy(np.array(labels)).long().cuda())
94 |
95 | # forward
96 | outputs = model(inputs)
97 | if isinstance(outputs, list):
98 | loss = criterion(outputs[0], labels)
99 | loss += criterion(outputs[1], labels)
100 | outputs = outputs[0]
101 |
102 | else:
103 | loss = criterion(outputs, labels)
104 | _, preds = torch.max(outputs, 1)
105 |
106 | # statistics
107 | val_loss += loss.data[0]
108 | batch_corrects = torch.sum((preds == labels)).data[0]
109 | val_corrects += batch_corrects
110 |
111 | val_loss = val_loss / val_size
112 | val_acc = 1.0 * val_corrects / len(data_set['val'])
113 |
114 | t1 = time.time()
115 | since = t1-t0
116 | logging.info('--'*30)
117 | logging.info('current lr:%s' % exp_lr_scheduler.get_lr())
118 |
119 | logging.info('%s epoch[%d]-val-loss: %.4f ||val-acc@1: %.4f ||time: %d'
120 | % (dt(), epoch, val_loss, val_acc, since))
121 |
122 | # save model
123 | save_path = os.path.join(save_dir,
124 | 'weights-%d-%d-[%.4f].pth'%(epoch,batch_cnt,val_acc))
125 | torch.save(model.state_dict(), save_path)
126 | logging.info('saved model to %s' % (save_path))
127 | logging.info('--' * 30)
128 |
129 |
130 |
--------------------------------------------------------------------------------