基于pytorch的cifar10数据集搭建的CNN,目前准确率为50%左右,可以修改哪些地方提高准确率达到90%以上?
代码
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可以适当增大
可参考
########################更新卷积参数############################
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卷积神经网络
可以参考下
常用的提高CNN准确率的方法:
增加数据集的规模。
改进模型结构。
使用正则化技术。
调整超参数。
使用更高级的训练技术,例如使用适应性的学习率调度、批量归一化、标签平滑等技术。
使用预训练的模型。
增加训练模型的规模来提高
增加卷积层数量试试
可以尝试以下几个方法:
增加模型的复杂度:增加卷积层、池化层或全连接层的数量,增加每个层的神经元数量。
使用更深的网络结构:尝试使用更深的网络结构,如 ResNet、DenseNet 或 VGG 等。
数据增强:对训练数据进行数据增强操作,如随机裁剪、水平翻转、旋转等。
学习率调整策略:尝试使用学习率衰减策略(如 StepLR、ReduceLROnPlateau 等)来动态调整学习率。适当降低学习率可以帮助模型更好地收敛。
正则化技术:使用正则化技术(如 L1/L2 正则化、Dropout 等)来防止过拟合。正则化技术可以帮助控制模型复杂度,并提高泛化能力。
批归一化:在卷积层或全连接层后添加批归一化层(Batch Normalization),可以加速收敛并提高模型性能。
超参数调优:尝试不同的超参数组合,如学习率、批大小、优化器类型等。
基于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
个人的经验之谈:
模型的优化方向无非是以下几种:
①增加高质量的样本,让训练的模型掌握更多的特征(推荐)
②增加模型的参数,让网络复杂度上升;
③参数优化,将现有的几种变量,如学习率、批大小、优化器类型等,设定几种组合,以精确度作为导向,找出当前最优组合.