基于 PyTorch 的Cifar图像分类器代码实现(线性,全连接,卷积)

基于 PyTorch 的Cifar图像分类器代码实现

做实验的时候一共要求做三个实验分别是只使用线性层实现,通过全连接实现,通过卷积实现,代码也是参考了许多前人的代码,有一定程度的修改,然而准确度低的不成样子,望各位海涵。

同时本次的实验是在python 3.7 Jupyter上运行的,Cifar数据在py文件同级目录下的data文件中。由于我的显卡不支持CUDA因此都是直接用cpu搞定的。最长的100个epoch可能要跑一两个小时左右,基本上40个epoch就可以得出大概的结果

仅使用线性层实现图像分类  正确率百分之四十

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import torchvision
import datetime

transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
 
# 训练模型的超参数
input_size = 3072
output_size = 10
num_epochs = 50
batch_size = 64
learning_rate = 0.001
 

train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)

test_dataset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)
 
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)
 
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)

#线性层的建立
model = nn.Linear(input_size, output_size)
 
# 损失函数和优化算法
criterion = nn.CrossEntropyLoss()  
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)  
 
# train_loader的大小,也就是含有多少个bach。
total_step = len(train_loader)
# 训练模型
# 在整个数据集上迭代的次数
for epoch in range(num_epochs):
    starttime = datetime.datetime.now()
    # 每次取一个bach进行训练。
    for i, (images, labels) in enumerate(train_loader):
        # 将数据reshape到模型需要的大小。
        images = images.reshape(-1,3*32*32)
        # 前向传播
        outputs = model(images)
        # 计算模型的loss
        loss = criterion(outputs, labels)
        # 后向传播,更新模型参数
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if (i+1) % 782 == 0:
            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.reshape(-1, 3*32*32)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()   
    print('Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))

 使用全连接层 正确率百分之五十六

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
import torchvision
import datetime
# Training settings
batch_size = 128
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
#更换下顺序便于训练多次
train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transform)

test_dataset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=True, transform=transform)

# Data Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=batch_size,
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                          batch_size=batch_size,
                                          shuffle=False)
y_loss=[]
y_time=[]
#在cifar中,为一个3*32*32的图像
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.l0 = nn.Linear(3072,2048)
        self.l1 = nn.Linear(2048, 1024)
        self.l2 = nn.Linear(1024, 512)
        self.l3 = nn.Linear(512, 256)
        self.l4 = nn.Linear(256, 128)
        self.l5 = nn.Linear(128, 10)

    def forward(self, x):
        x = x.view(-1, 3072)
        x = F.relu(self.l0(x))
        x = F.relu(self.l1(x))
        x = F.relu(self.l2(x))
        x = F.relu(self.l3(x))
        x = F.relu(self.l4(x))
        return F.log_softmax(self.l5(x), dim=1)
        #return self.l5(x)
        #如果直接使用self.15(x)会出现NAN的情况,也就是梯度爆炸

model = Net()

optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

def train(epoch):
    # 每次输入barch_idx个数据
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = Variable(data), Variable(target)

        optimizer.zero_grad()
        output = model(data)
        # loss
        loss = F.nll_loss(output, target)
        loss.backward()
        # update
        optimizer.step()
        if batch_idx % 391 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))
            y_loss.append(loss.item())

def test():
    test_loss = 0
    correct = 0
    # 测试集
    for data, target in test_loader:
        data, target = Variable(data, volatile=True), Variable(target)
        output = model(data)
        # sum up batch loss
        test_loss += F.nll_loss(output, target).item()
        # get the index of the max
        pred = output.data.max(1, keepdim=True)[1]
        correct += pred.eq(target.data.view_as(pred)).cpu().sum()

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

for epoch in range(1,100):
    starttime = datetime.datetime.now()
    train(epoch)
    endtime = datetime.datetime.now()
    y_time.append(endtime - starttime)
with torch.no_grad(): 
        test() 

 卷积层 正确率百分之六十三

import torch
import torchvision
import torchvision.transforms as transforms

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=4,
                                          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=4,
                                         shuffle=False, num_workers=1)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

# 3*32*32
from torch.autograd import  Variable
import torch.nn as nn
import torch.nn.functional as F
import datetime
y_loss=[]
y_time=[]
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 8, 7)#输入3通道,输出6通道,kernelsize=5
        #通过stride可以定义每次卷积移动的步长
        self.pool = nn.MaxPool2d(2, 2)
        #通过池化对信息进行筛选过滤
        self.conv2 = nn.Conv2d(8, 24, 7)
        #self.fc0 = nn.Linear(16 *5*5,10)
        
        #也可以直接进行输出,不用全连接层
        self.fc1 = nn.Linear(24 * 3 * 3,128)
        self.fc2 = nn.Linear(128,64)
        self.fc3 = nn.Linear(64, 10)

    def forward(self, x):
        #print(0,x.size())
        x = self.pool(F.relu(self.conv1(x)))
        #print(1,x.size())
        x = self.pool(F.relu(self.conv2(x)))
        #print(2,x.size())
        # fully connect
        x = x.view(-1, 24 * 3 * 3)
       # x = self.fc0(x)
       # print(3,x.size())
        x = F.relu(self.fc1(x))
       # print(4,x.size())
        x = F.relu(self.fc2(x))
       # print(5,x.size())
        x = self.fc3(x)
       # print(6,x.size())
        return x
    
net = Net()

import torch.optim as optim

criterion = nn.CrossEntropyLoss()

optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

if __name__ ==  '__main__':
    print("Beginning Training")
    for epoch in range(80):
        starttime = datetime.datetime.now()
        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            inputs, labels = data
            optimizer.zero_grad()
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
            if (i+1) % 12500 == 0: 
                print('[%d, %5d] loss: %.3f' %
                      (epoch + 1, i + 1, running_loss / 3125))
                running_loss = 0.0
                y_loss.append(loss.item())
                endtime = datetime.datetime.now()
                y_time.append(endtime - starttime)
    print("Finished Training")

    print("Beginning Testing")
    correct = 0
    total = 0
    for data in testloader:
        images, labels = data
        outputs = net(Variable(images))
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()

    print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

猜你喜欢

转载自blog.csdn.net/weixin_40693859/article/details/94736657