PyTorch基础(四)搭建简单卷积神经网络

前一阶段一直在准备毕业论文和软设的考试,终于忙完了,接着学习PyTorch,这篇博客主要讲述,如何利用PyTorch搭建简单的CNN网络来识别mnist数据集。

搭建CNN网络的主要步骤如下:

1、导入库文件

2、数据处理

3、下载数据集

4、构建DataLoader

5、构建模型

6、构建损失

7、构建优化器

8、训练模型

9、测试模型

这也是我这一篇文章的目录,这也是pytorch搭建模型的一个基本流程。

1、导入库文件 

import torch
import numpy

from torchvision import transforms#处理图像
from  torchvision import datasets#处理数据集
from torch.utils.data import DataLoader#加载数据集

import torch.nn.functional as F #导入激活函数


import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号

2、数据处理

#进行图像处理函数
transform = transforms.Compose([
    transforms.ToTensor(),#转化成Tensor
    transforms.Normalize((0.1307,),(0.3081,))#归一化处理 (x-u)/s
])

关于数据处理这一模块,自己还不是很理解,之后可能会写一写关于transforms的一些知识点。

3、下载数据集

pytorch提供了下载数据集的接口,可以利用datasets直接下载数据集。

#利用DataLoader下载数据集
train_dataset = datasets.MNIST(
    root='../dataset/mnist',#下载之后保存的文件路径
    download=False,#是否下载
    train=True,#是否是训练集
    transform = transform#对数据及逆行处理
)

test_dataset = datasets.MNIST(
    root='../dataset/mnist',
    download=False,
    train=False,
    transform= transform
)

关键点在于传入四个参数,root,download,train,tranform,分别代表数据保存文件路径、是否下载(若本地没有数据集,传入值为True)、是否是训练集、数据处理方式。

4、构建DataLoader

根据上一步的dataset数据集构造DataLoader,代码如下,这些操作都是固定的,以后训练其他数据也是这种模式。

#利用datasets构造数据集
#规范化之后的训练集
train_loader = DataLoader(
    dataset=train_dataset,
    batch_size=64,
    shuffle=True
)
#规范化之后的测试集
test_loader = DataLoader(
    dataset=test_dataset,
    batch_size=64,
    shuffle=True
)

构建完DataLoader之后,就可以任意加载一张图片,看看效果是什么样的。

#显示数据集
for i, (images, labels) in enumerate(train_loader):
    print(i)#下标
    print(images)#64个图片 是1*64*28*28
    print(labels)#64个图片对应的label 1*64
    plt.imshow(images[1].resize(28,28))
    plt.show()
    break

这段代码中,最最最最重要的就是在面对一个不知道的数据集时,如何知道它的大小是什么样的,train_loader是由image和label两个数据构成,打印结果如下:

PyTorch基础(四)搭建简单卷积神经网络_第1张图片

label的值如下图所示。 

PyTorch基础(四)搭建简单卷积神经网络_第2张图片

5、构建模型

在做完这些准备工作之后,就可以构建CNN网络模型,采用两层卷积层,卷积核采用10*1*5*5和20*10*5*5,池化层采用最大池化,最后在拼接一个全连接层。

#构建CNN模型
class Net(torch.nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = torch.nn.Conv2d(1,10,kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10,20,kernel_size=5)
        self.pooling = torch.nn.MaxPool2d(2)
        self.fc1 = torch.nn.Linear(320,10)

    def forward(self,x):
        #每次训练取多少元素
        batch_size = x.size(0)
        #先做Relu在做pooling
        x = self.pooling(F.relu(self.conv1(x)))
        x = self.pooling(F.relu(self.conv2(x)))
        x = x.view(batch_size,-1)
        x = self.fc1(x)
        return x
model = Net()

PyTorch基础(四)搭建简单卷积神经网络_第3张图片

6、构建损失

criterion = torch.nn.CrossEntropyLoss()

 注意点:当采用这个损失函数时,不要再构建网络最后加上softmax函数

7、构建优化器

#构建优化器
optimizer = torch.optim.SGD(model.parameters(),lr=0.01,momentum=0.5)

8、训练模型

def train(epoch):
    running_loss = 0
    #batch_idx batch的下标
    #datas 数据,1*batch_size*28*28  label
    for batch_idx,datas in enumerate(train_loader,0):
        inputs,targets = datas

        optimizer.zero_grad()

        outputs = model(inputs)
        loss = criterion(outputs,targets)
        loss.backward()

        optimizer.step()

        running_loss += loss.item()
        #输出300次的平均损失
        if batch_idx % 300 == 299:
            print('[%d,%5d] loss:%.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0

代码中最后部分是每计算300次的batch就输出300次平均的loss,这样便于查看模型的训练情况。

9、测试模型

#测试模型
def test():
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_loader:
            image,label = data
            output = model(image)
            # _代表最大的元素 pre代表索引  索引本质就代表了预测元素值
            _,pre = torch.max(output.data,dim=1)
            total += label.size(0)
            correct += (pre==label).sum().item()
    print('准确率为:%d %%'%(100*correct/total))

 看了这个代码,觉得别人写的代码模型是真的好,我自己肯定写不来这样的代码,先模仿,再创新吧!

所有的代码整合:

import torch
import numpy

from torchvision import transforms#处理图像
from  torchvision import datasets#处理数据集
from torch.utils.data import DataLoader#加载数据集

import torch.nn.functional as F #导入激活函数


import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号

#进行图像处理函数
transform = transforms.Compose([
    transforms.ToTensor(),#转化成Tensor
    transforms.Normalize((0.1307,),(0.3081,))#归一化处理 (x-u)/s
])
#利用DataLoader下载数据集
train_dataset = datasets.MNIST(
    root='../dataset/mnist',#下载之后保存的文件路径
    download=False,#是否下载
    train=True,#是否是训练集
    transform = transform#对数据及逆行处理
)

test_dataset = datasets.MNIST(
    root='../dataset/mnist',
    download=False,
    train=False,
    transform= transform
)

#利用datasets构造数据集
#规范化之后的训练集
train_loader = DataLoader(
    dataset=train_dataset,
    batch_size=64,
    shuffle=True
)
#规范化之后的测试集
test_loader = DataLoader(
    dataset=test_dataset,
    batch_size=64,
    shuffle=True
)
# #显示数据集
# for i, (images, labels) in enumerate(train_loader):
#     print(i)#下标
#     print(images)#64个图片 是1*64*28*28
#     print(labels)#64个图片对应的label 1*64
#     plt.imshow(images[1].resize(28,28))
#     plt.show()
#     break


#构建CNN模型
class Net(torch.nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = torch.nn.Conv2d(1,10,kernel_size=5)
        self.conv2 = torch.nn.Conv2d(10,20,kernel_size=5)
        self.pooling = torch.nn.MaxPool2d(2)
        self.fc1 = torch.nn.Linear(320,10)

    def forward(self,x):
        #每次训练取多少元素
        batch_size = x.size(0)
        #先做Relu在做pooling
        x = self.pooling(F.relu(self.conv1(x)))
        x = self.pooling(F.relu(self.conv2(x)))
        x = x.view(batch_size,-1)
        x = self.fc1(x)
        return x


#构建模型
model = Net()
#构建损失
criterion = torch.nn.CrossEntropyLoss()
#构建优化器
optimizer = torch.optim.SGD(model.parameters(),lr=0.01,momentum=0.5)
#训练模型

#用所有数据训练10次

def train(epoch):
    running_loss = 0
    #batch_idx batch的下标
    #datas 数据,1*batch_size*28*28  label
    for batch_idx,datas in enumerate(train_loader,0):
        inputs,targets = datas

        optimizer.zero_grad()

        outputs = model(inputs)
        loss = criterion(outputs,targets)
        loss.backward()

        optimizer.step()

        running_loss += loss.item()
        #输出300次的平均损失
        if batch_idx % 300 == 299:
            print('[%d,%5d] loss:%.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0

#测试模型
def test():
    correct = 0
    total = 0
    with torch.no_grad():
        for data in test_loader:
            image,label = data
            output = model(image)
            # _代表最大的元素 pre代表索引  索引本质就代表了预测元素值
            _,pre = torch.max(output.data,dim=1)
            total += label.size(0)
            correct += (pre==label).sum().item()
    print('准确率为:%d %%'%(100*correct/total))


if __name__ == '__main__':
    for epoch in range(3):
        #训练一次全部的数据 就测试一次准确率
        train(epoch)
        test()

 训练结果如下:

PyTorch基础(四)搭建简单卷积神经网络_第4张图片

综上所述,模型的预测结果已经不错。接下来开始学习比较经典的网络模型。 

你可能感兴趣的:(PyTorch,深度学习,python,神经网络,pytorch)