【pytorch】简单的一个模型做cifar10 分类(四)-类似投票机制进行模型集成

      题外话:这里还是得会用python用的6呀,谁说用深度学习不需要啥高深的python用法,简单就可以,其实还是要对python的各种库非常熟悉的。

        # print(arr[:, 0])  # [3 3 5]
        # print(Counter(arr[:, 0])) # Counter({3: 2, 5: 1})
        # print(Counter(arr[:, 0]).most_common(1))  # [(3, 2)]
        # print(Counter(arr[:, 0]).most_common(1)[0])  # (3, 2)
        # print(Counter(arr[:, 0]).most_common(1)[0][0]) # 3
        pre.clear()
        result = [Counter(arr[:, i]).most_common(1)[0][0] for i in range(BATCHSIZE)]

这里就是想介绍一下:

from collections import Counter计数器

看这里https://blog.csdn.net/ch_improve/article/details/893883891,2点挺好的,或者直接看python官方文档吧

     如果各个模型性能差不多,可以取各模型预测结果的平均值;如果模型性能相差较大,模型集成后的性能可能还不如一单个模型,相差较大时,可以采用加权平均的办法,其中权重可以采用SLSQP,Nelder-mead,Powell,CG,BFGS等优化算法获取。

epoch:97集成模型的正确率74.5
模型0的正确率为:70.66
模型1的正确率为:65.89
模型2的正确率为:69.75
epoch:98集成模型的正确率75.09
模型0的正确率为:71.65
模型1的正确率为:65.62
模型2的正确率为:68.66
epoch:99集成模型的正确率74.89
模型0的正确率为:71.5
模型1的正确率为:65.46
模型2的正确率为:69.57

接下来看一个模型集成的实例:

# -*- coding: utf-8 -*-

'''
@Time    : 2020/8/13 16:33
@Author  : HHNa
@FileName: integrate.py
@Software: PyCharm
 
'''
# step0 导入库及下载数据
import torch
import torchvision
import torchvision.transforms as transforms
import torch.utils.data as data

# Data
print('==> Preparing data..')

transform_test = transforms.Compose([
    transforms.ToTensor(),
    # torchvision datasets are PILImage images of range [0, 1]
    # Tensors of normalized range [-1, 1]
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])

transform_train = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465),(0.2023, 0.1994, 0.2010)),

])

trainset = torchvision.datasets.CIFAR10(root=r'./data', train=True, download=False, transform=transform_train)
trainloader = data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=0)
# print(len(trainloader))
testset = torchvision.datasets.CIFAR10(root=r'./data', train=False, download=False, transform=transform_test)
testLoader = data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=0)
# print(len(testLoader))
classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']



import torch.nn as nn
import torch.nn.functional as F

# step 1
# 定义网络-pytorch官网给的网络
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        # torch.Size([6, 3, 5, 5])
        # print(self.conv1.weight.data.size())
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        # print(x.shape)  # 推理才会打印出来
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)

        return x

# 定义书本上的模型
class CNNnet(nn.Module):
    def __init__(self):
        super(CNNnet, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=5, stride=1)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(in_channels=16, out_channels=36, kernel_size=3,stride=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.fc1 = nn.Linear(1296, 128)  # 1296 = 36 * 6 *6
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x =self.pool1(F.relu(self.conv1(x)))
        x =self.pool2(F.relu(self.conv2(x)))
        x = x.view(-1, 36*6*6)
        x = F.relu(self.fc2(F.relu(self.fc1(x))))
        return x

# 采用全局平均池化模型的定义
class AAPnet(nn.Module):
    def __init__(self):
        super(AAPnet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 36, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        # 使用全局平均池化层
        self.app = nn.AdaptiveAvgPool2d(1)
        self.fc3 = nn.Linear(36, 10)

    def forward(self, x):
        x = self.pool1(F.relu(self.conv1(x)))
        x = self.pool2(F.relu(self.conv2(x)))
        x = self.app(x)
        x = x.view(x.shape[0], -1)
        x = self.fc3(x)
        return x

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
    def forward(self, x):
        out = F.relu(self.conv1(x))
        out = F.max_pool2d(out, 2)
        out = F.relu(self.conv2(out))
        out = F.max_pool2d(out, 2)
        print(out.shape)
        out = out.view(out.size(0), -1)
        out = F.relu(self.fc1(out))
        out = F.relu(self.fc2(out))
        out = self.fc3(out)
        return out

# Model
print('==> Building model..')
net1 = Net()
net2 = CNNnet()
net3 = AAPnet()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

EPOCHES = 100
LR = 0.001
mlps = [net1.to(device), net2.to(device), net3.to(device)]

# step2 选择优化器

a = [{"params": mlp.parameters()} for mlp in mlps]
optimizer = torch.optim.Adam(a, lr=LR)
loss_function = nn.CrossEntropyLoss()


import numpy as np
from collections import Counter
BATCHSIZE=100
# step3 模型训练
for ep in range(EPOCHES):
    for img,label in trainloader:
        img, label = img.to(device), label.to(device)
        optimizer.zero_grad()  # 权重参数梯度清除
        for mlp in mlps:
            mlp.train()
            # 正向及反向传播
            out = mlp(img)
            loss = loss_function(out, label)  #梯度
            loss.backward()
        optimizer.step() # 更新梯度

    pre=[]

    vote_correct = 0
    mlps_correct = [0 for i in range(len(mlps))]

    for img,label in testLoader:
        img, label = img.to(device), label.to(device)
        # print(label.shape)
        # # print(img.size)
        for i, mlp in enumerate(mlps):
            mlp.eval()
            out = mlp(img)

            _, prediction = torch.max(out, 1) # 按行取最大值
            # print(prediction)  # tensor
            pre_num = prediction.cpu().numpy()
            # print(pre_num)
            mlps_correct[i] += (pre_num == label.cpu().numpy()).sum()

            pre.append(pre_num)
        arr = np.array(pre)  # (3, 100)
        # print(arr[:, 0])  # [3 3 5]
        # print(Counter(arr[:, 0])) # Counter({3: 2, 5: 1})
        # print(Counter(arr[:, 0]).most_common(1))  # [(3, 2)]
        # print(Counter(arr[:, 0]).most_common(1)[0])  # (3, 2)
        # print(Counter(arr[:, 0]).most_common(1)[0][0]) # 3
        pre.clear()
        result = [Counter(arr[:, i]).most_common(1)[0][0] for i in range(BATCHSIZE)]
        vote_correct += (result == label.cpu().numpy()).sum()

    # len(testLoader) = 100,为啥除以100?因为就是100个bathsize呀。
    print("epoch:" + str(ep) + "集成模型的正确率" + str(vote_correct / len(testLoader)))

    for idx, coreect in enumerate(mlps_correct):
        print("模型"+str(idx)+"的正确率为:"+str(coreect/len(testLoader)))

 

你可能感兴趣的:(PyTorch)