基于pytorch的cifar10数据集搭建的CNN

基于pytorch的cifar10数据集搭建的CNN,目前准确率为50%左右,可以修改哪些地方提高准确率达到90%以上?
代码

img

img

img


import torch.nn as nn
import torch
import torchvision
一、创建网络模型
class Demonet(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv=nn.Sequential(   #卷积神经网络cnn 

            nn.Conv2d(3,24,5,1,2),   # 32-->32
            nn.ReLU(),
            nn.MaxPool2d(2),
            
            nn.Conv2d(24,32,5,1,2), # 32-->32
            nn.ReLU(),
            nn.MaxPool2d(2),
            
            nn.Conv2d(32,48,5,1,2), # 32-->32
            nn.ReLU(),
            nn.MaxPool2d(2),
            
            nn.Conv2d(48,96,5,1,2), # 32-->32
            nn.ReLU(),
            
        )
        self.fc=nn.Sequential(          #全连接神经网络
            nn.Linear(96*4*4,120),   # 一张图片:通道96 宽高分别为32 32 
            nn.ReLU(),
            nn.Linear(120,84),
            nn.ReLU(),
            nn.Linear(84,10),        # 图像的10分类
        )
        
    def forward(self,x):    #NCHW
        x=self.conv(x)
        x=torch.reshape(x,shape=(-1,96*4*4))
        x = x.view(-1,96*4*4)     #[n,c,h,w]  ---> [n,c*h*w]
        out=self.fc(x)              #[n,c*h*w]  ---> [n,10]
        return out
x = torch.randn(1,3,32,32)   #图片尺寸:NCHW 
net = Demonet()
net.forward(x)     #输入[n,c,h,w]  输出:[n,10]
二、加载数据集
train_ds = torchvision.datasets.CIFAR10(root='./cifar10',train=True,download=True,transform = torchvision.transforms.ToTensor())
train_dl = torch.utils.data.DataLoader(train_ds,batch_size=50,shuffle=True)
test_ds = torchvision.datasets.CIFAR10(root='./cifar10',train=False,download=True,transform = torchvision.transforms.ToTensor())
test_dl = torch.utils.data.DataLoader(test_ds,batch_size=50,shuffle=True)

import matplotlib.pyplot as plt

ts = torchvision.datasets.CIFAR10(root='./cifar10',train=True,download=False)
for i in range(10,20):
    plt.subplot(2,5,i-9)
    plt.imshow(ts[i][0])
    plt.title(ts[i][1])
    plt.axis('off')

三、损失函数、优化
net = Demonet().to('cuda')
loss_fn = torch.nn.CrossEntropyLoss()
opt = torch.optim.SDG(net.parameters(),lr=1e-4)
四、训练
for epoch in range(10):
    net.train()
    for i,(x,y) in enumerate(train_dl):
        x,y = x.to('cuda'),y.to('cuda')
        y_pred = net(x)
#        target = torch.zeros(256,10).scatter(1,y.view(-1,1),1)
        loss = loss_fn(y_pred,y)
    
#-------------三步曲----------
        opt.zero_grad()
        loss.backward()
        opt.step()
        
        if i%200==0:
            print('epochs:{}  {}/{}-loss:{:.4f}'.format(epoch,i,len(train_dl),loss))
            
    with torch.no_grad():
        net.eval()
        correct=0.
        total=0.
        for x,y in test_dl:
            x,y = x.to('cuda'),y.to('cuda')
            y_pred=net(x)
            _,predicted=torch.max(y_pred.data,1)   #每行的最大值的索引
            total+=y.size(0)
            correct+=(predicted==y).sum()
            epoch_acc=correct.float()/total

    
        print('[epochs{},epoch_acc:{:.2f}%'.format(epoch,epoch_acc*100))
        print('\n')
        print('_.'*20)



增加网络复杂度,包括卷积输出层数,全连接层节点数等
把epoch可以适当增大
可参考

  • 这篇博客: Pytorch搭建CIFAR10的CNN卷积神经网络中的 完整代码 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • ########################更新卷积参数############################
    import numpy as np
    import torch
    import torchvision
    import torchvision.transforms as transforms
    import matplotlib.pyplot as plt
    import torch.nn.functional as F
    
    #hyper parameter
    BATCH_SIZE = 4
    EPOCH = 2
    
    transform = transforms.Compose([transforms.ToTensor(),
                                    transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
    trainset = torchvision.datasets.CIFAR10(root='./data',train = True,
                                            download=True, transform=transform)
    trainloader = torch.utils.data.DataLoader(trainset,batch_size = BATCH_SIZE,
                                              shuffle = True, num_workers=1)
    
    testset = torchvision.datasets.CIFAR10(root='./data',train = False,
                                            download=True, transform=transform)
    testloader = torch.utils.data.DataLoader(testset,batch_size = BATCH_SIZE,
                                              shuffle = False, num_workers=1)
    
    classes = ('plane', 'car', 'bird', 'cat',
               'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    
    # plt.imshow(trainset.data[86]) #trainset.data中储存了原始数据,并且是array格式
    # plt.show()
    
    # dataiter = iter(trainloader)
    # images, labels = dataiter.next()
    # images_comb = torchvision.utils.make_grid(images)
    # images_comb_unnor = (images_comb*0.5+0.5).numpy()
    # plt.imshow(np.transpose(images_comb_unnor, (1, 2, 0)))
    # plt.show()
    
    class CNN_NET(torch.nn.Module):
        def __init__(self):
            super(CNN_NET,self).__init__()
            self.conv1 = torch.nn.Conv2d(in_channels = 3,
                                         out_channels = 64,
                                         kernel_size = 5,
                                         stride = 1,
                                         padding = 0)
            self.pool = torch.nn.MaxPool2d(kernel_size = 3,
                                           stride = 2)
            self.conv2 = torch.nn.Conv2d(64,64,5)
            self.fc1 = torch.nn.Linear(64*4*4,384)
            self.fc2 = torch.nn.Linear(384,192)
            self.fc3 = torch.nn.Linear(192,10)
    
        def forward(self,x):
            x=self.pool(F.relu(self.conv1(x)))
            x=self.pool(F.relu(self.conv2(x)))
            x=x.view(-1,64*4*4)
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
    
    net = CNN_NET()
    
    import torch.optim as optim
    
    optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)
    loss_func =torch.nn.CrossEntropyLoss()
    
    for epoch in range(EPOCH):
        running_loss = 0.0
        for step, data in enumerate(trainloader):
            b_x,b_y=data
            outputs = net.forward(b_x)
            loss = loss_func(outputs, b_y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            # 打印状态信息
            running_loss += loss.item()
            if step % 1000 == 999:    # 每2000批次打印一次
                print('[%d, %5d] loss: %.3f' %
                      (epoch + 1, step + 1, running_loss / 2000))
                running_loss = 0.0
    
    print('Finished Training')
    
    dataiter = iter(trainloader)
    images, labels = dataiter.next()
    images_comb = torchvision.utils.make_grid(images)
    images_comb_unnor = (images_comb*0.5+0.5).numpy()
    plt.imshow(np.transpose(images_comb_unnor, (1, 2, 0)))
    plt.show()
    
    predicts=net.forward(images)
    
    
    
    
    ########测试集精度#######
    correct = 0
    total = 0
    with torch.no_grad():
        #不计算梯度,节省时间
        for (images,labels) in testloader:
            outputs = net(images)
            numbers,predicted = torch.max(outputs.data,1)
            total +=labels.size(0)
            correct+=(predicted==labels).sum().item()
    
    print('Accuracy of the network on the 10000 test images: %d %%' % (
        100 * correct / total))
    

采用chatgpt:
修改后的代码:

import torch.nn as nn
import torch
import torchvision

# 创建网络模型
class Demonet(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(3, 24, 5, 1, 2),  # 32-->32
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Conv2d(24, 32, 5, 1, 2),  # 32-->32
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Conv2d(32, 48, 5, 1, 2),  # 32-->32
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Conv2d(48, 96, 5, 1, 2),  # 32-->32
            nn.ReLU(),
        )
        self.fc = nn.Sequential(
            nn.Linear(96 * 4 * 4, 120),  # 一张图片:通道96 宽高分别为32 32
            nn.ReLU(),
            nn.Dropout(0.5),  # 添加Dropout层进行正则化
            nn.Linear(120, 84),
            nn.ReLU(),
            nn.Dropout(0.5),  # 添加Dropout层进行正则化
            nn.Linear(84, 10),  # 图像的10分类
        )

    def forward(self, x):  # NCHW
        x = self.conv(x)
        x = torch.flatten(x, 1)  # 使用flatten替代reshape进行扁平化
        out = self.fc(x)
        return out

# 加载数据集
transform_train = torchvision.transforms.Compose([
    torchvision.transforms.RandomCrop(32, padding=4),
    torchvision.transforms.RandomHorizontalFlip(),
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),  # 图像标准化处理
])

transform_test = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),  # 图像标准化处理
])

train_ds = torchvision.datasets.CIFAR10(root='./cifar10', train=True, download=True, transform=transform_train)
train_dl = torch.utils.data.DataLoader(train_ds, batch_size=50, shuffle=True)
test_ds = torchvision.datasets.CIFAR10(root='./cifar10', train=False, download=True, transform=transform_test)
test_dl = torch.utils.data.DataLoader(test_ds, batch_size=50, shuffle=False)

# 损失函数、优化
net = Demonet().to('cuda')
loss_fn = torch.nn.CrossEntropyLoss()
opt = torch.optim.Adam(net.parameters(), lr=1e-3)  # 使用Adam优化器

# 训练
for epoch in range(50):  # 增加训练迭代次数
    net.train()
    for i, (x, y) in enumerate(train_dl):
        x, y = x.to('cuda'), y.to('cuda')
        y_pred = net(x)
        loss = loss_fn(y_pred, y)

        # 优化器的三步曲
        opt.zero_grad()
        loss.backward()
        opt.step()

        if i % 200 == 0:
            print('epochs:{}  {}/{}-loss:{:.4f}'.format(epoch, i, len(train_dl), loss))

    with torch.no_grad():
        net.eval()
        correct = 0.
        total = 0.
        for x, y in test_dl:
            x, y = x.to('cuda'), y.to('cuda')
            y_pred = net(x)
            _, predicted = torch.max(y_pred.data, 1)
            total += y.size(0)
            correct += (predicted == y).sum().item()  # 使用item()获取标量值
            epoch_acc = correct / total

        print('[epochs{}], epoch_acc:{:.2f}%'.format(epoch, epoch_acc * 100))
        print('\n')
        print('_.' * 20)

以上代码并不能保证准确率达到90%以上,因为准确率的提升还与训练集规模、模型结构等因素有关。但是,通过这些修改,你应该能够看到准确率有显著提升。你可以根据实际情况进行调整和优化。

Pytorch搭建CIFAR10的CNN卷积神经网络
可以参考下


Pytorch搭建CNN(重复元素的网络VGG)实现cifar-10分类:20轮近74%准确率_伯纳乌的小草的博客-CSDN博客 参考书目:动手学深度学习(pytorch版)原书链接import torchfrom torch import nnfrom torch.nn import initimport torchvisionimport torchvision.transforms as transformsimport sysimport d2lzh_pytorch as d2limport time... https://blog.csdn.net/weixin_45850972/article/details/105200139

常用的提高CNN准确率的方法:
增加数据集的规模。
改进模型结构。
使用正则化技术。
调整超参数。
使用更高级的训练技术,例如使用适应性的学习率调度、批量归一化、标签平滑等技术。
使用预训练的模型。

增加训练模型的规模来提高

增加卷积层数量试试

可以尝试以下几个方法:

  1. 增加模型的复杂度:增加卷积层、池化层或全连接层的数量,增加每个层的神经元数量。

  2. 使用更深的网络结构:尝试使用更深的网络结构,如 ResNet、DenseNet 或 VGG 等。

  3. 数据增强:对训练数据进行数据增强操作,如随机裁剪、水平翻转、旋转等。

  4. 学习率调整策略:尝试使用学习率衰减策略(如 StepLR、ReduceLROnPlateau 等)来动态调整学习率。适当降低学习率可以帮助模型更好地收敛。

  5. 正则化技术:使用正则化技术(如 L1/L2 正则化、Dropout 等)来防止过拟合。正则化技术可以帮助控制模型复杂度,并提高泛化能力。

  6. 批归一化:在卷积层或全连接层后添加批归一化层(Batch Normalization),可以加速收敛并提高模型性能。

  7. 超参数调优:尝试不同的超参数组合,如学习率、批大小、优化器类型等。

基于bing、GPT部分内容和本人思考总结:
以下是一个基于PyTorch的CIFAR-10数据集的简单CNN模型的示例代码。为了提高准确率,你可以尝试以下几个方面的修改:

增加网络深度:增加卷积层或全连接层的数量,增加网络的复杂度,有助于提取更多的特征信息。

增加网络宽度:增加卷积核的数量或全连接层的神经元数量,使网络能够学习更多的特征。

使用更复杂的网络结构:例如ResNet、DenseNet等深度残差网络或密集连接网络,这些网络结构具有更强的建模能力。

调整超参数:例如学习率、批次大小、训练迭代次数等。使用不同的超参数组合可能会对模型性能产生显著影响。

数据增强:通过对训练数据进行随机的平移、旋转、缩放等操作,增加数据样本的多样性,有助于提高模型的泛化能力。

使用预训练模型:在CIFAR-10上进行训练时,可以使用在大规模图像数据集上预训练的模型进行初始化,然后在CIFAR-10数据集上进行微调,以利用预训练模型的知识。

使用正则化技术:例如L1或L2正则化、dropout等,以减少模型的过拟合现象。

请注意,以上只是一些可能的改进方法,并不保证能够确切地提高准确率至90%以上。具体的改进策略需要根据实际情况进行调试和尝试。

python
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms

# 定义网络结构
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        self.fc1 = nn.Linear(4 * 4 * 128, 256)
        self.fc2 = nn.Linear(256, 10)

    def forward(self, x):
        x = nn.functional.relu(self.conv1(x))
        x = nn.functional.max_pool2d(x, 2)
        x = nn.functional.relu(self.conv2(x))
        x = nn.functional.max_pool2d(x, 2)
        x = nn.functional.relu(self.conv3(x))
        x = nn.functional.max_pool2d(x, 2)
        x = x.view(-1, 4 * 4 * 128)
        x = nn.functional.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 数据预处理和加载
transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False)

# 初始化网络和优化器
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

# 训练网络
for epoch in range(10):
    running_loss = 0.0
    for i, data in enumerate(train_loader, 0):
        inputs, labels = data
        optimizer.zero_grad()

        outputs = net(inputs)
        loss = criterion(outputs, labels

个人的经验之谈:
模型的优化方向无非是以下几种:
①增加高质量的样本,让训练的模型掌握更多的特征(推荐)
②增加模型的参数,让网络复杂度上升;
③参数优化,将现有的几种变量,如学习率、批大小、优化器类型等,设定几种组合,以精确度作为导向,找出当前最优组合.