大家好,我是cv君,今天分享一份源码,有了这份代码,你就是一个Kaggle的一个图像分类赛排行榜因为这是很久以前的比赛,不知道还开不开榜,比如选择你还可以去刷Kaggle的Mnist排行榜99.93+分以上就能进入排行榜(没记错的话)这个Mnist,每个AI的选手都做过,大家可以看我这篇文章,是进Mnist排行榜的代码:https://blog.csdn.net/qq_46098574/article/details/113383390

我们今天不做Mnist了,我们做几年前,特别著名的cat-dog分类!这份代码,你可以得到99.3以上的准确率,你想知道当时这个比赛进排行榜多少分吗?98.9!我们做了什么呢?

迁移学习模型集成数据增强调优调参优化提分冻结网络欢迎来到动手撸深度学习~

cv君力挺的,最值得看的专栏系列:动手撸深度学习学习完本系列,你能从调包侠到一个能独立打比赛的朋友周边的神!文章付费,不想让太多人白嫖!!!因为全部原创,很珍贵!!看完你会感谢我的~感兴趣的话,就来看看吧~首先,大家通过上两节,我们已经通过Keras搭建了自己的神经网络,并且学习了搭建方法,数据增强方法,Dropout等的使用方法和原理,并且学习了迁移学习的几种方式,并且实现了得到了98.5以上的准确率,我们距离排行榜还有一些些距离。这一节我们开始:

迁移学习模型集成数据增强调优调参优化提分冻结网络

现在来看代码:老规矩,导入库

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data
import torch.nn.functional as F
import torchvision
import torchvision.models as models
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
导入两个模型并冻结
model_resnet18 = torch.hub.load('pytorch/vision', 'resnet18', pretrained=True)
model_resnet34 = torch.hub.load('pytorch/vision', 'resnet34', pretrained=True)

for name, param in model_resnet18.named_parameters():
    if ("bn" not in name):
        param.requires_grad = False

for name, param in model_resnet34.named_parameters():
    if ("bn" not in name):
        param.requires_grad = False

训练分类器权重
num_classes = 2

model_resnet18.fc = nn.Sequential(nn.Linear(model_resnet18.fc.in_features, 512),
                                  nn.ReLU(),
                                  nn.Dropout(),
                                  nn.Linear(512, num_classes))

model_resnet34.fc = nn.Sequential(nn.Linear(model_resnet34.fc.in_features, 512),
                                  nn.ReLU(),
                                  nn.Dropout(),
                                  nn.Linear(512, num_classes))

定义训练
def train(model, optimizer, loss_fn, train_loader, val_loader, epochs=2, device="cpu"):
    for epoch in range(epochs):
        training_loss = 0.0
        valid_loss = 0.0
        model.train()
        for batch in train_loader:
            optimizer.zero_grad()
            inputs, targets = batch
            inputs = inputs.to(device)
            targets = targets.to(device)
            output = model(inputs)
            loss = loss_fn(output, targets)
            loss.backward()
            optimizer.step()
            training_loss += loss.data.item() * inputs.size(0)
            print(loss)
        training_loss /= len(train_loader.dataset)

        model.eval()
        num_correct = 0
        num_examples = 0
        for batch in val_loader:
            inputs, targets = batch
            inputs = inputs.to(device)
            output = model(inputs)
            targets = targets.to(device)
            optimizer.zero_grad()

            loss = loss_fn(output, targets)
            valid_loss += loss.data.item() * inputs.size(0)

            correct = torch.eq(torch.max(F.softmax(output, dim=1), dim=1)[1], targets).view(-1)
            num_correct += torch.sum(correct).item()
            num_examples += correct.shape[0]
        valid_loss /= len(val_loader.dataset)

        print(
            'Epoch: {}, Training Loss: {:.4f}, Validation Loss: {:.4f}, accuracy = {:.4f}'.format(epoch, training_loss,
                                 
训练数据读取
batch_size=40
img_dimensions = 224

# Normalize to the ImageNet mean and standard deviation
# Could calculate it for the cats/dogs data set, but the ImageNet
# values give acceptable results here.
img_transforms = transforms.Compose([
    transforms.Resize((img_dimensions, img_dimensions)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
    ])

img_test_transforms = transforms.Compose([
    transforms.Resize((img_dimensions,img_dimensions)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
    ])
    
train_data_path = "train_total/"
train_data = torchvision.datasets.ImageFolder(root=train_data_path,transform=img_transforms, is_valid_file=check_image)

validation_data_path = "val_total/"
validation_data = torchvision.datasets.ImageFolder(root=validation_data_path,transform=img_test_transforms, is_valid_file=check_image)

test_data_path = "val_total/"
test_data = torchvision.datasets.ImageFolder(root=test_data_path, transform=img_test_transforms, is_valid_file=check_image)

num_workers = 0
train_data_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True, num_workers=num_workers)
validation_data_loader = torch.utils.data.DataLoader(validation_data, batch_size=batch_size, shuffle=False, num_workers=num_workers)
test_data_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, shuffle=False, num_workers=num_workers)

测试
def test_model(model):
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_data_loader:
            images, labels = data[0].to(device), data[1].to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print('correct: {:d}  total: {:d}'.format(correct, total))
    print('accuracy = {:f}'.format(correct / total))

训练部分
model_resnet18.to(device)
optimizer = optim.Adam(model_resnet18.parameters(), lr=0.001)
train(model_resnet18, optimizer, torch.nn.CrossEntropyLoss(), train_data_loader, validation_data_loader, epochs=2, device=device)
test_model(model_resnet18)


model_resnet34.to(device)
optimizer = optim.Adam(model_resnet34.parameters(), lr=0.001)
train(model_resnet34, optimizer, torch.nn.CrossEntropyLoss(), train_data_loader, validation_data_loader, epochs=2, device=device)
test_model(model_resnet34)


torch.save(model_resnet18.state_dict(), "./models/model_resnet18.pth")
torch.save(model_resnet34.state_dict(), "./models/model_resnet34.pth")


训练完毕 可以实际验证结果啦~
resnet18 = torch.hub.load('pytorch/vision', 'resnet18')
resnet18.fc = nn.Sequential(nn.Linear(resnet18.fc.in_features, 512), nn.ReLU(), nn.Dropout(), nn.Linear(512, num_classes))
resnet18.load_state_dict(torch.load('./models/model_resnet18.pth'))
resnet18.eval()

resnet34 = torch.hub.load('pytorch/vision', 'resnet34')
resnet34.fc = nn.Sequential(nn.Linear(resnet34.fc.in_features, 512), nn.ReLU(), nn.Dropout(), nn.Linear(512, num_classes))
resnet34.load_state_dict(torch.load('./models/model_resnet34.pth'))
resnet34.to(device)
resnet34.eval()
def predict():
    import os
    def find_classes(dir):
        classes = os.listdir(dir)
        classes.sort()
        class_to_idx = {classes[i]: i for i in range(len(classes))}
        return classes, class_to_idx

    def make_prediction(model, filename):
        labels, _ = find_classes('test1/')
        img = Image.open(filename)
        img = img_test_transforms(img)
        img = img.unsqueeze(0)
        prediction = model(img.to(device))
        prediction = prediction.argmax()
        print(prediction)

    make_prediction(model_resnet34.to(device), 'test1/14.jpg')
    make_prediction(model_resnet34.to(device), 'test1/10.jpg')

def val():
    models_ensemble = [resnet18.to(device), resnet34.to(device)]
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_data_loader:
            images, labels = data[0].to(device), data[1].to(device)
            predictions = [i(images).data for i in models_ensemble]
            avg_predictions = torch.mean(torch.stack(predictions), dim=0)
            _, predicted = torch.max(avg_predictions, 1)

            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    print('accuracy = {:f}'.format(correct / total))
    print('correct: {:d}  total: {:d}'.format(correct, total))
val()
predict()
测试时集成模型
models_ensemble = [resnet18.to(device), resnet34.to(device)]
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_data_loader:
            images, labels = data[0].to(device), data[1].to(device)
            predictions = [i(images).data for i in models_ensemble]
            avg_predictions = torch.mean(torch.stack(predictions), dim=0)
            _, predicted = torch.max(avg_predictions, 1)

            total += labels.size(0)
            correct += (predicted == labels).sum().item()


大家可以看到模型集成地方式,当然这只是一种集成方法

何谓模型集成

即通过训练多个模型,对带预测数据进行拟合(训练时集成)和验证时集成(测试时多模型投票或者平均或者比例方式)


以上通过10折交叉验证,可训练得到10个CNN模型,集成方法有:

平均法:将10个模型预测结果的概率取平均值,然后解码为具体字符投票法:对10个模型预测结果进行投票,得到最终字符12

各个代码,函数的具体意思,请看我的视频~视频很详细地介绍了。视频地址:链接:https://pan.baidu.com/s/1teabC-TIfc-8MPVcV_Q76g提取码:deep一定要看看嗷,这里讲的清晰一些。