├── DN4_2019_Version ├── DN4_Test_5way1shot.py ├── DN4_Test_5way5shot.py ├── DN4_Train_5way1shot.py ├── DN4_Train_5way1shot_DA.py ├── DN4_Train_5way1shot_Resnet.py ├── DN4_Train_5way5shot.py ├── DN4_Train_5way5shot_DA.py ├── DN4_Train_5way5shot_Resnet.py ├── LICENSE ├── README.md ├── dataset │ ├── CubBird_prepare_csv.py │ ├── CubBirds │ │ ├── test.csv │ │ ├── train.csv │ │ └── val.csv │ ├── StanforCar_prepare_csv.py │ ├── StanfordCars │ │ ├── test.csv │ │ ├── train.csv │ │ └── val.csv │ ├── StanfordDog_prepare_csv.py │ ├── StanfordDogs │ │ ├── test.csv │ │ ├── train.csv │ │ └── val.csv │ ├── datasets_csv.py │ └── miniImageNet │ │ ├── test.csv │ │ ├── train.csv │ │ └── val.csv ├── imgs │ ├── Flowchart.bmp │ ├── Results_finegrained.bmp │ └── Results_miniImageNet2.bmp ├── models │ └── network.py └── results │ ├── DN4_miniImageNet_Conv64F_5Way_1Shot_K3 │ ├── Test_resutls.txt │ ├── model_best.pth.tar │ └── opt_resutls.txt │ ├── DN4_miniImageNet_Conv64F_5Way_5Shot_K3 │ ├── Test_resutls.txt │ ├── model_best.pth.tar │ └── opt_resutls.txt │ ├── DN4_miniImageNet_ResNet256F_5Way_1Shot_K3 │ ├── Test_resutls.txt │ └── opt_resutls.txt │ └── DN4_miniImageNet_ResNet256F_5Way_5Shot_K3 │ ├── Test_resutls.txt │ └── opt_resutls.txt ├── LICENSE ├── README.md ├── Test_DN4.py ├── Train_DN4.py ├── dataset ├── CubBirds │ ├── test.csv │ ├── train.csv │ └── val.csv ├── Prepare_csv_CubBird.py ├── Prepare_csv_StanfordCar.py ├── Prepare_csv_StanfordDog.py ├── StanfordCars │ ├── test.csv │ ├── train.csv │ └── val.csv ├── StanfordDogs │ ├── test.csv │ ├── train.csv │ └── val.csv ├── general_dataloader.py └── miniImageNet │ ├── test.csv │ ├── train.csv │ └── val.csv ├── models ├── backbone.py ├── classifier.py └── network.py ├── results ├── SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot │ ├── Loss.png │ ├── Test_results.txt │ ├── opt_results.txt │ ├── test_loss.txt │ ├── train_loss.txt │ └── val_loss.txt ├── SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot │ ├── Loss.png │ ├── Test_results.txt │ ├── opt_results.txt │ ├── test_loss.txt │ ├── train_loss.txt │ └── val_loss.txt ├── SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot │ ├── Loss.png │ ├── Test_results.txt │ ├── Test_results_New.txt │ ├── model_best.pth.tar │ ├── opt_results.txt │ ├── test_loss.txt │ ├── train_loss.txt │ └── val_loss.txt ├── SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot │ ├── Loss.png │ ├── Test_results.txt │ ├── model_best.pth.tar │ ├── opt_results.txt │ ├── test_loss.txt │ ├── train_loss.txt │ └── val_loss.txt └── test └── utils.py /DN4_2019_Version/DN4_Test_5way1shot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author: Wenbin Li (liwenbin.nju@gmail.com) 6 | Date: April 9, 2019 7 | Version: V0 8 | 9 | Citation: 10 | @inproceedings{li2019DN4, 11 | title={Revisiting Local Descriptor based Image-to-Class Measure for Few-shot Learning}, 12 | author={Li, Wenbin and Wang, Lei and Xu, Jinglin and Huo, Jing and Gao Yang and Luo, Jiebo}, 13 | booktitle={CVPR}, 14 | year={2019} 15 | } 16 | """ 17 | 18 | 19 | from __future__ import print_function 20 | import argparse 21 | import os 22 | import random 23 | import shutil 24 | import numpy as np 25 | import torch 26 | import torch.nn as nn 27 | import torch.nn.parallel 28 | import torch.backends.cudnn as cudnn 29 | import torch.optim as optim 30 | import torch.utils.data 31 | import torchvision.datasets as dset 32 | import torchvision.transforms as transforms 33 | import torchvision.utils as vutils 34 | from torch.autograd import grad 35 | import time 36 | from torch import autograd 37 | from PIL import ImageFile 38 | import scipy as sp 39 | import scipy.stats 40 | import pdb 41 | 42 | 43 | # ============================ Data & Networks ===================================== 44 | from dataset.datasets_csv import Imagefolder_csv 45 | import models.network as DN4Net 46 | # ================================================================================== 47 | 48 | 49 | ImageFile.LOAD_TRUNCATED_IMAGES = True 50 | os.environ['CUDA_DEVICE_ORDER']='PCI_BUS_ID' 51 | os.environ['CUDA_VISIBLE_DEVICES']='0' 52 | 53 | 54 | # Load the pre-trained model 55 | model_trained = './results/DN4_miniImageNet_Conv64F_5Way_1Shot_K3/model_best.pth.tar' 56 | 57 | 58 | parser = argparse.ArgumentParser() 59 | parser.add_argument('--dataset_dir', default='/Datasets/miniImageNet--ravi', help='/miniImageNet') 60 | parser.add_argument('--data_name', default='miniImageNet', help='miniImageNet|StanfordDog|StanfordCar|CubBird') 61 | parser.add_argument('--mode', default='test', help='train|val|test') 62 | parser.add_argument('--outf', default='./results/DN4') 63 | parser.add_argument('--resume', default=model_trained, type=str, help='path to the lastest checkpoint (default: none)') 64 | parser.add_argument('--basemodel', default='Conv64F', help='Conv64F|ResNet256F') 65 | parser.add_argument('--workers', type=int, default=8) 66 | # Few-shot parameters # 67 | parser.add_argument('--imageSize', type=int, default=84) 68 | parser.add_argument('--episodeSize', type=int, default=1, help='the mini-batch size of training') 69 | parser.add_argument('--testepisodeSize', type=int, default=1, help='one episode is taken as a mini-batch') 70 | parser.add_argument('--epochs', type=int, default=30, help='the total number of training epoch') 71 | parser.add_argument('--episode_train_num', type=int, default=10000, help='the total number of training episodes') 72 | parser.add_argument('--episode_val_num', type=int, default=1000, help='the total number of evaluation episodes') 73 | parser.add_argument('--episode_test_num', type=int, default=600, help='the total number of testing episodes') 74 | parser.add_argument('--way_num', type=int, default=5, help='the number of way/class') 75 | parser.add_argument('--shot_num', type=int, default=1, help='the number of shot') 76 | parser.add_argument('--query_num', type=int, default=15, help='the number of queries') 77 | parser.add_argument('--neighbor_k', type=int, default=3, help='the number of k-nearest neighbors') 78 | parser.add_argument('--lr', type=float, default=0.005, help='learning rate, default=0.005') 79 | parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5') 80 | parser.add_argument('--cuda', action='store_true', default=True, help='enables cuda') 81 | parser.add_argument('--ngpu', type=int, default=1, help='the number of gpus') 82 | parser.add_argument('--nc', type=int, default=3, help='input image channels') 83 | parser.add_argument('--clamp_lower', type=float, default=-0.01) 84 | parser.add_argument('--clamp_upper', type=float, default=0.01) 85 | parser.add_argument('--print_freq', '-p', default=100, type=int, metavar='N', help='print frequency (default: 100)') 86 | opt = parser.parse_args() 87 | opt.cuda = True 88 | cudnn.benchmark = True 89 | 90 | 91 | 92 | # ======================================= Define functions ============================================= 93 | def validate(val_loader, model, criterion, epoch_index, F_txt): 94 | batch_time = AverageMeter() 95 | losses = AverageMeter() 96 | top1 = AverageMeter() 97 | 98 | 99 | # switch to evaluate mode 100 | model.eval() 101 | accuracies = [] 102 | 103 | 104 | end = time.time() 105 | for episode_index, (query_images, query_targets, support_images, support_targets) in enumerate(val_loader): 106 | 107 | # Convert query and support images 108 | query_images = torch.cat(query_images, 0) 109 | input_var1 = query_images.cuda() 110 | 111 | 112 | input_var2 = [] 113 | for i in range(len(support_images)): 114 | temp_support = support_images[i] 115 | temp_support = torch.cat(temp_support, 0) 116 | temp_support = temp_support.cuda() 117 | input_var2.append(temp_support) 118 | 119 | 120 | # Deal with the targets 121 | target = torch.cat(query_targets, 0) 122 | target = target.cuda() 123 | 124 | # Calculate the output 125 | output = model(input_var1, input_var2) 126 | loss = criterion(output, target) 127 | 128 | 129 | # measure accuracy and record loss 130 | prec1, _ = accuracy(output, target, topk=(1, 3)) 131 | losses.update(loss.item(), query_images.size(0)) 132 | top1.update(prec1[0], query_images.size(0)) 133 | accuracies.append(prec1) 134 | 135 | 136 | # measure elapsed time 137 | batch_time.update(time.time() - end) 138 | end = time.time() 139 | 140 | 141 | #============== print the intermediate results ==============# 142 | if episode_index % opt.print_freq == 0 and episode_index != 0: 143 | 144 | print('Test-({0}): [{1}/{2}]\t' 145 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 146 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 147 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 148 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1)) 149 | 150 | print('Test-({0}): [{1}/{2}]\t' 151 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 152 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 153 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 154 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1), file=F_txt) 155 | 156 | 157 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1)) 158 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1), file=F_txt) 159 | 160 | return top1.avg, accuracies 161 | 162 | 163 | class AverageMeter(object): 164 | """Computes and stores the average and current value""" 165 | def __init__(self): 166 | self.reset() 167 | 168 | def reset(self): 169 | self.val = 0 170 | self.avg = 0 171 | self.sum = 0 172 | self.count = 0 173 | 174 | def update(self, val, n=1): 175 | self.val = val 176 | self.sum += val * n 177 | self.count += n 178 | self.avg = self.sum / self.count 179 | 180 | 181 | 182 | def accuracy(output, target, topk=(1,)): 183 | """Computes the precision@k for the specified values of k""" 184 | with torch.no_grad(): 185 | maxk = max(topk) 186 | batch_size = target.size(0) 187 | 188 | _, pred = output.topk(maxk, 1, True, True) 189 | pred = pred.t() 190 | correct = pred.eq(target.view(1, -1).expand_as(pred)) 191 | 192 | res = [] 193 | for k in topk: 194 | correct_k = correct[:k].view(-1).float().sum(0, keepdim=True) 195 | res.append(correct_k.mul_(100.0 / batch_size)) 196 | return res 197 | 198 | 199 | def mean_confidence_interval(data, confidence=0.95): 200 | a = [1.0*np.array(data[i].cpu()) for i in range(len(data))] 201 | n = len(a) 202 | m, se = np.mean(a), scipy.stats.sem(a) 203 | h = se * sp.stats.t._ppf((1+confidence)/2., n-1) 204 | return m,h 205 | 206 | 207 | 208 | # ======================================== Settings of path ============================================ 209 | # saving path 210 | opt.outf = opt.outf+'_'+opt.data_name+'_'+str(opt.basemodel)+'_'+str(opt.way_num)+'Way_'+str(opt.shot_num)+'Shot'+'_K'+str(opt.neighbor_k) 211 | 212 | if not os.path.exists(opt.outf): 213 | os.makedirs(opt.outf) 214 | 215 | if torch.cuda.is_available() and not opt.cuda: 216 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 217 | 218 | # save the opt and results to a txt file 219 | txt_save_path = os.path.join(opt.outf, 'Test_resutls.txt') 220 | F_txt = open(txt_save_path, 'a+') 221 | print(opt) 222 | print(opt, file=F_txt) 223 | 224 | 225 | 226 | # ========================================== Model Config =============================================== 227 | ngpu = int(opt.ngpu) 228 | global best_prec1, epoch_index 229 | best_prec1 = 0 230 | epoch_index = 0 231 | 232 | model = DN4Net.define_DN4Net(which_model=opt.basemodel, num_classes=opt.way_num, neighbor_k=opt.neighbor_k, norm='batch', 233 | init_type='normal', use_gpu=opt.cuda) 234 | 235 | # define loss function (criterion) and optimizer 236 | criterion = nn.CrossEntropyLoss().cuda() 237 | optimizer = optim.Adam(model.parameters(), lr=opt.lr, betas=(opt.beta1, 0.9)) 238 | 239 | 240 | # optionally resume from a checkpoint 241 | if opt.resume: 242 | if os.path.isfile(opt.resume): 243 | print("=> loading checkpoint '{}'".format(opt.resume)) 244 | checkpoint = torch.load(opt.resume) 245 | epoch_index = checkpoint['epoch_index'] 246 | best_prec1 = checkpoint['best_prec1'] 247 | model.load_state_dict(checkpoint['state_dict']) 248 | optimizer.load_state_dict(checkpoint['optimizer']) 249 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index'])) 250 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index']), file=F_txt) 251 | else: 252 | print("=> no checkpoint found at '{}'".format(opt.resume)) 253 | print("=> no checkpoint found at '{}'".format(opt.resume), file=F_txt) 254 | 255 | if opt.ngpu > 1: 256 | model = nn.DataParallel(model, range(opt.ngpu)) 257 | 258 | # print the architecture of the network 259 | print(model) 260 | print(model, file=F_txt) 261 | 262 | 263 | 264 | 265 | # ============================================ Testing phase ======================================== 266 | print('\n............Start testing............') 267 | start_time = time.time() 268 | repeat_num = 5 # repeat running the testing code several times 269 | 270 | 271 | total_accuracy = 0.0 272 | total_h = np.zeros(repeat_num) 273 | total_accuracy_vector = [] 274 | for r in range(repeat_num): 275 | print('===================================== Round %d =====================================' %r) 276 | print('===================================== Round %d =====================================' %r, file=F_txt) 277 | 278 | # ======================================= Folder of Datasets ======================================= 279 | 280 | # image transform & normalization 281 | ImgTransform = transforms.Compose([ 282 | transforms.Resize((opt.imageSize, opt.imageSize)), 283 | transforms.ToTensor(), 284 | transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), 285 | ]) 286 | 287 | testset = Imagefolder_csv( 288 | data_dir=opt.dataset_dir, mode=opt.mode, image_size=opt.imageSize, transform=ImgTransform, 289 | episode_num=opt.episode_test_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 290 | ) 291 | print('Testset: %d-------------%d' %(len(testset), r), file=F_txt) 292 | 293 | 294 | 295 | # ========================================== Load Datasets ========================================= 296 | test_loader = torch.utils.data.DataLoader( 297 | testset, batch_size=opt.testepisodeSize, shuffle=True, 298 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 299 | ) 300 | 301 | 302 | # =========================================== Evaluation ========================================== 303 | prec1, accuracies = validate(test_loader, model, criterion, epoch_index, F_txt) 304 | 305 | 306 | test_accuracy, h = mean_confidence_interval(accuracies) 307 | print("Test accuracy", test_accuracy, "h", h[0]) 308 | print("Test accuracy", test_accuracy, "h", h[0], file=F_txt) 309 | total_accuracy += test_accuracy 310 | total_accuracy_vector.extend(accuracies) 311 | total_h[r] = h 312 | 313 | 314 | aver_accuracy, _ = mean_confidence_interval(total_accuracy_vector) 315 | print("Aver_accuracy:", aver_accuracy, "Aver_h", total_h.mean()) 316 | print("Aver_accuracy:", aver_accuracy, "Aver_h", total_h.mean(), file=F_txt) 317 | F_txt.close() 318 | 319 | # ============================================== Testing End ========================================== 320 | -------------------------------------------------------------------------------- /DN4_2019_Version/DN4_Test_5way5shot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author: Wenbin Li (liwenbin.nju@gmail.com) 6 | Date: April 9, 2019 7 | Version: V0 8 | 9 | Citation: 10 | @inproceedings{li2019DN4, 11 | title={Revisiting Local Descriptor based Image-to-Class Measure for Few-shot Learning}, 12 | author={Li, Wenbin and Wang, Lei and Xu, Jinglin and Huo, Jing and Gao Yang and Luo, Jiebo}, 13 | booktitle={CVPR}, 14 | year={2019} 15 | } 16 | """ 17 | 18 | 19 | from __future__ import print_function 20 | import argparse 21 | import os 22 | import random 23 | import shutil 24 | import numpy as np 25 | import torch 26 | import torch.nn as nn 27 | import torch.nn.parallel 28 | import torch.backends.cudnn as cudnn 29 | import torch.optim as optim 30 | import torch.utils.data 31 | import torchvision.datasets as dset 32 | import torchvision.transforms as transforms 33 | import torchvision.utils as vutils 34 | from torch.autograd import grad 35 | import time 36 | from torch import autograd 37 | from PIL import ImageFile 38 | import scipy as sp 39 | import scipy.stats 40 | import pdb 41 | 42 | 43 | # ============================ Data & Networks ===================================== 44 | from dataset.datasets_csv import Imagefolder_csv 45 | import models.network as DN4Net 46 | # ================================================================================== 47 | 48 | 49 | ImageFile.LOAD_TRUNCATED_IMAGES = True 50 | os.environ['CUDA_DEVICE_ORDER']='PCI_BUS_ID' 51 | os.environ['CUDA_VISIBLE_DEVICES']='0' 52 | 53 | 54 | # Load the pre-trained model 55 | model_trained = './results/DN4_miniImageNet_Conv64F_5Way_5Shot_K3/model_best.pth.tar' 56 | 57 | 58 | parser = argparse.ArgumentParser() 59 | parser.add_argument('--dataset_dir', default='/Datasets/miniImageNet--ravi', help='/miniImageNet') 60 | parser.add_argument('--data_name', default='miniImageNet', help='miniImageNet|StanfordDog|StanfordCar|CubBird') 61 | parser.add_argument('--mode', default='test', help='train|val|test') 62 | parser.add_argument('--outf', default='./results/DN4') 63 | parser.add_argument('--resume', default=model_trained, type=str, help='path to the lastest checkpoint (default: none)') 64 | parser.add_argument('--basemodel', default='Conv64F', help='Conv64F|ResNet256F') 65 | parser.add_argument('--workers', type=int, default=8) 66 | # Few-shot parameters # 67 | parser.add_argument('--imageSize', type=int, default=84) 68 | parser.add_argument('--episodeSize', type=int, default=1, help='the mini-batch size of training') 69 | parser.add_argument('--testepisodeSize', type=int, default=1, help='one episode is taken as a mini-batch') 70 | parser.add_argument('--epochs', type=int, default=30, help='the total number of training epoch') 71 | parser.add_argument('--episode_train_num', type=int, default=10000, help='the total number of training episodes') 72 | parser.add_argument('--episode_val_num', type=int, default=1000, help='the total number of evaluation episodes') 73 | parser.add_argument('--episode_test_num', type=int, default=600, help='the total number of testing episodes') 74 | parser.add_argument('--way_num', type=int, default=5, help='the number of way/class') 75 | parser.add_argument('--shot_num', type=int, default=5, help='the number of shot') 76 | parser.add_argument('--query_num', type=int, default=15, help='the number of queries') 77 | parser.add_argument('--neighbor_k', type=int, default=3, help='the number of k-nearest neighbors') 78 | parser.add_argument('--lr', type=float, default=0.005, help='learning rate, default=0.005') 79 | parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5') 80 | parser.add_argument('--cuda', action='store_true', default=True, help='enables cuda') 81 | parser.add_argument('--ngpu', type=int, default=1, help='the number of gpus') 82 | parser.add_argument('--nc', type=int, default=3, help='input image channels') 83 | parser.add_argument('--clamp_lower', type=float, default=-0.01) 84 | parser.add_argument('--clamp_upper', type=float, default=0.01) 85 | parser.add_argument('--print_freq', '-p', default=100, type=int, metavar='N', help='print frequency (default: 100)') 86 | opt = parser.parse_args() 87 | opt.cuda = True 88 | cudnn.benchmark = True 89 | 90 | 91 | 92 | # ======================================= Define functions ============================================= 93 | def validate(val_loader, model, criterion, epoch_index, F_txt): 94 | batch_time = AverageMeter() 95 | losses = AverageMeter() 96 | top1 = AverageMeter() 97 | 98 | 99 | # switch to evaluate mode 100 | model.eval() 101 | accuracies = [] 102 | 103 | 104 | end = time.time() 105 | for episode_index, (query_images, query_targets, support_images, support_targets) in enumerate(val_loader): 106 | 107 | # Convert query and support images 108 | query_images = torch.cat(query_images, 0) 109 | input_var1 = query_images.cuda() 110 | 111 | 112 | input_var2 = [] 113 | for i in range(len(support_images)): 114 | temp_support = support_images[i] 115 | temp_support = torch.cat(temp_support, 0) 116 | temp_support = temp_support.cuda() 117 | input_var2.append(temp_support) 118 | 119 | 120 | # Deal with the target 121 | target = torch.cat(query_targets, 0) 122 | target = target.cuda() 123 | 124 | # Calculate the output 125 | output = model(input_var1, input_var2) 126 | loss = criterion(output, target) 127 | 128 | 129 | # measure accuracy and record loss 130 | prec1, _ = accuracy(output, target, topk=(1, 3)) 131 | losses.update(loss.item(), query_images.size(0)) 132 | top1.update(prec1[0], query_images.size(0)) 133 | accuracies.append(prec1) 134 | 135 | 136 | # measure elapsed time 137 | batch_time.update(time.time() - end) 138 | end = time.time() 139 | 140 | 141 | #============== print the intermediate results ==============# 142 | if episode_index % opt.print_freq == 0 and episode_index != 0: 143 | 144 | print('Test-({0}): [{1}/{2}]\t' 145 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 146 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 147 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 148 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1)) 149 | 150 | print('Test-({0}): [{1}/{2}]\t' 151 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 152 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 153 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 154 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1), file=F_txt) 155 | 156 | 157 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1)) 158 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1), file=F_txt) 159 | 160 | return top1.avg, accuracies 161 | 162 | 163 | class AverageMeter(object): 164 | """Computes and stores the average and current value""" 165 | def __init__(self): 166 | self.reset() 167 | 168 | def reset(self): 169 | self.val = 0 170 | self.avg = 0 171 | self.sum = 0 172 | self.count = 0 173 | 174 | def update(self, val, n=1): 175 | self.val = val 176 | self.sum += val * n 177 | self.count += n 178 | self.avg = self.sum / self.count 179 | 180 | 181 | 182 | def accuracy(output, target, topk=(1,)): 183 | """Computes the precision@k for the specified values of k""" 184 | with torch.no_grad(): 185 | maxk = max(topk) 186 | batch_size = target.size(0) 187 | 188 | _, pred = output.topk(maxk, 1, True, True) 189 | pred = pred.t() 190 | correct = pred.eq(target.view(1, -1).expand_as(pred)) 191 | 192 | res = [] 193 | for k in topk: 194 | correct_k = correct[:k].view(-1).float().sum(0, keepdim=True) 195 | res.append(correct_k.mul_(100.0 / batch_size)) 196 | return res 197 | 198 | 199 | def mean_confidence_interval(data, confidence=0.95): 200 | a = [1.0*np.array(data[i].cpu()) for i in range(len(data))] 201 | n = len(a) 202 | m, se = np.mean(a), scipy.stats.sem(a) 203 | h = se * sp.stats.t._ppf((1+confidence)/2., n-1) 204 | return m,h 205 | 206 | 207 | 208 | # ======================================== Settings of path ============================================ 209 | # saving path 210 | opt.outf = opt.outf+'_'+opt.data_name+'_'+str(opt.basemodel)+'_'+str(opt.way_num)+'Way_'+str(opt.shot_num)+'Shot'+'_K'+str(opt.neighbor_k) 211 | 212 | if not os.path.exists(opt.outf): 213 | os.makedirs(opt.outf) 214 | 215 | if torch.cuda.is_available() and not opt.cuda: 216 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 217 | 218 | # save the opt and results to a txt file 219 | txt_save_path = os.path.join(opt.outf, 'Test_resutls.txt') 220 | F_txt = open(txt_save_path, 'a+') 221 | print(opt) 222 | print(opt, file=F_txt) 223 | 224 | 225 | 226 | # ========================================== Model Config =============================================== 227 | ngpu = int(opt.ngpu) 228 | global best_prec1, epoch_index 229 | best_prec1 = 0 230 | epoch_index = 0 231 | 232 | model = DN4Net.define_DN4Net(which_model=opt.basemodel, num_classes=opt.way_num, neighbor_k=opt.neighbor_k, norm='batch', 233 | init_type='normal', use_gpu=opt.cuda) 234 | 235 | # define loss function (criterion) and optimizer 236 | criterion = nn.CrossEntropyLoss().cuda() 237 | optimizer = optim.Adam(model.parameters(), lr=opt.lr, betas=(opt.beta1, 0.9)) 238 | 239 | 240 | # optionally resume from a checkpoint 241 | if opt.resume: 242 | if os.path.isfile(opt.resume): 243 | print("=> loading checkpoint '{}'".format(opt.resume)) 244 | checkpoint = torch.load(opt.resume) 245 | epoch_index = checkpoint['epoch_index'] 246 | best_prec1 = checkpoint['best_prec1'] 247 | model.load_state_dict(checkpoint['state_dict']) 248 | optimizer.load_state_dict(checkpoint['optimizer']) 249 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index'])) 250 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index']), file=F_txt) 251 | else: 252 | print("=> no checkpoint found at '{}'".format(opt.resume)) 253 | print("=> no checkpoint found at '{}'".format(opt.resume), file=F_txt) 254 | 255 | if opt.ngpu > 1: 256 | model = nn.DataParallel(model, range(opt.ngpu)) 257 | 258 | # print the architecture of the network 259 | print(model) 260 | print(model, file=F_txt) 261 | 262 | 263 | 264 | 265 | # ============================================ Testing phase ======================================== 266 | print('\n............Start testing............') 267 | start_time = time.time() 268 | repeat_num = 5 # repeat running the testing code several times 269 | 270 | 271 | total_accuracy = 0.0 272 | total_h = np.zeros(repeat_num) 273 | total_accuracy_vector = [] 274 | for r in range(repeat_num): 275 | print('===================================== Round %d =====================================' %r) 276 | print('===================================== Round %d =====================================' %r, file=F_txt) 277 | 278 | # ======================================= Folder of Datasets ======================================= 279 | 280 | # image transform & normalization 281 | ImgTransform = transforms.Compose([ 282 | transforms.Resize((opt.imageSize, opt.imageSize)), 283 | transforms.ToTensor(), 284 | transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), 285 | ]) 286 | 287 | testset = Imagefolder_csv( 288 | data_dir=opt.dataset_dir, mode=opt.mode, image_size=opt.imageSize, transform=ImgTransform, 289 | episode_num=opt.episode_test_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 290 | ) 291 | print('Testset: %d-------------%d' %(len(testset), r), file=F_txt) 292 | 293 | 294 | 295 | # ========================================== Load Datasets ========================================= 296 | test_loader = torch.utils.data.DataLoader( 297 | testset, batch_size=opt.testepisodeSize, shuffle=True, 298 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 299 | ) 300 | 301 | 302 | # =========================================== Evaluation ========================================== 303 | prec1, accuracies = validate(test_loader, model, criterion, epoch_index, F_txt) 304 | 305 | 306 | test_accuracy, h = mean_confidence_interval(accuracies) 307 | print("Test accuracy", test_accuracy, "h", h[0]) 308 | print("Test accuracy", test_accuracy, "h", h[0], file=F_txt) 309 | total_accuracy += test_accuracy 310 | total_accuracy_vector.extend(accuracies) 311 | total_h[r] = h 312 | 313 | 314 | aver_accuracy, _ = mean_confidence_interval(total_accuracy_vector) 315 | print("Aver_accuracy:", aver_accuracy, "Aver_h", total_h.mean()) 316 | print("Aver_accuracy:", aver_accuracy, "Aver_h", total_h.mean(), file=F_txt) 317 | F_txt.close() 318 | 319 | # ============================================== Testing End ========================================== 320 | -------------------------------------------------------------------------------- /DN4_2019_Version/DN4_Train_5way1shot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author: Wenbin Li (liwenbin.nju@gmail.com) 6 | Date: April 9, 2019 7 | Version: V0 8 | 9 | Citation: 10 | @inproceedings{li2019DN4, 11 | title={Revisiting Local Descriptor based Image-to-Class Measure for Few-shot Learning}, 12 | author={Li, Wenbin and Wang, Lei and Xu, Jinglin and Huo, Jing and Gao Yang and Luo, Jiebo}, 13 | booktitle={CVPR}, 14 | year={2019} 15 | } 16 | """ 17 | 18 | 19 | from __future__ import print_function 20 | import argparse 21 | import os 22 | import random 23 | import shutil 24 | import numpy as np 25 | import torch 26 | import torch.nn as nn 27 | import torch.nn.parallel 28 | import torch.backends.cudnn as cudnn 29 | import torch.optim as optim 30 | import torch.utils.data 31 | import torchvision.datasets as dset 32 | import torchvision.transforms as transforms 33 | import torchvision.utils as vutils 34 | from torch.autograd import grad 35 | import time 36 | from torch import autograd 37 | from PIL import ImageFile 38 | import pdb 39 | import sys 40 | sys.dont_write_bytecode = True 41 | 42 | 43 | # ============================ Data & Networks ===================================== 44 | from dataset.datasets_csv import Imagefolder_csv 45 | import models.network as DN4Net 46 | # ================================================================================== 47 | 48 | 49 | ImageFile.LOAD_TRUNCATED_IMAGES = True 50 | os.environ['CUDA_DEVICE_ORDER']='PCI_BUS_ID' 51 | os.environ['CUDA_VISIBLE_DEVICES']='0' 52 | 53 | 54 | parser = argparse.ArgumentParser() 55 | parser.add_argument('--dataset_dir', default='/Datasets/miniImageNet--ravi', help='/miniImageNet') 56 | parser.add_argument('--data_name', default='miniImageNet', help='miniImageNet|StanfordDog|StanfordCar|CubBird') 57 | parser.add_argument('--mode', default='train', help='train|val|test') 58 | parser.add_argument('--outf', default='./results/DN4') 59 | parser.add_argument('--resume', default='', type=str, help='path to the lastest checkpoint (default: none)') 60 | parser.add_argument('--basemodel', default='Conv64F', help='Conv64F|ResNet256F') 61 | parser.add_argument('--workers', type=int, default=8) 62 | # Few-shot parameters # 63 | parser.add_argument('--imageSize', type=int, default=84) 64 | parser.add_argument('--episodeSize', type=int, default=1, help='the mini-batch size of training') 65 | parser.add_argument('--testepisodeSize', type=int, default=1, help='one episode is taken as a mini-batch') 66 | parser.add_argument('--epochs', type=int, default=30, help='the total number of training epoch') 67 | parser.add_argument('--episode_train_num', type=int, default=10000, help='the total number of training episodes') 68 | parser.add_argument('--episode_val_num', type=int, default=1000, help='the total number of evaluation episodes') 69 | parser.add_argument('--episode_test_num', type=int, default=1000, help='the total number of testing episodes') 70 | parser.add_argument('--way_num', type=int, default=5, help='the number of way/class') 71 | parser.add_argument('--shot_num', type=int, default=1, help='the number of shot') 72 | parser.add_argument('--query_num', type=int, default=15, help='the number of queries') 73 | parser.add_argument('--neighbor_k', type=int, default=3, help='the number of k-nearest neighbors') 74 | parser.add_argument('--lr', type=float, default=0.005, help='learning rate, default=0.005') 75 | parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5') 76 | parser.add_argument('--cuda', action='store_true', default=True, help='enables cuda') 77 | parser.add_argument('--ngpu', type=int, default=1, help='the number of gpus') 78 | parser.add_argument('--nc', type=int, default=3, help='input image channels') 79 | parser.add_argument('--clamp_lower', type=float, default=-0.01) 80 | parser.add_argument('--clamp_upper', type=float, default=0.01) 81 | parser.add_argument('--print_freq', '-p', default=100, type=int, metavar='N', help='print frequency (default: 100)') 82 | opt = parser.parse_args() 83 | opt.cuda = True 84 | cudnn.benchmark = True 85 | 86 | 87 | 88 | # ======================================= Define functions ============================================= 89 | 90 | def adjust_learning_rate(optimizer, epoch_num): 91 | """Sets the learning rate to the initial LR decayed by 0.05 every 10 epochs""" 92 | lr = opt.lr * (0.05 ** (epoch_num // 10)) 93 | for param_group in optimizer.param_groups: 94 | param_group['lr'] = lr 95 | 96 | 97 | def train(train_loader, model, criterion, optimizer, epoch_index, F_txt): 98 | batch_time = AverageMeter() 99 | data_time = AverageMeter() 100 | losses = AverageMeter() 101 | top1 = AverageMeter() 102 | 103 | 104 | end = time.time() 105 | for episode_index, (query_images, query_targets, support_images, support_targets) in enumerate(train_loader): 106 | 107 | # Measure data loading time 108 | data_time.update(time.time() - end) 109 | 110 | # Convert query and support images 111 | query_images = torch.cat(query_images, 0) 112 | input_var1 = query_images.cuda() 113 | 114 | input_var2 = [] 115 | for i in range(len(support_images)): 116 | temp_support = support_images[i] 117 | temp_support = torch.cat(temp_support, 0) 118 | temp_support = temp_support.cuda() 119 | input_var2.append(temp_support) 120 | 121 | # Deal with the targets 122 | target = torch.cat(query_targets, 0) 123 | target = target.cuda() 124 | 125 | # Calculate the output 126 | output = model(input_var1, input_var2) 127 | loss = criterion(output, target) 128 | 129 | # Compute gradients and do SGD step 130 | optimizer.zero_grad() 131 | loss.backward() 132 | optimizer.step() 133 | 134 | 135 | # Measure accuracy and record loss 136 | prec1, _ = accuracy(output, target, topk=(1,3)) 137 | losses.update(loss.item(), query_images.size(0)) 138 | top1.update(prec1[0], query_images.size(0)) 139 | 140 | 141 | # Measure elapsed time 142 | batch_time.update(time.time() - end) 143 | end = time.time() 144 | 145 | 146 | #============== print the intermediate results ==============# 147 | if episode_index % opt.print_freq == 0 and episode_index != 0: 148 | 149 | print('Eposide-({0}): [{1}/{2}]\t' 150 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 151 | 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t' 152 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 153 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 154 | epoch_index, episode_index, len(train_loader), batch_time=batch_time, data_time=data_time, loss=losses, top1=top1)) 155 | 156 | print('Eposide-({0}): [{1}/{2}]\t' 157 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 158 | 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t' 159 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 160 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 161 | epoch_index, episode_index, len(train_loader), batch_time=batch_time, data_time=data_time, loss=losses, top1=top1), file=F_txt) 162 | 163 | 164 | 165 | def validate(val_loader, model, criterion, epoch_index, best_prec1, F_txt): 166 | batch_time = AverageMeter() 167 | losses = AverageMeter() 168 | top1 = AverageMeter() 169 | 170 | 171 | # switch to evaluate mode 172 | model.eval() 173 | accuracies = [] 174 | 175 | 176 | end = time.time() 177 | for episode_index, (query_images, query_targets, support_images, support_targets) in enumerate(val_loader): 178 | 179 | # Convert query and support images 180 | query_images = torch.cat(query_images, 0) 181 | input_var1 = query_images.cuda() 182 | 183 | 184 | input_var2 = [] 185 | for i in range(len(support_images)): 186 | temp_support = support_images[i] 187 | temp_support = torch.cat(temp_support, 0) 188 | temp_support = temp_support.cuda() 189 | input_var2.append(temp_support) 190 | 191 | 192 | # Deal with the targets 193 | target = torch.cat(query_targets, 0) 194 | target = target.cuda() 195 | 196 | # Calculate the output 197 | output = model(input_var1, input_var2) 198 | loss = criterion(output, target) 199 | 200 | 201 | # measure accuracy and record loss 202 | prec1, _ = accuracy(output, target, topk=(1, 3)) 203 | losses.update(loss.item(), query_images.size(0)) 204 | top1.update(prec1[0], query_images.size(0)) 205 | accuracies.append(prec1) 206 | 207 | 208 | # measure elapsed time 209 | batch_time.update(time.time() - end) 210 | end = time.time() 211 | 212 | 213 | #============== print the intermediate results ==============# 214 | if episode_index % opt.print_freq == 0 and episode_index != 0: 215 | 216 | print('Test-({0}): [{1}/{2}]\t' 217 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 218 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 219 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 220 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1)) 221 | 222 | print('Test-({0}): [{1}/{2}]\t' 223 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 224 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 225 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 226 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1), file=F_txt) 227 | 228 | 229 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1)) 230 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1), file=F_txt) 231 | 232 | return top1.avg, accuracies 233 | 234 | 235 | 236 | def save_checkpoint(state, filename='checkpoint.pth.tar'): 237 | torch.save(state, filename) 238 | 239 | 240 | class AverageMeter(object): 241 | """Computes and stores the average and current value""" 242 | def __init__(self): 243 | self.reset() 244 | 245 | def reset(self): 246 | self.val = 0 247 | self.avg = 0 248 | self.sum = 0 249 | self.count = 0 250 | 251 | def update(self, val, n=1): 252 | self.val = val 253 | self.sum += val * n 254 | self.count += n 255 | self.avg = self.sum / self.count 256 | 257 | 258 | def accuracy(output, target, topk=(1,)): 259 | """Computes the precision@k for the specified values of k""" 260 | with torch.no_grad(): 261 | maxk = max(topk) 262 | batch_size = target.size(0) 263 | 264 | _, pred = output.topk(maxk, 1, True, True) 265 | pred = pred.t() 266 | correct = pred.eq(target.view(1, -1).expand_as(pred)) 267 | 268 | res = [] 269 | for k in topk: 270 | correct_k = correct[:k].view(-1).float().sum(0, keepdim=True) 271 | res.append(correct_k.mul_(100.0 / batch_size)) 272 | return res 273 | 274 | 275 | 276 | # ======================================== Settings of path ============================================ 277 | # saving path 278 | opt.outf = opt.outf+'_'+opt.data_name+'_'+str(opt.basemodel)+'_'+str(opt.way_num)+'Way_'+str(opt.shot_num)+'Shot'+'_K'+str(opt.neighbor_k) 279 | 280 | if not os.path.exists(opt.outf): 281 | os.makedirs(opt.outf) 282 | 283 | if torch.cuda.is_available() and not opt.cuda: 284 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 285 | 286 | # save the opt and results to a txt file 287 | txt_save_path = os.path.join(opt.outf, 'opt_resutls.txt') 288 | F_txt = open(txt_save_path, 'a+') 289 | print(opt) 290 | print(opt, file=F_txt) 291 | 292 | 293 | 294 | # ========================================== Model Config =============================================== 295 | ngpu = int(opt.ngpu) 296 | global best_prec1, epoch_index 297 | best_prec1 = 0 298 | epoch_index = 0 299 | 300 | model = DN4Net.define_DN4Net(which_model=opt.basemodel, num_classes=opt.way_num, neighbor_k=opt.neighbor_k, norm='batch', 301 | init_type='normal', use_gpu=opt.cuda) 302 | 303 | # define loss function (criterion) and optimizer 304 | criterion = nn.CrossEntropyLoss().cuda() 305 | optimizer = optim.Adam(model.parameters(), lr=opt.lr, betas=(opt.beta1, 0.9)) 306 | 307 | 308 | # optionally resume from a checkpoint 309 | if opt.resume: 310 | if os.path.isfile(opt.resume): 311 | print("=> loading checkpoint '{}'".format(opt.resume)) 312 | checkpoint = torch.load(opt.resume) 313 | epoch_index = checkpoint['epoch_index'] 314 | best_prec1 = checkpoint['best_prec1'] 315 | model.load_state_dict(checkpoint['state_dict']) 316 | optimizer.load_state_dict(checkpoint['optimizer']) 317 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index'])) 318 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index']), file=F_txt) 319 | else: 320 | print("=> no checkpoint found at '{}'".format(opt.resume)) 321 | print("=> no checkpoint found at '{}'".format(opt.resume), file=F_txt) 322 | 323 | if opt.ngpu > 1: 324 | model = nn.DataParallel(model, range(opt.ngpu)) 325 | 326 | # print the architecture of the network 327 | print(model) 328 | print(model, file=F_txt) 329 | 330 | 331 | 332 | 333 | # ======================================== Training phase =============================================== 334 | print('\n............Start training............\n') 335 | start_time = time.time() 336 | 337 | 338 | for epoch_item in range(opt.epochs): 339 | print('===================================== Epoch %d =====================================' %epoch_item) 340 | print('===================================== Epoch %d =====================================' %epoch_item, file=F_txt) 341 | adjust_learning_rate(optimizer, epoch_item) 342 | 343 | 344 | # ======================================= Folder of Datasets ======================================= 345 | # image transform & normalization 346 | ImgTransform = transforms.Compose([ 347 | transforms.Resize((opt.imageSize, opt.imageSize)), 348 | transforms.ToTensor(), 349 | transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), 350 | ]) 351 | 352 | trainset = Imagefolder_csv( 353 | data_dir=opt.dataset_dir, mode=opt.mode, image_size=opt.imageSize, transform=ImgTransform, 354 | episode_num=opt.episode_train_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 355 | ) 356 | valset = Imagefolder_csv( 357 | data_dir=opt.dataset_dir, mode='val', image_size=opt.imageSize, transform=ImgTransform, 358 | episode_num=opt.episode_val_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 359 | ) 360 | testset = Imagefolder_csv( 361 | data_dir=opt.dataset_dir, mode='test', image_size=opt.imageSize, transform=ImgTransform, 362 | episode_num=opt.episode_test_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 363 | ) 364 | 365 | print('Trainset: %d' %len(trainset)) 366 | print('Valset: %d' %len(valset)) 367 | print('Testset: %d' %len(testset)) 368 | print('Trainset: %d' %len(trainset), file=F_txt) 369 | print('Valset: %d' %len(valset), file=F_txt) 370 | print('Testset: %d' %len(testset), file=F_txt) 371 | 372 | 373 | 374 | # ========================================== Load Datasets ========================================= 375 | train_loader = torch.utils.data.DataLoader( 376 | trainset, batch_size=opt.episodeSize, shuffle=True, 377 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 378 | ) 379 | val_loader = torch.utils.data.DataLoader( 380 | valset, batch_size=opt.testepisodeSize, shuffle=True, 381 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 382 | ) 383 | test_loader = torch.utils.data.DataLoader( 384 | testset, batch_size=opt.testepisodeSize, shuffle=True, 385 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 386 | ) 387 | 388 | 389 | # ============================================ Training =========================================== 390 | # Fix the parameters of Batch Normalization after 10000 episodes (1 epoch) 391 | if epoch_item < 1: 392 | model.train() 393 | else: 394 | model.eval() 395 | 396 | # Train for 10000 episodes in each epoch 397 | train(train_loader, model, criterion, optimizer, epoch_item, F_txt) 398 | 399 | 400 | # =========================================== Evaluation ========================================== 401 | print('============ Validation on the val set ============') 402 | print('============ validation on the val set ============', file=F_txt) 403 | prec1, _ = validate(val_loader, model, criterion, epoch_item, best_prec1, F_txt) 404 | 405 | 406 | # record the best prec@1 and save checkpoint 407 | is_best = prec1 > best_prec1 408 | best_prec1 = max(prec1, best_prec1) 409 | 410 | # save the checkpoint 411 | if is_best: 412 | save_checkpoint( 413 | { 414 | 'epoch_index': epoch_item, 415 | 'arch': opt.basemodel, 416 | 'state_dict': model.state_dict(), 417 | 'best_prec1': best_prec1, 418 | 'optimizer' : optimizer.state_dict(), 419 | }, os.path.join(opt.outf, 'model_best.pth.tar')) 420 | 421 | 422 | if epoch_item % 10 == 0: 423 | filename = os.path.join(opt.outf, 'epoch_%d.pth.tar' %epoch_item) 424 | save_checkpoint( 425 | { 426 | 'epoch_index': epoch_item, 427 | 'arch': opt.basemodel, 428 | 'state_dict': model.state_dict(), 429 | 'best_prec1': best_prec1, 430 | 'optimizer' : optimizer.state_dict(), 431 | }, filename) 432 | 433 | 434 | # Testing Prase 435 | print('============ Testing on the test set ============') 436 | print('============ Testing on the test set ============', file=F_txt) 437 | prec1, _ = validate(test_loader, model, criterion, epoch_item, best_prec1, F_txt) 438 | 439 | 440 | F_txt.close() 441 | print('............Training is end............') 442 | 443 | # ============================================ Training End ============================================================== 444 | -------------------------------------------------------------------------------- /DN4_2019_Version/DN4_Train_5way5shot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author: Wenbin Li (liwenbin.nju@gmail.com) 6 | Date: April 9, 2019 7 | Version: V0 8 | 9 | Citation: 10 | @inproceedings{li2019DN4, 11 | title={Revisiting Local Descriptor based Image-to-Class Measure for Few-shot Learning}, 12 | author={Li, Wenbin and Wang, Lei and Xu, Jinglin and Huo, Jing and Gao Yang and Luo, Jiebo}, 13 | booktitle={CVPR}, 14 | year={2019} 15 | } 16 | """ 17 | 18 | 19 | from __future__ import print_function 20 | import argparse 21 | import os 22 | import random 23 | import shutil 24 | import numpy as np 25 | import torch 26 | import torch.nn as nn 27 | import torch.nn.parallel 28 | import torch.backends.cudnn as cudnn 29 | import torch.optim as optim 30 | import torch.utils.data 31 | import torchvision.datasets as dset 32 | import torchvision.transforms as transforms 33 | import torchvision.utils as vutils 34 | from torch.autograd import grad 35 | import time 36 | from torch import autograd 37 | from PIL import ImageFile 38 | import pdb 39 | import sys 40 | sys.dont_write_bytecode = True 41 | 42 | 43 | # ============================ Data & Networks ===================================== 44 | from dataset.datasets_csv import Imagefolder_csv 45 | import models.network as DN4Net 46 | # ================================================================================== 47 | 48 | 49 | ImageFile.LOAD_TRUNCATED_IMAGES = True 50 | os.environ['CUDA_DEVICE_ORDER']='PCI_BUS_ID' 51 | os.environ['CUDA_VISIBLE_DEVICES']='0' 52 | 53 | 54 | parser = argparse.ArgumentParser() 55 | parser.add_argument('--dataset_dir', default='/Datasets/miniImageNet--ravi', help='/miniImageNet') 56 | parser.add_argument('--data_name', default='miniImageNet', help='miniImageNet|StanfordDog|StanfordCar|CubBird') 57 | parser.add_argument('--mode', default='train', help='train|val|test') 58 | parser.add_argument('--outf', default='./results/DN4') 59 | parser.add_argument('--resume', default='', type=str, help='path to the lastest checkpoint (default: none)') 60 | parser.add_argument('--basemodel', default='Conv64F', help='Conv64F|ResNet256F') 61 | parser.add_argument('--workers', type=int, default=8) 62 | # Few-shot parameters # 63 | parser.add_argument('--imageSize', type=int, default=84) 64 | parser.add_argument('--episodeSize', type=int, default=1, help='the mini-batch size of training') 65 | parser.add_argument('--testepisodeSize', type=int, default=1, help='one episode is taken as a mini-batch') 66 | parser.add_argument('--epochs', type=int, default=30, help='the total number of training epoch') 67 | parser.add_argument('--episode_train_num', type=int, default=10000, help='the total number of training episodes') 68 | parser.add_argument('--episode_val_num', type=int, default=1000, help='the total number of evaluation episodes') 69 | parser.add_argument('--episode_test_num', type=int, default=1000, help='the total number of testing episodes') 70 | parser.add_argument('--way_num', type=int, default=5, help='the number of way/class') 71 | parser.add_argument('--shot_num', type=int, default=5, help='the number of shot') 72 | parser.add_argument('--query_num', type=int, default=10, help='the number of queries') 73 | parser.add_argument('--neighbor_k', type=int, default=3, help='the number of k-nearest neighbors') 74 | parser.add_argument('--lr', type=float, default=0.005, help='learning rate, default=0.005') 75 | parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5') 76 | parser.add_argument('--cuda', action='store_true', default=True, help='enables cuda') 77 | parser.add_argument('--ngpu', type=int, default=1, help='the number of gpus') 78 | parser.add_argument('--nc', type=int, default=3, help='input image channels') 79 | parser.add_argument('--clamp_lower', type=float, default=-0.01) 80 | parser.add_argument('--clamp_upper', type=float, default=0.01) 81 | parser.add_argument('--print_freq', '-p', default=100, type=int, metavar='N', help='print frequency (default: 100)') 82 | opt = parser.parse_args() 83 | opt.cuda = True 84 | cudnn.benchmark = True 85 | 86 | 87 | 88 | # ======================================= Define functions ============================================= 89 | 90 | def adjust_learning_rate(optimizer, epoch_num): 91 | """Sets the learning rate to the initial LR decayed by 0.05 every 10 epochs""" 92 | lr = opt.lr * (0.05 ** (epoch_num // 10)) 93 | for param_group in optimizer.param_groups: 94 | param_group['lr'] = lr 95 | 96 | 97 | def train(train_loader, model, criterion, optimizer, epoch_index, F_txt): 98 | batch_time = AverageMeter() 99 | data_time = AverageMeter() 100 | losses = AverageMeter() 101 | top1 = AverageMeter() 102 | 103 | 104 | end = time.time() 105 | for episode_index, (query_images, query_targets, support_images, support_targets) in enumerate(train_loader): 106 | 107 | # Measure data loading time 108 | data_time.update(time.time() - end) 109 | 110 | # Convert query and support images 111 | query_images = torch.cat(query_images, 0) 112 | input_var1 = query_images.cuda() 113 | 114 | input_var2 = [] 115 | for i in range(len(support_images)): 116 | temp_support = support_images[i] 117 | temp_support = torch.cat(temp_support, 0) 118 | temp_support = temp_support.cuda() 119 | input_var2.append(temp_support) 120 | 121 | # Deal with the targets 122 | target = torch.cat(query_targets, 0) 123 | target = target.cuda() 124 | 125 | # Calculate the output 126 | output = model(input_var1, input_var2) 127 | loss = criterion(output, target) 128 | 129 | # Compute gradients and do SGD step 130 | optimizer.zero_grad() 131 | loss.backward() 132 | optimizer.step() 133 | 134 | 135 | # Measure accuracy and record loss 136 | prec1, _ = accuracy(output, target, topk=(1,3)) 137 | losses.update(loss.item(), query_images.size(0)) 138 | top1.update(prec1[0], query_images.size(0)) 139 | 140 | 141 | # Measure elapsed time 142 | batch_time.update(time.time() - end) 143 | end = time.time() 144 | 145 | 146 | #============== print the intermediate results ==============# 147 | if episode_index % opt.print_freq == 0 and episode_index != 0: 148 | 149 | print('Eposide-({0}): [{1}/{2}]\t' 150 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 151 | 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t' 152 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 153 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 154 | epoch_index, episode_index, len(train_loader), batch_time=batch_time, data_time=data_time, loss=losses, top1=top1)) 155 | 156 | print('Eposide-({0}): [{1}/{2}]\t' 157 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 158 | 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t' 159 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 160 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 161 | epoch_index, episode_index, len(train_loader), batch_time=batch_time, data_time=data_time, loss=losses, top1=top1), file=F_txt) 162 | 163 | 164 | 165 | def validate(val_loader, model, criterion, epoch_index, best_prec1, F_txt): 166 | batch_time = AverageMeter() 167 | losses = AverageMeter() 168 | top1 = AverageMeter() 169 | 170 | 171 | # switch to evaluate mode 172 | model.eval() 173 | accuracies = [] 174 | 175 | 176 | end = time.time() 177 | for episode_index, (query_images, query_targets, support_images, support_targets) in enumerate(val_loader): 178 | 179 | # Convert query and support images 180 | query_images = torch.cat(query_images, 0) 181 | input_var1 = query_images.cuda() 182 | 183 | 184 | input_var2 = [] 185 | for i in range(len(support_images)): 186 | temp_support = support_images[i] 187 | temp_support = torch.cat(temp_support, 0) 188 | temp_support = temp_support.cuda() 189 | input_var2.append(temp_support) 190 | 191 | 192 | # Deal with the target 193 | target = torch.cat(query_targets, 0) 194 | target = target.cuda() 195 | 196 | # Calculate the output 197 | output = model(input_var1, input_var2) 198 | loss = criterion(output, target) 199 | 200 | 201 | # measure accuracy and record loss 202 | prec1, _ = accuracy(output, target, topk=(1, 3)) 203 | losses.update(loss.item(), query_images.size(0)) 204 | top1.update(prec1[0], query_images.size(0)) 205 | accuracies.append(prec1) 206 | 207 | 208 | # measure elapsed time 209 | batch_time.update(time.time() - end) 210 | end = time.time() 211 | 212 | 213 | #============== print the intermediate results ==============# 214 | if episode_index % opt.print_freq == 0 and episode_index != 0: 215 | 216 | print('Test-({0}): [{1}/{2}]\t' 217 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 218 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 219 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 220 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1)) 221 | 222 | print('Test-({0}): [{1}/{2}]\t' 223 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 224 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 225 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 226 | epoch_index, episode_index, len(val_loader), batch_time=batch_time, loss=losses, top1=top1), file=F_txt) 227 | 228 | 229 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1)) 230 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1), file=F_txt) 231 | 232 | return top1.avg, accuracies 233 | 234 | 235 | 236 | def save_checkpoint(state, filename='checkpoint.pth.tar'): 237 | torch.save(state, filename) 238 | 239 | 240 | class AverageMeter(object): 241 | """Computes and stores the average and current value""" 242 | def __init__(self): 243 | self.reset() 244 | 245 | def reset(self): 246 | self.val = 0 247 | self.avg = 0 248 | self.sum = 0 249 | self.count = 0 250 | 251 | def update(self, val, n=1): 252 | self.val = val 253 | self.sum += val * n 254 | self.count += n 255 | self.avg = self.sum / self.count 256 | 257 | 258 | def accuracy(output, target, topk=(1,)): 259 | """Computes the precision@k for the specified values of k""" 260 | with torch.no_grad(): 261 | maxk = max(topk) 262 | batch_size = target.size(0) 263 | 264 | _, pred = output.topk(maxk, 1, True, True) 265 | pred = pred.t() 266 | correct = pred.eq(target.view(1, -1).expand_as(pred)) 267 | 268 | res = [] 269 | for k in topk: 270 | correct_k = correct[:k].view(-1).float().sum(0, keepdim=True) 271 | res.append(correct_k.mul_(100.0 / batch_size)) 272 | return res 273 | 274 | 275 | 276 | # ======================================== Settings of path ============================================ 277 | # saving path 278 | opt.outf = opt.outf+'_'+opt.data_name+'_'+str(opt.basemodel)+'_'+str(opt.way_num)+'Way_'+str(opt.shot_num)+'Shot'+'_K'+str(opt.neighbor_k) 279 | 280 | if not os.path.exists(opt.outf): 281 | os.makedirs(opt.outf) 282 | 283 | if torch.cuda.is_available() and not opt.cuda: 284 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 285 | 286 | # save the opt and results to a txt file 287 | txt_save_path = os.path.join(opt.outf, 'opt_resutls.txt') 288 | F_txt = open(txt_save_path, 'a+') 289 | print(opt) 290 | print(opt, file=F_txt) 291 | 292 | 293 | 294 | # ========================================== Model Config =============================================== 295 | ngpu = int(opt.ngpu) 296 | global best_prec1, epoch_index 297 | best_prec1 = 0 298 | epoch_index = 0 299 | 300 | model = DN4Net.define_DN4Net(which_model=opt.basemodel, num_classes=opt.way_num, neighbor_k=opt.neighbor_k, norm='batch', 301 | init_type='normal', use_gpu=opt.cuda) 302 | 303 | # define loss function (criterion) and optimizer 304 | criterion = nn.CrossEntropyLoss().cuda() 305 | optimizer = optim.Adam(model.parameters(), lr=opt.lr, betas=(opt.beta1, 0.9)) 306 | 307 | 308 | # optionally resume from a checkpoint 309 | if opt.resume: 310 | if os.path.isfile(opt.resume): 311 | print("=> loading checkpoint '{}'".format(opt.resume)) 312 | checkpoint = torch.load(opt.resume) 313 | epoch_index = checkpoint['epoch_index'] 314 | best_prec1 = checkpoint['best_prec1'] 315 | model.load_state_dict(checkpoint['state_dict']) 316 | optimizer.load_state_dict(checkpoint['optimizer']) 317 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index'])) 318 | print("=> loaded checkpoint '{}' (epoch {})".format(opt.resume, checkpoint['epoch_index']), file=F_txt) 319 | else: 320 | print("=> no checkpoint found at '{}'".format(opt.resume)) 321 | print("=> no checkpoint found at '{}'".format(opt.resume), file=F_txt) 322 | 323 | if opt.ngpu > 1: 324 | model = nn.DataParallel(model, range(opt.ngpu)) 325 | 326 | # print the architecture of the network 327 | print(model) 328 | print(model, file=F_txt) 329 | 330 | 331 | 332 | 333 | # ======================================== Training phase =============================================== 334 | print('\n............Start training............\n') 335 | start_time = time.time() 336 | 337 | 338 | for epoch_item in range(opt.epochs): 339 | print('===================================== Epoch %d =====================================' %epoch_item) 340 | print('===================================== Epoch %d =====================================' %epoch_item, file=F_txt) 341 | adjust_learning_rate(optimizer, epoch_item) 342 | 343 | 344 | # ======================================= Folder of Datasets ======================================= 345 | # image transform & normalization 346 | ImgTransform = transforms.Compose([ 347 | transforms.Resize((opt.imageSize, opt.imageSize)), 348 | transforms.ToTensor(), 349 | transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), 350 | ]) 351 | 352 | trainset = Imagefolder_csv( 353 | data_dir=opt.dataset_dir, mode=opt.mode, image_size=opt.imageSize, transform=ImgTransform, 354 | episode_num=opt.episode_train_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 355 | ) 356 | valset = Imagefolder_csv( 357 | data_dir=opt.dataset_dir, mode='val', image_size=opt.imageSize, transform=ImgTransform, 358 | episode_num=opt.episode_val_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 359 | ) 360 | testset = Imagefolder_csv( 361 | data_dir=opt.dataset_dir, mode='test', image_size=opt.imageSize, transform=ImgTransform, 362 | episode_num=opt.episode_test_num, way_num=opt.way_num, shot_num=opt.shot_num, query_num=opt.query_num 363 | ) 364 | 365 | print('Trainset: %d' %len(trainset)) 366 | print('Valset: %d' %len(valset)) 367 | print('Testset: %d' %len(testset)) 368 | print('Trainset: %d' %len(trainset), file=F_txt) 369 | print('Valset: %d' %len(valset), file=F_txt) 370 | print('Testset: %d' %len(testset), file=F_txt) 371 | 372 | 373 | 374 | # ========================================== Load Datasets ========================================= 375 | train_loader = torch.utils.data.DataLoader( 376 | trainset, batch_size=opt.episodeSize, shuffle=True, 377 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 378 | ) 379 | val_loader = torch.utils.data.DataLoader( 380 | valset, batch_size=opt.testepisodeSize, shuffle=True, 381 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 382 | ) 383 | test_loader = torch.utils.data.DataLoader( 384 | testset, batch_size=opt.testepisodeSize, shuffle=True, 385 | num_workers=int(opt.workers), drop_last=True, pin_memory=True 386 | ) 387 | 388 | 389 | # ============================================ Training =========================================== 390 | # Fix the parameters of Batch Normalization after 10000 episodes (1 epoch) 391 | if epoch_item < 1: 392 | model.train() 393 | else: 394 | model.eval() 395 | 396 | # Train for 10000 episodes in each epoch 397 | train(train_loader, model, criterion, optimizer, epoch_item, F_txt) 398 | 399 | 400 | # =========================================== Evaluation ========================================== 401 | print('============ Validation on the val set ============') 402 | print('============ validation on the val set ============', file=F_txt) 403 | prec1, _ = validate(val_loader, model, criterion, epoch_item, best_prec1, F_txt) 404 | 405 | 406 | # record the best prec@1 and save checkpoint 407 | is_best = prec1 > best_prec1 408 | best_prec1 = max(prec1, best_prec1) 409 | 410 | # save the checkpoint 411 | if is_best: 412 | save_checkpoint( 413 | { 414 | 'epoch_index': epoch_item, 415 | 'arch': opt.basemodel, 416 | 'state_dict': model.state_dict(), 417 | 'best_prec1': best_prec1, 418 | 'optimizer' : optimizer.state_dict(), 419 | }, os.path.join(opt.outf, 'model_best.pth.tar')) 420 | 421 | 422 | if epoch_item % 10 == 0: 423 | filename = os.path.join(opt.outf, 'epoch_%d.pth.tar' %epoch_item) 424 | save_checkpoint( 425 | { 426 | 'epoch_index': epoch_item, 427 | 'arch': opt.basemodel, 428 | 'state_dict': model.state_dict(), 429 | 'best_prec1': best_prec1, 430 | 'optimizer' : optimizer.state_dict(), 431 | }, filename) 432 | 433 | 434 | # Testing Prase 435 | print('============ Testing on the test set ============') 436 | print('============ Testing on the test set ============', file=F_txt) 437 | prec1, _ = validate(test_loader, model, criterion, epoch_item, best_prec1, F_txt) 438 | 439 | 440 | F_txt.close() 441 | print('............Training is end............') 442 | 443 | # ============================================ Training End ============================================================== 444 | -------------------------------------------------------------------------------- /DN4_2019_Version/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Wenbin Li 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | 26 | --------------------------- LICENSE FOR CovaMNet -------------------------------- 27 | BSD License 28 | 29 | For CovaMNet software 30 | Copyright (c) 2019, Wenbin Li 31 | All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | 36 | * Redistributions of source code must retain the above copyright notice, this 37 | list of conditions and the following disclaimer. 38 | 39 | * Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer in the documentation 41 | and/or other materials provided with the distribution. 42 | 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /DN4_2019_Version/README.md: -------------------------------------------------------------------------------- 1 | # DN4 in PyTorch 2 | 3 | We provide a PyTorch implementation of DN4 for few-shot learning. If you use this code for your research, please cite: 4 | 5 | [Revisiting Local Descriptor based Image-to-Class Measure for Few-shot Learning](http://cs.nju.edu.cn/rl/people/liwb/CVPR19.pdf).
6 | [Wenbin Li](https://cs.nju.edu.cn/liwenbin/), Lei Wang, Jinglin Xu, Jing Huo, Yang Gao and Jiebo Luo. In CVPR 2019.
7 | 8 | 9 | 10 | ## Prerequisites 11 | - Linux 12 | - Python 3 13 | - Pytorch 0.4 or 1.0 14 | - GPU + CUDA CuDNN 15 | - pillow, torchvision, scipy, numpy 16 | 17 | ## Getting Started 18 | ### Installation 19 | 20 | - Clone this repo: 21 | ```bash 22 | git clone https://github.com/WenbinLee/DN4.git 23 | cd DN4 24 | ``` 25 | 26 | - Install [PyTorch](http://pytorch.org) 1.0 and other dependencies. 27 | 28 | ### Datasets 29 | - [miniImageNet](https://drive.google.com/file/d/1fUBrpv8iutYwdL4xE1rX_R9ef6tyncX9/view). 30 | - [StanfordDog](http://vision.stanford.edu/aditya86/ImageNetDogs/). 31 | - [StanfordCar](https://ai.stanford.edu/~jkrause/cars/car_dataset.html). 32 | - [CUB-200](http://www.vision.caltech.edu/visipedia/CUB-200.html).
33 | Thanks [Victor Garcia](https://github.com/vgsatorras/few-shot-gnn) for providing the miniImageNet dataset. In our paper, we just used the CUB-200 dataset. In fact, there is a newer revision of this dataset with more images, see [Caltech-UCSD Birds-200-2011](http://www.vision.caltech.edu/visipedia/CUB-200-2011.html). Note, if you use these datasets, please cite the corresponding papers. 34 | 35 | 36 | ### miniImageNet Few-shot Classification 37 | - Train a 5-way 1-shot model based on Conv64F or ResNet256F: 38 | ```bash 39 | python DN4_Train_5way1shot.py --dataset_dir ./datasets/miniImageNet --data_name miniImageNet 40 | or 41 | python DN4_Train_5way1shot_Resnet.py --dataset_dir ./datasets/miniImageNet --data_name miniImageNet 42 | ``` 43 | - Test the model (specify the dataset_dir, basemodel, and data_name first): 44 | ```bash 45 | python DN4_Test_5way1shot.py --resume ./results/DN4_miniImageNet_Conv64F_5Way_1Shot_K3/model_best.pth.tar --basemodel Conv64F 46 | or 47 | python DN4_Test_5way1shot.py --resume ./results/DN4_miniImageNet_ResNet256F_5Way_1Shot_K3/model_best.pth.tar --basemodel ResNet256F 48 | ``` 49 | 50 | - The results on the miniImageNet dataset (If you set neighbor_k as 1, you may get better results in some cases): 51 | 52 | 53 | 54 | ### Fine-grained Few-shot Classification 55 | - Data prepocessing (e.g., StanfordDog) 56 | - Specify the path of the dataset and the saving path. 57 | - Run the preprocessing script. 58 | ```bash 59 | #!./dataset/StanfordDog_prepare_csv.py 60 | python ./dataset/StanfordDog_prepare_csv.py 61 | ``` 62 | - Train a 5-way 1-shot model: 63 | ```bash 64 | python DN4_Train_5way1shot.py --dataset_dir ./datasets/StanfordDog --data_name StanfordDog 65 | ``` 66 | - Test the model (specify the dataset_dir and data_name first): 67 | ```bash 68 | python DN4_Test_5way1shot.py --resume ./results/DN4_StanfordDog_Conv64F_5_Way_1_Shot/model_best.pth.tar --basemodel Conv64F 69 | ``` 70 | - The results on the fine-grained datasets: 71 | 72 | 73 | 74 | 75 | ## Citation 76 | If you use this code for your research, please cite our paper. 77 | ``` 78 | @inproceedings{li2019DN4, 79 | title={Revisiting Local Descriptor based Image-to-Class Measure for Few-shot Learning}, 80 | author={Li, Wenbin and Wang, Lei and Xu, Jinglin and Huo, Jing and Gao Yang and Luo, Jiebo}, 81 | booktitle={CVPR}, 82 | year={2019} 83 | } 84 | ``` 85 | -------------------------------------------------------------------------------- /DN4_2019_Version/dataset/CubBird_prepare_csv.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Wenbin Li 3 | ## Date: Dec. 16 2018 4 | ## 5 | ## Divide data into train/val/test in a csv version 6 | ## Output: train.csv, val.csv, test.csv 7 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | 9 | import os 10 | import csv 11 | import numpy as np 12 | import random 13 | from PIL import Image 14 | import pdb 15 | 16 | 17 | data_dir = '/FewShot/Datasets/CUB_birds' # the path of the download dataset 18 | save_dir = '/FewShot/Datasets/CUB_birds/For_FewShot' # the saving path of the divided dataset 19 | 20 | 21 | if not os.path.exists(os.path.join(save_dir, 'images')): 22 | os.makedirs(os.path.join(save_dir, 'images')) 23 | 24 | images_dir = os.path.join(data_dir, 'images') 25 | train_class_num = 130 26 | val_class_num = 20 27 | test_class_num = 50 28 | 29 | 30 | 31 | # get all the dog classes 32 | classes_list = [class_name for class_name in os.listdir(images_dir) if os.path.isdir(os.path.join(images_dir, class_name))] 33 | 34 | 35 | # divide the train/val/test set 36 | random.seed(200) 37 | train_list = random.sample(classes_list, train_class_num) 38 | remain_list = [rem for rem in classes_list if rem not in train_list] 39 | val_list = random.sample(remain_list, val_class_num) 40 | test_list = [rem for rem in remain_list if rem not in val_list] 41 | 42 | 43 | # save data into csv file----- Train 44 | train_data = [] 45 | for class_name in train_list: 46 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 47 | train_data.extend(images) 48 | print('Train----%s' %class_name) 49 | 50 | # read images and store these images 51 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 52 | for index, img_path in enumerate(img_paths): 53 | img = Image.open(img_path) 54 | img = img.convert('RGB') 55 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 56 | 57 | 58 | with open(os.path.join(save_dir, 'train.csv'), 'w') as csvfile: 59 | writer = csv.writer(csvfile) 60 | 61 | writer.writerow(['filename', 'label']) 62 | writer.writerows(train_data) 63 | 64 | 65 | 66 | 67 | # save data into csv file----- Val 68 | val_data = [] 69 | for class_name in val_list: 70 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 71 | val_data.extend(images) 72 | print('Val----%s' %class_name) 73 | 74 | # read images and store these images 75 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 76 | for index, img_path in enumerate(img_paths): 77 | img = Image.open(img_path) 78 | img = img.convert('RGB') 79 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 80 | 81 | with open(os.path.join(save_dir, 'val.csv'), 'w') as csvfile: 82 | writer = csv.writer(csvfile) 83 | 84 | writer.writerow(['filename', 'label']) 85 | writer.writerows(val_data) 86 | 87 | 88 | 89 | 90 | # save data into csv file----- Test 91 | test_data = [] 92 | for class_name in test_list: 93 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 94 | test_data.extend(images) 95 | print('Test----%s' %class_name) 96 | 97 | # read images and store these images 98 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 99 | for index, img_path in enumerate(img_paths): 100 | img = Image.open(img_path) 101 | img = img.convert('RGB') 102 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 103 | 104 | 105 | with open(os.path.join(save_dir, 'test.csv'), 'w') as csvfile: 106 | writer = csv.writer(csvfile) 107 | 108 | writer.writerow(['filename', 'label']) 109 | writer.writerows(test_data) 110 | -------------------------------------------------------------------------------- /DN4_2019_Version/dataset/StanforCar_prepare_csv.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Wenbin Li 3 | ## Date: Dec. 16 2018 4 | ## 5 | ## Divide data into train/val/test in a csv version 6 | ## Output: train.csv, val.csv, test.csv 7 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | 9 | import os 10 | import csv 11 | import numpy as np 12 | import random 13 | from PIL import Image 14 | import pdb 15 | 16 | 17 | data_dir = '/FewShot/Datasets/Stanford_cars' # the path of the download dataset 18 | save_dir = '/FewShot/Datasets/Stanford_cars/For_FewShot' # the saving path of the divided dataset 19 | 20 | 21 | if not os.path.exists(os.path.join(save_dir, 'images')): 22 | os.makedirs(os.path.join(save_dir, 'images')) 23 | 24 | images_dir = os.path.join(data_dir, 'images') 25 | train_class_num = 130 26 | val_class_num = 17 27 | test_class_num = 49 28 | 29 | 30 | 31 | # get all the dog classes 32 | classes_list = [class_name for class_name in os.listdir(images_dir) if os.path.isdir(os.path.join(images_dir, class_name))] 33 | 34 | 35 | # divide the train/val/test set 36 | random.seed(196) 37 | train_list = random.sample(classes_list, train_class_num) 38 | remain_list = [rem for rem in classes_list if rem not in train_list] 39 | val_list = random.sample(remain_list, val_class_num) 40 | test_list = [rem for rem in remain_list if rem not in val_list] 41 | 42 | 43 | # save data into csv file----- Train 44 | train_data = [] 45 | for class_name in train_list: 46 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 47 | train_data.extend(images) 48 | print('Train----%s' %class_name) 49 | 50 | # read images and store these images 51 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 52 | for index, img_path in enumerate(img_paths): 53 | img = Image.open(img_path) 54 | img = img.convert('RGB') 55 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 56 | 57 | 58 | with open(os.path.join(save_dir, 'train.csv'), 'w') as csvfile: 59 | writer = csv.writer(csvfile) 60 | 61 | writer.writerow(['filename', 'label']) 62 | writer.writerows(train_data) 63 | 64 | 65 | 66 | 67 | # save data into csv file----- Val 68 | val_data = [] 69 | for class_name in val_list: 70 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 71 | val_data.extend(images) 72 | print('Val----%s' %class_name) 73 | 74 | # read images and store these images 75 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 76 | for index, img_path in enumerate(img_paths): 77 | img = Image.open(img_path) 78 | img = img.convert('RGB') 79 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 80 | 81 | with open(os.path.join(save_dir, 'val.csv'), 'w') as csvfile: 82 | writer = csv.writer(csvfile) 83 | 84 | writer.writerow(['filename', 'label']) 85 | writer.writerows(val_data) 86 | 87 | 88 | 89 | 90 | # save data into csv file----- Test 91 | test_data = [] 92 | for class_name in test_list: 93 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 94 | test_data.extend(images) 95 | print('Test----%s' %class_name) 96 | 97 | # read images and store these images 98 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 99 | for index, img_path in enumerate(img_paths): 100 | img = Image.open(img_path) 101 | img = img.convert('RGB') 102 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 103 | 104 | 105 | with open(os.path.join(save_dir, 'test.csv'), 'w') as csvfile: 106 | writer = csv.writer(csvfile) 107 | 108 | writer.writerow(['filename', 'label']) 109 | writer.writerows(test_data) 110 | -------------------------------------------------------------------------------- /DN4_2019_Version/dataset/StanfordDog_prepare_csv.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Wenbin Li 3 | ## Date: Dec. 16 2018 4 | ## 5 | ## Divide data into train/val/test in a csv version 6 | ## Output: train.csv, val.csv, test.csv 7 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | 9 | import os 10 | import csv 11 | import numpy as np 12 | import random 13 | from PIL import Image 14 | import pdb 15 | 16 | 17 | data_dir = '/FewShot/Datasets/Stanford_dogs' # the path of the download dataset 18 | save_dir = '/FewShot/Datasets/Stanford_dogs/For_FewShot' # the saving path of the divided dataset 19 | 20 | 21 | if not os.path.exists(os.path.join(save_dir, 'images')): 22 | os.makedirs(os.path.join(save_dir, 'images')) 23 | 24 | images_dir = os.path.join(data_dir, 'Images') 25 | train_class_num = 70 26 | val_class_num = 20 27 | test_class_num = 30 28 | 29 | 30 | 31 | # get all the dog classes 32 | classes_list = [class_name for class_name in os.listdir(images_dir) if os.path.isdir(os.path.join(images_dir, class_name))] 33 | 34 | 35 | # divide the train/val/test set 36 | random.seed(120) 37 | train_list = random.sample(classes_list, train_class_num) 38 | remain_list = [rem for rem in classes_list if rem not in train_list] 39 | val_list = random.sample(remain_list, val_class_num) 40 | test_list = [rem for rem in remain_list if rem not in val_list] 41 | 42 | 43 | # save data into csv file----- Train 44 | train_data = [] 45 | for class_name in train_list: 46 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 47 | train_data.extend(images) 48 | print('Train----%s' %class_name) 49 | 50 | # read images and store these images 51 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 52 | for index, img_path in enumerate(img_paths): 53 | img = Image.open(img_path) 54 | img = img.convert('RGB') 55 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 56 | 57 | 58 | with open(os.path.join(save_dir, 'train.csv'), 'w') as csvfile: 59 | writer = csv.writer(csvfile) 60 | 61 | writer.writerow(['filename', 'label']) 62 | writer.writerows(train_data) 63 | 64 | 65 | 66 | 67 | # save data into csv file----- Val 68 | val_data = [] 69 | for class_name in val_list: 70 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 71 | val_data.extend(images) 72 | print('Val----%s' %class_name) 73 | 74 | # read images and store these images 75 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 76 | for index, img_path in enumerate(img_paths): 77 | img = Image.open(img_path) 78 | img = img.convert('RGB') 79 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 80 | 81 | with open(os.path.join(save_dir, 'val.csv'), 'w') as csvfile: 82 | writer = csv.writer(csvfile) 83 | 84 | writer.writerow(['filename', 'label']) 85 | writer.writerows(val_data) 86 | 87 | 88 | 89 | 90 | # save data into csv file----- Test 91 | test_data = [] 92 | for class_name in test_list: 93 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 94 | test_data.extend(images) 95 | print('Test----%s' %class_name) 96 | 97 | # read images and store these images 98 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 99 | for index, img_path in enumerate(img_paths): 100 | img = Image.open(img_path) 101 | img = img.convert('RGB') 102 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 103 | 104 | 105 | with open(os.path.join(save_dir, 'test.csv'), 'w') as csvfile: 106 | writer = csv.writer(csvfile) 107 | 108 | writer.writerow(['filename', 'label']) 109 | writer.writerows(test_data) 110 | -------------------------------------------------------------------------------- /DN4_2019_Version/dataset/datasets_csv.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path as path 3 | import json 4 | import torch 5 | import torch.utils.data as data 6 | import numpy as np 7 | import random 8 | from PIL import Image 9 | import pdb 10 | import csv 11 | import sys 12 | sys.dont_write_bytecode = True 13 | 14 | 15 | 16 | def pil_loader(path): 17 | # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835) 18 | with open(path, 'rb') as f: 19 | with Image.open(f) as img: 20 | return img.convert('RGB') 21 | 22 | 23 | def accimage_loader(path): 24 | import accimage 25 | try: 26 | return accimage.Image(path) 27 | except IOError: 28 | # Potentially a decoding problem, fall back to PIL.Image 29 | return pil_loader(path) 30 | 31 | 32 | def gray_loader(path): 33 | with open(path, 'rb') as f: 34 | with Image.open(f) as img: 35 | return img.convert('P') 36 | 37 | 38 | def default_loader(path): 39 | from torchvision import get_image_backend 40 | if get_image_backend() == 'accimage': 41 | return accimage_loader(path) 42 | else: 43 | return pil_loader(path) 44 | 45 | 46 | def find_classes(dir): 47 | classes = [d for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))] 48 | classes.sort() 49 | class_to_idx = {classes[i]: i for i in range(len(classes))} 50 | 51 | return classes, class_to_idx 52 | 53 | 54 | class Imagefolder_csv(object): 55 | """ 56 | Imagefolder for miniImageNet--ravi, StanfordDog, StanfordCar and CubBird datasets. 57 | Images are stored in the folder of "images"; 58 | Indexes are stored in the CSV files. 59 | """ 60 | 61 | def __init__(self, data_dir="", mode="train", image_size=84, data_name="miniImageNet", 62 | transform=None, loader=default_loader, gray_loader=gray_loader, 63 | episode_num=1000, way_num=5, shot_num=5, query_num=5): 64 | 65 | super(Imagefolder_csv, self).__init__() 66 | 67 | 68 | # set the paths of the csv files 69 | train_csv = os.path.join(data_dir, 'train.csv') 70 | val_csv = os.path.join(data_dir, 'val.csv') 71 | test_csv = os.path.join(data_dir, 'test.csv') 72 | 73 | 74 | data_list = [] 75 | e = 0 76 | if mode == "train": 77 | 78 | # store all the classes and images into a dict 79 | class_img_dict = {} 80 | with open(train_csv) as f_csv: 81 | f_train = csv.reader(f_csv, delimiter=',') 82 | for row in f_train: 83 | if f_train.line_num == 1: 84 | continue 85 | img_name, img_class = row 86 | 87 | if img_class in class_img_dict: 88 | class_img_dict[img_class].append(img_name) 89 | else: 90 | class_img_dict[img_class]=[] 91 | class_img_dict[img_class].append(img_name) 92 | f_csv.close() 93 | class_list = class_img_dict.keys() 94 | 95 | 96 | while e < episode_num: 97 | 98 | # construct each episode 99 | episode = [] 100 | e += 1 101 | temp_list = random.sample(class_list, way_num) 102 | label_num = -1 103 | 104 | for item in temp_list: 105 | label_num += 1 106 | imgs_set = class_img_dict[item] 107 | support_imgs = random.sample(imgs_set, shot_num) 108 | query_imgs = [val for val in imgs_set if val not in support_imgs] 109 | 110 | if query_num < len(query_imgs): 111 | query_imgs = random.sample(query_imgs, query_num) 112 | 113 | 114 | # the dir of support set 115 | query_dir = [path.join(data_dir, 'images', i) for i in query_imgs] 116 | support_dir = [path.join(data_dir, 'images', i) for i in support_imgs] 117 | 118 | 119 | data_files = { 120 | "query_img": query_dir, 121 | "support_set": support_dir, 122 | "target": label_num 123 | } 124 | episode.append(data_files) 125 | data_list.append(episode) 126 | 127 | 128 | elif mode == "val": 129 | 130 | # store all the classes and images into a dict 131 | class_img_dict = {} 132 | with open(val_csv) as f_csv: 133 | f_val = csv.reader(f_csv, delimiter=',') 134 | for row in f_val: 135 | if f_val.line_num == 1: 136 | continue 137 | img_name, img_class = row 138 | 139 | if img_class in class_img_dict: 140 | class_img_dict[img_class].append(img_name) 141 | else: 142 | class_img_dict[img_class]=[] 143 | class_img_dict[img_class].append(img_name) 144 | f_csv.close() 145 | class_list = class_img_dict.keys() 146 | 147 | 148 | 149 | while e < episode_num: # setting the episode number to 600 150 | 151 | # construct each episode 152 | episode = [] 153 | e += 1 154 | temp_list = random.sample(class_list, way_num) 155 | label_num = -1 156 | 157 | for item in temp_list: 158 | label_num += 1 159 | imgs_set = class_img_dict[item] 160 | support_imgs = random.sample(imgs_set, shot_num) 161 | query_imgs = [val for val in imgs_set if val not in support_imgs] 162 | 163 | if query_num Image-to-Class layer 138 | # Dataset: 3 x 84 x 84, for miniImageNet 139 | # Filters: 64->64->64->64 140 | # Mapping Sizes: 84->42->21->21->21 141 | 142 | 143 | class FourLayer_64F(nn.Module): 144 | def __init__(self, norm_layer=nn.BatchNorm2d, num_classes=5, neighbor_k=3): 145 | super(FourLayer_64F, self).__init__() 146 | 147 | if type(norm_layer) == functools.partial: 148 | use_bias = norm_layer.func == nn.InstanceNorm2d 149 | else: 150 | use_bias = norm_layer == nn.InstanceNorm2d 151 | 152 | self.features = nn.Sequential( # 3*84*84 153 | nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=use_bias), 154 | norm_layer(64), 155 | nn.LeakyReLU(0.2, True), 156 | nn.MaxPool2d(kernel_size=2, stride=2), # 64*42*42 157 | 158 | nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=use_bias), 159 | norm_layer(64), 160 | nn.LeakyReLU(0.2, True), 161 | nn.MaxPool2d(kernel_size=2, stride=2), # 64*21*21 162 | 163 | nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=use_bias), 164 | norm_layer(64), 165 | nn.LeakyReLU(0.2, True), # 64*21*21 166 | 167 | nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=use_bias), 168 | norm_layer(64), 169 | nn.LeakyReLU(0.2, True), # 64*21*21 170 | ) 171 | 172 | self.imgtoclass = ImgtoClass_Metric(neighbor_k=neighbor_k) # 1*num_classes 173 | 174 | 175 | 176 | def forward(self, input1, input2): 177 | 178 | # extract features of input1--query image 179 | q = self.features(input1) 180 | 181 | # extract features of input2--support set 182 | S = [] 183 | for i in range(len(input2)): 184 | support_set_sam = self.features(input2[i]) 185 | B, C, h, w = support_set_sam.size() 186 | support_set_sam = support_set_sam.permute(1, 0, 2, 3) 187 | support_set_sam = support_set_sam.contiguous().view(C, -1) 188 | S.append(support_set_sam) 189 | 190 | x = self.imgtoclass(q, S) # get Batch*num_classes 191 | 192 | return x 193 | 194 | 195 | 196 | #========================== Define an image-to-class layer ==========================# 197 | 198 | 199 | class ImgtoClass_Metric(nn.Module): 200 | def __init__(self, neighbor_k=3): 201 | super(ImgtoClass_Metric, self).__init__() 202 | self.neighbor_k = neighbor_k 203 | 204 | 205 | # Calculate the k-Nearest Neighbor of each local descriptor 206 | def cal_cosinesimilarity(self, input1, input2): 207 | B, C, h, w = input1.size() 208 | Similarity_list = [] 209 | 210 | for i in range(B): 211 | query_sam = input1[i] 212 | query_sam = query_sam.view(C, -1) 213 | query_sam = torch.transpose(query_sam, 0, 1) 214 | query_sam_norm = torch.norm(query_sam, 2, 1, True) 215 | query_sam = query_sam/query_sam_norm 216 | 217 | if torch.cuda.is_available(): 218 | inner_sim = torch.zeros(1, len(input2)).cuda() 219 | 220 | for j in range(len(input2)): 221 | support_set_sam = input2[j] 222 | support_set_sam_norm = torch.norm(support_set_sam, 2, 0, True) 223 | support_set_sam = support_set_sam/support_set_sam_norm 224 | 225 | # cosine similarity between a query sample and a support category 226 | innerproduct_matrix = query_sam@support_set_sam 227 | 228 | # choose the top-k nearest neighbors 229 | topk_value, topk_index = torch.topk(innerproduct_matrix, self.neighbor_k, 1) 230 | inner_sim[0, j] = torch.sum(topk_value) 231 | 232 | Similarity_list.append(inner_sim) 233 | 234 | Similarity_list = torch.cat(Similarity_list, 0) 235 | 236 | return Similarity_list 237 | 238 | 239 | def forward(self, x1, x2): 240 | 241 | Similarity_list = self.cal_cosinesimilarity(x1, x2) 242 | 243 | return Similarity_list 244 | 245 | 246 | 247 | 248 | ############################################################################## 249 | # Classes: ResNetLike 250 | ############################################################################## 251 | 252 | # Model: ResNetLike 253 | # Refer to: https://github.com/gidariss/FewShotWithoutForgetting 254 | # Input: One query image and a support set 255 | # Base_model: 4 ResBlock layers --> Image-to-Class layer 256 | # Dataset: 3 x 84 x 84, for miniImageNet 257 | # Filters: 64->96->128->256 258 | 259 | 260 | 261 | class ResBlock(nn.Module): 262 | def __init__(self, nFin, nFout): 263 | super(ResBlock, self).__init__() 264 | 265 | self.conv_block = nn.Sequential() 266 | self.conv_block.add_module('BNorm1', nn.BatchNorm2d(nFin)) 267 | self.conv_block.add_module('LRelu1', nn.LeakyReLU(0.2)) 268 | self.conv_block.add_module('ConvL1', nn.Conv2d(nFin, nFout, kernel_size=3, padding=1, bias=False)) 269 | self.conv_block.add_module('BNorm2', nn.BatchNorm2d(nFout)) 270 | self.conv_block.add_module('LRelu2', nn.LeakyReLU(0.2)) 271 | self.conv_block.add_module('ConvL2', nn.Conv2d(nFout, nFout, kernel_size=3, padding=1, bias=False)) 272 | self.conv_block.add_module('BNorm3', nn.BatchNorm2d(nFout)) 273 | self.conv_block.add_module('LRelu3', nn.LeakyReLU(0.2)) 274 | self.conv_block.add_module('ConvL3', nn.Conv2d(nFout, nFout, kernel_size=3, padding=1, bias=False)) 275 | 276 | self.skip_layer = nn.Conv2d(nFin, nFout, kernel_size=1, stride=1) 277 | 278 | 279 | def forward(self, x): 280 | return self.skip_layer(x) + self.conv_block(x) 281 | 282 | 283 | 284 | class ResNetLike(nn.Module): 285 | def __init__(self, opt, neighbor_k=3): 286 | super(ResNetLike, self).__init__() 287 | 288 | self.in_planes = opt['in_planes'] 289 | self.out_planes = [64, 96, 128, 256] 290 | self.num_stages = 4 291 | 292 | if type(opt['norm_layer']) == functools.partial: 293 | use_bias = opt['norm_layer'].func == nn.InstanceNorm2d 294 | else: 295 | use_bias = opt['norm_layer'] == nn.InstanceNorm2d 296 | 297 | 298 | if type(self.out_planes) == int: 299 | self.out_planes = [self.out_planes for i in range(self.num_stages)] 300 | 301 | assert(type(self.out_planes)==list) 302 | assert(len(self.out_planes)==self.num_stages) 303 | num_planes = [self.out_planes[0],] + self.out_planes 304 | userelu = opt['userelu'] if ('userelu' in opt) else False 305 | dropout = opt['dropout'] if ('dropout' in opt) else 0 306 | 307 | self.feat_extractor = nn.Sequential() 308 | self.feat_extractor.add_module('ConvL0', nn.Conv2d(self.in_planes, num_planes[0], kernel_size=3, padding=1)) 309 | 310 | for i in range(self.num_stages): 311 | self.feat_extractor.add_module('ResBlock'+str(i), ResBlock(num_planes[i], num_planes[i+1])) 312 | if i loaded checkpoint './results/DN4_new_miniImageNet_Conv64_5Way_1Shot_K3/model_best.pth.tar' (epoch 14) 3 | RelationNet_64( 4 | (features): Sequential( 5 | (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 6 | (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 7 | (2): LeakyReLU(negative_slope=0.2, inplace) 8 | (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 9 | (4): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 10 | (5): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 11 | (6): LeakyReLU(negative_slope=0.2, inplace) 12 | (7): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 13 | (8): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 14 | (9): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (10): LeakyReLU(negative_slope=0.2, inplace) 16 | (11): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 17 | (12): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 18 | (13): LeakyReLU(negative_slope=0.2, inplace) 19 | ) 20 | (indefense): CovaInDefense() 21 | ) 22 | ===================================== Round 0 ===================================== 23 | Testset: 600-------------0 24 | Test-(14): [100/600] Time 0.100 (0.268) Loss 1.179 (1.186) Prec@1 49.333 (52.528) 25 | Test-(14): [200/600] Time 0.224 (0.243) Loss 1.092 (1.199) Prec@1 50.667 (51.788) 26 | Test-(14): [300/600] Time 0.384 (0.232) Loss 1.505 (1.189) Prec@1 34.667 (52.385) 27 | Test-(14): [400/600] Time 0.382 (0.225) Loss 0.973 (1.192) Prec@1 54.667 (52.416) 28 | Test-(14): [500/600] Time 0.090 (0.223) Loss 1.079 (1.194) Prec@1 53.333 (52.357) 29 | * Prec@1 52.500 Best_prec1 50.575 30 | Test accuracy 52.500004 h 0.80446684 31 | ===================================== Round 1 ===================================== 32 | Testset: 600-------------1 33 | Test-(14): [100/600] Time 0.290 (0.227) Loss 1.000 (1.210) Prec@1 60.000 (51.116) 34 | Test-(14): [200/600] Time 0.229 (0.200) Loss 1.053 (1.233) Prec@1 53.333 (50.600) 35 | Test-(14): [300/600] Time 0.110 (0.200) Loss 1.421 (1.231) Prec@1 44.000 (50.693) 36 | Test-(14): [400/600] Time 0.307 (0.199) Loss 1.354 (1.222) Prec@1 41.333 (51.009) 37 | Test-(14): [500/600] Time 0.114 (0.199) Loss 1.151 (1.219) Prec@1 52.000 (51.180) 38 | * Prec@1 51.731 Best_prec1 50.575 39 | Test accuracy 51.731113 h 0.8235916 40 | ===================================== Round 2 ===================================== 41 | Testset: 600-------------2 42 | Test-(14): [100/600] Time 0.208 (0.229) Loss 1.802 (1.252) Prec@1 44.000 (49.914) 43 | Test-(14): [200/600] Time 0.140 (0.214) Loss 1.204 (1.230) Prec@1 60.000 (50.793) 44 | Test-(14): [300/600] Time 0.266 (0.208) Loss 1.311 (1.216) Prec@1 36.000 (51.380) 45 | Test-(14): [400/600] Time 0.172 (0.205) Loss 1.237 (1.228) Prec@1 46.667 (50.820) 46 | Test-(14): [500/600] Time 0.227 (0.203) Loss 1.130 (1.221) Prec@1 57.333 (51.026) 47 | * Prec@1 51.327 Best_prec1 50.575 48 | Test accuracy 51.32667 h 0.8058099 49 | ===================================== Round 3 ===================================== 50 | Testset: 600-------------3 51 | Test-(14): [100/600] Time 0.360 (0.232) Loss 0.992 (1.202) Prec@1 54.667 (51.419) 52 | Test-(14): [200/600] Time 0.321 (0.216) Loss 1.203 (1.191) Prec@1 54.667 (52.219) 53 | Test-(14): [300/600] Time 0.096 (0.210) Loss 1.212 (1.199) Prec@1 49.333 (52.049) 54 | Test-(14): [400/600] Time 0.139 (0.201) Loss 0.988 (1.194) Prec@1 69.333 (52.226) 55 | Test-(14): [500/600] Time 0.107 (0.199) Loss 1.068 (1.202) Prec@1 61.333 (52.035) 56 | * Prec@1 52.222 Best_prec1 50.575 57 | Test accuracy 52.222225 h 0.8044752 58 | ===================================== Round 4 ===================================== 59 | Testset: 600-------------4 60 | Test-(14): [100/600] Time 0.286 (0.225) Loss 1.180 (1.212) Prec@1 61.333 (52.409) 61 | Test-(14): [200/600] Time 0.141 (0.204) Loss 1.534 (1.221) Prec@1 48.000 (51.794) 62 | Test-(14): [300/600] Time 0.327 (0.205) Loss 1.679 (1.217) Prec@1 28.000 (51.743) 63 | Test-(14): [400/600] Time 0.246 (0.204) Loss 1.055 (1.214) Prec@1 56.000 (51.744) 64 | Test-(14): [500/600] Time 0.122 (0.205) Loss 0.873 (1.206) Prec@1 61.333 (51.976) 65 | * Prec@1 52.153 Best_prec1 50.575 66 | Test accuracy 52.153336 h 0.82311034 67 | Aver_accuracy: 51.986668 Aver_h 0.36276007 68 | 69 | -------------------------------------------------------------------------------- /DN4_2019_Version/results/DN4_miniImageNet_Conv64F_5Way_1Shot_K3/model_best.pth.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/DN4_2019_Version/results/DN4_miniImageNet_Conv64F_5Way_1Shot_K3/model_best.pth.tar -------------------------------------------------------------------------------- /DN4_2019_Version/results/DN4_miniImageNet_Conv64F_5Way_5Shot_K3/Test_resutls.txt: -------------------------------------------------------------------------------- 1 | Namespace(basemodel='Conv64', beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, cuda=True, data_name='miniImageNet', dataset_dir='/localdisk/wli70/FewShot/MultiTask_FewShot-V0/dataset/miniImageNet/miniImageNet--ravi', episodeSize=1, episode_test_num=600, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.005, mode='test', nc=3, neighbor_k=3, ngpu=1, outf='./results/DN4_new2_miniImageNet_Conv64_5Way_5Shot_K3', print_freq=100, query_num=10, resume='./results/DN4_new2_miniImageNet_Conv64_5Way_5Shot_K3/model_best.pth.tar', shot_num=5, testepisodeSize=1, way_num=5, workers=8) 2 | => loaded checkpoint './results/DN4_new2_miniImageNet_Conv64_5Way_5Shot_K3/model_best.pth.tar' (epoch 16) 3 | RelationNet_64( 4 | (features): Sequential( 5 | (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 6 | (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 7 | (2): LeakyReLU(negative_slope=0.2, inplace) 8 | (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 9 | (4): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 10 | (5): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 11 | (6): LeakyReLU(negative_slope=0.2, inplace) 12 | (7): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 13 | (8): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 14 | (9): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (10): LeakyReLU(negative_slope=0.2, inplace) 16 | (11): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 17 | (12): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 18 | (13): LeakyReLU(negative_slope=0.2, inplace) 19 | ) 20 | (indefense): CovaInDefense() 21 | ) 22 | ===================================== Round 0 ===================================== 23 | Testset: 600-------------0 24 | Test-(16): [100/600] Time 0.190 (0.217) Loss 0.320 (0.775) Prec@1 86.000 (71.149) 25 | Test-(16): [200/600] Time 0.258 (0.196) Loss 0.422 (0.741) Prec@1 88.000 (72.368) 26 | Test-(16): [300/600] Time 0.125 (0.189) Loss 0.500 (0.746) Prec@1 84.000 (72.033) 27 | Test-(16): [400/600] Time 0.147 (0.186) Loss 0.940 (0.758) Prec@1 66.000 (71.541) 28 | Test-(16): [500/600] Time 0.258 (0.184) Loss 1.100 (0.767) Prec@1 68.000 (71.082) 29 | * Prec@1 71.133 Best_prec1 69.308 30 | Test accuracy 71.13333 h 0.73003995 31 | ===================================== Round 1 ===================================== 32 | Testset: 600-------------1 33 | Test-(16): [100/600] Time 0.283 (0.204) Loss 1.065 (0.774) Prec@1 64.000 (71.208) 34 | Test-(16): [200/600] Time 0.204 (0.185) Loss 0.573 (0.783) Prec@1 78.000 (71.114) 35 | Test-(16): [300/600] Time 0.180 (0.182) Loss 0.441 (0.771) Prec@1 80.000 (71.236) 36 | Test-(16): [400/600] Time 0.114 (0.181) Loss 0.828 (0.763) Prec@1 70.000 (71.646) 37 | Test-(16): [500/600] Time 0.213 (0.181) Loss 0.868 (0.768) Prec@1 70.000 (71.553) 38 | * Prec@1 71.337 Best_prec1 69.308 39 | Test accuracy 71.33667 h 0.67178565 40 | ===================================== Round 2 ===================================== 41 | Testset: 600-------------2 42 | Test-(16): [100/600] Time 0.156 (0.194) Loss 1.051 (0.779) Prec@1 62.000 (70.931) 43 | Test-(16): [200/600] Time 0.165 (0.181) Loss 0.976 (0.789) Prec@1 62.000 (70.866) 44 | Test-(16): [300/600] Time 0.189 (0.179) Loss 0.915 (0.788) Prec@1 66.000 (70.651) 45 | Test-(16): [400/600] Time 0.263 (0.177) Loss 0.268 (0.790) Prec@1 90.000 (70.623) 46 | Test-(16): [500/600] Time 0.142 (0.177) Loss 0.483 (0.786) Prec@1 84.000 (70.683) 47 | * Prec@1 70.890 Best_prec1 69.308 48 | Test accuracy 70.89 h 0.69875926 49 | ===================================== Round 3 ===================================== 50 | Testset: 600-------------3 51 | Test-(16): [100/600] Time 0.173 (0.205) Loss 0.882 (0.813) Prec@1 64.000 (69.030) 52 | Test-(16): [200/600] Time 0.105 (0.190) Loss 0.705 (0.787) Prec@1 66.000 (70.109) 53 | Test-(16): [300/600] Time 0.104 (0.185) Loss 0.839 (0.778) Prec@1 70.000 (70.771) 54 | Test-(16): [400/600] Time 0.141 (0.182) Loss 0.532 (0.788) Prec@1 80.000 (70.549) 55 | Test-(16): [500/600] Time 0.160 (0.181) Loss 1.124 (0.784) Prec@1 64.000 (70.762) 56 | * Prec@1 70.733 Best_prec1 69.308 57 | Test accuracy 70.73333 h 0.7160883 58 | ===================================== Round 4 ===================================== 59 | Testset: 600-------------4 60 | Test-(16): [100/600] Time 0.212 (0.199) Loss 0.710 (0.803) Prec@1 76.000 (70.495) 61 | Test-(16): [200/600] Time 0.178 (0.185) Loss 0.384 (0.785) Prec@1 90.000 (71.214) 62 | Test-(16): [300/600] Time 0.189 (0.182) Loss 1.127 (0.780) Prec@1 56.000 (70.970) 63 | Test-(16): [400/600] Time 0.250 (0.181) Loss 0.466 (0.774) Prec@1 80.000 (71.082) 64 | Test-(16): [500/600] Time 0.111 (0.177) Loss 1.089 (0.781) Prec@1 62.000 (70.858) 65 | * Prec@1 71.013 Best_prec1 69.308 66 | Test accuracy 71.013336 h 0.71682656 67 | Aver_accuracy: 71.02133 Aver_h 0.31553766 68 | 69 | -------------------------------------------------------------------------------- /DN4_2019_Version/results/DN4_miniImageNet_Conv64F_5Way_5Shot_K3/model_best.pth.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/DN4_2019_Version/results/DN4_miniImageNet_Conv64F_5Way_5Shot_K3/model_best.pth.tar -------------------------------------------------------------------------------- /DN4_2019_Version/results/DN4_miniImageNet_ResNet256F_5Way_1Shot_K3/Test_resutls.txt: -------------------------------------------------------------------------------- 1 | Namespace(basemodel='ResNet256F', beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, cuda=True, data_name='miniImageNet', dataset_dir='/localdisk/wli70/FewShot/MultiTask_FewShot-V0/dataset/miniImageNet/miniImageNet--ravi', episodeSize=1, episode_test_num=600, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.005, mode='test', nc=3, neighbor_k=3, ngpu=1, outf='./results/DN4_new_miniImageNet_ResNet256F_5Way_1Shot_K3', print_freq=100, query_num=15, resume='./results/DN4_new_miniImageNet_ResNet256F_5Way_1Shot_K3/model_best.pth.tar', shot_num=1, testepisodeSize=1, way_num=5, workers=8) 2 | => loaded checkpoint './results/DN4_new_miniImageNet_ResNet256F_5Way_1Shot_K3/model_best.pth.tar' (epoch 21) 3 | ResNetLike( 4 | (feat_extractor): Sequential( 5 | (ConvL0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 6 | (ResBlock0): ResBlock( 7 | (conv_block): Sequential( 8 | (BNorm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 9 | (LRelu1): LeakyReLU(negative_slope=0.2) 10 | (ConvL1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 11 | (BNorm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 12 | (LRelu2): LeakyReLU(negative_slope=0.2) 13 | (ConvL2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 14 | (BNorm3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (LRelu3): LeakyReLU(negative_slope=0.2) 16 | (ConvL3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 17 | ) 18 | (skip_layer): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)) 19 | ) 20 | (MaxPool0): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 21 | (ResBlock1): ResBlock( 22 | (conv_block): Sequential( 23 | (BNorm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 24 | (LRelu1): LeakyReLU(negative_slope=0.2) 25 | (ConvL1): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 26 | (BNorm2): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 27 | (LRelu2): LeakyReLU(negative_slope=0.2) 28 | (ConvL2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 29 | (BNorm3): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 30 | (LRelu3): LeakyReLU(negative_slope=0.2) 31 | (ConvL3): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 32 | ) 33 | (skip_layer): Conv2d(64, 96, kernel_size=(1, 1), stride=(1, 1)) 34 | ) 35 | (MaxPool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 36 | (ResBlock2): ResBlock( 37 | (conv_block): Sequential( 38 | (BNorm1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 39 | (LRelu1): LeakyReLU(negative_slope=0.2) 40 | (ConvL1): Conv2d(96, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 41 | (BNorm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 42 | (LRelu2): LeakyReLU(negative_slope=0.2) 43 | (ConvL2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 44 | (BNorm3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 45 | (LRelu3): LeakyReLU(negative_slope=0.2) 46 | (ConvL3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 47 | ) 48 | (skip_layer): Conv2d(96, 128, kernel_size=(1, 1), stride=(1, 1)) 49 | ) 50 | (ResBlock3): ResBlock( 51 | (conv_block): Sequential( 52 | (BNorm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 53 | (LRelu1): LeakyReLU(negative_slope=0.2) 54 | (ConvL1): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 55 | (BNorm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 56 | (LRelu2): LeakyReLU(negative_slope=0.2) 57 | (ConvL2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 58 | (BNorm3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 59 | (LRelu3): LeakyReLU(negative_slope=0.2) 60 | (ConvL3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 61 | ) 62 | (skip_layer): Conv2d(128, 256, kernel_size=(1, 1), stride=(1, 1)) 63 | ) 64 | (ReluF1): LeakyReLU(negative_slope=0.2, inplace) 65 | ) 66 | (indefense): CovaInDefense() 67 | ) 68 | ===================================== Round 0 ===================================== 69 | Testset: 600-------------0 70 | Test-(21): [100/600] Time 0.171 (0.270) Loss 1.190 (1.144) Prec@1 56.000 (55.406) 71 | Test-(21): [200/600] Time 0.194 (0.250) Loss 1.474 (1.186) Prec@1 52.000 (53.672) 72 | Test-(21): [300/600] Time 0.125 (0.240) Loss 0.996 (1.176) Prec@1 56.000 (54.277) 73 | Test-(21): [400/600] Time 0.304 (0.236) Loss 0.880 (1.173) Prec@1 57.333 (54.081) 74 | Test-(21): [500/600] Time 0.163 (0.234) Loss 1.191 (1.174) Prec@1 57.333 (54.172) 75 | * Prec@1 54.107 Best_prec1 55.108 76 | Test accuracy 54.106667 h 0.81440806 77 | ===================================== Round 1 ===================================== 78 | Testset: 600-------------1 79 | Test-(21): [100/600] Time 0.180 (0.232) Loss 1.646 (1.174) Prec@1 33.333 (53.941) 80 | Test-(21): [200/600] Time 0.363 (0.229) Loss 1.564 (1.179) Prec@1 36.000 (53.844) 81 | Test-(21): [300/600] Time 0.116 (0.226) Loss 1.212 (1.196) Prec@1 46.667 (53.085) 82 | Test-(21): [400/600] Time 0.167 (0.222) Loss 1.674 (1.192) Prec@1 37.333 (53.303) 83 | Test-(21): [500/600] Time 0.237 (0.221) Loss 1.183 (1.189) Prec@1 42.667 (53.408) 84 | * Prec@1 53.709 Best_prec1 55.108 85 | Test accuracy 53.708885 h 0.8318296 86 | ===================================== Round 2 ===================================== 87 | Testset: 600-------------2 88 | Test-(21): [100/600] Time 0.228 (0.242) Loss 1.240 (1.176) Prec@1 50.667 (53.611) 89 | Test-(21): [200/600] Time 0.241 (0.232) Loss 1.087 (1.148) Prec@1 58.667 (55.171) 90 | Test-(21): [300/600] Time 0.120 (0.230) Loss 1.588 (1.161) Prec@1 45.333 (54.808) 91 | Test-(21): [400/600] Time 0.264 (0.225) Loss 1.097 (1.160) Prec@1 48.000 (54.657) 92 | Test-(21): [500/600] Time 0.239 (0.223) Loss 1.099 (1.159) Prec@1 50.667 (54.752) 93 | * Prec@1 54.771 Best_prec1 55.108 94 | Test accuracy 54.771107 h 0.8287496 95 | ===================================== Round 3 ===================================== 96 | Testset: 600-------------3 97 | Test-(21): [100/600] Time 0.150 (0.250) Loss 0.953 (1.153) Prec@1 57.333 (54.125) 98 | Test-(21): [200/600] Time 0.138 (0.236) Loss 0.955 (1.147) Prec@1 64.000 (54.740) 99 | Test-(21): [300/600] Time 0.209 (0.232) Loss 1.115 (1.152) Prec@1 44.000 (54.551) 100 | Test-(21): [400/600] Time 0.124 (0.230) Loss 1.205 (1.145) Prec@1 50.667 (54.856) 101 | Test-(21): [500/600] Time 0.155 (0.230) Loss 1.584 (1.142) Prec@1 41.333 (55.039) 102 | * Prec@1 54.938 Best_prec1 55.108 103 | Test accuracy 54.93778 h 0.8403389 104 | ===================================== Round 4 ===================================== 105 | Testset: 600-------------4 106 | Test-(21): [100/600] Time 0.314 (0.240) Loss 1.260 (1.125) Prec@1 49.333 (55.459) 107 | Test-(21): [200/600] Time 0.129 (0.218) Loss 1.045 (1.139) Prec@1 65.333 (55.111) 108 | Test-(21): [300/600] Time 0.333 (0.218) Loss 0.834 (1.151) Prec@1 68.000 (54.653) 109 | Test-(21): [400/600] Time 0.161 (0.218) Loss 2.335 (1.153) Prec@1 34.667 (54.550) 110 | Test-(21): [500/600] Time 0.276 (0.219) Loss 1.044 (1.155) Prec@1 56.000 (54.456) 111 | * Prec@1 54.367 Best_prec1 55.108 112 | Test accuracy 54.36667 h 0.7963865 113 | Aver_accuracy: 54.378223 Aver_h 0.36733297 114 | 115 | -------------------------------------------------------------------------------- /DN4_2019_Version/results/DN4_miniImageNet_ResNet256F_5Way_5Shot_K3/Test_resutls.txt: -------------------------------------------------------------------------------- 1 | Namespace(basemodel='ResNet256F', beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, cuda=True, data_name='miniImageNet', dataset_dir='/localdisk/wli70/FewShot/MultiTask_FewShot-V0/dataset/miniImageNet/miniImageNet--ravi', episodeSize=1, episode_test_num=600, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.005, mode='test', nc=3, neighbor_k=3, ngpu=1, outf='./results/DN4_new_miniImageNet_ResNet256F_5Way_5Shot_K3', print_freq=100, query_num=10, resume='./results/DN4_new_miniImageNet_ResNet256F_5Way_5Shot_K3/model_best.pth.tar', shot_num=5, testepisodeSize=1, way_num=5, workers=8) 2 | => loaded checkpoint './results/DN4_new_miniImageNet_ResNet256F_5Way_5Shot_K3/model_best.pth.tar' (epoch 25) 3 | ResNetLike( 4 | (feat_extractor): Sequential( 5 | (ConvL0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 6 | (ResBlock0): ResBlock( 7 | (conv_block): Sequential( 8 | (BNorm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 9 | (LRelu1): LeakyReLU(negative_slope=0.2) 10 | (ConvL1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 11 | (BNorm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 12 | (LRelu2): LeakyReLU(negative_slope=0.2) 13 | (ConvL2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 14 | (BNorm3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (LRelu3): LeakyReLU(negative_slope=0.2) 16 | (ConvL3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 17 | ) 18 | (skip_layer): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1)) 19 | ) 20 | (MaxPool0): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 21 | (ResBlock1): ResBlock( 22 | (conv_block): Sequential( 23 | (BNorm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 24 | (LRelu1): LeakyReLU(negative_slope=0.2) 25 | (ConvL1): Conv2d(64, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 26 | (BNorm2): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 27 | (LRelu2): LeakyReLU(negative_slope=0.2) 28 | (ConvL2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 29 | (BNorm3): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 30 | (LRelu3): LeakyReLU(negative_slope=0.2) 31 | (ConvL3): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 32 | ) 33 | (skip_layer): Conv2d(64, 96, kernel_size=(1, 1), stride=(1, 1)) 34 | ) 35 | (MaxPool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 36 | (ResBlock2): ResBlock( 37 | (conv_block): Sequential( 38 | (BNorm1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 39 | (LRelu1): LeakyReLU(negative_slope=0.2) 40 | (ConvL1): Conv2d(96, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 41 | (BNorm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 42 | (LRelu2): LeakyReLU(negative_slope=0.2) 43 | (ConvL2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 44 | (BNorm3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 45 | (LRelu3): LeakyReLU(negative_slope=0.2) 46 | (ConvL3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 47 | ) 48 | (skip_layer): Conv2d(96, 128, kernel_size=(1, 1), stride=(1, 1)) 49 | ) 50 | (ResBlock3): ResBlock( 51 | (conv_block): Sequential( 52 | (BNorm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 53 | (LRelu1): LeakyReLU(negative_slope=0.2) 54 | (ConvL1): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 55 | (BNorm2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 56 | (LRelu2): LeakyReLU(negative_slope=0.2) 57 | (ConvL2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 58 | (BNorm3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 59 | (LRelu3): LeakyReLU(negative_slope=0.2) 60 | (ConvL3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 61 | ) 62 | (skip_layer): Conv2d(128, 256, kernel_size=(1, 1), stride=(1, 1)) 63 | ) 64 | (ReluF1): LeakyReLU(negative_slope=0.2, inplace) 65 | ) 66 | (indefense): CovaInDefense() 67 | ) 68 | ===================================== Round 0 ===================================== 69 | Testset: 600-------------0 70 | Test-(25): [100/600] Time 0.166 (0.208) Loss 1.320 (0.678) Prec@1 52.000 (74.733) 71 | Test-(25): [200/600] Time 0.154 (0.192) Loss 0.801 (0.697) Prec@1 70.000 (74.259) 72 | Test-(25): [300/600] Time 0.170 (0.196) Loss 0.993 (0.697) Prec@1 70.000 (74.186) 73 | Test-(25): [400/600] Time 0.184 (0.199) Loss 0.421 (0.696) Prec@1 76.000 (74.219) 74 | Test-(25): [500/600] Time 0.188 (0.199) Loss 0.769 (0.700) Prec@1 66.000 (74.048) 75 | * Prec@1 74.103 Best_prec1 75.458 76 | Test accuracy 74.10333 h 0.6610412 77 | ===================================== Round 1 ===================================== 78 | Testset: 600-------------1 79 | Test-(25): [100/600] Time 0.158 (0.225) Loss 0.865 (0.668) Prec@1 64.000 (75.723) 80 | Test-(25): [200/600] Time 0.221 (0.212) Loss 0.561 (0.685) Prec@1 76.000 (75.025) 81 | Test-(25): [300/600] Time 0.219 (0.208) Loss 0.977 (0.690) Prec@1 72.000 (74.777) 82 | Test-(25): [400/600] Time 0.205 (0.207) Loss 0.944 (0.697) Prec@1 62.000 (74.529) 83 | Test-(25): [500/600] Time 0.272 (0.206) Loss 0.402 (0.694) Prec@1 88.000 (74.587) 84 | * Prec@1 74.530 Best_prec1 75.458 85 | Test accuracy 74.53 h 0.6211143 86 | ===================================== Round 2 ===================================== 87 | Testset: 600-------------2 88 | Test-(25): [100/600] Time 0.165 (0.219) Loss 0.868 (0.677) Prec@1 72.000 (75.881) 89 | Test-(25): [200/600] Time 0.221 (0.210) Loss 0.434 (0.691) Prec@1 86.000 (75.164) 90 | Test-(25): [300/600] Time 0.220 (0.206) Loss 0.732 (0.701) Prec@1 66.000 (74.711) 91 | Test-(25): [400/600] Time 0.157 (0.205) Loss 1.067 (0.704) Prec@1 58.000 (74.584) 92 | Test-(25): [500/600] Time 0.188 (0.205) Loss 0.786 (0.708) Prec@1 72.000 (74.427) 93 | * Prec@1 74.530 Best_prec1 75.458 94 | Test accuracy 74.53 h 0.6545631 95 | ===================================== Round 3 ===================================== 96 | Testset: 600-------------3 97 | Test-(25): [100/600] Time 0.301 (0.225) Loss 0.619 (0.679) Prec@1 78.000 (75.624) 98 | Test-(25): [200/600] Time 0.190 (0.212) Loss 0.605 (0.694) Prec@1 78.000 (74.607) 99 | Test-(25): [300/600] Time 0.155 (0.208) Loss 0.571 (0.689) Prec@1 76.000 (74.950) 100 | Test-(25): [400/600] Time 0.169 (0.209) Loss 0.406 (0.687) Prec@1 86.000 (74.918) 101 | Test-(25): [500/600] Time 0.198 (0.208) Loss 0.608 (0.683) Prec@1 74.000 (75.038) 102 | * Prec@1 74.950 Best_prec1 75.458 103 | Test accuracy 74.95 h 0.6368377 104 | ===================================== Round 4 ===================================== 105 | Testset: 600-------------4 106 | Test-(25): [100/600] Time 0.188 (0.231) Loss 0.818 (0.728) Prec@1 74.000 (74.218) 107 | Test-(25): [200/600] Time 0.279 (0.220) Loss 0.806 (0.718) Prec@1 66.000 (73.930) 108 | Test-(25): [300/600] Time 0.304 (0.217) Loss 0.874 (0.726) Prec@1 64.000 (73.821) 109 | Test-(25): [400/600] Time 0.158 (0.213) Loss 0.961 (0.716) Prec@1 64.000 (74.195) 110 | Test-(25): [500/600] Time 0.160 (0.211) Loss 0.266 (0.713) Prec@1 88.000 (74.184) 111 | * Prec@1 74.103 Best_prec1 75.458 112 | Test accuracy 74.10333 h 0.7051564 113 | Aver_accuracy: 74.44334 Aver_h 0.2930813 114 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Wenbin Li 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | 26 | --------------------------- LICENSE FOR DN4 -------------------------------- 27 | BSD License 28 | 29 | For DN4 software 30 | Copyright (c) 2019, Wenbin Li 31 | All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | 36 | * Redistributions of source code must retain the above copyright notice, this 37 | list of conditions and the following disclaimer. 38 | 39 | * Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer in the documentation 41 | and/or other materials provided with the distribution. 42 | 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DN4 in PyTorch (2023 Version) 2 | 3 | We provide a PyTorch implementation of DN4 for few-shot learning. 4 | If you use this code, please cite: 5 | 6 | [Revisiting Local Descriptor based Image-to-Class Measure for Few-shot Learning](http://cs.nju.edu.cn/rl/people/liwb/CVPR19.pdf).
7 | [Wenbin Li](https://cs.nju.edu.cn/liwenbin/), Lei Wang, Jinglin Xu, Jing Huo, Yang Gao and Jiebo Luo. In CVPR 2019.
8 | 9 | 10 | 11 | ## Prerequisites 12 | - Linux 13 | - Python 3.8 14 | - Pytorch 1.7.0 15 | - GPU + CUDA CuDNN 16 | - pillow, torchvision, scipy, numpy 17 | 18 | ## Getting Started 19 | ### Installation 20 | 21 | - Clone this repo: 22 | ```bash 23 | git clone https://github.com/WenbinLee/DN4.git 24 | cd DN4 25 | ``` 26 | 27 | - Install [PyTorch](http://pytorch.org) 1.7.0 and other dependencies. 28 | 29 | ### Datasets 30 | [Caltech-UCSD Birds-200-2011](https://data.caltech.edu/records/20098), [Standford Cars](https://ai.stanford.edu/~jkrause/cars/car_dataset.html), [Standford Dogs](http://vision.stanford.edu/aditya86/ImageNetDogs/main.html), [*mini*ImageNet](https://arxiv.org/abs/1606.04080v2) and [*tiered*ImageNet](https://arxiv.org/abs/1803.00676) are available at [Google Drive](https://drive.google.com/drive/u/1/folders/1SEoARH5rADckI-_gZSQRkLclrunL-yb0) and [百度网盘(提取码:yr1w)](https://pan.baidu.com/s/1M3jFo2OI5GTOpytxgtO1qA). 31 | 32 | 33 | ### miniImageNet Few-shot Classification 34 | - Train a 5-way 1-shot model based on Conv64: 35 | ```bash 36 | python Train_DN4.py --dataset_dir ./path/to/miniImageNet --data_name miniImageNet --encoder_model Conv64F_Local --way_num 5 --shot_num 1 37 | ``` 38 | - Train a 5-way 1-shot model based on ResNet12: 39 | ```bash 40 | python Train_DN4.py --dataset_dir ./path/to/miniImageNet --data_name miniImageNet --encoder_model ResNet12 --way_num 5 --shot_num 1 41 | ``` 42 | - Test the model (specify the dataset_dir, encoder_model, and data_name first): 43 | ```bash 44 | python Test_DN4.py --resume ./results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/ --encoder_model Conv64F_Local 45 | ``` 46 | 47 | 48 | ## Latest results on miniImageNet (2023) 49 | (Compared to the originally reported results in the paper. * denotes that ResNet256F is used.) 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
MethodBackbone5-way 1-shot5-way 5-shot
2019 Version2023 Version2019 Version2023 Version
DN4 Conv64F_Local 51.24 51.97 71.02 73.19
ResNet12 54.37* 61.23 74.44* 75.66
80 | 81 | 82 | 83 | - The results on the miniImageNet dataset reported in the orinigal paper: 84 | 85 | 86 | 87 | 88 | ## Citation 89 | If you use this code for your research, please cite our paper. 90 | ``` 91 | @inproceedings{DN4_CVPR_2019, 92 | author = {Wenbin Li and 93 | Lei Wang and 94 | Jinglin Xu and 95 | Jing Huo and 96 | Yang Gao and 97 | Jiebo Luo}, 98 | title = {Revisiting Local Descriptor Based Image-To-Class Measure for Few-Shot Learning}, 99 | booktitle = {{IEEE} Conference on Computer Vision and Pattern Recognition (CVPR)}, 100 | pages = {7260--7268}, 101 | year = {2019} 102 | } 103 | ``` 104 | -------------------------------------------------------------------------------- /Test_DN4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author: Wenbin Li (liwenbin@nju.edu.cn) 6 | Date: June 18, 2023 7 | Version: V5 8 | 9 | Citation: 10 | @inproceedings{DN4_CVPR_2019, 11 | author = {Wenbin Li and 12 | Lei Wang and 13 | Jinglin Xu and 14 | Jing Huo and 15 | Yang Gao and 16 | Jiebo Luo}, 17 | title = {Revisiting Local Descriptor Based Image-To-Class Measure for Few-Shot Learning}, 18 | booktitle = {{IEEE} Conference on Computer Vision and Pattern Recognition (CVPR)}, 19 | pages = {7260--7268}, 20 | year = {2019} 21 | } 22 | """ 23 | 24 | from __future__ import print_function 25 | import argparse 26 | import os 27 | import random 28 | import shutil 29 | import numpy as np 30 | import torch 31 | import torch.nn as nn 32 | import torch.nn.parallel 33 | import torch.backends.cudnn as cudnn 34 | import torch.optim as optim 35 | import torch.utils.data 36 | import torchvision.datasets as dset 37 | import torchvision.transforms as transforms 38 | import torchvision.utils as vutils 39 | from torch.autograd import grad 40 | import time 41 | from torch import autograd 42 | from PIL import ImageFile 43 | import pdb 44 | import copy 45 | import sys 46 | sys.dont_write_bytecode = True 47 | 48 | 49 | # ============================ Data & Networks ===================================== 50 | import dataset.general_dataloader as FewShotDataloader 51 | import models.network as FewShotNet 52 | import utils 53 | # ================================================================================== 54 | 55 | 56 | ImageFile.LOAD_TRUNCATED_IMAGES = True 57 | os.environ['CUDA_DEVICE_ORDER']='PCI_BUS_ID' 58 | os.environ['CUDA_VISIBLE_DEVICES']='6' 59 | 60 | 61 | model_trained = './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/' 62 | 63 | 64 | parser = argparse.ArgumentParser() 65 | parser.add_argument('--dataset_dir', default='/data1/Liwenbin/Datasets/miniImageNet--ravi', help='/miniImageNet--ravi') 66 | parser.add_argument('--data_name', default='miniImageNet', help='miniImageNet|StanfordDog|StanfordCar|CubBird_2011') 67 | parser.add_argument('--mode', default='test', help='train|val|test') 68 | parser.add_argument('--outf', default='./results/') 69 | parser.add_argument('--resume', default=model_trained, type=str, help='path to the lastest checkpoint (default: none)') 70 | parser.add_argument('--encoder_model', default='Conv64F_Local', help='Conv64F|Conv64F_Local') 71 | parser.add_argument('--classifier_model', default='DN4', help='ProtoNet|DN4') 72 | parser.add_argument('--workers', type=int, default=4) 73 | parser.add_argument('--imageSize', type=int, default=84) 74 | parser.add_argument('--train_aug', action='store_true', default=True, help='Perform data augmentation or not during training') 75 | parser.add_argument('--test_aug', action='store_true', default=False, help='Perform data augmentation or not during test') 76 | # Few-shot parameters # 77 | parser.add_argument('--episodeSize', type=int, default=1, help='the mini-batch size of training') 78 | parser.add_argument('--testepisodeSize', type=int, default=1, help='one episode is taken as a mini-batch') 79 | parser.add_argument('--epochs', type=int, default=30, help='the total number of training epoch') 80 | parser.add_argument('--start_epoch', default=0, type=int, help='manual epoch number (useful on restarts)') 81 | parser.add_argument('--episode_train_num', type=int, default=10000, help='the total number of training episodes') 82 | parser.add_argument('--episode_val_num', type=int, default=1000, help='the total number of evaluation episodes') 83 | parser.add_argument('--episode_test_num', type=int, default=1000, help='the total number of testing episodes') 84 | parser.add_argument('--way_num', type=int, default=5, help='the number of way/class') 85 | parser.add_argument('--shot_num', type=int, default=1, help='the number of shot') 86 | parser.add_argument('--query_num', type=int, default=15, help='the number of queries') 87 | parser.add_argument('--aug_shot_num', type=int, default=20, help='the number of augmented support images of each class during test') 88 | parser.add_argument('--neighbor_k', type=int, default=3, help='the number of k-nearest neighbors') 89 | # Other parameters # 90 | parser.add_argument('--lr', type=float, default=0.05, help='initial learning rate') 91 | parser.add_argument('--cosine', type=bool, default=True, help='using cosine annealing') 92 | parser.add_argument('--lr_decay_epochs', type=list, default=[60,80], help='where to decay lr, can be a list') 93 | parser.add_argument('--lr_decay_rate', type=float, default=0.1, help='decay rate for learning rate') 94 | parser.add_argument('--weight_decay', type=float, default=5e-4, help='weight decay') 95 | parser.add_argument('--momentum', type=float, default=0.9, help='momentum') 96 | parser.add_argument('--adam', action='store_true', default=False, help='use adam optimizer') 97 | parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5') 98 | parser.add_argument('--cuda', action='store_true', default=True, help='enables cuda') 99 | parser.add_argument('--ngpu', type=int, default=1, help='the number of gpus') 100 | parser.add_argument('--nc', type=int, default=3, help='input image channels') 101 | parser.add_argument('--clamp_lower', type=float, default=-0.01) 102 | parser.add_argument('--clamp_upper', type=float, default=0.01) 103 | parser.add_argument('--print_freq', '-p', default=100, type=int, help='print frequency (default: 100)') 104 | opt = parser.parse_args() 105 | opt.cuda = True 106 | cudnn.benchmark = True 107 | 108 | 109 | 110 | # ======================================= Define Test Function ============================================= 111 | def test(test_loader, model, criterion, epoch_index, best_prec1, F_txt): 112 | batch_time = utils.AverageMeter() 113 | losses = utils.AverageMeter() 114 | top1 = utils.AverageMeter() 115 | 116 | 117 | # switch to evaluate mode 118 | model.eval() 119 | accuracies = [] 120 | 121 | end = time.time() 122 | for episode_index, (query_images, query_targets, support_images, support_targets) in enumerate(test_loader): 123 | 124 | 125 | # Convert query and support images 126 | input_var1 = torch.cat(query_images, 0).cuda() 127 | input_var2 = torch.cat(support_images, 0).squeeze(0).cuda() 128 | input_var2 = input_var2.contiguous().view(-1, input_var2.size(2), input_var2.size(3), input_var2.size(4)) 129 | 130 | 131 | # Deal with the targets 132 | target = torch.cat(query_targets, 0).cuda() 133 | 134 | 135 | # Calculate the output 136 | output = model(input_var1, input_var2) 137 | loss = criterion(output, target) 138 | 139 | 140 | # Measure accuracy and record loss 141 | prec1, _ = utils.accuracy(output, target, topk=(1,3)) 142 | losses.update(loss.item(), target.size(0)) 143 | top1.update(prec1[0], target.size(0)) 144 | accuracies.append(prec1) 145 | 146 | 147 | # measure elapsed time 148 | batch_time.update(time.time() - end) 149 | end = time.time() 150 | 151 | 152 | #============== print the intermediate results ==============# 153 | if episode_index % opt.print_freq == 0 and episode_index != 0: 154 | 155 | print('Test-({0}): [{1}/{2}]\t' 156 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 157 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 158 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 159 | epoch_index, episode_index, len(test_loader), batch_time=batch_time, loss=losses, top1=top1)) 160 | 161 | print('Test-({0}): [{1}/{2}]\t' 162 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 163 | 'Loss {loss.val:.3f} ({loss.avg:.3f})\t' 164 | 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})'.format( 165 | epoch_index, episode_index, len(test_loader), batch_time=batch_time, loss=losses, top1=top1), file=F_txt) 166 | 167 | 168 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1)) 169 | print(' * Prec@1 {top1.avg:.3f} Best_prec1 {best_prec1:.3f}'.format(top1=top1, best_prec1=best_prec1), file=F_txt) 170 | 171 | return top1.avg, losses.avg, accuracies 172 | 173 | 174 | 175 | if __name__=='__main__': 176 | 177 | model = FewShotNet.define_model(encoder_model=opt.encoder_model, classifier_model=opt.classifier_model, norm='batch', 178 | way_num=opt.way_num, shot_num=opt.shot_num, init_type='normal', use_gpu=opt.cuda) 179 | 180 | # define loss function (criterion) and optimizer 181 | criterion = nn.CrossEntropyLoss().cuda() 182 | 183 | # ============================================ Test phase ============================================ 184 | # Set the save path 185 | opt.outf, F_txt_test = utils.set_save_test_path2(opt) 186 | print('========================================== Start Test ==========================================\n') 187 | print('========================================== Start Test ==========================================\n', file=F_txt_test) 188 | 189 | # Load the trained best model 190 | best_model_path = os.path.join(opt.resume, 'model_best.pth.tar') 191 | checkpoint = utils.get_resume_file(best_model_path, F_txt_test) 192 | epoch_index = checkpoint['epoch_index'] 193 | best_prec1 = checkpoint['best_prec1'] 194 | model.load_state_dict(checkpoint['model']) 195 | 196 | 197 | # print the parameters and architecture of the model 198 | print(opt) 199 | print(opt, file=F_txt_test) 200 | 201 | 202 | # Repeat five times 203 | repeat_num = 5 204 | total_accuracy = 0.0 205 | total_h = np.zeros(repeat_num) 206 | for r in range(repeat_num): 207 | 208 | print('==================== The %d-th round ====================' %r) 209 | print('==================== The %d-th round ====================' %r, file=F_txt_test) 210 | 211 | # ======================================= Loaders of Datasets ======================================= 212 | _, _, test_loader = FewShotDataloader.get_Fewshot_dataloader(opt, ['train', 'val', 'test']) 213 | 214 | 215 | # evaluate on validation/test set 216 | with torch.no_grad(): 217 | prec1, test_loss, accuracies = test(test_loader, model, criterion, epoch_index, best_prec1, F_txt_test) 218 | test_accuracy, h = utils.mean_confidence_interval(accuracies) 219 | total_accuracy += test_accuracy 220 | total_h[r] = h 221 | 222 | print('Test accuracy: %f h: %f \n' %(test_accuracy, h)) 223 | print('Test accuracy: %f h: %f \n' %(test_accuracy, h), file=F_txt_test) 224 | print('Mean_accuracy: %f h: %f' %(total_accuracy/repeat_num, total_h.mean())) 225 | print('Mean_accuracy: %f h: %f' %(total_accuracy/repeat_num, total_h.mean()), file=F_txt_test) 226 | print('===================================== Test is END =====================================\n') 227 | print('===================================== Test is END =====================================\n', file=F_txt_test) 228 | F_txt_test.close() -------------------------------------------------------------------------------- /dataset/Prepare_csv_CubBird.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Wenbin Li 3 | ## Date: Dec. 16 2018 4 | ## 5 | ## Divide data into train/val/test in a csv version 6 | ## Output: train.csv, val.csv, test.csv 7 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | 9 | import os 10 | import csv 11 | import numpy as np 12 | import random 13 | from PIL import Image 14 | import pdb 15 | 16 | 17 | data_dir = '/FewShot/Datasets/CUB_birds' # the path of the download dataset 18 | save_dir = '/FewShot/Datasets/CUB_birds/For_FewShot' # the saving path of the divided dataset 19 | 20 | 21 | if not os.path.exists(os.path.join(save_dir, 'images')): 22 | os.makedirs(os.path.join(save_dir, 'images')) 23 | 24 | images_dir = os.path.join(data_dir, 'images') 25 | train_class_num = 130 26 | val_class_num = 20 27 | test_class_num = 50 28 | 29 | 30 | 31 | # get all the dog classes 32 | classes_list = [class_name for class_name in os.listdir(images_dir) if os.path.isdir(os.path.join(images_dir, class_name))] 33 | 34 | 35 | # divide the train/val/test set 36 | random.seed(200) 37 | train_list = random.sample(classes_list, train_class_num) 38 | remain_list = [rem for rem in classes_list if rem not in train_list] 39 | val_list = random.sample(remain_list, val_class_num) 40 | test_list = [rem for rem in remain_list if rem not in val_list] 41 | 42 | 43 | # save data into csv file----- Train 44 | train_data = [] 45 | for class_name in train_list: 46 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 47 | train_data.extend(images) 48 | print('Train----%s' %class_name) 49 | 50 | # read images and store these images 51 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 52 | for index, img_path in enumerate(img_paths): 53 | img = Image.open(img_path) 54 | img = img.convert('RGB') 55 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 56 | 57 | 58 | with open(os.path.join(save_dir, 'train.csv'), 'w') as csvfile: 59 | writer = csv.writer(csvfile) 60 | 61 | writer.writerow(['filename', 'label']) 62 | writer.writerows(train_data) 63 | 64 | 65 | 66 | 67 | # save data into csv file----- Val 68 | val_data = [] 69 | for class_name in val_list: 70 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 71 | val_data.extend(images) 72 | print('Val----%s' %class_name) 73 | 74 | # read images and store these images 75 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 76 | for index, img_path in enumerate(img_paths): 77 | img = Image.open(img_path) 78 | img = img.convert('RGB') 79 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 80 | 81 | with open(os.path.join(save_dir, 'val.csv'), 'w') as csvfile: 82 | writer = csv.writer(csvfile) 83 | 84 | writer.writerow(['filename', 'label']) 85 | writer.writerows(val_data) 86 | 87 | 88 | 89 | 90 | # save data into csv file----- Test 91 | test_data = [] 92 | for class_name in test_list: 93 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 94 | test_data.extend(images) 95 | print('Test----%s' %class_name) 96 | 97 | # read images and store these images 98 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 99 | for index, img_path in enumerate(img_paths): 100 | img = Image.open(img_path) 101 | img = img.convert('RGB') 102 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 103 | 104 | 105 | with open(os.path.join(save_dir, 'test.csv'), 'w') as csvfile: 106 | writer = csv.writer(csvfile) 107 | 108 | writer.writerow(['filename', 'label']) 109 | writer.writerows(test_data) 110 | -------------------------------------------------------------------------------- /dataset/Prepare_csv_StanfordCar.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Wenbin Li 3 | ## Date: Dec. 16 2018 4 | ## 5 | ## Divide data into train/val/test in a csv version 6 | ## Output: train.csv, val.csv, test.csv 7 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | 9 | import os 10 | import csv 11 | import numpy as np 12 | import random 13 | from PIL import Image 14 | import pdb 15 | 16 | 17 | data_dir = '/FewShot/Datasets/Stanford_cars' # the path of the download dataset 18 | save_dir = '/FewShot/Datasets/Stanford_cars/For_FewShot' # the saving path of the divided dataset 19 | 20 | 21 | if not os.path.exists(os.path.join(save_dir, 'images')): 22 | os.makedirs(os.path.join(save_dir, 'images')) 23 | 24 | images_dir = os.path.join(data_dir, 'images') 25 | train_class_num = 130 26 | val_class_num = 17 27 | test_class_num = 49 28 | 29 | 30 | 31 | # get all the dog classes 32 | classes_list = [class_name for class_name in os.listdir(images_dir) if os.path.isdir(os.path.join(images_dir, class_name))] 33 | 34 | 35 | # divide the train/val/test set 36 | random.seed(196) 37 | train_list = random.sample(classes_list, train_class_num) 38 | remain_list = [rem for rem in classes_list if rem not in train_list] 39 | val_list = random.sample(remain_list, val_class_num) 40 | test_list = [rem for rem in remain_list if rem not in val_list] 41 | 42 | 43 | # save data into csv file----- Train 44 | train_data = [] 45 | for class_name in train_list: 46 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 47 | train_data.extend(images) 48 | print('Train----%s' %class_name) 49 | 50 | # read images and store these images 51 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 52 | for index, img_path in enumerate(img_paths): 53 | img = Image.open(img_path) 54 | img = img.convert('RGB') 55 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 56 | 57 | 58 | with open(os.path.join(save_dir, 'train.csv'), 'w') as csvfile: 59 | writer = csv.writer(csvfile) 60 | 61 | writer.writerow(['filename', 'label']) 62 | writer.writerows(train_data) 63 | 64 | 65 | 66 | 67 | # save data into csv file----- Val 68 | val_data = [] 69 | for class_name in val_list: 70 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 71 | val_data.extend(images) 72 | print('Val----%s' %class_name) 73 | 74 | # read images and store these images 75 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 76 | for index, img_path in enumerate(img_paths): 77 | img = Image.open(img_path) 78 | img = img.convert('RGB') 79 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 80 | 81 | with open(os.path.join(save_dir, 'val.csv'), 'w') as csvfile: 82 | writer = csv.writer(csvfile) 83 | 84 | writer.writerow(['filename', 'label']) 85 | writer.writerows(val_data) 86 | 87 | 88 | 89 | 90 | # save data into csv file----- Test 91 | test_data = [] 92 | for class_name in test_list: 93 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 94 | test_data.extend(images) 95 | print('Test----%s' %class_name) 96 | 97 | # read images and store these images 98 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 99 | for index, img_path in enumerate(img_paths): 100 | img = Image.open(img_path) 101 | img = img.convert('RGB') 102 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 103 | 104 | 105 | with open(os.path.join(save_dir, 'test.csv'), 'w') as csvfile: 106 | writer = csv.writer(csvfile) 107 | 108 | writer.writerow(['filename', 'label']) 109 | writer.writerows(test_data) 110 | -------------------------------------------------------------------------------- /dataset/Prepare_csv_StanfordDog.py: -------------------------------------------------------------------------------- 1 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | ## Created by: Wenbin Li 3 | ## Date: Dec. 16 2018 4 | ## 5 | ## Divide data into train/val/test in a csv version 6 | ## Output: train.csv, val.csv, test.csv 7 | ##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 | 9 | import os 10 | import csv 11 | import numpy as np 12 | import random 13 | from PIL import Image 14 | import pdb 15 | 16 | 17 | data_dir = '/FewShot/Datasets/Stanford_dogs' # the path of the download dataset 18 | save_dir = '/FewShot/Datasets/Stanford_dogs/For_FewShot' # the saving path of the divided dataset 19 | 20 | 21 | if not os.path.exists(os.path.join(save_dir, 'images')): 22 | os.makedirs(os.path.join(save_dir, 'images')) 23 | 24 | images_dir = os.path.join(data_dir, 'Images') 25 | train_class_num = 70 26 | val_class_num = 20 27 | test_class_num = 30 28 | 29 | 30 | 31 | # get all the dog classes 32 | classes_list = [class_name for class_name in os.listdir(images_dir) if os.path.isdir(os.path.join(images_dir, class_name))] 33 | 34 | 35 | # divide the train/val/test set 36 | random.seed(120) 37 | train_list = random.sample(classes_list, train_class_num) 38 | remain_list = [rem for rem in classes_list if rem not in train_list] 39 | val_list = random.sample(remain_list, val_class_num) 40 | test_list = [rem for rem in remain_list if rem not in val_list] 41 | 42 | 43 | # save data into csv file----- Train 44 | train_data = [] 45 | for class_name in train_list: 46 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 47 | train_data.extend(images) 48 | print('Train----%s' %class_name) 49 | 50 | # read images and store these images 51 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 52 | for index, img_path in enumerate(img_paths): 53 | img = Image.open(img_path) 54 | img = img.convert('RGB') 55 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 56 | 57 | 58 | with open(os.path.join(save_dir, 'train.csv'), 'w') as csvfile: 59 | writer = csv.writer(csvfile) 60 | 61 | writer.writerow(['filename', 'label']) 62 | writer.writerows(train_data) 63 | 64 | 65 | 66 | 67 | # save data into csv file----- Val 68 | val_data = [] 69 | for class_name in val_list: 70 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 71 | val_data.extend(images) 72 | print('Val----%s' %class_name) 73 | 74 | # read images and store these images 75 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 76 | for index, img_path in enumerate(img_paths): 77 | img = Image.open(img_path) 78 | img = img.convert('RGB') 79 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 80 | 81 | with open(os.path.join(save_dir, 'val.csv'), 'w') as csvfile: 82 | writer = csv.writer(csvfile) 83 | 84 | writer.writerow(['filename', 'label']) 85 | writer.writerows(val_data) 86 | 87 | 88 | 89 | 90 | # save data into csv file----- Test 91 | test_data = [] 92 | for class_name in test_list: 93 | images = [[i, class_name] for i in os.listdir(os.path.join(images_dir, class_name))] 94 | test_data.extend(images) 95 | print('Test----%s' %class_name) 96 | 97 | # read images and store these images 98 | img_paths = [os.path.join(images_dir, class_name, i) for i in os.listdir(os.path.join(images_dir, class_name))] 99 | for index, img_path in enumerate(img_paths): 100 | img = Image.open(img_path) 101 | img = img.convert('RGB') 102 | img.save(os.path.join(save_dir, 'images', images[index][0]), quality=100) 103 | 104 | 105 | with open(os.path.join(save_dir, 'test.csv'), 'w') as csvfile: 106 | writer = csv.writer(csvfile) 107 | 108 | writer.writerow(['filename', 'label']) 109 | writer.writerows(test_data) 110 | -------------------------------------------------------------------------------- /models/classifier.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.nn import init 4 | import numpy as np 5 | import torch.nn.functional as F 6 | import utils 7 | import pdb 8 | from abc import abstractmethod 9 | from torch.nn.utils.weight_norm import WeightNorm 10 | 11 | 12 | 13 | # =========================== Few-shot learning method: ProtoNet =========================== # 14 | class Prototype_Metric(nn.Module): 15 | ''' 16 | The classifier module of ProtoNet by using the mean prototype and Euclidean distance, 17 | which is also Non-parametric. 18 | "Prototypical networks for few-shot learning. NeurIPS 2017." 19 | ''' 20 | def __init__(self, way_num=5, shot_num=5, neighbor_k=3): 21 | super(Prototype_Metric, self).__init__() 22 | self.way_num = way_num 23 | self.avgpool = nn.AdaptiveAvgPool2d(1) 24 | 25 | 26 | # Calculate the Euclidean distance between the query and the mean prototype of the support class. 27 | def cal_EuclideanDis(self, input1, input2): 28 | ''' 29 | input1 (query images): 75 * 64 * 5 * 5 30 | input2 (support set): 25 * 64 * 5 * 5 31 | ''' 32 | 33 | # input1---query images 34 | # query = input1.view(input1.size(0), -1) # 75 * 1600 (Conv64F) 35 | query = self.avgpool(input1).squeeze(3).squeeze(2) # 75 * 64 36 | query = query.unsqueeze(1) # 75 * 1 * 1600 (Conv64F) 37 | 38 | 39 | # input2--support set 40 | input2 = self.avgpool(input2).squeeze(3).squeeze(2) # 25 * 64 41 | # input2 = input2.view(input2.size(0), -1) # 25 * 1600 42 | support_set = input2.contiguous().view(self.way_num, -1, input2.size(1)) # 5 * 5 * 1600 43 | support_set = torch.mean(support_set, 1) # 5 * 1600 44 | 45 | 46 | # Euclidean distances between a query set and a support set 47 | proto_dis = -torch.pow(query-support_set, 2).sum(2) # 75 * 5 48 | 49 | 50 | return proto_dis 51 | 52 | 53 | def forward(self, x1, x2): 54 | 55 | proto_dis = self.cal_EuclideanDis(x1, x2) 56 | 57 | return proto_dis 58 | 59 | 60 | 61 | # =========================== Few-shot learning method: DN4 =========================== # 62 | class ImgtoClass_Metric(nn.Module): 63 | ''' 64 | Image-to-class classifier module for DN4, which is a Non-parametric classifier. 65 | "Revisiting local descriptor based image-to-class measure for few-shot learning. CVPR 2019." 66 | ''' 67 | def __init__(self, way_num=5, shot_num=5, neighbor_k=3): 68 | super(ImgtoClass_Metric, self).__init__() 69 | self.neighbor_k = neighbor_k 70 | self.shot_num = shot_num 71 | 72 | 73 | # Calculate the Image-to-class similarity between the query and support class via k-NN. 74 | def cal_cosinesimilarity(self, input1, input2): 75 | ''' 76 | input1 (query images): 75 * 64 * 21 * 21 77 | input2 (support set): 25 * 64 * 21 * 21 78 | ''' 79 | 80 | # input1---query images 81 | input1 = input1.contiguous().view(input1.size(0), input1.size(1), -1) # 75 * 64 * 441 (Conv64F_Local) 82 | input1 = input1.permute(0, 2, 1) # 75 * 441 * 64 (Conv64F_Local) 83 | 84 | 85 | # input2--support set 86 | input2 = input2.contiguous().view(input2.size(0), input2.size(1), -1) # 25 * 64 * 441 87 | input2 = input2.permute(0, 2, 1) # 25 * 441 * 64 88 | 89 | 90 | # L2 Normalization 91 | input1_norm = torch.norm(input1, 2, 2, True) # 75 * 441 * 1 92 | query = input1/input1_norm # 75 * 441 * 64 93 | query = query.unsqueeze(1) # 75 * 1 * 441 *64 94 | 95 | 96 | input2_norm = torch.norm(input2, 2, 2, True) # 25 * 441 * 1 97 | support_set = input2/input2_norm # 25 * 441 * 64 98 | support_set = support_set.contiguous().view(-1, 99 | self.shot_num*support_set.size(1), support_set.size(2)) # 5 * 2205 * 64 100 | support_set = support_set.permute(0, 2, 1) # 5 * 64 * 2205 101 | 102 | 103 | # cosine similarity between a query set and a support set 104 | innerproduct_matrix = torch.matmul(query, support_set) # 75 * 5 * 441 * 2205 105 | 106 | 107 | # choose the top-k nearest neighbors 108 | topk_value, topk_index = torch.topk(innerproduct_matrix, self.neighbor_k, 3) # 75 * 5 * 441 * 3 109 | img2class_sim = torch.sum(torch.sum(topk_value, 3), 2) # 75 * 5 110 | 111 | 112 | return img2class_sim 113 | 114 | 115 | def forward(self, x1, x2): 116 | 117 | img2class_sim = self.cal_cosinesimilarity(x1, x2) 118 | 119 | return img2class_sim 120 | -------------------------------------------------------------------------------- /models/network.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.nn import init 4 | import numpy as np 5 | import functools 6 | import random 7 | import pdb 8 | import copy 9 | import sys 10 | sys.dont_write_bytecode = True 11 | 12 | 13 | 14 | # ============================ Backbone & Classifier =============================== 15 | import models.backbone as backbone 16 | import models.classifier as classifier 17 | from sklearn import metrics 18 | from sklearn.linear_model import LogisticRegression 19 | # ================================================================================== 20 | ''' 21 | All models consist of two parts: backbone module and classifier module. 22 | ''' 23 | 24 | 25 | ############################################################################### 26 | # Functions 27 | ############################################################################### 28 | 29 | encoder_dict = dict( 30 | Conv64F = backbone.Conv64F, 31 | Conv64F_Local = backbone.Conv64F_Local, 32 | ResNet10 = backbone.ResNet10, 33 | ResNet12 = backbone.ResNet12, 34 | SeResNet12 = backbone.SeResNet12, 35 | ResNet18 = backbone.ResNet18, 36 | ResNet34 = backbone.ResNet34, 37 | ResNet50 = backbone.ResNet50, 38 | ResNet101 = backbone.ResNet101) 39 | 40 | 41 | classifier_dict = dict( 42 | ProtoNet = classifier.Prototype_Metric, 43 | DN4 = classifier.ImgtoClass_Metric) 44 | 45 | 46 | 47 | def weights_init_normal(m): 48 | classname = m.__class__.__name__ 49 | # pdb.set_trace() 50 | # print(classname) 51 | if classname.find('Conv') != -1: 52 | init.normal_(m.weight.data, 0.0, 0.02) 53 | elif classname.find('Linear') != -1: 54 | init.normal_(m.weight.data, 0.0, 0.02) 55 | elif classname.find('BatchNorm2d') != -1: 56 | init.normal_(m.weight.data, 1.0, 0.02) 57 | init.constant_(m.bias.data, 0.0) 58 | 59 | 60 | def weights_init_xavier(m): 61 | classname = m.__class__.__name__ 62 | # print(classname) 63 | if classname.find('Conv') != -1: 64 | init.xavier_normal_(m.weight.data, gain=0.02) 65 | elif classname.find('Linear') != -1: 66 | init.xavier_normal_(m.weight.data, gain=0.02) 67 | elif classname.find('BatchNorm2d') != -1: 68 | init.normal_(m.weight.data, 1.0, 0.02) 69 | init.constant_(m.bias.data, 0.0) 70 | 71 | 72 | def weights_init_kaiming(m): 73 | classname = m.__class__.__name__ 74 | # print(classname) 75 | if classname.find('Conv') != -1: 76 | init.kaiming_normal_(m.weight.data, a=0, mode='fan_in') 77 | elif classname.find('Linear') != -1: 78 | init.kaiming_normal_(m.weight.data, a=0, mode='fan_in') 79 | elif classname.find('BatchNorm2d') != -1: 80 | init.normal_(m.weight.data, 1.0, 0.02) 81 | init.constant_(m.bias.data, 0.0) 82 | 83 | 84 | def weights_init_orthogonal(m): 85 | classname = m.__class__.__name__ 86 | print(classname) 87 | if classname.find('Conv') != -1: 88 | init.orthogonal_(m.weight.data, gain=1) 89 | elif classname.find('Linear') != -1: 90 | init.orthogonal_(m.weight.data, gain=1) 91 | elif classname.find('BatchNorm2d') != -1: 92 | init.normal_(m.weight.data, 1.0, 0.02) 93 | init.constant_(m.bias.data, 0.0) 94 | 95 | 96 | def init_weights(net, init_type='normal'): 97 | print('initialization method [%s]' % init_type) 98 | if init_type == 'normal': 99 | net.apply(weights_init_normal) 100 | elif init_type == 'xavier': 101 | net.apply(weights_init_xavier) 102 | elif init_type == 'kaiming': 103 | net.apply(weights_init_kaiming) 104 | elif init_type == 'orthogonal': 105 | net.apply(weights_init_orthogonal) 106 | else: 107 | raise NotImplementedError('initialization method [%s] is not implemented' % init_type) 108 | 109 | 110 | def get_norm_layer(norm_type='instance'): 111 | if norm_type == 'batch': 112 | norm_layer = functools.partial(nn.BatchNorm2d, affine=True) 113 | elif norm_type == 'instance': 114 | norm_layer = functools.partial(nn.InstanceNorm2d, affine=False) 115 | elif norm_type == 'none': 116 | norm_layer = None 117 | else: 118 | raise NotImplementedError('normalization layer [%s] is not found' % norm_type) 119 | return norm_layer 120 | 121 | 122 | def print_network(net): 123 | num_params = 0 124 | for param in net.parameters(): 125 | num_params += param.numel() 126 | 127 | print('Total number of parameters: %d' % num_params) 128 | 129 | 130 | 131 | def define_model(pretrained=False, model_root=None, encoder_model='Conv64F', classifier_model='DN4', norm='batch', init_type='normal', use_gpu=True, **kwargs): 132 | model = None 133 | norm_layer = get_norm_layer(norm_type=norm) 134 | 135 | if use_gpu: 136 | assert(torch.cuda.is_available()) 137 | 138 | if classifier_model in ['ProtoNet', 'DN4']: 139 | model = Fewshot_model(encoder_model=encoder_model, classifier_model=classifier_model, **kwargs) 140 | 141 | else: 142 | raise NotImplementedError('Model name [%s] is not recognized' % classifier_model) 143 | 144 | # init_weights(model, init_type=init_type) 145 | print_network(model) 146 | 147 | if use_gpu: 148 | model.cuda() 149 | 150 | if pretrained: 151 | model.load_state_dict(model_root) 152 | 153 | return model 154 | 155 | 156 | 157 | 158 | class Fewshot_model(nn.Module): 159 | ''' 160 | Define a few-shot learning model, which consists of an embedding module and a classifier moduel. 161 | ''' 162 | def __init__(self, encoder_model='Conv64F', classifier_model='DN4', class_num=64, way_num=5, shot_num=5, query_num=10, neighbor_k=3): 163 | super(Fewshot_model, self).__init__() 164 | self.encoder_model = encoder_model 165 | self.classifier_model = classifier_model 166 | self.way_num = way_num 167 | self.shot_num = shot_num 168 | self.query_num = query_num 169 | self.neighbor_k = neighbor_k 170 | self.loss_type = 'softmax' 171 | 172 | if encoder_model == 'Conv64F': 173 | self.feature_dim = 64 174 | elif encoder_model == 'Conv64F_Local': 175 | self.feature_dim = 64 176 | elif encoder_model in ['ResNet10', 'ResNet18', 'ResNet34']: 177 | self.feature_dim = 512 178 | elif encoder_model in ['ResNet12', 'SeResNet12']: 179 | self.feature_dim = 640 180 | elif encoder_model in ['ResNet50', 'ResNet101']: 181 | self.feature_dim = 2048 182 | 183 | encoder_module = encoder_dict[self.encoder_model] 184 | classifier_module = classifier_dict[self.classifier_model] 185 | 186 | self.features = encoder_module() 187 | self.classifier = classifier_module(way_num=self.way_num, shot_num=self.shot_num, neighbor_k=self.neighbor_k) 188 | 189 | 190 | for m in self.modules(): 191 | if isinstance(m, nn.Conv1d): 192 | init.normal_(m.weight.data, 0.0, 0.02) 193 | elif isinstance(m, nn.Linear): 194 | init.normal_(m.weight.data, 0.0, 0.02) 195 | elif isinstance(m, nn.BatchNorm2d): 196 | init.normal_(m.weight.data, 1.0, 0.02) 197 | init.constant_(m.bias.data, 0.0) 198 | 199 | 200 | def forward(self, input1, input2, is_feature=False): 201 | 202 | # pdb.set_trace() 203 | x1 = self.features(input1) # query: 75 * 64 * 21 * 21 204 | x2 = self.features(input2) # support set: 25 * 64 * 21 * 21 205 | 206 | out = self.classifier(x1, x2) 207 | 208 | if is_feature: 209 | return x1, x2, out 210 | else: 211 | return out 212 | 213 | 214 | class Model_with_reused_Encoder(nn.Module): 215 | ''' 216 | Construct a new few-shot model by reusing a pre-trained embedding module. 217 | ''' 218 | def __init__(self, pre_trained_model, new_classifier='DN4', way_num=5, shot_num=5, neighbor_k=3): 219 | super(Model_with_reused_Encoder, self).__init__() 220 | self.way_num = way_num 221 | self.shot_num = shot_num 222 | self.neighbor_k = neighbor_k 223 | self.model = pre_trained_model 224 | 225 | # Only use the features module 226 | self.features = nn.Sequential( 227 | *list(self.model.features.children()) 228 | ) 229 | 230 | classifier_module = classifier_dict[new_classifier] 231 | self.classifier = classifier_module(way_num=self.way_num, shot_num=self.shot_num, neighbor_k=self.neighbor_k) 232 | 233 | 234 | def forward(self, input1, input2): 235 | 236 | # pdb.set_trace() 237 | x1 = self.features(input1) 238 | x2 = self.features(input2) 239 | out = self.classifier(x1, x2) 240 | 241 | return out 242 | 243 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/Loss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/Loss.png -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/Test_results.txt: -------------------------------------------------------------------------------- 1 | ========================================== Start Test ========================================== 2 | 3 | => loading checkpoint './results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' 4 | => loaded checkpoint './results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' (epoch 28) 5 | Namespace(adam=False, aug_shot_num=20, beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, classifier_model='DN4', cosine=True, cuda=True, current_epoch=29, data_name='miniImageNet', dataset_dir='/data1/Liwenbin/Datasets/miniImageNet--ravi', encoder_model='ResNet12', episodeSize=1, episode_test_num=1000, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.01, lr_decay_epochs=[60, 80], lr_decay_rate=0.1, mode='train', momentum=0.9, nc=3, neighbor_k=3, ngpu=1, outf='./results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot', print_freq=100, query_num=15, resume='', shot_num=1, start_epoch=0, test_aug=False, testepisodeSize=1, train_aug=True, way_num=5, weight_decay=0.0005, workers=4) 6 | Fewshot_model( 7 | (features): ResNet_84( 8 | (layer1): Sequential( 9 | (0): BasicBlock( 10 | (conv1): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 11 | (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 12 | (relu): LeakyReLU(negative_slope=0.1) 13 | (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 14 | (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (conv3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 16 | (bn3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 17 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 18 | (downsample): Sequential( 19 | (0): Conv2d(3, 64, kernel_size=(1, 1), stride=(1, 1), bias=False) 20 | (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 21 | ) 22 | (DropBlock): DropBlock() 23 | ) 24 | ) 25 | (layer2): Sequential( 26 | (0): BasicBlock( 27 | (conv1): Conv2d(64, 160, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 28 | (bn1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 29 | (relu): LeakyReLU(negative_slope=0.1) 30 | (conv2): Conv2d(160, 160, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 31 | (bn2): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 32 | (conv3): Conv2d(160, 160, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 33 | (bn3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 34 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 35 | (downsample): Sequential( 36 | (0): Conv2d(64, 160, kernel_size=(1, 1), stride=(1, 1), bias=False) 37 | (1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 38 | ) 39 | (DropBlock): DropBlock() 40 | ) 41 | ) 42 | (layer3): Sequential( 43 | (0): BasicBlock( 44 | (conv1): Conv2d(160, 320, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 45 | (bn1): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 46 | (relu): LeakyReLU(negative_slope=0.1) 47 | (conv2): Conv2d(320, 320, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 48 | (bn2): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 49 | (conv3): Conv2d(320, 320, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 50 | (bn3): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 51 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 52 | (downsample): Sequential( 53 | (0): Conv2d(160, 320, kernel_size=(1, 1), stride=(1, 1), bias=False) 54 | (1): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 55 | ) 56 | (DropBlock): DropBlock() 57 | ) 58 | ) 59 | (layer4): Sequential( 60 | (0): BasicBlock( 61 | (conv1): Conv2d(320, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 62 | (bn1): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 63 | (relu): LeakyReLU(negative_slope=0.1) 64 | (conv2): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 65 | (bn2): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 66 | (conv3): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 67 | (bn3): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 68 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 69 | (downsample): Sequential( 70 | (0): Conv2d(320, 640, kernel_size=(1, 1), stride=(1, 1), bias=False) 71 | (1): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 72 | ) 73 | (DropBlock): DropBlock() 74 | ) 75 | ) 76 | ) 77 | (classifier): ImgtoClass_Metric() 78 | ) 79 | ==================== The 0-th round ==================== 80 | Val-(28): [100/1000] Time 0.05 (0.10) Loss 1.22 (1.05) Prec@1 54.67 (61.43) 81 | Val-(28): [200/1000] Time 0.05 (0.09) Loss 0.88 (1.07) Prec@1 66.67 (60.48) 82 | Val-(28): [300/1000] Time 0.13 (0.09) Loss 1.69 (1.06) Prec@1 46.67 (60.99) 83 | Val-(28): [400/1000] Time 0.05 (0.09) Loss 1.24 (1.07) Prec@1 65.33 (61.02) 84 | Val-(28): [500/1000] Time 0.05 (0.09) Loss 0.84 (1.07) Prec@1 68.00 (60.71) 85 | Val-(28): [600/1000] Time 0.36 (0.09) Loss 0.91 (1.07) Prec@1 66.67 (60.80) 86 | Val-(28): [700/1000] Time 0.05 (0.09) Loss 0.93 (1.06) Prec@1 62.67 (60.78) 87 | Val-(28): [800/1000] Time 0.05 (0.09) Loss 0.94 (1.07) Prec@1 64.00 (60.58) 88 | Val-(28): [900/1000] Time 0.32 (0.09) Loss 0.76 (1.06) Prec@1 70.67 (60.74) 89 | * Prec@1 60.87 Best_prec1 65.43 90 | Test accuracy: 60.868000 h: 0.637646 91 | 92 | ==================== The 1-th round ==================== 93 | Val-(28): [100/1000] Time 0.21 (0.10) Loss 0.76 (1.04) Prec@1 70.67 (61.50) 94 | Val-(28): [200/1000] Time 0.05 (0.10) Loss 1.00 (1.02) Prec@1 60.00 (61.67) 95 | Val-(28): [300/1000] Time 0.05 (0.09) Loss 0.99 (1.03) Prec@1 69.33 (61.46) 96 | Val-(28): [400/1000] Time 0.10 (0.09) Loss 1.13 (1.03) Prec@1 54.67 (61.54) 97 | Val-(28): [500/1000] Time 0.18 (0.09) Loss 1.08 (1.03) Prec@1 60.00 (61.27) 98 | Val-(28): [600/1000] Time 0.05 (0.09) Loss 1.33 (1.04) Prec@1 48.00 (61.21) 99 | Val-(28): [700/1000] Time 0.05 (0.09) Loss 0.81 (1.04) Prec@1 66.67 (61.05) 100 | Val-(28): [800/1000] Time 0.05 (0.09) Loss 0.81 (1.04) Prec@1 68.00 (61.04) 101 | Val-(28): [900/1000] Time 0.05 (0.09) Loss 1.61 (1.04) Prec@1 40.00 (61.05) 102 | * Prec@1 61.27 Best_prec1 65.43 103 | Test accuracy: 61.273331 h: 0.623978 104 | 105 | ==================== The 2-th round ==================== 106 | Val-(28): [100/1000] Time 0.05 (0.10) Loss 1.26 (1.07) Prec@1 60.00 (60.48) 107 | Val-(28): [200/1000] Time 0.05 (0.10) Loss 0.73 (1.05) Prec@1 70.67 (61.12) 108 | Val-(28): [300/1000] Time 0.05 (0.09) Loss 1.11 (1.04) Prec@1 56.00 (61.37) 109 | Val-(28): [400/1000] Time 0.05 (0.09) Loss 1.07 (1.04) Prec@1 64.00 (61.43) 110 | Val-(28): [500/1000] Time 0.05 (0.09) Loss 0.80 (1.04) Prec@1 62.67 (61.51) 111 | Val-(28): [600/1000] Time 0.05 (0.09) Loss 1.22 (1.04) Prec@1 58.67 (61.49) 112 | Val-(28): [700/1000] Time 0.05 (0.09) Loss 0.96 (1.04) Prec@1 66.67 (61.38) 113 | Val-(28): [800/1000] Time 0.05 (0.09) Loss 0.76 (1.04) Prec@1 70.67 (61.50) 114 | Val-(28): [900/1000] Time 0.05 (0.09) Loss 1.78 (1.04) Prec@1 40.00 (61.45) 115 | * Prec@1 61.63 Best_prec1 65.43 116 | Test accuracy: 61.627998 h: 0.610496 117 | 118 | ==================== The 3-th round ==================== 119 | Val-(28): [100/1000] Time 0.08 (0.09) Loss 1.08 (1.06) Prec@1 50.67 (60.48) 120 | Val-(28): [200/1000] Time 0.19 (0.09) Loss 0.98 (1.05) Prec@1 64.00 (61.27) 121 | Val-(28): [300/1000] Time 0.05 (0.09) Loss 1.23 (1.04) Prec@1 64.00 (61.29) 122 | Val-(28): [400/1000] Time 0.05 (0.09) Loss 0.85 (1.04) Prec@1 72.00 (61.25) 123 | Val-(28): [500/1000] Time 0.05 (0.09) Loss 1.09 (1.05) Prec@1 53.33 (61.10) 124 | Val-(28): [600/1000] Time 0.05 (0.09) Loss 1.08 (1.05) Prec@1 68.00 (61.05) 125 | Val-(28): [700/1000] Time 0.05 (0.09) Loss 1.34 (1.05) Prec@1 49.33 (61.04) 126 | Val-(28): [800/1000] Time 0.13 (0.09) Loss 1.39 (1.05) Prec@1 42.67 (61.26) 127 | Val-(28): [900/1000] Time 0.05 (0.09) Loss 1.28 (1.05) Prec@1 50.67 (61.21) 128 | * Prec@1 61.30 Best_prec1 65.43 129 | Test accuracy: 61.296005 h: 0.624320 130 | 131 | ==================== The 4-th round ==================== 132 | Val-(28): [100/1000] Time 0.06 (0.10) Loss 0.50 (1.04) Prec@1 77.33 (61.06) 133 | Val-(28): [200/1000] Time 0.08 (0.09) Loss 1.02 (1.02) Prec@1 60.00 (61.52) 134 | Val-(28): [300/1000] Time 0.05 (0.09) Loss 1.72 (1.05) Prec@1 44.00 (60.99) 135 | Val-(28): [400/1000] Time 0.05 (0.09) Loss 0.86 (1.05) Prec@1 68.00 (60.94) 136 | Val-(28): [500/1000] Time 0.05 (0.09) Loss 0.62 (1.05) Prec@1 78.67 (60.92) 137 | Val-(28): [600/1000] Time 0.05 (0.09) Loss 0.95 (1.05) Prec@1 65.33 (60.82) 138 | Val-(28): [700/1000] Time 0.15 (0.09) Loss 0.89 (1.04) Prec@1 58.67 (61.02) 139 | Val-(28): [800/1000] Time 0.05 (0.09) Loss 0.51 (1.05) Prec@1 80.00 (60.88) 140 | Val-(28): [900/1000] Time 0.05 (0.09) Loss 1.04 (1.05) Prec@1 61.33 (61.10) 141 | * Prec@1 61.09 Best_prec1 65.43 142 | Test accuracy: 61.090668 h: 0.634639 143 | 144 | Mean_accuracy: 61.231200 h: 0.626216 145 | ===================================== Test is END ===================================== 146 | 147 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/test_loss.txt: -------------------------------------------------------------------------------- 1 | 1.253673746883869233e+00 2 | 1.175363154888153128e+00 3 | 1.126533054888248397e+00 4 | 1.116016005635261488e+00 5 | 1.086189859867096041e+00 6 | 1.077181908696889900e+00 7 | 1.091881560593843448e+00 8 | 1.071739518642425448e+00 9 | 1.066117631584405867e+00 10 | 1.045860359370708537e+00 11 | 1.052673544406890871e+00 12 | 1.021202118217945154e+00 13 | 1.059072216629981966e+00 14 | 1.075823018640279738e+00 15 | 1.018044667035341355e+00 16 | 1.032609475791454345e+00 17 | 1.032400890231132573e+00 18 | 1.050499824374914182e+00 19 | 1.015169827967882243e+00 20 | 1.077288622945547170e+00 21 | 1.008571608692407695e+00 22 | 1.012665395826101378e+00 23 | 1.059207549989223507e+00 24 | 1.020502974927425477e+00 25 | 1.031800021022558189e+00 26 | 1.021756289094686521e+00 27 | 1.040406664311885887e+00 28 | 1.048552886307239529e+00 29 | 1.050527185380458750e+00 30 | 1.044508923292160052e+00 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/train_loss.txt: -------------------------------------------------------------------------------- 1 | 1.395911455857753669e+00 2 | 1.235713104736805068e+00 3 | 1.144744067624211326e+00 4 | 1.076060488390922609e+00 5 | 1.011772379270196032e+00 6 | 9.715176198184489742e-01 7 | 9.266147161453962555e-01 8 | 8.854524700559676109e-01 9 | 8.517675985291600638e-01 10 | 8.144459471218288282e-01 11 | 7.861138152942060975e-01 12 | 7.514922330245376036e-01 13 | 7.213985654670744818e-01 14 | 6.938584349561482956e-01 15 | 6.661867645502090873e-01 16 | 6.298230365678667564e-01 17 | 6.092061093773692981e-01 18 | 5.818210175462067424e-01 19 | 5.511680436317808462e-01 20 | 5.301910962749272205e-01 21 | 5.055666309557854676e-01 22 | 4.742365922626107788e-01 23 | 4.432025669872760587e-01 24 | 4.220217605788260662e-01 25 | 4.013453226396814233e-01 26 | 3.774004172056913409e-01 27 | 3.547824192937463761e-01 28 | 3.351189949912484756e-01 29 | 3.251082921743392862e-01 30 | 3.225487162891309545e-01 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_1Shot/val_loss.txt: -------------------------------------------------------------------------------- 1 | 1.302756758093833955e+00 2 | 1.206469823241233863e+00 3 | 1.167996160447597465e+00 4 | 1.110277335435152057e+00 5 | 1.078763202548026934e+00 6 | 1.060682893872261001e+00 7 | 1.056014724582433617e+00 8 | 1.025647476971149441e+00 9 | 1.028116998285055095e+00 10 | 1.029297127872705442e+00 11 | 1.063265623092651380e+00 12 | 1.031772689104080154e+00 13 | 1.007225043669343068e+00 14 | 1.014933643430471433e+00 15 | 1.000232069969177351e+00 16 | 1.010613498389720810e+00 17 | 9.800566422045230430e-01 18 | 1.021281833261251437e+00 19 | 9.849715006053447741e-01 20 | 9.727315579056740047e-01 21 | 9.694692134708166043e-01 22 | 9.776101870536804128e-01 23 | 9.603498172610998029e-01 24 | 9.599604772925376395e-01 25 | 9.734738064706325300e-01 26 | 9.642601183503866080e-01 27 | 9.656532637029886512e-01 28 | 9.440980364978313055e-01 29 | 9.491272331327199607e-01 30 | 9.420109668523073410e-01 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/Loss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/Loss.png -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/Test_results.txt: -------------------------------------------------------------------------------- 1 | ========================================== Start Test ========================================== 2 | 3 | => loading checkpoint './results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/model_best.pth.tar' 4 | => loaded checkpoint './results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/model_best.pth.tar' (epoch 28) 5 | Namespace(adam=False, aug_shot_num=20, beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, classifier_model='DN4', cosine=True, cuda=True, current_epoch=29, data_name='miniImageNet', dataset_dir='/data1/Liwenbin/Datasets/miniImageNet--ravi', encoder_model='ResNet12', episodeSize=1, episode_test_num=1000, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.01, lr_decay_epochs=[60, 80], lr_decay_rate=0.1, mode='train', momentum=0.9, nc=3, neighbor_k=3, ngpu=1, outf='./results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot', print_freq=100, query_num=15, resume='', shot_num=5, start_epoch=0, test_aug=False, testepisodeSize=1, train_aug=True, way_num=5, weight_decay=0.0005, workers=4) 6 | Fewshot_model( 7 | (features): ResNet_84( 8 | (layer1): Sequential( 9 | (0): BasicBlock( 10 | (conv1): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 11 | (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 12 | (relu): LeakyReLU(negative_slope=0.1) 13 | (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 14 | (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (conv3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 16 | (bn3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 17 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 18 | (downsample): Sequential( 19 | (0): Conv2d(3, 64, kernel_size=(1, 1), stride=(1, 1), bias=False) 20 | (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 21 | ) 22 | (DropBlock): DropBlock() 23 | ) 24 | ) 25 | (layer2): Sequential( 26 | (0): BasicBlock( 27 | (conv1): Conv2d(64, 160, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 28 | (bn1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 29 | (relu): LeakyReLU(negative_slope=0.1) 30 | (conv2): Conv2d(160, 160, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 31 | (bn2): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 32 | (conv3): Conv2d(160, 160, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 33 | (bn3): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 34 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 35 | (downsample): Sequential( 36 | (0): Conv2d(64, 160, kernel_size=(1, 1), stride=(1, 1), bias=False) 37 | (1): BatchNorm2d(160, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 38 | ) 39 | (DropBlock): DropBlock() 40 | ) 41 | ) 42 | (layer3): Sequential( 43 | (0): BasicBlock( 44 | (conv1): Conv2d(160, 320, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 45 | (bn1): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 46 | (relu): LeakyReLU(negative_slope=0.1) 47 | (conv2): Conv2d(320, 320, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 48 | (bn2): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 49 | (conv3): Conv2d(320, 320, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 50 | (bn3): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 51 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 52 | (downsample): Sequential( 53 | (0): Conv2d(160, 320, kernel_size=(1, 1), stride=(1, 1), bias=False) 54 | (1): BatchNorm2d(320, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 55 | ) 56 | (DropBlock): DropBlock() 57 | ) 58 | ) 59 | (layer4): Sequential( 60 | (0): BasicBlock( 61 | (conv1): Conv2d(320, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 62 | (bn1): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 63 | (relu): LeakyReLU(negative_slope=0.1) 64 | (conv2): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 65 | (bn2): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 66 | (conv3): Conv2d(640, 640, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) 67 | (bn3): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 68 | (maxpool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 69 | (downsample): Sequential( 70 | (0): Conv2d(320, 640, kernel_size=(1, 1), stride=(1, 1), bias=False) 71 | (1): BatchNorm2d(640, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 72 | ) 73 | (DropBlock): DropBlock() 74 | ) 75 | ) 76 | ) 77 | (classifier): ImgtoClass_Metric() 78 | ) 79 | ==================== The 0-th round ==================== 80 | Val-(28): [100/1000] Time 0.06 (0.13) Loss 0.71 (0.65) Prec@1 62.67 (74.59) 81 | Val-(28): [200/1000] Time 0.06 (0.12) Loss 0.42 (0.66) Prec@1 85.33 (74.28) 82 | Val-(28): [300/1000] Time 0.06 (0.12) Loss 0.81 (0.64) Prec@1 70.67 (74.85) 83 | Val-(28): [400/1000] Time 0.24 (0.11) Loss 0.53 (0.65) Prec@1 80.00 (74.90) 84 | Val-(28): [500/1000] Time 0.29 (0.11) Loss 0.94 (0.65) Prec@1 66.67 (74.95) 85 | Val-(28): [600/1000] Time 0.06 (0.11) Loss 0.68 (0.64) Prec@1 68.00 (75.30) 86 | Val-(28): [700/1000] Time 0.06 (0.11) Loss 0.70 (0.65) Prec@1 74.67 (75.08) 87 | Val-(28): [800/1000] Time 0.06 (0.11) Loss 0.42 (0.65) Prec@1 86.67 (75.14) 88 | Val-(28): [900/1000] Time 0.06 (0.11) Loss 0.69 (0.64) Prec@1 66.67 (75.23) 89 | * Prec@1 75.18 Best_prec1 79.01 90 | Test accuracy: 75.177338 h: 0.484989 91 | 92 | ==================== The 1-th round ==================== 93 | Val-(28): [100/1000] Time 0.23 (0.12) Loss 0.46 (0.63) Prec@1 81.33 (75.18) 94 | Val-(28): [200/1000] Time 0.06 (0.11) Loss 1.15 (0.63) Prec@1 57.33 (75.66) 95 | Val-(28): [300/1000] Time 0.23 (0.11) Loss 0.65 (0.63) Prec@1 74.67 (75.69) 96 | Val-(28): [400/1000] Time 0.24 (0.11) Loss 0.56 (0.63) Prec@1 76.00 (75.73) 97 | Val-(28): [500/1000] Time 0.06 (0.11) Loss 0.48 (0.63) Prec@1 84.00 (75.73) 98 | Val-(28): [600/1000] Time 0.10 (0.11) Loss 0.98 (0.63) Prec@1 57.33 (75.85) 99 | Val-(28): [700/1000] Time 0.06 (0.11) Loss 0.53 (0.63) Prec@1 80.00 (75.68) 100 | Val-(28): [800/1000] Time 0.08 (0.11) Loss 0.58 (0.63) Prec@1 73.33 (75.81) 101 | Val-(28): [900/1000] Time 0.28 (0.11) Loss 0.40 (0.63) Prec@1 86.67 (75.94) 102 | * Prec@1 75.93 Best_prec1 79.01 103 | Test accuracy: 75.931999 h: 0.497722 104 | 105 | ==================== The 2-th round ==================== 106 | Val-(28): [100/1000] Time 0.06 (0.12) Loss 0.78 (0.63) Prec@1 64.00 (75.63) 107 | Val-(28): [200/1000] Time 0.06 (0.11) Loss 1.04 (0.62) Prec@1 58.67 (76.11) 108 | Val-(28): [300/1000] Time 0.06 (0.11) Loss 0.42 (0.62) Prec@1 84.00 (76.10) 109 | Val-(28): [400/1000] Time 0.06 (0.11) Loss 0.43 (0.62) Prec@1 89.33 (76.03) 110 | Val-(28): [500/1000] Time 0.06 (0.11) Loss 0.70 (0.63) Prec@1 76.00 (75.74) 111 | Val-(28): [600/1000] Time 0.06 (0.11) Loss 0.46 (0.63) Prec@1 80.00 (75.63) 112 | Val-(28): [700/1000] Time 0.06 (0.11) Loss 0.68 (0.63) Prec@1 73.33 (75.49) 113 | Val-(28): [800/1000] Time 0.06 (0.11) Loss 0.63 (0.63) Prec@1 80.00 (75.52) 114 | Val-(28): [900/1000] Time 0.06 (0.11) Loss 0.35 (0.63) Prec@1 89.33 (75.61) 115 | * Prec@1 75.61 Best_prec1 79.01 116 | Test accuracy: 75.614670 h: 0.494373 117 | 118 | ==================== The 3-th round ==================== 119 | Val-(28): [100/1000] Time 0.20 (0.12) Loss 0.81 (0.61) Prec@1 70.67 (77.37) 120 | Val-(28): [200/1000] Time 0.06 (0.12) Loss 0.55 (0.61) Prec@1 80.00 (77.21) 121 | Val-(28): [300/1000] Time 0.06 (0.11) Loss 0.51 (0.62) Prec@1 89.33 (76.69) 122 | Val-(28): [400/1000] Time 0.06 (0.11) Loss 0.82 (0.63) Prec@1 64.00 (76.38) 123 | Val-(28): [500/1000] Time 0.06 (0.11) Loss 0.83 (0.63) Prec@1 70.67 (76.36) 124 | Val-(28): [600/1000] Time 0.11 (0.11) Loss 0.60 (0.62) Prec@1 76.00 (76.27) 125 | Val-(28): [700/1000] Time 0.06 (0.11) Loss 0.41 (0.63) Prec@1 85.33 (76.00) 126 | Val-(28): [800/1000] Time 0.06 (0.11) Loss 0.89 (0.63) Prec@1 68.00 (76.05) 127 | Val-(28): [900/1000] Time 0.06 (0.11) Loss 0.50 (0.63) Prec@1 81.33 (75.89) 128 | * Prec@1 75.86 Best_prec1 79.01 129 | Test accuracy: 75.863998 h: 0.491147 130 | 131 | ==================== The 4-th round ==================== 132 | Val-(28): [100/1000] Time 0.21 (0.12) Loss 0.82 (0.63) Prec@1 62.67 (76.01) 133 | Val-(28): [200/1000] Time 0.06 (0.12) Loss 0.90 (0.65) Prec@1 69.33 (75.33) 134 | Val-(28): [300/1000] Time 0.06 (0.12) Loss 0.56 (0.64) Prec@1 80.00 (75.90) 135 | Val-(28): [400/1000] Time 0.06 (0.12) Loss 1.05 (0.63) Prec@1 69.33 (75.95) 136 | Val-(28): [500/1000] Time 0.06 (0.11) Loss 1.07 (0.63) Prec@1 60.00 (75.80) 137 | Val-(28): [600/1000] Time 0.06 (0.11) Loss 0.69 (0.63) Prec@1 80.00 (75.94) 138 | Val-(28): [700/1000] Time 0.06 (0.11) Loss 0.75 (0.63) Prec@1 65.33 (75.91) 139 | Val-(28): [800/1000] Time 0.06 (0.11) Loss 0.34 (0.63) Prec@1 85.33 (75.93) 140 | Val-(28): [900/1000] Time 0.24 (0.11) Loss 0.72 (0.63) Prec@1 73.33 (75.79) 141 | * Prec@1 75.73 Best_prec1 79.01 142 | Test accuracy: 75.732002 h: 0.479748 143 | 144 | Mean_accuracy: 75.664001 h: 0.489596 145 | ===================================== Test is END ===================================== 146 | 147 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/test_loss.txt: -------------------------------------------------------------------------------- 1 | 8.425347571074962572e-01 2 | 7.676017894446849343e-01 3 | 7.155224827527999487e-01 4 | 6.975680709481238972e-01 5 | 6.747762677669525422e-01 6 | 6.798861018270254686e-01 7 | 6.394134938269853130e-01 8 | 6.571893894076347165e-01 9 | 6.605198022127151125e-01 10 | 6.350636517703532880e-01 11 | 6.165688731074333573e-01 12 | 6.264167745858431058e-01 13 | 6.172348148077726471e-01 14 | 6.424799344837665016e-01 15 | 6.057428984493017365e-01 16 | 6.356335954070091443e-01 17 | 6.404178363978862976e-01 18 | 6.325181835740805170e-01 19 | 6.327834124863147558e-01 20 | 6.353237496763467496e-01 21 | 6.283777105212211556e-01 22 | 6.428970314860343871e-01 23 | 6.132191962748766434e-01 24 | 6.240370995253324837e-01 25 | 6.418749737814068990e-01 26 | 6.256901976466179294e-01 27 | 6.413167422860860389e-01 28 | 6.382769202739000391e-01 29 | 6.326134659498929835e-01 30 | 6.346755950599909379e-01 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/train_loss.txt: -------------------------------------------------------------------------------- 1 | 1.069172682148218145e+00 2 | 8.350652296170592015e-01 3 | 7.287498992070555737e-01 4 | 6.581147375971079239e-01 5 | 6.009942553445696278e-01 6 | 5.563013286013156478e-01 7 | 5.161444501563906551e-01 8 | 4.785886963196098742e-01 9 | 4.452948411948978724e-01 10 | 4.179902077697217333e-01 11 | 3.942830233976244991e-01 12 | 3.718382237531244749e-01 13 | 3.492388568334281462e-01 14 | 3.236543662257492793e-01 15 | 3.041007597845047927e-01 16 | 2.851266865017824115e-01 17 | 2.625101308761164653e-01 18 | 2.476264038450084748e-01 19 | 2.288478393948636946e-01 20 | 2.139564101365394877e-01 21 | 1.958350068296305924e-01 22 | 1.807401515219360655e-01 23 | 1.679967967917211369e-01 24 | 1.548463949769502412e-01 25 | 1.432186931292293575e-01 26 | 1.333264289785409396e-01 27 | 1.259894539327127971e-01 28 | 1.197119251540861989e-01 29 | 1.167707228128449098e-01 30 | 1.138622411621035974e-01 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.01_DN4_ResNet12_Epoch_30_miniImageNet_84_84_5Way_5Shot/val_loss.txt: -------------------------------------------------------------------------------- 1 | 8.759202211499214075e-01 2 | 8.044318869411944961e-01 3 | 7.252530652880668782e-01 4 | 6.950626986473799063e-01 5 | 6.620363071709871594e-01 6 | 6.551726454049349169e-01 7 | 6.436411685943603800e-01 8 | 6.343203865736722902e-01 9 | 5.940749592334032547e-01 10 | 6.189273901581764381e-01 11 | 6.109338519275188117e-01 12 | 5.949030190035701215e-01 13 | 5.794951391220092285e-01 14 | 5.854391817450523838e-01 15 | 6.124846868738531569e-01 16 | 6.087907980903982663e-01 17 | 5.970074675455689928e-01 18 | 5.879807460978627720e-01 19 | 5.804871315881610094e-01 20 | 5.789883091896772527e-01 21 | 5.938965923488139786e-01 22 | 5.820528274029492799e-01 23 | 5.751057557091117101e-01 24 | 5.993690277859569093e-01 25 | 5.804712954238057110e-01 26 | 5.830413467884063561e-01 27 | 5.741889033764601136e-01 28 | 5.786011957153678331e-01 29 | 5.678801862224936992e-01 30 | 5.741089160293341154e-01 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/Loss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/Loss.png -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/Test_results.txt: -------------------------------------------------------------------------------- 1 | ========================================== Start Test ========================================== 2 | 3 | => loading checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' 4 | => loaded checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' (epoch 29) 5 | Namespace(adam=False, aug_shot_num=20, beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, classifier_model='DN4', cosine=True, cuda=True, current_epoch=29, data_name='miniImageNet', dataset_dir='/data1/Liwenbin/Datasets/miniImageNet--ravi', encoder_model='Conv64F_Local', episodeSize=1, episode_test_num=1000, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.05, lr_decay_epochs=[60, 80], lr_decay_rate=0.1, mode='train', momentum=0.9, nc=3, neighbor_k=3, ngpu=1, outf='./results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot', print_freq=100, query_num=15, resume='', shot_num=1, start_epoch=0, test_aug=False, testepisodeSize=1, train_aug=True, way_num=5, weight_decay=0.0005, workers=4) 6 | Fewshot_model( 7 | (features): Conv64F_Local( 8 | (features): Sequential( 9 | (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 10 | (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 11 | (2): LeakyReLU(negative_slope=0.2, inplace=True) 12 | (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 13 | (4): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 14 | (5): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (6): LeakyReLU(negative_slope=0.2, inplace=True) 16 | (7): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 17 | (8): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 18 | (9): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 19 | (10): LeakyReLU(negative_slope=0.2, inplace=True) 20 | (11): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 21 | (12): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 22 | (13): LeakyReLU(negative_slope=0.2, inplace=True) 23 | ) 24 | ) 25 | (classifier): ImgtoClass_Metric() 26 | ) 27 | ==================== The 0-th round ==================== 28 | Val-(29): [100/1000] Time 0.02 (0.12) Loss 1.34 (1.11) Prec@1 45.33 (53.72) 29 | Val-(29): [200/1000] Time 0.03 (0.11) Loss 1.09 (1.14) Prec@1 62.67 (52.50) 30 | Val-(29): [300/1000] Time 0.03 (0.10) Loss 1.06 (1.16) Prec@1 57.33 (51.86) 31 | Val-(29): [400/1000] Time 0.22 (0.10) Loss 0.89 (1.16) Prec@1 68.00 (52.31) 32 | Val-(29): [500/1000] Time 0.08 (0.10) Loss 1.12 (1.16) Prec@1 60.00 (52.18) 33 | Val-(29): [600/1000] Time 0.06 (0.10) Loss 0.99 (1.16) Prec@1 62.67 (52.54) 34 | Val-(29): [700/1000] Time 0.02 (0.10) Loss 1.19 (1.16) Prec@1 44.00 (52.43) 35 | Val-(29): [800/1000] Time 0.02 (0.10) Loss 0.87 (1.16) Prec@1 62.67 (52.36) 36 | Val-(29): [900/1000] Time 0.25 (0.10) Loss 1.05 (1.16) Prec@1 48.00 (52.41) 37 | * Prec@1 52.21 Best_prec1 50.33 38 | Test accuracy: 52.206673 h: 0.621866 39 | 40 | ==================== The 1-th round ==================== 41 | Val-(29): [100/1000] Time 0.02 (0.11) Loss 1.42 (1.18) Prec@1 33.33 (53.02) 42 | Val-(29): [200/1000] Time 0.02 (0.10) Loss 0.88 (1.18) Prec@1 69.33 (52.31) 43 | Val-(29): [300/1000] Time 0.21 (0.10) Loss 1.19 (1.18) Prec@1 52.00 (52.14) 44 | Val-(29): [400/1000] Time 0.02 (0.10) Loss 1.18 (1.18) Prec@1 53.33 (51.84) 45 | Val-(29): [500/1000] Time 0.06 (0.10) Loss 1.22 (1.19) Prec@1 46.67 (51.67) 46 | Val-(29): [600/1000] Time 0.02 (0.10) Loss 1.09 (1.18) Prec@1 54.67 (51.82) 47 | Val-(29): [700/1000] Time 0.10 (0.10) Loss 1.42 (1.18) Prec@1 36.00 (51.87) 48 | Val-(29): [800/1000] Time 0.02 (0.10) Loss 1.31 (1.18) Prec@1 42.67 (51.94) 49 | Val-(29): [900/1000] Time 0.03 (0.10) Loss 1.14 (1.18) Prec@1 45.33 (51.97) 50 | * Prec@1 51.90 Best_prec1 50.33 51 | Test accuracy: 51.901333 h: 0.633740 52 | 53 | ==================== The 2-th round ==================== 54 | Val-(29): [100/1000] Time 0.22 (0.10) Loss 1.01 (1.15) Prec@1 56.00 (53.64) 55 | Val-(29): [200/1000] Time 0.02 (0.09) Loss 1.20 (1.18) Prec@1 45.33 (52.54) 56 | Val-(29): [300/1000] Time 0.02 (0.09) Loss 1.10 (1.18) Prec@1 56.00 (52.10) 57 | Val-(29): [400/1000] Time 0.02 (0.09) Loss 1.07 (1.18) Prec@1 60.00 (52.48) 58 | Val-(29): [500/1000] Time 0.02 (0.09) Loss 1.10 (1.18) Prec@1 54.67 (52.43) 59 | Val-(29): [600/1000] Time 0.02 (0.09) Loss 1.19 (1.18) Prec@1 54.67 (52.40) 60 | Val-(29): [700/1000] Time 0.02 (0.09) Loss 1.17 (1.17) Prec@1 53.33 (52.58) 61 | Val-(29): [800/1000] Time 0.20 (0.09) Loss 1.29 (1.18) Prec@1 49.33 (52.26) 62 | Val-(29): [900/1000] Time 0.25 (0.09) Loss 1.57 (1.18) Prec@1 37.33 (52.12) 63 | * Prec@1 52.08 Best_prec1 50.33 64 | Test accuracy: 52.081333 h: 0.622958 65 | 66 | ==================== The 3-th round ==================== 67 | Val-(29): [100/1000] Time 0.05 (0.10) Loss 1.72 (1.15) Prec@1 37.33 (53.80) 68 | Val-(29): [200/1000] Time 0.02 (0.10) Loss 0.76 (1.16) Prec@1 77.33 (53.14) 69 | Val-(29): [300/1000] Time 0.02 (0.09) Loss 1.19 (1.16) Prec@1 54.67 (52.66) 70 | Val-(29): [400/1000] Time 0.29 (0.09) Loss 1.05 (1.16) Prec@1 57.33 (52.61) 71 | Val-(29): [500/1000] Time 0.11 (0.09) Loss 0.90 (1.17) Prec@1 69.33 (52.30) 72 | Val-(29): [600/1000] Time 0.19 (0.09) Loss 1.14 (1.17) Prec@1 48.00 (52.35) 73 | Val-(29): [700/1000] Time 0.02 (0.09) Loss 1.12 (1.17) Prec@1 58.67 (52.33) 74 | Val-(29): [800/1000] Time 0.03 (0.09) Loss 1.12 (1.17) Prec@1 42.67 (52.32) 75 | Val-(29): [900/1000] Time 0.02 (0.09) Loss 1.06 (1.17) Prec@1 57.33 (52.21) 76 | * Prec@1 52.09 Best_prec1 50.33 77 | Test accuracy: 52.091999 h: 0.621697 78 | 79 | ==================== The 4-th round ==================== 80 | Val-(29): [100/1000] Time 0.02 (0.10) Loss 1.44 (1.21) Prec@1 34.67 (50.19) 81 | Val-(29): [200/1000] Time 0.02 (0.10) Loss 1.64 (1.20) Prec@1 36.00 (50.75) 82 | Val-(29): [300/1000] Time 0.21 (0.10) Loss 1.57 (1.18) Prec@1 22.67 (51.54) 83 | Val-(29): [400/1000] Time 0.14 (0.09) Loss 0.85 (1.18) Prec@1 76.00 (51.87) 84 | Val-(29): [500/1000] Time 0.36 (0.09) Loss 1.24 (1.17) Prec@1 53.33 (51.85) 85 | Val-(29): [600/1000] Time 0.02 (0.09) Loss 0.82 (1.18) Prec@1 72.00 (51.76) 86 | Val-(29): [700/1000] Time 0.02 (0.09) Loss 0.83 (1.18) Prec@1 68.00 (51.68) 87 | Val-(29): [800/1000] Time 0.30 (0.09) Loss 1.60 (1.19) Prec@1 26.67 (51.64) 88 | Val-(29): [900/1000] Time 0.18 (0.09) Loss 1.27 (1.18) Prec@1 40.00 (51.66) 89 | * Prec@1 51.61 Best_prec1 50.33 90 | Test accuracy: 51.610668 h: 0.607089 91 | 92 | Mean_accuracy: 51.978401 h: 0.621470 93 | ===================================== Test is END ===================================== 94 | 95 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/Test_results_New.txt: -------------------------------------------------------------------------------- 1 | ========================================== Start Test ========================================== 2 | 3 | => loading checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' 4 | => loaded checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' (epoch 29) 5 | Namespace(adam=False, aug_shot_num=20, beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, classifier_model='DN4', cosine=True, cuda=True, data_name='miniImageNet', dataset_dir='/data1/Liwenbin/Datasets/miniImageNet--ravi', encoder_model='Conv64F_Local', episodeSize=1, episode_test_num=1000, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.05, lr_decay_epochs=[60, 80], lr_decay_rate=0.1, mode='test', momentum=0.9, nc=3, neighbor_k=3, ngpu=1, outf='./results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/', print_freq=100, query_num=15, resume='./results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/', shot_num=1, start_epoch=0, test_aug=False, testepisodeSize=1, train_aug=True, way_num=5, weight_decay=0.0005, workers=4) 6 | ==================== The 0-th round ==================== 7 | ========================================== Start Test ========================================== 8 | 9 | => loading checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' 10 | => loaded checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar' (epoch 29) 11 | Namespace(adam=False, aug_shot_num=20, beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, classifier_model='DN4', cosine=True, cuda=True, data_name='miniImageNet', dataset_dir='/data1/Liwenbin/Datasets/miniImageNet--ravi', encoder_model='Conv64F_Local', episodeSize=1, episode_test_num=1000, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.05, lr_decay_epochs=[60, 80], lr_decay_rate=0.1, mode='test', momentum=0.9, nc=3, neighbor_k=3, ngpu=1, outf='./results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/', print_freq=100, query_num=15, resume='./results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/', shot_num=1, start_epoch=0, test_aug=False, testepisodeSize=1, train_aug=True, way_num=5, weight_decay=0.0005, workers=4) 12 | ==================== The 0-th round ==================== 13 | Test-(29): [100/1000] Time 0.244 (0.097) Loss 1.098 (1.179) Prec@1 60.000 (51.644) 14 | Test-(29): [200/1000] Time 0.024 (0.092) Loss 1.127 (1.175) Prec@1 53.333 (52.060) 15 | Test-(29): [300/1000] Time 0.024 (0.092) Loss 1.503 (1.178) Prec@1 34.667 (52.089) 16 | Test-(29): [400/1000] Time 0.026 (0.091) Loss 0.846 (1.180) Prec@1 72.000 (51.930) 17 | Test-(29): [500/1000] Time 0.026 (0.090) Loss 1.146 (1.182) Prec@1 52.000 (52.106) 18 | Test-(29): [600/1000] Time 0.292 (0.089) Loss 1.327 (1.183) Prec@1 42.667 (51.958) 19 | Test-(29): [700/1000] Time 0.023 (0.089) Loss 1.357 (1.185) Prec@1 48.000 (51.897) 20 | Test-(29): [800/1000] Time 0.023 (0.088) Loss 0.942 (1.185) Prec@1 58.667 (51.895) 21 | Test-(29): [900/1000] Time 0.027 (0.088) Loss 0.965 (1.183) Prec@1 62.667 (51.917) 22 | * Prec@1 51.981 Best_prec1 50.331 23 | Test accuracy: 51.981335 h: 0.623445 24 | 25 | ==================== The 1-th round ==================== 26 | Test-(29): [100/1000] Time 0.337 (0.091) Loss 1.486 (1.190) Prec@1 33.333 (50.746) 27 | Test-(29): [200/1000] Time 0.140 (0.089) Loss 1.199 (1.175) Prec@1 46.667 (51.708) 28 | Test-(29): [300/1000] Time 0.024 (0.087) Loss 1.035 (1.187) Prec@1 56.000 (51.384) 29 | Test-(29): [400/1000] Time 0.024 (0.089) Loss 1.222 (1.175) Prec@1 46.667 (51.920) 30 | Test-(29): [500/1000] Time 0.054 (0.088) Loss 1.057 (1.175) Prec@1 53.333 (51.880) 31 | Test-(29): [600/1000] Time 0.024 (0.088) Loss 1.111 (1.175) Prec@1 54.667 (51.783) 32 | Test-(29): [700/1000] Time 0.024 (0.089) Loss 1.389 (1.175) Prec@1 33.333 (51.804) 33 | Test-(29): [800/1000] Time 0.028 (0.090) Loss 1.017 (1.172) Prec@1 62.667 (51.983) 34 | Test-(29): [900/1000] Time 0.024 (0.090) Loss 1.332 (1.175) Prec@1 42.667 (51.809) 35 | * Prec@1 51.777 Best_prec1 50.331 36 | Test accuracy: 51.777332 h: 0.618619 37 | 38 | ==================== The 2-th round ==================== 39 | Test-(29): [100/1000] Time 0.026 (0.095) Loss 1.546 (1.148) Prec@1 33.333 (53.861) 40 | Test-(29): [200/1000] Time 0.024 (0.091) Loss 0.740 (1.162) Prec@1 74.667 (52.909) 41 | Test-(29): [300/1000] Time 0.227 (0.090) Loss 1.211 (1.171) Prec@1 53.333 (52.558) 42 | Test-(29): [400/1000] Time 0.088 (0.090) Loss 1.384 (1.173) Prec@1 36.000 (52.156) 43 | Test-(29): [500/1000] Time 0.030 (0.089) Loss 0.973 (1.175) Prec@1 57.333 (51.933) 44 | Test-(29): [600/1000] Time 0.024 (0.089) Loss 1.199 (1.171) Prec@1 46.667 (52.204) 45 | Test-(29): [700/1000] Time 0.169 (0.088) Loss 1.340 (1.174) Prec@1 38.667 (52.065) 46 | Test-(29): [800/1000] Time 0.065 (0.088) Loss 1.505 (1.175) Prec@1 37.333 (51.955) 47 | Test-(29): [900/1000] Time 0.024 (0.088) Loss 1.106 (1.176) Prec@1 61.333 (51.907) 48 | * Prec@1 51.929 Best_prec1 50.331 49 | Test accuracy: 51.929337 h: 0.627479 50 | 51 | ==================== The 3-th round ==================== 52 | Test-(29): [100/1000] Time 0.024 (0.096) Loss 1.036 (1.210) Prec@1 57.333 (50.389) 53 | Test-(29): [200/1000] Time 0.024 (0.095) Loss 1.280 (1.203) Prec@1 46.667 (50.348) 54 | Test-(29): [300/1000] Time 0.024 (0.093) Loss 1.511 (1.188) Prec@1 38.667 (51.375) 55 | Test-(29): [400/1000] Time 0.024 (0.091) Loss 0.993 (1.195) Prec@1 62.667 (50.983) 56 | Test-(29): [500/1000] Time 0.024 (0.090) Loss 1.449 (1.196) Prec@1 33.333 (50.986) 57 | Test-(29): [600/1000] Time 0.025 (0.090) Loss 1.508 (1.193) Prec@1 46.667 (51.115) 58 | Test-(29): [700/1000] Time 0.024 (0.090) Loss 1.150 (1.190) Prec@1 57.333 (51.249) 59 | Test-(29): [800/1000] Time 0.024 (0.090) Loss 1.544 (1.190) Prec@1 40.000 (51.244) 60 | Test-(29): [900/1000] Time 0.023 (0.090) Loss 1.315 (1.186) Prec@1 49.333 (51.399) 61 | * Prec@1 51.361 Best_prec1 50.331 62 | Test accuracy: 51.361336 h: 0.646845 63 | 64 | ==================== The 4-th round ==================== 65 | Test-(29): [100/1000] Time 0.358 (0.100) Loss 1.408 (1.200) Prec@1 46.667 (51.366) 66 | Test-(29): [200/1000] Time 0.241 (0.096) Loss 1.475 (1.200) Prec@1 37.333 (51.104) 67 | Test-(29): [300/1000] Time 0.024 (0.095) Loss 0.959 (1.199) Prec@1 62.667 (51.101) 68 | Test-(29): [400/1000] Time 0.036 (0.093) Loss 0.947 (1.195) Prec@1 60.000 (51.096) 69 | Test-(29): [500/1000] Time 0.149 (0.093) Loss 1.124 (1.186) Prec@1 61.333 (51.494) 70 | Test-(29): [600/1000] Time 0.289 (0.092) Loss 0.671 (1.183) Prec@1 73.333 (51.527) 71 | Test-(29): [700/1000] Time 0.023 (0.091) Loss 1.445 (1.182) Prec@1 38.667 (51.576) 72 | Test-(29): [800/1000] Time 0.216 (0.092) Loss 1.014 (1.184) Prec@1 56.000 (51.531) 73 | Test-(29): [900/1000] Time 0.156 (0.092) Loss 1.263 (1.184) Prec@1 52.000 (51.596) 74 | * Prec@1 51.655 Best_prec1 50.331 75 | Test accuracy: 51.654667 h: 0.620802 76 | 77 | Mean_accuracy: 51.740801 h: 0.627438 78 | ===================================== Test is END ===================================== 79 | 80 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/model_best.pth.tar -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/test_loss.txt: -------------------------------------------------------------------------------- 1 | 1.588965280413627612e+00 2 | 1.580805958509445164e+00 3 | 1.553094785094261132e+00 4 | 1.513077440857887312e+00 5 | 1.484222897410392816e+00 6 | 1.442642955780029324e+00 7 | 1.422873528480529837e+00 8 | 1.422249255418777558e+00 9 | 1.337551431953907022e+00 10 | 1.319544102966785371e+00 11 | 1.330531956791877857e+00 12 | 1.313925987958908026e+00 13 | 1.324365826487541309e+00 14 | 1.304923660099506444e+00 15 | 1.288792364060878715e+00 16 | 1.278352851450443195e+00 17 | 1.310629327356815255e+00 18 | 1.292831373512744797e+00 19 | 1.260266643941402531e+00 20 | 1.291257175683975245e+00 21 | 1.252241140484809945e+00 22 | 1.232725776433944764e+00 23 | 1.259019998848438293e+00 24 | 1.212792974293231962e+00 25 | 1.217878570377826764e+00 26 | 1.233708600878715478e+00 27 | 1.197975303232669875e+00 28 | 1.217177280008792772e+00 29 | 1.183406202018260966e+00 30 | 1.175420023381710033e+00 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/train_loss.txt: -------------------------------------------------------------------------------- 1 | 1.761601435124874104e+00 2 | 1.562190455317497229e+00 3 | 1.549602791261672996e+00 4 | 1.530674070775508877e+00 5 | 1.498226171290874431e+00 6 | 1.475548240065574612e+00 7 | 1.454539830613136298e+00 8 | 1.432932049363851545e+00 9 | 1.418241293960809779e+00 10 | 1.400847774267196755e+00 11 | 1.390578488349914599e+00 12 | 1.379888338118791635e+00 13 | 1.367536048835515938e+00 14 | 1.360217748552560835e+00 15 | 1.349348247718811011e+00 16 | 1.337980837726592931e+00 17 | 1.329394348561763861e+00 18 | 1.316805605852603867e+00 19 | 1.302767693603038790e+00 20 | 1.295108445727825242e+00 21 | 1.279733602273464221e+00 22 | 1.273384560090303319e+00 23 | 1.256879824048280803e+00 24 | 1.242287492871284593e+00 25 | 1.230280000776052374e+00 26 | 1.218111183929443397e+00 27 | 1.200011553645133899e+00 28 | 1.192383873623609647e+00 29 | 1.175867653366923227e+00 30 | 1.168693618550896707e+00 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_1Shot/val_loss.txt: -------------------------------------------------------------------------------- 1 | 1.575199795722961316e+00 2 | 1.569603443980216895e+00 3 | 1.561417399406433093e+00 4 | 1.534682530045509363e+00 5 | 1.505603410720825153e+00 6 | 1.491549753427505509e+00 7 | 1.456938738226890573e+00 8 | 1.433602441072463929e+00 9 | 1.405755109906196676e+00 10 | 1.375410828590392986e+00 11 | 1.398355887174606238e+00 12 | 1.378046454668045095e+00 13 | 1.365522751629352660e+00 14 | 1.353747321248054414e+00 15 | 1.372285865902900692e+00 16 | 1.337879590153694176e+00 17 | 1.341320399284362752e+00 18 | 1.344282808244228411e+00 19 | 1.327187149405479438e+00 20 | 1.343007812678813861e+00 21 | 1.320870438754558673e+00 22 | 1.330829265534877681e+00 23 | 1.306217297494411511e+00 24 | 1.282890752315521299e+00 25 | 1.274596982717514093e+00 26 | 1.257495359361171738e+00 27 | 1.256209821581840469e+00 28 | 1.244305944681167508e+00 29 | 1.224589444100856683e+00 30 | 1.212966168940067258e+00 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/Loss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/Loss.png -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/Test_results.txt: -------------------------------------------------------------------------------- 1 | ========================================== Start Test ========================================== 2 | 3 | => loading checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/model_best.pth.tar' 4 | => loaded checkpoint './results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/model_best.pth.tar' (epoch 29) 5 | Namespace(adam=False, aug_shot_num=20, beta1=0.5, clamp_lower=-0.01, clamp_upper=0.01, classifier_model='DN4', cosine=True, cuda=True, current_epoch=29, data_name='miniImageNet', dataset_dir='/data1/Liwenbin/Datasets/miniImageNet--ravi', encoder_model='Conv64F_Local', episodeSize=1, episode_test_num=1000, episode_train_num=10000, episode_val_num=1000, epochs=30, imageSize=84, lr=0.05, lr_decay_epochs=[60, 80], lr_decay_rate=0.1, mode='train', momentum=0.9, nc=3, neighbor_k=3, ngpu=1, outf='./results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot', print_freq=100, query_num=15, resume='', shot_num=5, start_epoch=0, test_aug=False, testepisodeSize=1, train_aug=True, way_num=5, weight_decay=0.0005, workers=4) 6 | Fewshot_model( 7 | (features): Conv64F_Local( 8 | (features): Sequential( 9 | (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 10 | (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 11 | (2): LeakyReLU(negative_slope=0.2, inplace=True) 12 | (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 13 | (4): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 14 | (5): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 15 | (6): LeakyReLU(negative_slope=0.2, inplace=True) 16 | (7): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 17 | (8): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 18 | (9): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 19 | (10): LeakyReLU(negative_slope=0.2, inplace=True) 20 | (11): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) 21 | (12): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) 22 | (13): LeakyReLU(negative_slope=0.2, inplace=True) 23 | ) 24 | ) 25 | (classifier): ImgtoClass_Metric() 26 | ) 27 | ==================== The 0-th round ==================== 28 | Val-(29): [100/1000] Time 0.07 (0.16) Loss 0.32 (0.74) Prec@1 88.00 (72.30) 29 | Val-(29): [200/1000] Time 0.26 (0.16) Loss 0.51 (0.71) Prec@1 82.67 (73.39) 30 | Val-(29): [300/1000] Time 0.07 (0.15) Loss 0.50 (0.70) Prec@1 82.67 (73.47) 31 | Val-(29): [400/1000] Time 0.06 (0.14) Loss 0.41 (0.70) Prec@1 78.67 (73.39) 32 | Val-(29): [500/1000] Time 0.06 (0.13) Loss 0.76 (0.70) Prec@1 73.33 (73.26) 33 | Val-(29): [600/1000] Time 0.06 (0.13) Loss 0.60 (0.70) Prec@1 81.33 (73.26) 34 | Val-(29): [700/1000] Time 0.06 (0.13) Loss 0.42 (0.71) Prec@1 88.00 (73.12) 35 | Val-(29): [800/1000] Time 0.21 (0.12) Loss 0.60 (0.71) Prec@1 77.33 (73.05) 36 | Val-(29): [900/1000] Time 0.20 (0.12) Loss 0.48 (0.71) Prec@1 80.00 (73.06) 37 | * Prec@1 73.09 Best_prec1 71.56 38 | Test accuracy: 73.085335 h: 0.482404 39 | 40 | ==================== The 1-th round ==================== 41 | Val-(29): [100/1000] Time 0.41 (0.12) Loss 1.07 (0.71) Prec@1 60.00 (73.44) 42 | Val-(29): [200/1000] Time 0.19 (0.11) Loss 0.95 (0.72) Prec@1 72.00 (72.96) 43 | Val-(29): [300/1000] Time 0.07 (0.11) Loss 0.81 (0.71) Prec@1 69.33 (73.29) 44 | Val-(29): [400/1000] Time 0.06 (0.11) Loss 0.90 (0.71) Prec@1 64.00 (73.24) 45 | Val-(29): [500/1000] Time 0.06 (0.11) Loss 0.63 (0.71) Prec@1 77.33 (73.21) 46 | Val-(29): [600/1000] Time 0.06 (0.11) Loss 0.74 (0.71) Prec@1 68.00 (73.17) 47 | Val-(29): [700/1000] Time 0.06 (0.11) Loss 0.87 (0.71) Prec@1 62.67 (73.11) 48 | Val-(29): [800/1000] Time 0.07 (0.11) Loss 0.47 (0.70) Prec@1 80.00 (73.24) 49 | Val-(29): [900/1000] Time 0.07 (0.11) Loss 0.65 (0.71) Prec@1 81.33 (73.19) 50 | * Prec@1 73.31 Best_prec1 71.56 51 | Test accuracy: 73.306664 h: 0.481580 52 | 53 | ==================== The 2-th round ==================== 54 | Val-(29): [100/1000] Time 0.07 (0.12) Loss 0.75 (0.71) Prec@1 76.00 (72.54) 55 | Val-(29): [200/1000] Time 0.07 (0.12) Loss 1.17 (0.70) Prec@1 53.33 (72.80) 56 | Val-(29): [300/1000] Time 0.20 (0.11) Loss 0.56 (0.70) Prec@1 81.33 (73.16) 57 | Val-(29): [400/1000] Time 0.06 (0.11) Loss 0.96 (0.70) Prec@1 52.00 (73.07) 58 | Val-(29): [500/1000] Time 0.06 (0.11) Loss 0.58 (0.70) Prec@1 76.00 (73.13) 59 | Val-(29): [600/1000] Time 0.07 (0.11) Loss 0.39 (0.70) Prec@1 85.33 (73.05) 60 | Val-(29): [700/1000] Time 0.06 (0.11) Loss 0.64 (0.70) Prec@1 74.67 (73.24) 61 | Val-(29): [800/1000] Time 0.07 (0.11) Loss 0.88 (0.70) Prec@1 62.67 (73.23) 62 | Val-(29): [900/1000] Time 0.06 (0.11) Loss 0.64 (0.70) Prec@1 76.00 (73.17) 63 | * Prec@1 72.99 Best_prec1 71.56 64 | Test accuracy: 72.990669 h: 0.497712 65 | 66 | ==================== The 3-th round ==================== 67 | Val-(29): [100/1000] Time 0.06 (0.16) Loss 0.90 (0.69) Prec@1 61.33 (73.58) 68 | Val-(29): [200/1000] Time 0.24 (0.16) Loss 0.58 (0.69) Prec@1 77.33 (74.02) 69 | Val-(29): [300/1000] Time 0.06 (0.16) Loss 0.57 (0.69) Prec@1 80.00 (73.67) 70 | Val-(29): [400/1000] Time 0.07 (0.15) Loss 0.72 (0.70) Prec@1 72.00 (73.12) 71 | Val-(29): [500/1000] Time 0.07 (0.14) Loss 0.40 (0.70) Prec@1 82.67 (73.27) 72 | Val-(29): [600/1000] Time 0.23 (0.14) Loss 0.68 (0.70) Prec@1 78.67 (73.28) 73 | Val-(29): [700/1000] Time 0.15 (0.15) Loss 1.27 (0.70) Prec@1 52.00 (73.45) 74 | Val-(29): [800/1000] Time 0.22 (0.14) Loss 0.60 (0.70) Prec@1 77.33 (73.51) 75 | Val-(29): [900/1000] Time 0.22 (0.14) Loss 0.69 (0.70) Prec@1 76.00 (73.45) 76 | * Prec@1 73.48 Best_prec1 71.56 77 | Test accuracy: 73.482674 h: 0.479026 78 | 79 | ==================== The 4-th round ==================== 80 | Val-(29): [100/1000] Time 0.06 (0.12) Loss 0.96 (0.70) Prec@1 65.33 (72.95) 81 | Val-(29): [200/1000] Time 0.07 (0.11) Loss 0.51 (0.70) Prec@1 85.33 (73.09) 82 | Val-(29): [300/1000] Time 0.07 (0.11) Loss 0.83 (0.70) Prec@1 64.00 (73.29) 83 | Val-(29): [400/1000] Time 0.19 (0.11) Loss 0.68 (0.70) Prec@1 73.33 (73.18) 84 | Val-(29): [500/1000] Time 0.06 (0.11) Loss 0.52 (0.71) Prec@1 82.67 (73.05) 85 | Val-(29): [600/1000] Time 0.17 (0.11) Loss 0.78 (0.70) Prec@1 73.33 (73.16) 86 | Val-(29): [700/1000] Time 0.25 (0.11) Loss 0.58 (0.70) Prec@1 76.00 (73.31) 87 | Val-(29): [800/1000] Time 0.08 (0.11) Loss 0.55 (0.70) Prec@1 81.33 (73.22) 88 | Val-(29): [900/1000] Time 0.10 (0.11) Loss 0.46 (0.71) Prec@1 81.33 (73.13) 89 | * Prec@1 73.13 Best_prec1 71.56 90 | Test accuracy: 73.125336 h: 0.501544 91 | 92 | Mean_accuracy: 73.198135 h: 0.488453 93 | ===================================== Test is END ===================================== 94 | 95 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/model_best.pth.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinLee/DN4/440857b23a5bc9798004f81f732c5cc9272a99b8/results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/model_best.pth.tar -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/test_loss.txt: -------------------------------------------------------------------------------- 1 | 1.345906615495681802e+00 2 | 1.103285467445850321e+00 3 | 1.060474659025669064e+00 4 | 9.981950015425682388e-01 5 | 9.811021184921264737e-01 6 | 9.786735889315605341e-01 7 | 9.327543408870696551e-01 8 | 8.975806340277194817e-01 9 | 8.827502713799476597e-01 10 | 9.025217817425728040e-01 11 | 8.698854534029960561e-01 12 | 8.654945094585418941e-01 13 | 8.590273474156856492e-01 14 | 8.348823354840279043e-01 15 | 8.583094394803046923e-01 16 | 8.240921595692634050e-01 17 | 8.346195108592510126e-01 18 | 8.080945486724376847e-01 19 | 8.381706591546534968e-01 20 | 8.250573616027832013e-01 21 | 7.829902250170707179e-01 22 | 7.623370675742626723e-01 23 | 7.903140447139740399e-01 24 | 7.611604312360287228e-01 25 | 7.565869103670119777e-01 26 | 7.281737144589424116e-01 27 | 7.320693117082118784e-01 28 | 7.268759717345237847e-01 29 | 7.113414543271064927e-01 30 | 7.156810471117496242e-01 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/train_loss.txt: -------------------------------------------------------------------------------- 1 | 1.496538908123969946e+00 2 | 1.257998045879602511e+00 3 | 1.146439006930589644e+00 4 | 1.095848687407374289e+00 5 | 1.059380434823036232e+00 6 | 1.029195302659273059e+00 7 | 1.004549385365843817e+00 8 | 9.767368407040833977e-01 9 | 9.582664603412150983e-01 10 | 9.425074189394712088e-01 11 | 9.286693536251783287e-01 12 | 9.149164662480354648e-01 13 | 9.021934506341815485e-01 14 | 8.881664996087551556e-01 15 | 8.808592478379607682e-01 16 | 8.674960011214017941e-01 17 | 8.568784933090209943e-01 18 | 8.401622610181570527e-01 19 | 8.321849884554743948e-01 20 | 8.175077314525842631e-01 21 | 8.011071323052049165e-01 22 | 7.911748012885451153e-01 23 | 7.759259826585650499e-01 24 | 7.611166337728499931e-01 25 | 7.434809941619634488e-01 26 | 7.278668548434972241e-01 27 | 7.116137386247515240e-01 28 | 6.960380281150341242e-01 29 | 6.869022204510867313e-01 30 | 6.795899570740759899e-01 31 | -------------------------------------------------------------------------------- /results/SGD_Cosine_Lr0.05_DN4_Conv64F_Local_Epoch_30_miniImageNet_84_84_5Way_5Shot/val_loss.txt: -------------------------------------------------------------------------------- 1 | 1.386973905324935918e+00 2 | 1.162551319837570096e+00 3 | 1.106109781026840100e+00 4 | 1.060794358670711590e+00 5 | 1.056823077559471136e+00 6 | 1.032484755963086975e+00 7 | 9.956440748572349397e-01 8 | 9.643782387077808327e-01 9 | 9.402065452635288700e-01 10 | 9.695851418972015745e-01 11 | 9.229096755981445188e-01 12 | 9.295306026339530403e-01 13 | 9.344420723021030772e-01 14 | 8.799210217893123076e-01 15 | 9.087069990336894554e-01 16 | 8.725697695910931140e-01 17 | 8.700383878946303939e-01 18 | 8.599405329823494037e-01 19 | 8.809840641617775470e-01 20 | 8.594751699566841596e-01 21 | 8.228730600774287751e-01 22 | 8.301036271154880186e-01 23 | 8.254547930657863963e-01 24 | 8.042804000973701184e-01 25 | 8.040184194743633661e-01 26 | 7.724396421313285410e-01 27 | 7.655473987609148212e-01 28 | 7.647515845596790651e-01 29 | 7.482675210982561165e-01 30 | 7.426448170393705750e-01 31 | -------------------------------------------------------------------------------- /results/test: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import os 3 | import pdb 4 | import scipy as sp 5 | import scipy.stats 6 | import numpy as np 7 | import matplotlib 8 | import matplotlib.pyplot as plt 9 | 10 | 11 | 12 | def adjust_learning_rate(opt, optimizer, epoch, F_txt): 13 | """Sets the learning rate to the initial LR decayed by 2 every 10 epoches""" 14 | if opt.classifier_model == 'Baseline': 15 | lr = opt.lr * (0.5 ** (epoch // 30)) 16 | else: 17 | lr = opt.lr * (0.1 ** (epoch // 10)) 18 | print('Learning rate: %f' %lr) 19 | print('Learning rate: %f' %lr, file=F_txt) 20 | for param_group in optimizer.param_groups: 21 | param_group['lr'] = lr 22 | 23 | 24 | def adjust_learning_rate2(opt, optimizer, epoch, F_txt): 25 | """Sets the learning rate to the initial LR decayed by decay rate every steep step""" 26 | steps = np.sum(epoch > np.asarray(opt.lr_decay_epochs)) 27 | if steps > 0: 28 | new_lr = opt.lr * (opt.lr_decay_rate ** steps) 29 | print('Learning rate: %f' %new_lr) 30 | print('Learning rate: %f' %new_lr, file=F_txt) 31 | for param_group in optimizer.param_groups: 32 | param_group['lr'] = new_lr 33 | 34 | 35 | def count_parameters(model): 36 | """Count the total number of parameters in one model""" 37 | return sum(p.numel() for p in model.parameters() if p.requires_grad) 38 | 39 | 40 | def save_checkpoint(state, filename='checkpoint.pth.tar'): 41 | torch.save(state, filename) 42 | 43 | 44 | class AverageMeter(object): 45 | """Computes and stores the average and current value""" 46 | def __init__(self): 47 | self.reset() 48 | 49 | def reset(self): 50 | self.val = 0 51 | self.avg = 0 52 | self.sum = 0 53 | self.count = 0 54 | 55 | def update(self, val, n=1): 56 | self.val = val 57 | self.sum += val * n 58 | self.count += n 59 | self.avg = self.sum / self.count 60 | 61 | 62 | def accuracy(output, target, topk=(1,)): 63 | """Computes the precision@k for the specified values of k""" 64 | with torch.no_grad(): 65 | maxk = max(topk) 66 | batch_size = target.size(0) 67 | 68 | _, pred = output.topk(maxk, 1, True, True) 69 | pred = pred.t() 70 | correct = pred.eq(target.view(1, -1).expand_as(pred)) 71 | 72 | res = [] 73 | for k in topk: 74 | correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True) 75 | res.append(correct_k.mul_(100.0 / batch_size)) 76 | return res 77 | 78 | 79 | def mean_confidence_interval(data, confidence=0.95): 80 | a = [1.0*np.array(data[i].cpu()) for i in range(len(data))] 81 | n = len(a) 82 | m, se = np.mean(a), scipy.stats.sem(a) 83 | h = se * sp.stats.t._ppf((1+confidence)/2., n-1) 84 | return m,h 85 | 86 | 87 | 88 | def set_save_path(opt): 89 | ''' 90 | Settings of the save path 91 | ''' 92 | opt.outf = opt.outf + opt.classifier_model + '_' + opt.encoder_model + '_' + 'Epoch_' + str(opt.epochs) + '_' +\ 93 | opt.data_name + '_' + str(opt.imageSize) + '_' + str(opt.imageSize) + '_' + str(opt.way_num)+'Way_'+str(opt.shot_num)+'Shot' 94 | 95 | if not os.path.exists(opt.outf): 96 | os.makedirs(opt.outf) 97 | 98 | if torch.cuda.is_available() and not opt.cuda: 99 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 100 | 101 | # save the opt and results to txt file 102 | txt_save_path = os.path.join(opt.outf, 'opt_results.txt') 103 | F_txt = open(txt_save_path, 'a+') 104 | 105 | return opt.outf, F_txt 106 | 107 | 108 | 109 | 110 | def set_save_test_path(opt, finetune=False): 111 | ''' 112 | Settings of the save path 113 | ''' 114 | 115 | if not os.path.exists(opt.outf): 116 | os.makedirs(opt.outf) 117 | 118 | if torch.cuda.is_available() and not opt.cuda: 119 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 120 | 121 | # save the opt and results to txt file 122 | if finetune: 123 | txt_save_path = os.path.join(opt.outf, 'Test_Finetune_results.txt') 124 | else: 125 | txt_save_path = os.path.join(opt.outf, 'Test_results.txt') 126 | F_txt_test = open(txt_save_path, 'a+') 127 | 128 | return F_txt_test 129 | 130 | 131 | 132 | def set_save_test_path2(opt, finetune=False): 133 | ''' 134 | Settings of the save path 135 | ''' 136 | 137 | if not str(opt.resume).endswith('/'): 138 | opt.outf = opt.resume + '/' 139 | else: 140 | opt.outf = opt.resume 141 | 142 | if not os.path.exists(opt.outf): 143 | os.makedirs(opt.outf) 144 | 145 | if torch.cuda.is_available() and not opt.cuda: 146 | print("WARNING: You have a CUDA device, so you should probably run with --cuda") 147 | 148 | # save the opt and results to txt file 149 | if finetune: 150 | txt_save_path = os.path.join(opt.outf, 'Test_Finetune_results_New.txt') 151 | else: 152 | txt_save_path = os.path.join(opt.outf, 'Test_results_New.txt') 153 | F_txt_test = open(txt_save_path, 'a+') 154 | 155 | return opt.outf, F_txt_test 156 | 157 | 158 | 159 | def get_resume_file(checkpoint_dir, F_txt): 160 | 161 | if os.path.isfile(checkpoint_dir): 162 | print("=> loading checkpoint '{}'".format(checkpoint_dir)) 163 | print("=> loading checkpoint '{}'".format(checkpoint_dir), file=F_txt) 164 | checkpoint = torch.load(checkpoint_dir) 165 | print("=> loaded checkpoint '{}' (epoch {})".format(checkpoint_dir, checkpoint['epoch_index'])) 166 | print("=> loaded checkpoint '{}' (epoch {})".format(checkpoint_dir, checkpoint['epoch_index']), file=F_txt) 167 | 168 | return checkpoint 169 | else: 170 | print("=> no checkpoint found at '{}'".format(checkpoint_dir)) 171 | print("=> no checkpoint found at '{}'".format(checkpoint_dir), file=F_txt) 172 | 173 | return None 174 | 175 | 176 | def plot_loss_curve(opt, train_loss, val_loss, test_loss=None): 177 | 178 | if test_loss: 179 | train_loss = np.array(train_loss) 180 | val_loss = np.array(val_loss) 181 | test_loss = np.array(test_loss) 182 | 183 | 184 | # Save lossed to txt 185 | np.savetxt(os.path.join(opt.outf, 'train_loss.txt'), train_loss) 186 | np.savetxt(os.path.join(opt.outf, 'val_loss.txt'), val_loss) 187 | np.savetxt(os.path.join(opt.outf, 'test_loss.txt'), test_loss) 188 | 189 | # Plot the loss curves 190 | fig, ax = plt.subplots() 191 | ax.plot(range(0, opt.epochs), train_loss, label='Train loss') 192 | ax.plot(range(0, opt.epochs), val_loss, label='Val loss') 193 | ax.plot(range(0, opt.epochs), test_loss, label='Test loss') 194 | legend = ax.legend(loc='upper right', fontsize='medium') 195 | plt.savefig(os.path.join(opt.outf, 'Loss.png'), bbox_inches='tight') 196 | # plt.show() 197 | else: 198 | train_loss = np.array(train_loss) 199 | val_loss = np.array(val_loss) 200 | 201 | 202 | # Save lossed to txt 203 | np.savetxt(os.path.join(opt.outf, 'train_loss.txt'), train_loss) 204 | np.savetxt(os.path.join(opt.outf, 'val_loss.txt'), val_loss) 205 | 206 | 207 | # Plot the loss curves 208 | fig, ax = plt.subplots() 209 | ax.plot(range(0, opt.epochs), train_loss, label='Train loss') 210 | ax.plot(range(0, opt.epochs), val_loss, label='Val loss') 211 | legend = ax.legend(loc='upper right', fontsize='medium') 212 | plt.savefig(os.path.join(opt.outf, 'Loss.png'), bbox_inches='tight') 213 | # plt.show() 214 | 215 | 216 | 217 | 218 | 219 | 220 | --------------------------------------------------------------------------------