前言
前面五篇文章,介紹了模型搭建、資料準備及pytorch中常用的計算方法等,有了上述基礎後就可以訓練和測試模型了,下面這篇文章會簡單介紹下在pytorch架構下如何測試深度學習模型,以及一些常用代碼。
模型測試
同樣,以一個簡單的分類模型為例,對應的測試代碼:
# 模型測試model.eval() with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: images = images.to(device) labels = labels.to(device) outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('在10000張測試照片上測試模型的精度: {} %' .format(100 * correct / total))
Mixup訓練
beta_distribution = torch.distributions.beta.Beta(alpha, alpha)for images, labels in train_loader: images, labels = images.cuda(), labels.cuda() # 混合照片和标簽。 lambda_ = beta_distribution.sample([]).item() index = torch.randperm(images.size(0)).cuda() mixed_images = lambda_ * images + (1 - lambda_) * images[index, :] label_a, label_b = labels, labels[index] # 混合損失。 scores = model(mixed_images) loss = (lambda_ * loss_function(scores, label_a) + (1 - lambda_) * loss_function(scores, label_b)) optimizer.zero_grad() loss.backward() optimizer.step()
儲存與加載斷點
訓練過程中,可能會出現訓練意外中斷的情況。為了能夠恢複訓練,需要同時儲存模型和優化器的狀态,以及目前的訓練輪數。
start_epoch = 0# 加載checkpoint.if resume: # resume為參數,第一次訓練時設為0,中斷再訓練時設為1 model_path = os.path.join('model', 'best_checkpoint.pth.tar') assert os.path.isfile(model_path) checkpoint = torch.load(model_path) best_acc = checkpoint['best_acc'] start_epoch = checkpoint['epoch'] model.load_state_dict(checkpoint['model']) optimizer.load_state_dict(checkpoint['optimizer']) print('Load checkpoint at epoch {}.'.format(start_epoch)) print('Best accuracy so far {}.'.format(best_acc))# 訓練模型for epoch in range(start_epoch, num_epochs): ... # 測試模型 ... # 儲存checkpoint is_best = current_acc > best_acc best_acc = max(current_acc, best_acc) checkpoint = { 'best_acc': best_acc, 'epoch': epoch + 1, 'model': model.state_dict(), 'optimizer': optimizer.state_dict(), } model_path = os.path.join('model', 'checkpoint.pth.tar') best_model_path = os.path.join('model', 'best_checkpoint.pth.tar') torch.save(checkpoint, model_path) if is_best: shutil.copy(model_path, best_model_path)
提取預訓練模型某層的卷積特征
很多模型,往往不會從頭開始訓練,這樣會浪費大量的時間,是以常用的做法是加載其他預訓練的模型。以ImageNet預訓練模型為例,提取其中某一層的卷積特征:
# VGG-16 relu5-3 feature.model = torchvision.models.vgg16(pretrained=True).features[:-1]# VGG-16 pool5 feature.model = torchvision.models.vgg16(pretrained=True).features# VGG-16 fc7 feature.model = torchvision.models.vgg16(pretrained=True)model.classifier = torch.nn.Sequential(*list(model.classifier.children())[:-3])# ResNet GAP feature.model = torchvision.models.resnet18(pretrained=True)model = torch.nn.Sequential(collections.OrderedDict( list(model.named_children())[:-1]))with torch.no_grad(): model.eval() conv_representation = model(image)
同理,也可以提取ImageNet 預訓練模型中多層的卷積特征:
class FeatureExtractor(torch.nn.Module): """Helper class to extract several convolution features from the given pre-trained model. Attributes: _model, torch.nn.Module. _layers_to_extract, list or set Example: >>> model = torchvision.models.resnet152(pretrained=True) >>> model = torch.nn.Sequential(collections.OrderedDict( list(model.named_children())[:-1])) >>> conv_representation = FeatureExtractor( pretrained_model=model, layers_to_extract={'layer1', 'layer2', 'layer3', 'layer4'})(image) """ def __init__(self, pretrained_model, layers_to_extract): torch.nn.Module.__init__(self) self._model = pretrained_model self._model.eval() self._layers_to_extract = set(layers_to_extract) def forward(self, x): with torch.no_grad(): conv_representation = [] for name, layer in self._model.named_children(): x = layer(x) if name in self._layers_to_extract: conv_representation.append(x) return conv_representation
未完待續...