zl程序教程

您现在的位置是:首页 >  其他

当前栏目

2022“域见杯”医检人工智能开发者大赛Rank 48代码分享(附过采样和降采样实现)

开发者人工智能代码 实现 分享 2022 大赛 采样
2023-09-27 14:23:05 时间

比赛

https://competition.huaweicloud.com/information/1000041723/introduction

代码

!pip install torch==1.11.0
!pip install torchvision==0.12.0
!pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113
Looking in indexes: http://mirrors.aliyun.com/pypi/simple, https://download.pytorch.org/whl/cu113
Requirement already satisfied: torch in ./miniconda3/lib/python3.8/site-packages (1.10.0+cu113)
Requirement already satisfied: torchvision in ./miniconda3/lib/python3.8/site-packages (0.11.1+cu113)
Requirement already satisfied: torchaudio in ./miniconda3/lib/python3.8/site-packages (0.10.0+cu113)
Requirement already satisfied: typing-extensions in ./miniconda3/lib/python3.8/site-packages (from torch) (4.0.0)
Requirement already satisfied: pillow!=8.3.0,>=5.3.0 in ./miniconda3/lib/python3.8/site-packages (from torchvision) (8.4.0)
Requirement already satisfied: numpy in ./miniconda3/lib/python3.8/site-packages (from torchvision) (1.21.4)
[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv[0m
!pip install torchtoolbox -i https://pypi.tuna.tsinghua.edu.cn/simple
import os
import time
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
from torch.autograd import Variable
import torchvision
from torchvision import datasets, models, transforms
from torch.utils.data.sampler import  WeightedRandomSampler
import numpy as np
#import albumentations as A
def seed_torch(seed=2021):
	random.seed(seed)
	os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现
	np.random.seed(seed)
	torch.manual_seed(seed)
	torch.cuda.manual_seed(seed)
	torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.
	torch.backends.cudnn.benchmark = False
	torch.backends.cudnn.deterministic = True

seed_torch()
mean_nums = [0.849, 0.838, 0.851]
std_nums = [0.146, 0.154, 0.114]
from torchtoolbox.transform import Cutout

train_dataTrans = transforms.Compose([
            transforms.Resize(640),
            transforms.CenterCrop(640),
            Cutout(),
            #transforms.RandomHorizontalFlip(),  # 水平翻转
            #transforms.RandomVerticalFlip(),  # 垂直翻转
            transforms.RandomRotation(degrees=(-5,5)),  # 随机选择图片
            #transforms.ColorJitter(brightness=0, contrast=0.5, saturation=0, hue=0),
            #transforms.RandomErasing(), # 对图像进行随机遮挡
            #transforms.RandomAffine(), # 图像放射变换
            #transforms.RandomErasing(), # 随机遮挡
            #transforms.RandAugment(),
            transforms.ToTensor(),
            transforms.Normalize(mean_nums, std_nums)
])

val_dataTrans = transforms.Compose([
            transforms.Resize(640),
            transforms.CenterCrop(640),
            transforms.ToTensor(),
            transforms.Normalize(mean_nums, std_nums)
])
 
data_dir = './autodl-nas/'
train_data_dir = './autodl-nas/train'
val_data_dir = './autodl-nas/val'
train_dataset = datasets.ImageFolder(train_data_dir, train_dataTrans)
print(train_dataset.class_to_idx)
val_dataset = datasets.ImageFolder(val_data_dir, val_dataTrans)

image_datasets = {'train':train_dataset,'val':val_dataset}


# 参考 https://blog.csdn.net/TH_NUM/article/details/80877772
# 参考 https://blog.csdn.net/weixin_40970506/article/details/109467365
#按样本权重采样器
def creater_sampler(train_set):
        classes_idx = train_set.class_to_idx
        appear_times = Variable(torch.zeros(len(classes_idx), 1))
        for label in train_set.targets:
            appear_times[label] += 1
        classes_weight = (1./(appear_times / len(train_set))).view( -1)
        weight=list(map(lambda x:classes_weight[x],train_set.targets))
        num_sample=int(len(train_set))
        print("num_sample:{}\n".format(num_sample))
        print("total:{}".format(num_sample)+",targets0:{},targets1:{},targets2:{},targets3:{}".format(appear_times[0],appear_times[1],appear_times[2],appear_times[3]))
        sampler = WeightedRandomSampler(weight, num_sample, replacement=False)
        return sampler
train_sampler = creater_sampler(train_dataset)
val_sampler = creater_sampler(val_dataset)

dataloders = {x: torch.utils.data.DataLoader(image_datasets[x],
                                             batch_size=8,
                                             sampler=creater_sampler(image_datasets[x]),
                                             num_workers=4) for x in ['train', 'val']}

dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}

use_gpu = torch.cuda.is_available()
{'ASC-H&HSIL': 0, 'ASC-US&LSIL': 1, 'NILM': 2, 'SCC&AdC': 3}
num_sample:6932

total:6932,targets0:tensor([1488.]),targets1:tensor([3246.]),targets2:tensor([1824.]),targets3:tensor([374.])
num_sample:1688

total:1688,targets0:tensor([401.]),targets1:tensor([732.]),targets2:tensor([494.]),targets3:tensor([61.])
num_sample:6932

total:6932,targets0:tensor([1488.]),targets1:tensor([3246.]),targets2:tensor([1824.]),targets3:tensor([374.])
num_sample:1688

total:1688,targets0:tensor([401.]),targets1:tensor([732.]),targets2:tensor([494.]),targets3:tensor([61.])
# 混合精度
from torch.optim.lr_scheduler import CosineAnnealingLR
scaler = torch.cuda.amp.GradScaler()
def train_model(model, lossfunc, optimizer, scheduler, num_epochs=10):
    start_time = time.time()

    best_model_wts = model.state_dict()
    best_acc = 0.0

    for epoch in range(num_epochs):
        print('Epoch {}/{}'.format(epoch, num_epochs - 1))
        print('-' * 10)

        # Each epoch has a training and validation phase
        for phase in ['train', 'val']:
            if phase == 'train':
                scheduler.step()
                model.train(True)  # Set model to training mode
            else:
                model.train(False)  # Set model to evaluate mode

            running_loss = 0.0
            running_corrects = 0.0

            # Iterate over data.
            for data in dataloders[phase]:
                # get the inputs
                inputs, labels = data
                

                # wrap them in Variable
                if use_gpu:
                    inputs = Variable(inputs.cuda())
                    labels = Variable(labels.cuda())
                else:
                    inputs, labels = Variable(inputs), Variable(labels)

                # zero the parameter gradients
                optimizer.zero_grad()

                # forward
                outputs = model(inputs)
                _, preds = torch.max(outputs.data, 1)
                loss = lossfunc(outputs, labels)

                # backward + optimize only if in training phase
                if phase == 'train':
                    #loss.backward()
                    scaler.scale(loss).backward()
                    #optimizer.step()
                    scaler.step(optimizer)
                    scaler.update()

                # statistics
                running_loss += loss.data
                running_corrects += torch.sum(preds == labels.data).to(torch.float32)

            epoch_loss = running_loss / dataset_sizes[phase]
            epoch_acc = running_corrects / dataset_sizes[phase]

            print('{} Loss: {:.4f} Acc: {:.4f}'.format(
                phase, epoch_loss, epoch_acc))

            # deep copy the model
            if phase == 'val' and epoch_acc > best_acc:
                best_acc = epoch_acc
                best_model_wts = model.state_dict()

    elapsed_time = time.time() - start_time
    print('Training complete in {:.0f}m {:.0f}s'.format(
        elapsed_time // 60, elapsed_time % 60))
    print('Best val Acc: {:4f}'.format(best_acc))

    # load best model weights
    model.load_state_dict(best_model_wts)
  
    return model
class LabelSmoothingCrossEntropy(nn.Module):
    """
    Cross Entropy loss with label smoothing.
    """
    def __init__(self, smoothing=0.1):
        """
        Constructor for the LabelSmoothing module.
        :param smoothing: label smoothing factor
        """
        super(LabelSmoothingCrossEntropy, self).__init__()
        assert 0.0 < smoothing < 1.0
        self.smoothing = smoothing
        self.confidence = 1. - smoothing

    def forward(self, x, target):
        """
        写法1
        """
        # logprobs = F.log_softmax(x, dim=-1)
        # nll_loss = -logprobs.gather(dim=-1, index=target.unsqueeze(1))
        # nll_loss = nll_loss.squeeze(1)  # 得到交叉熵损失
        # # 注意这里要结合公式来理解,同时留意预测正确的那个类,也有a/K,其中a为平滑因子,K为类别数
        # smooth_loss = -logprobs.mean(dim=1)
        # loss = self.confidence * nll_loss + self.smoothing * smooth_loss
        """
        写法2
        """
        y_hat = torch.softmax(x, dim=1)
        # 这里cross_loss和nll_loss等价
        cross_loss = self.cross_entropy(y_hat, target)
        smooth_loss = -torch.log(y_hat).mean(dim=1)
        # smooth_loss也可以用下面的方法计算,注意loga + logb = log(ab)
        # smooth_loss = -torch.log(torch.prod(y_hat, dim=1)) / y_hat.shape[1]
        loss = self.confidence * cross_loss + self.smoothing * smooth_loss
        return loss.mean()

    def cross_entropy(self, y_hat, y):
        return - torch.log(y_hat[range(len(y_hat)), y])
# 针对多分类任务的 CELoss 和 Focal Loss
# https://blog.csdn.net/m0_37531129/article/details/107831624
import torch
import torch.nn as nn
import torch.nn.functional as F
class CELoss(nn.Module):
    def __init__(self, class_num, alpha=None, use_alpha=False, size_average=True):
        super(CELoss, self).__init__()
        self.class_num = class_num
        self.alpha = alpha
        if use_alpha:
            self.alpha = torch.tensor(alpha).cuda()
        self.softmax = nn.Softmax(dim=1)
        self.use_alpha = use_alpha
        self.size_average = size_average
    def forward(self, pred, target):
        prob = self.softmax(pred.view(-1,self.class_num))
        prob = prob.clamp(min=0.0001,max=1.0)
        target_ = torch.zeros(target.size(0),self.class_num).cuda()
        target_.scatter_(1, target.view(-1, 1).long(), 1.)
        if self.use_alpha:
            batch_loss = - self.alpha.double() * prob.log().double() * target_.double()
        else:
            batch_loss = - prob.log().double() * target_.double()
        batch_loss = batch_loss.sum(dim=1)
        # print(prob[0],target[0],target_[0],batch_loss[0])
        # print('--')
        if self.size_average:
            loss = batch_loss.mean()
        else:
            loss = batch_loss.sum()
        return loss
    
class FocalLoss(nn.Module):
    def __init__(self, class_num, alpha=None, gamma=2, use_alpha=False, size_average=True):
        super(FocalLoss, self).__init__()
        self.class_num = class_num
        self.alpha = alpha
        self.gamma = gamma
        if use_alpha:
            self.alpha = torch.tensor(alpha).cuda()
        self.softmax = nn.Softmax(dim=1)
        self.use_alpha = use_alpha
        self.size_average = size_average
    def forward(self, pred, target):
        prob = self.softmax(pred.view(-1,self.class_num))
        prob = prob.clamp(min=0.0001,max=1.0)
        target_ = torch.zeros(target.size(0),self.class_num).cuda()
        target_.scatter_(1, target.view(-1, 1).long(), 1.)
        if self.use_alpha:
            batch_loss = - self.alpha.double() * torch.pow(1-prob,self.gamma).double() * prob.log().double() * target_.double()
        else:
            batch_loss = - torch.pow(1-prob,self.gamma).double() * prob.log().double() * target_.double()
        batch_loss = batch_loss.sum(dim=1)
        if self.size_average:
            loss = batch_loss.mean()
        else:
            loss = batch_loss.sum()
        return loss
# get model and replace the original fc layer with your fc layer
model_ft = models.resnet50(pretrained=True, progress=False)
#model_ft = models.resnet101(pretrained=True, progress=False)
#print(model_ft)
num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs, len(train_dataset.classes))

#model_ft = models.efficientnet_b1(pretrained=True, progress=False)
#print(model_ft)
#num_ftrs = model_ft.classifier[1].in_features
#model_ft.classifier[1] = nn.Linear(num_ftrs, len(train_dataset.classes))

if use_gpu:
    model_ft = model_ft.cuda()

# define loss function
#lossfunc = nn.CrossEntropyLoss()
lossfunc = LabelSmoothingCrossEntropy(smoothing=0.1)
#lossfunc = nn.BCEWithLogitsLoss()
#lossfunc = FocalLoss(class_num=len(train_dataset.classes))
# setting optimizer and trainable parameters
params = model_ft.parameters()
# list(model_ft.fc.parameters())+list(model_ft.layer4.parameters())
#params = list(model_ft.fc.parameters())+list( model_ft.parameters())
#params = list(model_ft.fc.parameters())
#params = list(model_ft.heads.head.parameters())

from torchtoolbox.optimizer import Lookahead
#optimizer_ft = optim.SGD(params, lr=0.001, momentum=0.9)
#optimizer_ft = optim.SGD(filter(lambda p: p.requires_grad, params), lr=1e-3, momentum=0.9) 
optimizer_ft = torch.optim.Adam(filter(lambda p: p.requires_grad, params), lr=1e-4)
#optimizer_ft = torch.optim.AdamW(params, lr=1e-3)
optimizer_ft = Lookahead(optimizer_ft)

# Decay LR by a factor of 0.1 every 7 epochs
#exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=2, gamma=0.1)
exp_lr_scheduler = lr_scheduler.CosineAnnealingLR(optimizer_ft, T_max=2)
# 传入优化器让学习率受其管理,当连续3次没有减少loss时就会减少学习率(乘以0.7)
#exp_lr_scheduler = lr_scheduler.ReduceLROnPlateau(optimizer_ft, mode="min", patience=3, factor=0.7)
#exp_lr_scheduler = lr_scheduler.ReduceLROnPlateau(optimizer_ft,'min',factor=0.5,patience=5,verbose=True,min_lr=1e-6)  

model_ft = train_model(model=model_ft,
                           lossfunc=lossfunc,
                           optimizer=optimizer_ft,
                           scheduler=exp_lr_scheduler,
                           num_epochs=25)
Epoch 0/24
----------
train Loss: 0.1080 Acc: 0.7027
val Loss: 0.1288 Acc: 0.6463
Epoch 1/24
----------
train Loss: 0.1571 Acc: 0.5593
val Loss: 0.1324 Acc: 0.6499
Epoch 2/24
----------
train Loss: 0.0953 Acc: 0.7778
val Loss: 0.1142 Acc: 0.7085
Epoch 3/24
----------
train Loss: 0.0943 Acc: 0.7856
val Loss: 0.1132 Acc: 0.7334
Epoch 4/24
----------
train Loss: 0.0829 Acc: 0.8459
val Loss: 0.1064 Acc: 0.7441
Epoch 5/24
----------
train Loss: 0.1351 Acc: 0.6167
val Loss: 0.1045 Acc: 0.7470
Epoch 6/24
----------
train Loss: 0.0787 Acc: 0.8609
val Loss: 0.1073 Acc: 0.7613
Epoch 7/24
----------
train Loss: 0.0825 Acc: 0.8410
val Loss: 0.1222 Acc: 0.6979
Epoch 8/24
----------
train Loss: 0.0752 Acc: 0.8821
val Loss: 0.1008 Acc: 0.7684
Epoch 9/24
----------
train Loss: 0.1068 Acc: 0.7128
val Loss: 0.0999 Acc: 0.7707
Epoch 10/24
----------
train Loss: 0.0691 Acc: 0.9110
val Loss: 0.1041 Acc: 0.7559
Epoch 11/24
----------
train Loss: 0.0759 Acc: 0.8772
val Loss: 0.1138 Acc: 0.7233
Epoch 12/24
----------
train Loss: 0.0667 Acc: 0.9257
val Loss: 0.0971 Acc: 0.7743
Epoch 13/24
----------
train Loss: 0.0981 Acc: 0.7346
val Loss: 0.0977 Acc: 0.7743
Epoch 14/24
----------
train Loss: 0.0627 Acc: 0.9433
val Loss: 0.1031 Acc: 0.7761
Epoch 15/24
----------
train Loss: 0.0685 Acc: 0.9130
val Loss: 0.1245 Acc: 0.7222
Epoch 16/24
----------
train Loss: 0.0618 Acc: 0.9475
val Loss: 0.1024 Acc: 0.7642
Epoch 17/24
----------
train Loss: 0.0926 Acc: 0.7643
val Loss: 0.0969 Acc: 0.7826
Epoch 18/24
----------
train Loss: 0.0580 Acc: 0.9634
val Loss: 0.1051 Acc: 0.7636
Epoch 19/24
----------
train Loss: 0.0644 Acc: 0.9377
val Loss: 0.1080 Acc: 0.7642
Epoch 20/24
----------
train Loss: 0.0581 Acc: 0.9618
val Loss: 0.1052 Acc: 0.7719
Epoch 21/24
----------
train Loss: 0.0850 Acc: 0.7969
val Loss: 0.1028 Acc: 0.7784
Epoch 22/24
----------
train Loss: 0.0546 Acc: 0.9794
val Loss: 0.1016 Acc: 0.7838
Epoch 23/24
----------
train Loss: 0.0603 Acc: 0.9514
val Loss: 0.1383 Acc: 0.7109
Epoch 24/24
----------
train Loss: 0.0557 Acc: 0.9717
val Loss: 0.0979 Acc: 0.7956
Training complete in 81m 39s
Best val Acc: 0.795616
torch.save(model_ft.state_dict(), './model.pth', _use_new_zipfile_serialization=False)
from math import exp
import numpy as np

from PIL import Image
import cv2

infer_transformation = transforms.Compose([
    transforms.Resize(640),
    transforms.CenterCrop(640),
    transforms.ToTensor(),
    transforms.Normalize(mean_nums, std_nums)
])


IMAGES_KEY = 'images'
MODEL_INPUT_KEY = 'images'
LABEL_OUTPUT_KEY = 'predicted_label'
MODEL_OUTPUT_KEY = 'scores'
LABELS_FILE_NAME = 'labels.txt'


def decode_image(file_content):
    image = Image.open(file_content)
    image = image.convert('RGB')
    return image

 
def read_label_list(path):
    with open(path, 'r',encoding="utf8") as f:
        label_list = f.read().split(os.linesep)
    label_list = [x.strip() for x in label_list if x.strip()]
    return label_list


def resnet50(model_path):

    """Constructs a ResNet-50 model.
    Args:
        pretrained (bool): If True, returns a model pre-trained on ImageNet
    """
    model = models.resnet50(pretrained=False)
    num_ftrs = model.fc.in_features
    model.fc = nn.Linear(num_ftrs, 4)
    model.load_state_dict(torch.load(model_path,map_location ='cpu'))
    # model.load_state_dict(torch.load(model_path))

    model.eval()

    return model


def predict(file_name):
    LABEL_LIST = read_label_list('./labels.txt')
    model = resnet50('./model.pth')
    
    image1 = decode_image(file_name)
    

    input_img = infer_transformation(image1)

    input_img = torch.autograd.Variable(torch.unsqueeze(input_img, dim=0).float(), requires_grad=False)

    logits_list =  model(input_img)[0].detach().numpy().tolist()
    print(logits_list)
    maxlist=max(logits_list)
    print(maxlist)

    z_exp = [exp(i-maxlist) for i in  logits_list]

    sum_z_exp = sum(z_exp)
    softmax = [round(i / sum_z_exp, 3) for i in z_exp]
    print(softmax)
    labels_to_logits = {
        LABEL_LIST[i]: s for i, s in enumerate(softmax)
    }
    
    predict_result = {
        LABEL_OUTPUT_KEY: max(labels_to_logits, key=labels_to_logits.get),
        MODEL_OUTPUT_KEY: labels_to_logits
    }

    return predict_result

file_name = './autodl-nas/val/ASC-US&LSIL/05147.jpg'
result = predict(file_name)  #可以替换其他图片
import matplotlib.pyplot as plt

plt.figure(figsize=(10,10)) #设置窗口大小
img = decode_image(file_name)
plt.imshow(img)
plt.show()

print(result)
[2.7242531776428223, -0.8248791694641113, 1.2405871152877808, -0.18008685111999512]
2.7242531776428223
[0.763, 0.022, 0.173, 0.042]
!pip install opencv-python
!pip install albumentations