文章目录
pip install python-box timm pytorch-lightning==1.4.0 grad-cam ttach
import os
import warnings
from pprint import pprint
from glob import glob
from tqdm import tqdm
import torch
import torch.optim as optim
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torchvision.transforms as T
from box import Box
from timm import create_model
from sklearn.model_selection import StratifiedKFold
from torchvision.io import read_image
from torch.utils.data import DataLoader, Dataset
from pytorch_grad_cam import GradCAMPlusPlus
from pytorch_grad_cam.utils.image import show_cam_on_image
import pytorch_lightning as pl
from pytorch_lightning.utilities.seed import seed_everything
from pytorch_lightning import callbacks
from pytorch_lightning.callbacks.progress import ProgressBarBase
from pytorch_lightning.callbacks.early_stopping import EarlyStopping
from pytorch_lightning.loggers import TensorBoardLogger
from pytorch_lightning import LightningDataModule, LightningModule
warnings.filterwarnings("ignore")
#tf_efficientnet_b0_ns
config = {'seed': 202126,
'root': '/kaggle/input/petfinder-pawpularity-score/',
'n_splits': 1,
'epoch': 1,
'trainer': {
'gpus': 1,
'accumulate_grad_batches': 1,
'progress_bar_refresh_rate': 1,
'fast_dev_run': False,
'num_sanity_val_steps': 0,
'resume_from_checkpoint': None,
},
'transform':{
'name': 'get_default_transforms',
'image_size': 224
},
'train_loader':{
'batch_size': 64,
'shuffle': True,
'num_workers': 4,
'pin_memory': False,
'drop_last': True,
},
'val_loader': {
'batch_size': 64,
'shuffle': False,
'num_workers': 4,
'pin_memory': False,
'drop_last': False
},
'model':{
'name': 'tf_efficientnet_b0_ns',
'output_dim': 1
},
'optimizer':{
'name': 'optim.AdamW',
'params':{
'lr': 1e-5
},
},
'scheduler':{
'name': 'optim.lr_scheduler.CosineAnnealingWarmRestarts',
'params':{
'T_0': 20,
'eta_min': 1e-4,
}
},
'loss': 'nn.BCEWithLogitsLoss',
}
config = Box(config)#配置参数并进行实例化
def mixup(x: torch.Tensor, y: torch.Tensor, alpha: float = 1.0):
assert alpha > 0, "alpha should be larger than 0"
assert x.size(0) > 1, "Mixup cannot be applied to a single instance."
lam = np.random.beta(alpha, alpha)
rand_index = torch.randperm(x.size()[0])
mixed_x = lam * x + (1 - lam) * x[rand_index, :]
target_a, target_b = y, y[rand_index]
return mixed_x, target_a, target_b, lam
class Model(pl.LightningModule):
def __init__(self, cfg):
super().__init__()
self.cfg = cfg
self.__build_model()
self._criterion = eval(self.cfg.loss)()
self.transform = get_default_transforms()
self.save_hyperparameters(cfg)
def __build_model(self):
self.backbone = create_model(
self.cfg.model.name, pretrained=True, num_classes=0, in_chans=3
)
num_features = self.backbone.num_features
self.fc = nn.Sequential(
nn.Dropout(0.5), nn.Linear(num_features, self.cfg.model.output_dim)
)
def forward(self, x):
f = self.backbone(x)
out = self.fc(f)
return out
def training_step(self, batch, batch_idx):
loss, pred, labels = self.__share_step(batch, 'train')
return {'loss': loss, 'pred': pred, 'labels': labels}
def validation_step(self, batch, batch_idx):
loss, pred, labels = self.__share_step(batch, 'val')
return {'pred': pred, 'labels': labels}
def __share_step(self, batch, mode):
images, labels = batch
labels = labels.float() / 100.0
images = self.transform[mode](images)
if torch.rand(1)[0] < 0.5 and mode == 'train':
mix_images, target_a, target_b, lam = mixup(images, labels, alpha=0.5)
logits = self.forward(mix_images).squeeze(1)
loss = self._criterion(logits, target_a) * lam + \
(1 - lam) * self._criterion(logits, target_b)
else:
logits = self.forward(images).squeeze(1)
loss = self._criterion(logits, labels)
pred = logits.sigmoid().detach().cpu() * 100.
labels = labels.detach().cpu() * 100.
return loss, pred, labels
def training_epoch_end(self, outputs):
self.__share_epoch_end(outputs, 'train')
def validation_epoch_end(self, outputs):
self.__share_epoch_end(outputs, 'val')
def __share_epoch_end(self, outputs, mode):
preds = []
labels = []
for out in outputs:
pred, label = out['pred'], out['labels']
preds.append(pred)
labels.append(label)
preds = torch.cat(preds)
labels = torch.cat(labels)
metrics = torch.sqrt(((labels - preds) ** 2).mean())
self.log(f'{mode}_loss', metrics)
def check_gradcam(self, dataloader, target_layer, target_category, reshape_transform=None):
cam = GradCAMPlusPlus(
model=self,
target_layers = [target_layer],
use_cuda=self.cfg.trainer.gpus,
reshape_transform=reshape_transform)
org_images, labels = iter(dataloader).next()
cam.batch_size = len(org_images)
images = self.transform['val'](org_images)
images = images.to(self.device)
logits = self.forward(images).squeeze(1)
pred = logits.sigmoid().detach().cpu().numpy() * 100
labels = labels.cpu().numpy()
grayscale_cam = cam(input_tensor=images, target_category=target_category, eigen_smooth=True)
org_images = org_images.detach().cpu().numpy().transpose(0, 2, 3, 1) / 255.
return org_images, grayscale_cam, pred, labels
def configure_optimizers(self):
optimizer = eval(self.cfg.optimizer.name)(
self.parameters(), **self.cfg.optimizer.params
)
scheduler = eval(self.cfg.scheduler.name)(
optimizer,
**self.cfg.scheduler.params
)
return [optimizer], [scheduler]
model = Model(config)
model.load_state_dict(torch.load(f'{config.model.name}/default/version_0/checkpoints/best_loss.ckpt')['state_dict'])
model = model.cuda().eval()
config.val_loader.batch_size = 64
datamodule = PetfinderDataModule(train_df, val_df, config)
print(model.backbone)
1. 查看层级结构方式
基于tf_efficientnet_b7_ns模型
class ETSSModel(nn.Module):
def __init__(self, model_name=CFG.model_name, out_dim=1):
super().__init__()
self.model = timm.create_model(model_name, pretrained=True, in_chans=1)
for n in (self.model.children()):print(n)
print("*1model.children()"*20)
for name, module in self.model._modules.items():print(name," : ",module)
print("*2model._modules.items()"*20)
for n in self.model.named_modules():print(n)
print("*3model.named_modules()"*20)
for n in (self.model.modules()):print(n)
print("*4model.modules()"*20)
self.n_features = self.model.classifier.in_features
self.model.classifier = nn.Linear(self.n_features, out_dim)
def forward(self, x):
output = self.model(x)
return output
输出
- model.children()
Conv2d(640, 2560, kernel_size=(1, 1), stride=(1, 1), bias=False)
BatchNorm2d(2560, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)
SiLU(inplace=True)
SelectAdaptivePool2d (pool_type=avg, flatten=True)
Linear(in_features=2560, out_features=1000, bias=True)
- model._modules.items()
conv_head : Conv2d(640, 2560, kernel_size=(1, 1), stride=(1, 1), bias=False)
bn2 : BatchNorm2d(2560, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)
act2 : SiLU(inplace=True)
global_pool : SelectAdaptivePool2d (pool_type=avg, flatten=True)
classifier : Linear(in_features=2560, out_features=1000, bias=True)
- model.named_modules()
BatchNorm2d(2560, eps=0.001, momentum=0.1, affine=True, track_running_stats=True)
SiLU(inplace=True)
SelectAdaptivePool2d (pool_type=avg, flatten=True)
AdaptiveAvgPool2d(output_size=1)
Linear(in_features=2560, out_features=1000, bias=True)
基于上述的模型对模型的输出维度进行更改
对于
class ETSSModel(nn.Module):
def __init__(self, model_name=CFG.model_name, out_dim=1):
super().__init__()
self.model = timm.create_model(model_name, pretrained=True, in_chans=1)
self.n_features = self.model.classifier.in_features
self.model.classifier = nn.Linear(self.n_features, out_dim)#由1000维改成1维
def forward(self, x):
output = self.model(x)
return output
对于
- model._modules.items()
(1): SwinTransformerBlock(
norm : LayerNorm((1536,), eps=1e-05, elementwise_affine=True)
avgpool : AdaptiveAvgPool1d(output_size=1)
head : Linear(in_features=1536, out_features=1000, bias=True)
改为
class ETSSModel(nn.Module):
def __init__(self, model_name=CFG.model_name, out_dim=1):
super().__init__()
self.model = timm.create_model(model_name, pretrained=True, in_chans=1)
self.n_features = self.model.head.in_features
self.model.head = nn.Linear(self.n_features, out_dim)#由1000维改成1维
def forward(self, x):
output = self.model(x)
return output