def __init__(self, num_classes, input_channel, pretrained): super(NASNetALarge, self).__init__() model = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained="imagenet") model.last_linear = nn.Linear(model.last_linear.in_features, num_classes) self.model = model
def get_outputs(image_dir, filename): models_name = ['resnet152', 'vgg19_bn', 'densenet161', 'nasnetalarge'] res = {} res_labels = {} for name in models_name: if name == 'densenet161': model_ft = torch.load('model_pretrained_densenet161.pkl') elif name == 'resnet152': model_ft = torch.load('model_pretrained_resnet152.pkl') elif name == 'vgg19_bn': model_ft = torch.load('model_pretrained_vgg19.pkl') data_transforms = transforms.Compose([ transforms.Scale(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])]) if name == 'nasnetalarge': model_ft = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') data_transforms = transforms.Compose([ transforms.Scale(377), transforms.CenterCrop(331), transforms.ToTensor(), transforms.Normalize(mean=model_ft.mean, std=model_ft.std)]) model_ft = torch.load('model_pretrained_nasnet.pkl') use_gpu = torch.cuda.is_available() model_ft.eval() test_dataset = TestData(image_dir, data_transforms) test_dataloader = DataLoader(test_dataset, batch_size=4, shuffle=False, num_workers=4) since = time.time() temp = [] temp_list = [] for i, batch in enumerate(test_dataloader): inputs, cid = batch temp_list.append(cid) if use_gpu: inputs = Variable(inputs.cuda()) else: inputs = Variable(inputs) outputs = model_ft(inputs) temp.append(softmax(outputs.data.cpu().numpy())) if i % 200 == 199: print('iter:{}'.format(i+1)) time_elapsed = time.time() - since print('Testing complete in {:.0f}m {:.0f}s'.format( time_elapsed // 60, time_elapsed % 60)) res[name] = np.concatenate(temp) res_labels[name] = [y for x in temp_list for y in x] print('{} finish'.format(name)) torch.save(res, filename) torch.save(res_labels, filename + '_label') return res
def test_nasnetalarge_model(input_var, pool, assert_equal_outputs): original_model = pretrainedmodels.nasnetalarge(pretrained='imagenet', num_classes=1000) finetune_model = make_model( 'nasnetalarge', num_classes=1000, pool=pool, pretrained=True, ) copy_module_weights(original_model.last_linear, finetune_model._classifier) assert_equal_outputs(input_var, original_model, finetune_model)
def __init__(self, num_classes, pretrained="imagenet"): super().__init__() self.model = nasnetalarge(pretrained=pretrained, num_classes=1000) self.model.avg_pool = nn.AdaptiveAvgPool2d(1) new_last_linear = nn.Linear(self.model.last_linear.in_features, num_classes) new_last_linear.weight.data = self.model.last_linear.weight.data[: num_classes] new_last_linear.bias.data = self.model.last_linear.bias.data[: num_classes] self.model.last_linear = new_last_linear
def nets(model, num_class): if model == 'inceptionv4': model = ptm.inceptionv4(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, num_class) return model if model == 'senet154': model = ptm.senet154(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, num_class) return model if model == 'pnasnet': model = ptm.pnasnet5large(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, num_class) return model if model == 'xception': model = ptm.xception(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, num_class) return model if model == 'incepresv2': model = ptm.inceptionresnetv2(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, num_class) return model if model == 'resnet152': model = models.resnet152(pretrained=True) model.fc = nn.Linear(2048, num_class) return model if model == 'se_resxt101': model = ptm.se_resnext101_32x4d(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, num_class) return model if model == 'nasnet': model = ptm.nasnetalarge(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, num_class) return model if model == 'dpn': # 224 input size model = ptm.dpn107(num_classes=1000, pretrained='imagenet+5k') model.last_linear = nn.Conv2d(model.last_linear.in_channels, num_class, kernel_size=1, bias=True) return model if model == 'resnext101':# 320 input size model = torch.hub.load('facebookresearch/WSL-Images', 'resnext101_32x16d_wsl') model.fc = nn.Linear(2048, num_class) return model
def nasnetalarge(input_size=(3, 331, 331), num_classes=1000, pretrained=None): # Minimum Input size = (96,96) one is must above than 97 model = models.nasnetalarge(num_classes=1000, pretrained=pretrained) if input_size != (3, 331, 331): model.conv0.conv = nn.Conv2d(in_channels=input_size[0], out_channels=96, kernel_size=3, padding=0, stride=2, bias=False) model.input_size = input_size # calculate last avgpool_1a kernel size test_tensor = torch.randn(1, input_size[0], input_size[1], input_size[2]) x_conv0 = model.conv0(test_tensor) x_stem_0 = model.cell_stem_0(x_conv0) x_stem_1 = model.cell_stem_1(x_conv0, x_stem_0) x_cell_0 = model.cell_0(x_stem_1, x_stem_0) x_cell_1 = model.cell_1(x_cell_0, x_stem_1) x_cell_2 = model.cell_2(x_cell_1, x_cell_0) x_cell_3 = model.cell_3(x_cell_2, x_cell_1) x_cell_4 = model.cell_4(x_cell_3, x_cell_2) x_cell_5 = model.cell_5(x_cell_4, x_cell_3) x_reduction_cell_0 = model.reduction_cell_0(x_cell_5, x_cell_4) x_cell_6 = model.cell_6(x_reduction_cell_0, x_cell_4) x_cell_7 = model.cell_7(x_cell_6, x_reduction_cell_0) x_cell_8 = model.cell_8(x_cell_7, x_cell_6) x_cell_9 = model.cell_9(x_cell_8, x_cell_7) x_cell_10 = model.cell_10(x_cell_9, x_cell_8) x_cell_11 = model.cell_11(x_cell_10, x_cell_9) x_reduction_cell_1 = model.reduction_cell_1(x_cell_11, x_cell_10) x_cell_12 = model.cell_12(x_reduction_cell_1, x_cell_10) x_cell_13 = model.cell_13(x_cell_12, x_reduction_cell_1) x_cell_14 = model.cell_14(x_cell_13, x_cell_12) x_cell_15 = model.cell_15(x_cell_14, x_cell_13) x_cell_16 = model.cell_16(x_cell_15, x_cell_14) x_cell_17 = model.cell_17(x_cell_16, x_cell_15) x = model.relu(x_cell_17) model.avg_pool = nn.AvgPool2d(kernel_size=(x.shape[2], x.shape[3])) x = model.avg_pool(x) x = x.view(x.size(0), -1).shape[1] model.last_linear = nn.Linear(in_features=x, out_features=num_classes, bias=True) return model
def generate_2D_model(opt): if opt['model'] == 'inception_v3': C, H, W = 3, 299, 299 model = pretrainedmodels.inceptionv3(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif opt['model'] == 'vgg16': C, H, W = 3, 224, 224 model = pretrainedmodels.vgg16(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif opt['model'] == 'vgg19': C, H, W = 3, 224, 224 model = pretrainedmodels.vgg19(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif opt['model'] == 'resnet50': C, H, W = 3, 224, 224 model = pretrainedmodels.resnet50(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif opt['model'] == 'resnet101': C, H, W = 3, 224, 224 model = pretrainedmodels.resnet101(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif opt['model'] == 'resnet152': C, H, W = 3, 224, 224 model = pretrainedmodels.resnet152(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif opt['model'] == 'inception_v4': C, H, W = 3, 299, 299 model = pretrainedmodels.inceptionv4(num_classes=1000, pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif opt['model'] == 'nasnet': C, H, W = 3, 331, 331 model = pretrainedmodels.nasnetalarge(num_classes=1001, pretrained='imagenet+background') load_image_fn = utils.LoadTransformImage(model) else: print("doesn't support %s" % (opt['model'])) model.last_linear = utils.Identity() model = nn.DataParallel(model) # if opt['saved_model'] != '': # model.load_state_dict(torch.load(opt['saved_model']), strict=False) model = model.cuda() return model
def main(): """main Module which select models and load. """ model = args.model # Use args.model as pretrain model if model == 'resnet152': original_model = torchvision.models.resnet152(pretrained=True) elif model == 'resnet50' or model == 'resnet50_3c': original_model = torchvision.models.resnet50(pretrained=True) elif model == 'densenet161': original_model = torchvision.models.densenet161(pretrained=True) elif model == 'pnasnet5large': original_model = pretrainedmodels.pnasnet5large(num_classes=1000, pretrained='imagenet') elif model == 'nasnetalarge': original_model = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') else: sys.exit(-1) net = FineTuneModel(original_model, model, args) #for name, param in original_model.named_children(): # print(name) #for name, param in net.named_children(): # print(name) if args.lm == False: CNN_Train(net, args) elif args.lm == True: # Load from saved model if os.path.isfile(args.model_path) == True: print("=> loading checkpoint '{}'".format(args.model_path)) checkpoint = torch.load(args.model_path) CNN_Train(net, args, checkpoint) else: print("=> no checkpoint found at '{}'".format(args.model_path)) else: print('Error --lm parameter') sys.exit(-1)
def nasnetalarge(num_classes, feature_extract, use_pretrained=True): """Funkcja zwracająca model nasnet_large :param num_classes: liczba szukanych cech :type num_classes: int :param feature_extract: czy ekstrachować cechy :type feature_extract: bool :param use_pretrained: czy używać wstępnie przetrenowanego modelu :type use_pretrained: bool :return: wygenerowny model,wielkość wejścia modelu,sugerowana średnia do normalizacji,sugerowane odchylenie standardowe do normalizacji :rtype: model, int, float, float """ model = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') set_parameter_requires_grad(model, feature_extract) num_ftrs = model.last_linear.in_features model.last_linear = nn.Sequential(nn.Linear(num_ftrs, num_classes), nn.Sigmoid()) input_size = 224 mean, std = [0.5, 0.5, 0.5], [0.5, 0.5, 0.5] return model, input_size, mean, std
C, H, W = 3, 224, 224 model = pretrainedmodels.resnet50(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif params['model'] == 'resnet101': C, H, W = 3, 224, 224 model = pretrainedmodels.resnet101(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif params['model'] == 'resnet152': C, H, W = 3, 224, 224 model = pretrainedmodels.resnet152(pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif params['model'] == 'inception_v4': C, H, W = 3, 299, 299 model = pretrainedmodels.inceptionv4(num_classes=1000, pretrained='imagenet') load_image_fn = utils.LoadTransformImage(model) elif params['model'] == 'nasnet': C, H, W = 3, 331, 331 model = pretrainedmodels.nasnetalarge(num_classes=1001, pretrained='imagenet+background') load_image_fn = utils.LoadTransformImage(model) else: print("doesn't support %s" % (params['model'])) model.last_linear = utils.Identity() model = nn.DataParallel(model) if params['saved_model'] != '': model.load_state_dict(torch.load(params['saved_model']), strict=False) model = model.cuda() extract_feats(params, model, load_image_fn)
def main(): global best_val_loss global best_val_acc start_epoch = args.start_epoch # start from epoch 0 or last checkpoint epoch env_name = args.env_name # create a unique id for naming purposes now = datetime.datetime.now() vis_file_out = env_name + str(now.year) + ';' + str(now.month) + ';' + \ str(now.day) + ';' + str(now.hour) + ';' + str(now.minute) # set up logger log_filename = './logs/' + str(vis_file_out) + '.txt' logger = configure_logging(log_filename) logger.info(args) # Data loading code if args.arch == "inception": scaler = 350 img_size = 299 norm_trans = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) elif args.arch == "nasnet": scaler = 354 img_size = 331 norm_trans = transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]) else: scaler = 280 img_size = 224 norm_trans = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) train_transform = transforms.Compose([ # transforms.Resize((img_size, img_size)), transforms.Resize(scaler), transforms.RandomResizedCrop(img_size), transforms.RandomRotation(degrees=args.random_angle, resample=Image.BILINEAR), transforms.RandomHorizontalFlip(), transforms.ToTensor(), norm_trans ]) train_transform2 = transforms.Compose([ # transforms.Resize((img_size, img_size)), transforms.Resize(img_size), transforms.CenterCrop(img_size), transforms.ToTensor(), norm_trans ]) test_transform = transforms.Compose([ # transforms.Resize((img_size, img_size)), transforms.Resize(scaler), transforms.CenterCrop(img_size), transforms.ToTensor(), norm_trans ]) # create train and test datasets fp_train = Path(args.train_path) fp_test = Path(args.test_path) df_train = pd.read_csv(args.train_labels_path, index_col=0) df_test = pd.read_csv('./data/kaggle_dbi/sample_submission.csv', index_col=0) if args.ensemble == 1: trainODDataset = DBI_dataset_ensemble(fp_train, df_train, df_test, is_train=True, transform=train_transform2) testODDataset = DBI_dataset_ensemble(fp_test, df_train, df_test, is_train=False, transform=test_transform) else: trainODDataset = DBI_dataset(fp_train, df_train, df_test, args.oxford_augment, is_train=True, transform=train_transform2) testODDataset = DBI_dataset(fp_test, df_train, df_test, args.oxford_augment, is_train=False, transform=test_transform) train_loader_all = torch.utils.data.DataLoader(trainODDataset, batch_size=args.train_batch, shuffle=False) test_indices = list(range(args.test_batch)) test_sampler = SubsetRandomSampler(test_indices) if args.debug_mode == 1: test_loader = torch.utils.data.DataLoader(testODDataset, batch_size=args.test_batch, sampler=test_sampler, shuffle=False) else: test_loader = torch.utils.data.DataLoader(testODDataset, batch_size=args.test_batch, shuffle=False) # load pretrained model for a soft start out_size = 120 print("=> using pre-trained model '{}'".format(args.arch)) if args.arch == 'inception': # model = models.inception_v3(pretrained=True, aux_logits=False) model = models.inception_v3(pretrained=True) num_ftrs = model.fc.in_features model.fc = nn.Linear(num_ftrs, out_size) num_ftrs = model.AuxLogits.fc.in_features model.AuxLogits.fc = nn.Linear(num_ftrs, out_size) elif args.arch == 'resnet18': # model = models.resnet18(pretrained=True) model = models.resnet101(pretrained=True) # model = models.alexnet(pretrained=True) # model = models.vgg16(pretrained=True) # switch to True if using VGG/ alexnet if False: model.classifier[6] = nn.Linear(4096, out_size) else: num_ftrs = model.fc.in_features model.fc = nn.Linear(num_ftrs, out_size) elif args.arch == 'nasnet': model = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') if args.freezeLayers == 'all': for param in model.parameters(): param.requires_grad = False num_ftrs = model.last_linear.in_features if args.transfer_oxford: model.last_linear = nn.Linear(num_ftrs, 25) else: model.last_linear = nn.Linear(num_ftrs, out_size) else: raise NotImplementedError( "only inception_v3, nanset and resnet18 are available at the moment" ) # set up loss function criterion = nn.CrossEntropyLoss() # load pretrained oxford pets model if args.transfer_oxford: # Load checkpoint. print('==> Resuming from pretrained oxford pets checkpoint..') logger.info('==> Resuming from pretrained oxford pets checkpoint..') assert os.path.isfile( args.transfer_oxford), 'Error: no checkpoint directory found!' checkpoint = torch.load(args.transfer_oxford) model.load_state_dict(checkpoint['state_dict']) num_ftrs = model.last_linear.in_features model.last_linear = nn.Linear(num_ftrs, out_size) # move models to GPU if use_cuda: print("using gpu") model.cuda() criterion.cuda() print('Total params: %.2fM' % (sum(p.numel() for p in model.parameters()) / 1000000.0)) # define optimizer # optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay) params_to_update = [] for name, param in model.named_parameters(): if param.requires_grad: params_to_update.append(param) print("\t", name) optimizer = optim.Adam(params_to_update, lr=args.lr, weight_decay=args.weight_decay) scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=8, verbose=True, factor=args.lr_reduce) # do model ensemble if args.ensemble == 1: print('==> doing ensemble..') logger.info('==> doing ensemble..') model_b = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') num_ftrs = model_b.last_linear.in_features model_b.last_linear = nn.Linear(num_ftrs, out_size) assert os.path.isfile( args.ensemble_path_a), 'Error: no checkpoint directory found!' checkpointa = torch.load(args.ensemble_path_a) checkpointb = torch.load(args.ensemble_path_b) model.load_state_dict(checkpointa['state_dict']) model_b.load_state_dict(checkpointb['state_dict']) model.cuda() model_b.cuda() # continue training of a model if args.resume: # Load checkpoint. print('==> Resuming from checkpoint..') logger.info('==> Resuming from checkpoint..') assert os.path.isfile( args.resume), 'Error: no checkpoint directory found!' # args.checkpoint = os.path.dirname(args.resume) checkpoint = torch.load(args.resume) best_val_loss = checkpoint['best_val_loss'] start_epoch = checkpoint['epoch'] model.load_state_dict(checkpoint['state_dict']) optimizer.load_state_dict(checkpoint['optimizer']) # print network arch to decide how many layers to freeze # for id, child in enumerate(model.children()): # for name, param in child.named_parameters(): # print(id, ': ', name) # freeze layers if args.freezeLayers == 'none': print("not freezing anything") logger.info("not freezing anything") elif args.freezeLayers == 'half': print("freezing first layers only") logger.info("freezing first layers only") if args.arch == 'inception': special_child = args.freezeLayersNum elif args.arch == 'resnet18': special_child = args.freezeLayersNum elif args.arch == 'nasnet': special_child = args.freezeLayersNum # special_child = 19 child_counter = 0 for child in model.children(): if child_counter < special_child: for param in child.parameters(): param.requires_grad = False else: break child_counter += 1 elif args.freezeLayers == 'all': print("freezing all layers except for the top layer") logger.info("freezing all layers except for the top layer") last_child = 0 if args.arch == 'inception': last_child = 17 elif args.arch == 'resnet18': last_child = 9 child_counter = 0 for child in model.children(): if child_counter < last_child: for param in child.parameters(): param.requires_grad = False else: break child_counter += 1 else: raise NotImplementedError( "only none/ half/ all options are available at the moment") # save feature vecs for better runtime on long epochs training if args.use_saved_feature_vecs == 1: args.epochs = 10000 # load base model pretrained on kaggle into memory if args.pretrained_kaggle: checkpoint = torch.load(args.pretrained_kaggle) model.load_state_dict(checkpoint['state_dict']) model.eval() # load saved feature vectors and labels if args.file_path_inputs_npy_to_load: feature_vecs_inputs = np.load(args.file_path_inputs_npy_to_load) feature_vecs_targets = np.load(args.file_path_targets_npy_to_load) else: # if no saved feature vectors and labels are given then create those files for future use feature_vecs_inputs, feature_vecs_targets = get_feature_vecs( train_loader_all, model) file_path_inputs_npy_to_save = 'C:/Users/Alfassy/PycharmProjects/Dog_Breed_Identification/saved_models/kaggle_dbi/feature_vecs_inputs' + str( vis_file_out) + '.npy' np.save(file_path_inputs_npy_to_save, feature_vecs_inputs) file_path_targets_npy_to_save = 'C:/Users/Alfassy/PycharmProjects/Dog_Breed_Identification/saved_models/kaggle_dbi/feature_vecs_targets' + str( vis_file_out) + '.npy' np.save(file_path_targets_npy_to_save, feature_vecs_targets) # separate data to train and val validation_split = 0.2 # num without oxford dataset_size = trainODDataset.img_num if args.debug_mode == 1: indices = list(range(int(dataset_size / 18))) else: indices = list(range(dataset_size)) split = int(np.floor(validation_split * len(indices))) np.random.seed(args.manualSeed) np.random.shuffle(indices) train_indices, val_indices = indices[split:], indices[:split] x_train = feature_vecs_inputs[train_indices] x_val = feature_vecs_inputs[val_indices] y_train = feature_vecs_targets[train_indices] y_val = feature_vecs_targets[val_indices] # the dataset is divided to [kaggle, oxford] so if we wish, we'll add oxford to the train data only. if args.oxford_augment == 1: x_train = np.concatenate((x_train, feature_vecs_inputs[range( trainODDataset.img_num, trainODDataset.img_num_with_oxford)])) y_train = np.concatenate((y_train, feature_vecs_targets[range( trainODDataset.img_num, trainODDataset.img_num_with_oxford)]), axis=0) top_only_train_dataset = TensorDataset(torch.FloatTensor(x_train), torch.LongTensor(y_train)) top_only_val_dataset = TensorDataset(torch.FloatTensor(x_val), torch.LongTensor(y_val)) train_loader = DataLoader(top_only_train_dataset, batch_size=4096, shuffle=True) val_loader = DataLoader(top_only_val_dataset, batch_size=4096, shuffle=True) # initialize a top model consists of a fc and dropout classifierModel = DropClassifier() # if starting from a trained base_model, also load his FC layer as an initialization unless resume_top_module is given if args.pretrained_kaggle: assert os.path.isfile(args.pretrained_kaggle ), 'Error: no checkpoint directory found!' checkpoint = torch.load(args.pretrained_kaggle) # classifierModel.last_linear.load_state_dict(list(model.children())[-1].state_dict()) classifierModel = DropClassifier( checkpoint['state_dict']['last_linear.weight'], checkpoint['state_dict']['last_linear.bias']) # classifierModel.last_linear.weight.data.fill_(checkpoint['state_dict']['last_linear.weight']) # classifierModel.last_linear.bias.data = checkpoint['state_dict']['last_linear.bias'] print(torch.load(args.pretrained_kaggle)['state_dict']) print(classifierModel.last_linear.weight) del checkpoint # load saved top module if args.resume_top_module: classifierModel.load_state_dict( torch.load(args.resume_top_module)['state_dict']) # set up optimizer for top module optimizer = optim.Adam(classifierModel.parameters(), lr=args.lr) scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=200, verbose=True, factor=args.lr_reduce) classifierModel.cuda() else: # split train and val validation_split = 0.2 dataset_size = trainODDataset.img_num if args.debug_mode == 1: indices = list(range(int(dataset_size / 18))) else: indices = list(range(dataset_size)) split = int(np.floor(validation_split * len(indices))) np.random.seed(args.manualSeed) np.random.shuffle(indices) train_indices, val_indices = indices[split:], indices[:split] # the dataset is divided to [kaggle, oxford] so if we wish, we'll add oxford to the train data only. if args.oxford_augment == 1: train_indices = np.concatenate( (train_indices, range(trainODDataset.img_num, trainODDataset.img_num_with_oxford)), axis=0) # Creating PT data samplers and loaders: train_sampler = SubsetRandomSampler(train_indices) valid_sampler = SubsetRandomSampler(val_indices) train_loader = torch.utils.data.DataLoader(trainODDataset, batch_size=args.train_batch, sampler=train_sampler) val_loader = torch.utils.data.DataLoader(trainODDataset, batch_size=args.train_batch, sampler=valid_sampler) # evaluation only mode if args.evaluate == 1: print('\nEvaluation only') logger.info('\nEvaluation only') # not checking val loss and acc in ensemble mode if args.ensemble == 1: test(test_loader, model, model_b, None, use_cuda, df_test, vis_file_out) else: # check val accuracy if args.use_saved_feature_vecs == 1: val_loss, val_acc, class_acc_list = val( val_loader, classifierModel, criterion, use_cuda, scheduler) else: val_loss, val_acc, class_acc_list = val( val_loader, model, criterion, use_cuda, scheduler) print("Val Loss: {}, Val Acc: {}".format(val_loss, val_acc)) logger.info("Val Loss: {}, Val Acc: {}".format(val_loss, val_acc)) if args.print_per_class_acc: for class_ind, class_acc in enumerate(class_acc_list): print('Class {} accuracy: {}'.format(class_ind, class_acc)) # create copmpetition excel if args.use_saved_feature_vecs == 1: # feature_vecs_inputs, feature_vecs_targets = get_feature_vecs(test_loader, model, test_mode=True) # print(feature_vecs_targets) # top_only_test_dataset = DBI_dataset_test_time(torch.FloatTensor(feature_vecs_inputs), feature_vecs_targets) # test_loader = DataLoader(top_only_test_dataset, batch_size=4096, shuffle=False) test(test_loader, model, None, classifierModel, use_cuda, df_test, vis_file_out) else: test(test_loader, model, None, None, use_cuda, df_test, vis_file_out) return # Train and val main loop for epoch in range(start_epoch, args.epochs): print('\nEpoch: [%d | %d] LR: %f' % (epoch + 1, args.epochs, state['lr'])) logger.info("Epoch: {} of {}, LR: {}".format(epoch + 1, args.epochs, state['lr'])) if args.use_saved_feature_vecs == 1: train_loss, train_acc = train(train_loader, classifierModel, criterion, optimizer, use_cuda) else: train_loss, train_acc = train(train_loader, model, criterion, optimizer, use_cuda) print("finished train, starting test on val set") logger.info("finished train, starting test on val set") if args.ensemble == 1: raise RuntimeError( "ensemble should only be ran in evaluation mode (evaluate=1)") else: if args.use_saved_feature_vecs == 1: val_loss, val_acc, class_acc_list = val( val_loader, classifierModel, criterion, use_cuda, scheduler) else: val_loss, val_acc, class_acc_list = val( val_loader, model, criterion, use_cuda, scheduler) print("learning rate: {}".format(get_learning_rate(optimizer))) logger.info("learning rate: {}".format(get_learning_rate(optimizer))) print("train loss: {}, train accuracy: {}".format( train_loss, train_acc)) logger.info("train loss: {}, train accuracy: {}".format( train_loss, train_acc)) print("val loss: {}, val accuracy: {}".format(val_loss, val_acc)) logger.info("val loss: {}, val accuracy: {}".format(val_loss, val_acc)) if args.print_per_class_acc: for class_ind, class_acc in enumerate(class_acc_list): print('Class {} accuracy: {}'.format(class_ind, class_acc)) # save model is_best = val_loss < best_val_loss best_val_loss = min(val_loss, best_val_loss) best_val_acc = max(val_acc, best_val_acc) filename = str(vis_file_out) if args.use_saved_feature_vecs == 1: save_checkpoint( { 'epoch': epoch + 1, 'state_dict': classifierModel.state_dict(), 'loss': val_loss, 'best_val_loss': best_val_loss, 'optimizer': optimizer.state_dict() }, is_best, checkpoint=args.checkpoint, filename=filename) else: save_checkpoint( { 'epoch': epoch + 1, 'state_dict': model.state_dict(), 'acc': val_loss, 'best_val_loss': best_val_loss, 'optimizer': optimizer.state_dict() }, is_best, checkpoint=args.checkpoint, filename=filename) # test_loss, test_acc = test(test_loader, model, criterion, use_cuda, scheduler, df_test, vis_file_out) print('Best val acc: {}'.format(best_val_acc)) print('Best val loss: {}'.format(best_val_loss)) logger.info('Best val acc: {}'.format(best_val_acc)) logger.info('Best val loss: {}'.format(best_val_loss))
import os import torch import torchvision import torch.nn as nn import torch.optim as optim from torch.optim import lr_scheduler import numpy as np from torch.utils.data import Dataset from torchvision import transforms, datasets from torch.autograd import Variable import matplotlib.pyplot as plt import time import pretrainedmodels model_ft = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') data_transforms = { 'train': transforms.Compose([ transforms.RandomSizedCrop(331), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean=model_ft.mean, std=model_ft.std) ]), 'val': transforms.Compose([ transforms.Scale(377), transforms.CenterCrop(331), transforms.ToTensor(), transforms.Normalize(mean=model_ft.mean, std=model_ft.std)
def main(): global best_val_acc start_epoch = args.start_epoch # start from epoch 0 or last checkpoint epoch # Data loading code if args.arch == "inception": scaler = 350 img_size = 299 norm_trans = transforms.Normalize( mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] ) elif args.arch == "nasnet": scaler = 354 img_size = 331 norm_trans = transforms.Normalize( mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5] ) else: scaler = 280 img_size = 224 norm_trans = transforms.Normalize( mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] ) # train_transform = transforms.Compose( # [ # # transforms.Resize((img_size, img_size)), # transforms.Resize(scaler), # transforms.RandomResizedCrop(img_size), # transforms.RandomRotation(degrees=args.random_angle, resample=Image.BILINEAR), # transforms.RandomHorizontalFlip(), # transforms.ToTensor() # ] # ) train_transform = transforms.Compose( [ # transforms.Resize((img_size, img_size)), transforms.Resize(scaler), transforms.RandomResizedCrop(img_size), transforms.RandomRotation(degrees=args.random_angle, resample=Image.BILINEAR), transforms.RandomHorizontalFlip(), transforms.ToTensor(), norm_trans ] ) test_transform = transforms.Compose( [ # transforms.Resize((img_size, img_size)), transforms.Resize(scaler), transforms.CenterCrop(img_size), transforms.ToTensor(), norm_trans ] ) # create train and test datasets imgs_path = Path(args.images_path) trainODDataset = oxford_dataset(imgs_path, transform=train_transform) validation_split = 0.2 dataset_size = len(trainODDataset) if args.debug_mode == 1: indices = list(range(int(dataset_size/18))) else: indices = list(range(dataset_size)) split = int(np.floor(validation_split * len(indices))) np.random.seed(args.manualSeed) np.random.shuffle(indices) train_indices, val_indices = indices[split:], indices[:split] # Creating PT data samplers and loaders: train_sampler = SubsetRandomSampler(train_indices) valid_sampler = SubsetRandomSampler(val_indices) train_loader = torch.utils.data.DataLoader(trainODDataset, batch_size=args.train_batch, sampler=train_sampler) val_loader = torch.utils.data.DataLoader(trainODDataset, batch_size=args.train_batch, sampler=valid_sampler) out_size = 25 print("=> using pre-trained model '{}'".format(args.arch)) if args.arch == 'inception': # model = models.inception_v3(pretrained=True, aux_logits=False) model = models.inception_v3(pretrained=True) num_ftrs = model.fc.in_features model.fc = nn.Linear(num_ftrs, out_size) num_ftrs = model.AuxLogits.fc.in_features model.AuxLogits.fc = nn.Linear(num_ftrs, out_size) elif args.arch == 'resnet18': # model = models.resnet18(pretrained=True) model = models.resnet101(pretrained=True) # model = models.alexnet(pretrained=True) # model = models.vgg16(pretrained=True) # switch to True if using VGG/ alexnet if False: model.classifier[6] = nn.Linear(4096, out_size) else: num_ftrs = model.fc.in_features model.fc = nn.Linear(num_ftrs, out_size) elif args.arch == 'nasnet': # model = models.inception_v3(pretrained=True, aux_logits=False) model = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') if args.freezeLayers == 'all': for param in model.parameters(): param.requires_grad = False num_ftrs = model.last_linear.in_features model.last_linear = nn.Linear(num_ftrs, out_size) else: raise NotImplementedError("only inception_v3 and resnet18 are available at the moment") criterion = nn.CrossEntropyLoss() if use_cuda: print("using gpu") model.cuda() criterion.cuda() # cudnn.benchmark = True print('Total params: %.2fM' % (sum(p.numel() for p in model.parameters())/1000000.0)) # define loss function (criterion) and optimizer # criterion = nn.CrossEntropyLoss().cuda() # optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay) optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=args.weight_decay) scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=8, verbose=True, factor=args.lr_reduce) env_name = args.env_name now = datetime.datetime.now() vis_file_out = env_name + str(now.year) + ';' + str(now.month) + ';' + \ str(now.day) + ';' + str(now.hour) + ';' + str(now.minute) # TODO: save to logs to disk # notes_logger = visdomLogger.VisdomTextLogger(update_type='APPEND', server=args.visdom_server, env=env_name) # notes_logger.log("Start time: {}".format(now)) # notes_logger.log("Args: {}".format(args)) # notes_logger.log("data lenght: {}".format(len(trainODDataset.trainImgPathLabels))) log_filename = './logs/' + str(vis_file_out) + '.txt' logger = configure_logging(log_filename) logger.info(args) if args.resume: # Load checkpoint. print('==> Resuming from checkpoint..') logger.info('==> Resuming from checkpoint..') assert os.path.isfile(args.resume), 'Error: no checkpoint directory found!' args.checkpoint = os.path.dirname(args.resume) checkpoint = torch.load(args.resume) best_val_acc = checkpoint['best_val_acc'] start_epoch = checkpoint['epoch'] model.load_state_dict(checkpoint['state_dict']) optimizer.load_state_dict(checkpoint['optimizer']) # print network arch to decide how many layers to freeze for id, child in enumerate(model.children()): for name, param in child.named_parameters(): print(id, ': ', name) exit() # freeze layers if args.freezeLayers == 'none': print("not freezing anything") logger.info("not freezing anything") elif args.freezeLayers == 'half': print("freezing first layers only") logger.info("freezing first layers only") if args.arch == 'inception': special_child = 5 elif args.arch == 'resnet18': special_child = 5 elif args.arch == 'nasnet': special_child = args.freezeLayersNum # special_child = 19 child_counter = 0 for child in model.children(): if child_counter < special_child: for param in child.parameters(): param.requires_grad = False else: break child_counter += 1 elif args.freezeLayers == 'all': print("freezing all layers except for the top layer") logger.info("freezing all layers except for the top layer") if args.arch == 'inception': last_child = 17 elif args.arch == 'resnet18': last_child = 9 elif args.arch == 'nasnet': last_child = 0 child_counter = 0 for child in model.children(): if child_counter < last_child: for param in child.parameters(): param.requires_grad = False else: break child_counter += 1 else: raise NotImplementedError("only none/ half/ all options are available at the moment") if args.evaluate == 1: print('\nEvaluation only') logger.info('\nEvaluation only') val_loss, val_acc = val(val_loader, model, criterion, use_cuda, scheduler) print("Val Loss: {}, Val Acc: {}".format(val_loss, val_acc)) logger.info("Val Loss: {}, Val Acc: {}".format(val_loss, val_acc)) return # Train and val for epoch in range(start_epoch, args.epochs): print('\nEpoch: [%d | %d] LR: %f' % (epoch + 1, args.epochs, state['lr'])) # notes_logger.log("Epoch: {} of {}, LR: {}".format(epoch+1, args.epochs, state['lr'])) logger.info("Epoch: {} of {}, LR: {}".format(epoch+1, args.epochs, state['lr'])) train_loss, train_acc = train(train_loader, model, criterion, optimizer, epoch, use_cuda) print("finished train, starting test") logger.info("finished train, starting test") val_loss, val_acc = val(val_loader, model, criterion, use_cuda, scheduler) # log loss and accuracy print("learning rate: {}".format(get_learning_rate(optimizer))) logger.info("learning rate: {}".format(get_learning_rate(optimizer))) print("train loss: {}, train accuracy: {}".format(train_loss, train_acc)) logger.info("train loss: {}, train accuracy: {}".format(train_loss, train_acc)) print("val loss: {}, val accuracy: {}".format(val_loss, val_acc)) logger.info("val loss: {}, val accuracy: {}".format(val_loss, val_acc)) # save model is_best = val_acc > best_val_acc best_val_acc = max(val_acc, best_val_acc) filename = str(vis_file_out) save_checkpoint({'epoch': epoch + 1, 'state_dict': model.state_dict(), 'acc': val_acc, 'best_val_acc': best_val_acc, 'optimizer': optimizer.state_dict() }, is_best, epoch, checkpoint=args.checkpoint, filename=filename) print('Best val acc: '.format(best_val_acc)) logger.info('Best val acc: '.format(best_val_acc))
def create_model(model_key, pretrained, num_of_classes, use_gpu): """Create CNN model Args: model_key (str): Name of the model to be created. pretrained: If True, only train the laster layer. num_of_classes (int): Number of categories of outputs. Returns: model_conv: A defined model to be train Raises: ValueError: Error while asking an unrecognized model. """ if model_key == 'resnet18': model_conv = torchvision.models.resnet18(pretrained=True) elif model_key == 'resnet34': model_conv = torchvision.models.resnet34(pretrained=True) elif model_key == 'resnet50': model_conv = torchvision.models.resnet50(pretrained=True) elif model_key == 'resnet101': model_conv = torchvision.models.resnet101(pretrained=True) elif model_key == 'inception_v3': model_conv = torchvision.models.inception_v3(pretrained=True) elif model_key == 'inceptionresnetv2': model_conv = pretrainedmodels.inceptionresnetv2(num_classes=1000, pretrained='imagenet') elif model_key == 'inceptionv4': model_conv = pretrainedmodels.inceptionv4(num_classes=1000, pretrained='imagenet') elif model_key == 'nasnetalarge': model_conv = pretrainedmodels.nasnetalarge(num_classes=1000, pretrained='imagenet') else: raise ValueError("Unrecognized name of model {}".format(model_key)) if pretrained: # Lock parameters for transfer learning for param in model_conv.parameters(): param.requires_grad = False # Parameters of newly constructed modules have requires_grad=True by default if model_key == 'nasnetalarge' or model_key == 'inceptionresnetv2' or model_key == 'inceptionv4': dim_feats = model_conv.last_linear.in_features # 2048 model_conv.last_linear = nn.Linear(dim_feats, num_of_classes) else: num_ftrs = model_conv.fc.in_features model_conv.fc = nn.Linear(num_ftrs, num_of_classes) # Initialize newly added module parameters if model_key == 'nasnetalarge' or model_key == 'inceptionresnetv2' or model_key == 'inceptionv4': nn.init.xavier_uniform(model_conv.last_linear.weight) nn.init.constant(model_conv.last_linear.bias, 0) else: nn.init.xavier_uniform(model_conv.fc.weight) nn.init.constant(model_conv.fc.bias, 0) if use_gpu: model_conv = model_conv.cuda() return model_conv
def main(): # 随机种子 np.random.seed(666) torch.manual_seed(666) torch.cuda.manual_seed_all(666) random.seed(666) # 获取当前文件名,用于创建模型及结果文件的目录 file_name = os.path.basename(__file__).split('.')[0] # 创建保存模型和结果的文件夹 if not os.path.exists('./model/%s' % file_name): os.makedirs('./model/%s' % file_name) if not os.path.exists('./result/%s' % file_name): os.makedirs('./result/%s' % file_name) # 创建日志文件 if not os.path.exists('./result/%s.txt' % file_name): with open('./result/%s.txt' % file_name, 'w') as acc_file: pass with open('./result/%s.txt' % file_name, 'a') as acc_file: acc_file.write('\n%s %s\n' % (time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime(time.time())), file_name)) # 默认使用PIL读图 def default_loader(path): # return Image.open(path) return Image.open(path).convert('RGB') # 训练集图片读取 class TrainDataset(Dataset): def __init__(self, label_list, transform=None, target_transform=None, loader=default_loader): imgs = [] for index, row in label_list.iterrows(): imgs.append((row['img_path'], row['label'])) self.imgs = imgs self.transform = transform self.target_transform = target_transform self.loader = loader def __getitem__(self, index): filename, label = self.imgs[index] img = self.loader(filename) if self.transform is not None: img = self.transform(img) return img, label def __len__(self): return len(self.imgs) # 验证集图片读取 class ValDataset(Dataset): def __init__(self, label_list, transform=None, target_transform=None, loader=default_loader): imgs = [] for index, row in label_list.iterrows(): imgs.append((row['img_path'], row['label'])) self.imgs = imgs self.transform = transform self.target_transform = target_transform self.loader = loader def __getitem__(self, index): filename, label = self.imgs[index] img = self.loader(filename) if self.transform is not None: img = self.transform(img) return img, label def __len__(self): return len(self.imgs) # 测试集图片读取 class TestDataset(Dataset): def __init__(self, label_list, transform=None, target_transform=None, loader=default_loader): imgs = [] for index, row in label_list.iterrows(): imgs.append((row['img_path'])) self.imgs = imgs self.transform = transform self.target_transform = target_transform self.loader = loader def __getitem__(self, index): filename = self.imgs[index] img = self.loader(filename) if self.transform is not None: img = self.transform(img) return img, filename def __len__(self): return len(self.imgs) # 数据增强:在给定角度中随机进行旋转 class FixedRotation(object): def __init__(self, angles): self.angles = angles def __call__(self, img): return fixed_rotate(img, self.angles) def fixed_rotate(img, angles): angles = list(angles) angles_num = len(angles) index = random.randint(0, angles_num - 1) return img.rotate(angles[index]) # 训练函数 def train(train_loader, model, criterion, optimizer, epoch): batch_time = AverageMeter() data_time = AverageMeter() losses = AverageMeter() acc = AverageMeter() # switch to train mode model.train() end = time.time() # 从训练集迭代器中获取训练数据 for i, (images, target) in enumerate(train_loader): # 评估图片读取耗时 data_time.update(time.time() - end) # 将图片和标签转化为tensor image_var = torch.tensor(images).cuda(async=True) label = torch.tensor(target).cuda(async=True) # 将图片输入网络,前传,生成预测值 y_pred = model(image_var) # 计算loss loss = criterion(y_pred, label) losses.update(loss.item(), images.size(0)) # 计算top1正确率 prec, PRED_COUNT = accuracy(y_pred.data, target, topk=(1, 1)) acc.update(prec, PRED_COUNT) # 对梯度进行反向传播,使用随机梯度下降更新网络权重 optimizer.zero_grad() loss.backward() optimizer.step() # 评估训练耗时 batch_time.update(time.time() - end) end = time.time() # 打印耗时与结果 if i % print_freq == 0: print('Epoch: [{0}][{1}/{2}]\t' 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t' 'Loss {loss.val:.4f} ({loss.avg:.4f})\t' 'Accuray {acc.val:.3f} ({acc.avg:.3f})'.format( epoch, i, len(train_loader), batch_time=batch_time, data_time=data_time, loss=losses, acc=acc)) # 验证函数 def validate(val_loader, model, criterion): batch_time = AverageMeter() losses = AverageMeter() acc = AverageMeter() # switch to evaluate mode model.eval() end = time.time() for i, (images, labels) in enumerate(val_loader): image_var = torch.tensor(images).cuda(async=True) target = torch.tensor(labels).cuda(async=True) # 图片前传。验证和测试时不需要更新网络权重,所以使用torch.no_grad(),表示不计算梯度 with torch.no_grad(): y_pred = model(image_var) loss = criterion(y_pred, target) # measure accuracy and record loss prec, PRED_COUNT = accuracy(y_pred.data, labels, topk=(1, 1)) losses.update(loss.item(), images.size(0)) acc.update(prec, PRED_COUNT) # measure elapsed time batch_time.update(time.time() - end) end = time.time() if i % print_freq == 0: print('TrainVal: [{0}/{1}]\t' 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 'Loss {loss.val:.4f} ({loss.avg:.4f})\t' 'Accuray {acc.val:.3f} ({acc.avg:.3f})'.format( i, len(val_loader), batch_time=batch_time, loss=losses, acc=acc)) print(' * Accuray {acc.avg:.3f}'.format(acc=acc), '(Previous Best Acc: %.3f)' % best_precision, ' * Loss {loss.avg:.3f}'.format(loss=losses), 'Previous Lowest Loss: %.3f)' % lowest_loss) return acc.avg, losses.avg # 测试函数 def test(test_loader, model): csv_map = OrderedDict({'filename': [], 'probability': []}) # switch to evaluate mode model.eval() for i, (images, filepath) in enumerate(tqdm(test_loader)): # bs, ncrops, c, h, w = images.size() filepath = [os.path.basename(i) for i in filepath] image_var = torch.tensor(images, requires_grad=False) # for pytorch 0.4 with torch.no_grad(): y_pred = model(image_var) # 使用softmax函数将图片预测结果转换成类别概率 smax = nn.Softmax(1) smax_out = smax(y_pred) # 保存图片名称与预测概率 csv_map['filename'].extend(filepath) for output in smax_out: prob = ';'.join([str(i) for i in output.data.tolist()]) csv_map['probability'].append(prob) # pdb.set_trace() result = pd.DataFrame(csv_map) result['probability'] = result['probability'].map( lambda x: [float(i) for i in x.split(';')]) # 转换成提交样例中的格式 sub_filename, sub_label = [], [] prob_list = [] for index, row in result.iterrows(): sub_filename.append(row['filename']) pred_label = np.argmax(row['probability']) prob_list.append([row['filename']] + row['probability']) if pred_label == 0: sub_label.append('norm') else: sub_label.append('defect%d' % pred_label) # 生成结果文件,保存在result文件夹中,可用于直接提交 submission = pd.DataFrame({ 'filename': sub_filename, 'label': sub_label }) submission.to_csv('./result/%s/submission.csv' % file_name, header=None, index=False) prob_map = pd.DataFrame(prob_list) prob_map.to_csv('./result/%s/prob_map.csv' % file_name, header=False, index=False) return # 保存最新模型以及最优模型 def save_checkpoint(state, is_best, is_lowest_loss, filename='./model/%s/checkpoint.pth.tar' % file_name): torch.save(state, filename) if is_best: shutil.copyfile(filename, './model/%s/model_best.pth.tar' % file_name) if is_lowest_loss: shutil.copyfile(filename, './model/%s/lowest_loss.pth.tar' % file_name) # 用于计算精度和时间的变化 class AverageMeter(object): """Computes and stores the average and current value""" def __init__(self): self.reset() def reset(self): self.val = 0 self.avg = 0 self.sum = 0 self.count = 0 def update(self, val, n=1): self.val = val self.sum += val * n self.count += n self.avg = self.sum / self.count # 学习率衰减:lr = lr / lr_decay def adjust_learning_rate(): nonlocal lr lr = lr / lr_decay return optim.Adam(model.parameters(), lr, weight_decay=weight_decay, amsgrad=True) # 计算top K准确率 def accuracy(y_pred, y_actual, topk=(1, )): """Computes the precision@k for the specified values of k""" final_acc = 0 maxk = max(topk) # for prob_threshold in np.arange(0, 1, 0.01): PRED_COUNT = y_actual.size(0) PRED_CORRECT_COUNT = 0 prob, pred = y_pred.topk(maxk, 1, True, True) # prob = np.where(prob > prob_threshold, prob, 0) for j in range(pred.size(0)): if int(y_actual[j]) == int(pred[j]): PRED_CORRECT_COUNT += 1 if PRED_COUNT == 0: final_acc = 0 else: final_acc = PRED_CORRECT_COUNT / PRED_COUNT return final_acc * 100, PRED_COUNT # 程序主体 # 设定GPU ID os.environ["CUDA_VISIBLE_DEVICES"] = '0, 1' # 小数据集上,batch size不易过大。如出现out of memory,应调小batch size batch_size = 12 # 进程数量,最好不要超过电脑最大进程数。windows下报错可以改为workers=0 workers = 0 # epoch数量,分stage进行,跑完一个stage后降低学习率进入下一个stage stage_epochs = [20, 10, 10] # 初始学习率 lr = 1e-4 # 学习率衰减系数 (new_lr = lr / lr_decay) lr_decay = 5 # 正则化系数 weight_decay = 1e-4 # 参数初始化 stage = 0 start_epoch = 0 total_epochs = sum(stage_epochs) best_precision = 0 lowest_loss = 100 # 设定打印频率,即多少step打印一次,用于观察loss和acc的实时变化 # 打印结果中,括号前面为实时loss和acc,括号内部为epoch内平均loss和acc print_freq = 1 # 验证集比例 val_ratio = 0.12 # 是否只验证,不训练 evaluate = True # 是否从断点继续跑 resume = False # 创建Nasnet模型 # xception.pretrained_settings['xception']['imagenet']['num_classes']=12 model = nasnetalarge(num_classes=1000) model.last_linear = nn.Linear(4032, 12) print(model) model = torch.nn.DataParallel(model).cuda() # optionally resume from a checkpoint if resume: checkpoint_path = './model/%s/checkpoint.pth.tar' % file_name if os.path.isfile(checkpoint_path): print("=> loading checkpoint '{}'".format(checkpoint_path)) checkpoint = torch.load(checkpoint_path) start_epoch = checkpoint['epoch'] + 1 best_precision = checkpoint['best_precision'] lowest_loss = checkpoint['lowest_loss'] stage = checkpoint['stage'] lr = checkpoint['lr'] model.load_state_dict(checkpoint['state_dict']) # 如果中断点恰好为转换stage的点,需要特殊处理 if start_epoch in np.cumsum(stage_epochs)[:-1]: stage += 1 optimizer = adjust_learning_rate() model.load_state_dict( torch.load('./model/%s/model_best.pth.tar' % file_name)['state_dict']) print("=> loaded checkpoint (epoch {})".format( checkpoint['epoch'])) else: print("=> no checkpoint found at '{}'".format(checkpoint_path)) # 读取训练图片列表 all_data = pd.read_csv('data/label.csv') # 分离训练集和测试集,stratify参数用于分层抽样 train_data_list, val_data_list = train_test_split( all_data, test_size=val_ratio, random_state=666, stratify=all_data['label']) # 读取测试图片列表 test_data_list = pd.read_csv('data/test.csv') # 图片归一化,由于采用ImageNet预训练网络,因此这里直接采用ImageNet网络的参数 normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 训练集图片变换,输入网络的尺寸为354*354 train_data = TrainDataset( train_data_list, transform=transforms.Compose([ transforms.Resize((360, 360)), transforms.ColorJitter(0.15, 0.15, 0.15, 0.075), transforms.RandomHorizontalFlip(), transforms.RandomGrayscale(), # transforms.RandomRotation(20), FixedRotation([0, 90, 180, 270]), transforms.RandomCrop(354), transforms.ToTensor(), normalize, ])) # 验证集图片变换 val_data = ValDataset(val_data_list, transform=transforms.Compose([ transforms.Resize((360, 360)), transforms.CenterCrop(354), transforms.ToTensor(), normalize, ])) # 测试集图片变换 test_data = TestDataset(test_data_list, transform=transforms.Compose([ transforms.Resize((360, 360)), transforms.CenterCrop(354), transforms.ToTensor(), normalize, ])) # 生成图片迭代器 train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, pin_memory=True, num_workers=workers) val_loader = DataLoader(val_data, batch_size=batch_size * 2, shuffle=False, pin_memory=False, num_workers=workers) test_loader = DataLoader(test_data, batch_size=batch_size * 2, shuffle=False, pin_memory=False, num_workers=workers) # 使用交叉熵损失函数 criterion = nn.CrossEntropyLoss().cuda() # 优化器,使用带amsgrad的Adam optimizer = optim.Adam(model.parameters(), lr, weight_decay=weight_decay, amsgrad=True) if evaluate: pass # validate(val_loader, model, criterion) else: # 开始训练 for epoch in range(start_epoch, total_epochs): # train for one epoch train(train_loader, model, criterion, optimizer, epoch) # evaluate on validation set precision, avg_loss = validate(val_loader, model, criterion) # 在日志文件中记录每个epoch的精度和loss with open('./result/%s.txt' % file_name, 'a') as acc_file: acc_file.write('Epoch: %2d, Precision: %.8f, Loss: %.8f\n' % (epoch, precision, avg_loss)) # 记录最高精度与最低loss,保存最新模型与最佳模型 is_best = precision > best_precision is_lowest_loss = avg_loss < lowest_loss best_precision = max(precision, best_precision) lowest_loss = min(avg_loss, lowest_loss) state = { 'epoch': epoch, 'state_dict': model.state_dict(), 'best_precision': best_precision, 'lowest_loss': lowest_loss, 'stage': stage, 'lr': lr, } save_checkpoint(state, is_best, is_lowest_loss) # 判断是否进行下一个stage if (epoch + 1) in np.cumsum(stage_epochs)[:-1]: stage += 1 optimizer = adjust_learning_rate() model.load_state_dict( torch.load('./model/%s/model_best.pth.tar' % file_name)['state_dict']) print('Step into next stage') with open('./result/%s.txt' % file_name, 'a') as acc_file: acc_file.write( '---------------Step into next stage----------------\n' ) # 记录线下最佳分数 with open('./result/%s.txt' % file_name, 'a') as acc_file: acc_file.write('* best acc: %.8f %s\n' % (best_precision, os.path.basename(__file__))) with open('./result/best_acc.txt', 'a') as acc_file: acc_file.write( '%s * best acc: %.8f %s\n' % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime( time.time())), best_precision, os.path.basename(__file__))) # 读取最佳模型,预测测试集,并生成可直接提交的结果文件 best_model = torch.load('./model/%s/checkpoint.pth.tar' % file_name) model.load_state_dict(best_model['state_dict']) test(test_loader=test_loader, model=model) # 释放GPU缓存 torch.cuda.empty_cache()
def main(train_root, train_csv, val_root, val_csv, test_root, test_csv, epochs, aug, model_name, batch_size, num_workers, val_samples, test_samples, early_stopping_patience, limit_data, images_per_epoch, split_id, _run): assert(model_name in ('inceptionv4', 'resnet152', 'densenet161', 'senet154', 'pnasnet5large', 'nasnetalarge', 'xception', 'squeezenet', 'resnext', 'dpn', 'inceptionresnetv2', 'mobilenetv2')) cv2.setNumThreads(0) AUGMENTED_IMAGES_DIR = os.path.join(fs_observer.dir, 'images') CHECKPOINTS_DIR = os.path.join(fs_observer.dir, 'checkpoints') BEST_MODEL_PATH = os.path.join(CHECKPOINTS_DIR, 'model_best.pth') LAST_MODEL_PATH = os.path.join(CHECKPOINTS_DIR, 'model_last.pth') RESULTS_CSV_PATH = os.path.join('results', 'results.csv') EXP_NAME = _run.meta_info['options']['--name'] EXP_ID = _run._id for directory in (AUGMENTED_IMAGES_DIR, CHECKPOINTS_DIR): os.makedirs(directory) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") if model_name == 'inceptionv4': model = ptm.inceptionv4(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, 2) aug['size'] = 299 aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'resnet152': model = models.resnet152(pretrained=True) model.fc = nn.Linear(model.fc.in_features, 2) aug['size'] = 224 aug['mean'] = [0.485, 0.456, 0.406] aug['std'] = [0.229, 0.224, 0.225] elif model_name == 'densenet161': model = models.densenet161(pretrained=True) model.classifier = nn.Linear(model.classifier.in_features, 2) aug['size'] = 224 aug['mean'] = [0.485, 0.456, 0.406] aug['std'] = [0.229, 0.224, 0.225] elif model_name == 'senet154': model = ptm.senet154(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, 2) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'squeezenet': model = ptm.squeezenet1_1(num_classes=1000, pretrained='imagenet') model.last_conv = nn.Conv2d( 512, 2, kernel_size=(1, 1), stride=(1, 1)) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'pnasnet5large': model = ptm.pnasnet5large(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, 2) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'nasnetalarge': model = ptm.nasnetalarge(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, 2) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'xception': model = ptm.xception(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, 2) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'dpn': model = ptm.dpn131(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Conv2d(model.last_linear.in_channels, 2, kernel_size=1, bias=True) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'resnext': model = ptm.resnext101_64x4d(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, 2) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'inceptionresnetv2': model = ptm.inceptionresnetv2(num_classes=1000, pretrained='imagenet') model.last_linear = nn.Linear(model.last_linear.in_features, 2) aug['size'] = model.input_size[1] aug['mean'] = model.mean aug['std'] = model.std elif model_name == 'mobilenetv2': model = MobileNetV2() model.load_state_dict(torch.load('./auglib/models/mobilenet_v2.pth')) model.classifier = nn.Sequential( nn.Dropout(0.2), nn.Linear(model.last_channel, 2), ) aug['size'] = 224 aug['mean'] = [0.485, 0.456, 0.406] aug['std'] = [0.229, 0.224, 0.225] model.to(device) augs = Augmentations(**aug) model.aug_params = aug datasets = { 'samples': CSVDataset(train_root, train_csv, 'image_id', 'melanoma', transform=augs.tf_augment, add_extension='.jpg', limit=(400, 433)), 'train': CSVDataset(train_root, train_csv, 'image_id', 'melanoma', transform=augs.tf_transform, add_extension='.jpg', random_subset_size=limit_data), 'val': CSVDatasetWithName( val_root, val_csv, 'image_id', 'melanoma', transform=augs.tf_transform, add_extension='.jpg'), 'test': CSVDatasetWithName( test_root, test_csv, 'image_id', 'melanoma', transform=augs.tf_transform, add_extension='.jpg'), 'test_no_aug': CSVDatasetWithName( test_root, test_csv, 'image_id', 'melanoma', transform=augs.no_augmentation, add_extension='.jpg'), 'test_144': CSVDatasetWithName( test_root, test_csv, 'image_id', 'melanoma', transform=augs.inception_crop, add_extension='.jpg'), } dataloaders = { 'train': DataLoader(datasets['train'], batch_size=batch_size, shuffle=True, num_workers=num_workers, worker_init_fn=set_seeds), 'samples': DataLoader(datasets['samples'], batch_size=batch_size, shuffle=False, num_workers=num_workers, worker_init_fn=set_seeds), } save_images(datasets['samples'], to=AUGMENTED_IMAGES_DIR, n=32) sample_batch, _ = next(iter(dataloaders['samples'])) save_image(make_grid(sample_batch, padding=0), os.path.join(AUGMENTED_IMAGES_DIR, 'grid.jpg')) criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=0.001) scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, factor=0.1, min_lr=1e-5, patience=8) metrics = { 'train': pd.DataFrame(columns=['epoch', 'loss', 'acc', 'auc']), 'val': pd.DataFrame(columns=['epoch', 'loss', 'acc', 'auc']) } best_val_auc = 0.0 best_epoch = 0 epochs_without_improvement = 0 if images_per_epoch: batches_per_epoch = images_per_epoch // batch_size else: batches_per_epoch = None for epoch in range(epochs): print('train epoch {}/{}'.format(epoch+1, epochs)) epoch_train_result = train_epoch( device, model, dataloaders, criterion, optimizer, batches_per_epoch) metrics['train'] = metrics['train'].append( {**epoch_train_result, 'epoch': epoch}, ignore_index=True) print('train', epoch_train_result) epoch_val_result, _ = test_with_augmentation( model, datasets['val'], device, num_workers, val_samples) metrics['val'] = metrics['val'].append( {**epoch_val_result, 'epoch': epoch}, ignore_index=True) print('val', epoch_val_result) print('-' * 40) scheduler.step(epoch_val_result['loss']) if epoch_val_result['auc'] > best_val_auc: best_val_auc = epoch_val_result['auc'] best_val_result = epoch_val_result best_epoch = epoch epochs_without_improvement = 0 torch.save(model, BEST_MODEL_PATH) else: epochs_without_improvement += 1 if epochs_without_improvement > early_stopping_patience: last_val_result = epoch_val_result torch.save(model, LAST_MODEL_PATH) break if epoch == (epochs-1): last_val_result = epoch_val_result torch.save(model, LAST_MODEL_PATH) for phase in ['train', 'val']: metrics[phase].epoch = metrics[phase].epoch.astype(int) metrics[phase].to_csv(os.path.join(fs_observer.dir, phase + '.csv'), index=False) # Run testing # TODO: reduce code repetition test_result, preds = test_with_augmentation( torch.load(BEST_MODEL_PATH), datasets['test'], device, num_workers, test_samples) print('[best] test', test_result) test_noaug_result, preds_noaug = test_with_augmentation( torch.load(BEST_MODEL_PATH), datasets['test_no_aug'], device, num_workers, 1) print('[best] test (no augmentation)', test_noaug_result) test_result_last, preds_last = test_with_augmentation( torch.load(LAST_MODEL_PATH), datasets['test'], device, num_workers, test_samples) print('[last] test', test_result_last) test_noaug_result_last, preds_noaug_last = test_with_augmentation( torch.load(LAST_MODEL_PATH), datasets['test_no_aug'], device, num_workers, 1) print('[last] test (no augmentation)', test_noaug_result_last) # Save predictions preds.to_csv(os.path.join(fs_observer.dir, 'test-aug-best.csv'), index=False, columns=['image', 'label', 'score']) preds_noaug.to_csv(os.path.join(fs_observer.dir, 'test-noaug-best.csv'), index=False, columns=['image', 'label', 'score']) preds_last.to_csv(os.path.join(fs_observer.dir, 'test-aug-last.csv'), index=False, columns=['image', 'label', 'score']) preds_noaug_last.to_csv(os.path.join(fs_observer.dir, 'test-noaug-last.csv'), index=False, columns=['image', 'label', 'score']) # TODO: Avoid repetition. # use ordereddict, or create a pandas df before saving with open(RESULTS_CSV_PATH, 'a') as file: file.write(','.join(( EXP_NAME, str(EXP_ID), str(split_id), str(best_epoch), str(best_val_result['loss']), str(best_val_result['acc']), str(best_val_result['auc']), str(best_val_result['avp']), str(best_val_result['sens']), str(best_val_result['spec']), str(last_val_result['loss']), str(last_val_result['acc']), str(last_val_result['auc']), str(last_val_result['avp']), str(last_val_result['sens']), str(last_val_result['spec']), str(best_val_auc), str(test_result['auc']), str(test_result_last['auc']), str(test_result['acc']), str(test_result_last['acc']), str(test_result['spec']), str(test_result_last['spec']), str(test_result['sens']), str(test_result_last['sens']), str(test_result['avp']), str(test_result_last['avp']), str(test_noaug_result['auc']), str(test_noaug_result_last['auc']), str(test_noaug_result['acc']), str(test_noaug_result_last['acc']), str(test_noaug_result['spec']), str(test_noaug_result_last['spec']), str(test_noaug_result['sens']), str(test_noaug_result_last['sens']), str(test_noaug_result['avp']), str(test_noaug_result_last['avp']), )) + '\n') return (test_noaug_result['auc'], test_result['auc'], )