卷积神经网络:Inception Model下的Mnist实例

import torch
import torch.nn as nn
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim

#1.构建数据集
batch_size=64
transform=transforms.Compose([ #compose类的实例化    RGB多通道(123)  w*h*c  转化为 通道数chanel*宽width*高h
    transforms.ToTensor(), #像素:Z(28*28)>>R(1*28*28) 转化为图像张量(C*W*H)
    transforms.Normalize((0.1307,),(0.3081,)) # 像素值:pixel(0~255)>>[0,1]  均值和方差 x=(x-mean)/std
])
train_dataset=datasets.MNIST(root='../dataset/mnist/',
                             train=True,
                             transform=transform,
                             download=True)
test_dataset=datasets.MNIST(root='../dataset/mnist/',
                             train=False,
                             transform=transform,
                             download=True)

train_loader=DataLoader(dataset=train_dataset,
                        batch_size=batch_size,
                        shuffle=True)
test_loader=DataLoader(dataset=test_dataset,
                        batch_size=batch_size,
                        shuffle=False)

#2.搭建神经网络
class Inception(nn.Module):
    def __init__(self,in_channels):#输入通道数定为未知量,当实例化模型时可以调用
        super(Inception,self).__init__()
        self.branch11=nn.Conv2d(in_channels,16,kernel_size=1)  #1*1的卷积分支 C1=16 图片形状(h,w)未发生变化

        self.branch55_1=nn.Conv2d(in_channels,16,kernel_size=1)
        self.branch55_2=nn.Conv2d(16,24,kernel_size=5,padding=2) #5*5的卷积分支 C2=24 图片形状不发生变化

        self.branch33_1=nn.Conv2d(in_channels,16,kernel_size=1)
        self.branch33_2=nn.Conv2d(16,24,kernel_size=3,padding=1)
        self.branch33_3=nn.Conv2d(24,24,kernel_size=3,padding=1) #3*3的卷积分支 C3=24 图片形状不发生变化

        self.branch_pool=nn.Conv2d(in_channels,24,kernel_size=1) #1*1的池化分支 C4=24 图片形状不发生变化

    def forward(self,x):
        branch11=self.branch11(x)

        branch55=self.branch55_1(x)
        branch55=self.branch55_2(branch55)

        branch33=self.branch33_1(x)
        branch33=self.branch33_2(branch33)
        branch33=self.branch33_3(branch33)

        branch_pool=F.avg_pool2d(x,kernel_size=3,stride=1,padding=1)
        branch_pool=self.branch_pool(branch_pool)

        outputs=[branch11,branch33,branch55,branch_pool]

        return torch.cat(outputs,dim=1)  #dim=1,(BCHW)的第二个维度C上合并  其他维度的值必须相同

class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1=nn.Conv2d(1,10,kernel_size=5)
        self.conv2=nn.Conv2d(88,20,kernel_size=5) #将Inception沿着C维度拼接之后,通道总数未=88

        self.incep1=Inception(in_channels=10)
        self.incep2=Inception(in_channels=20)

        self.mp=nn.MaxPool2d(kernel_size=2)
        self.fc=nn.Linear(1408,10)              ###

    def forward(self,x):
        in_size=x.size(0)
        x=F.relu(self.mp(self.conv1(x)))
        x=self.incep1(x)
        x=F.relu(self.mp(self.conv2(x)))
        x=self.incep2(x)
        x=x.view(in_size,-1)                    ###
        x=self.fc(x)                            ### 随机产生一个x 去掉这三行 输出x.size()
        return x

net=Net()
device=torch.device("cuda:0"if torch.cuda.is_available()else"cpu") #cuda:1 第二块显卡
net.to(device) #将模型迁移到GPU


#3.定义优化器和损失函数
criterion=nn.CrossEntropyLoss()  #这也算是神经网络的一部分
optimizer=optim.SGD(net.parameters(),lr=0.01,momentum=0.5) #冲量值定为0.5 更容易避免 鞍点 或 局部最优解 而找到全局最优解 下山更快

#4.训练模型
def train(epoch):
    running_loss=0.0
    for batch_idx, data in enumerate(train_loader, 0):  # 此函数返回小批量样本的下标数,0代表从第一个开始  ## i,(inputs,labels)
        inputs, target = data  # 本身读出的是一个样本,但是loader自动组合成矩阵并且转化成tensor
        inputs, target = inputs.to(device),target.to(device) #要放到同一块显卡上
        optimizer.zero_grad()

        outputs = net(inputs)
        loss=criterion(outputs,target)
        loss.backward()
        optimizer.step()

        running_loss+=loss.item()
        if batch_idx % 300 == 299:
            print('[%d,%5d] loss: %.3f' %(epoch+1,batch_idx+1,running_loss/300))
            running_loss=0.0
def test():
    correct=0 #正确数
    total=0   #总数
    with torch.no_grad(): #测试集不需要构建计算图
        for data in train_loader:
            images,labels=data
            images,labels=images.to(device),labels.to(device)
            outputs = net(images)
            _,predicted=torch.max(outputs.data,dim=1) #dim=1 代表对矩阵的行进行求最大值 返回最大值的数值和下标(类别)
            total+=labels.size(0)  #size为元组(N10) 返回N
            correct+=(predicted==labels).sum().item() #每行若预测正确,则为真 最后矩阵求和即为本批量正确个数
    print('Accurance on test set : %d %%' %(100*correct/total))

if __name__=='__main__':
    for epoch in range(10):
        train(epoch)
        test()             #每轮更新后进行一次测试

猜你喜欢

转载自blog.csdn.net/qq_21686871/article/details/114376576
今日推荐