基于Pytorch框架的Mnist网络实现和详解

基于Pytorch框架的Mnist网络实现和详解

文章首先感谢莫凡大神的pytorch教学视频,附链接:https://morvanzhou.github.io/tutorials/machine-learning/torch/

对深度学习感兴趣的小伙伴可以去看一下!

神经网络简化示意图:

 

1. 什么是卷积神经网络(CNN):

卷积神经网络(CNN——Convolutional Neural Network)是一种前馈神经网络。人工神经元可以响应周围单元。卷积神经网络包括卷积层和池化层。

2. 卷积神经网络的结构:


最左边的Image是输入层(Input Layer),首先,我们要有一个概念,对于我们人来说输入的是一张图片,但是对于电脑来说输入的是一个矩阵类型的数据,这些数据代表着这张图片的像素值。接着是卷积层(Convolution Layer),这一层的功能可以理解为:对输入的数据进行特征提取,每个卷积核每次从一个小区域提取到一个特征值,所有的特征值组合起来就得到了一个特征图,当用多个卷积核对输入数据进行特征提取时,就得到了多个特征图。这个卷积核我们称为(kernel)。再接着是池化层(Pooling Layer),所谓池化就是在不影响特征质量的情况下对图片进行压缩,以减少参数,池化主要有两种,一种是MaxPooling,一种是AvePooling。假设池化的内核是一个2*2的矩阵,采用MaxPooling则是输出其中的最大值,采用AvePooling则输出所有数据的平均值。

卷积+池化的组合可以在隐藏层中出现多次,上图中出现2次,而实际上则需要根据实际需求而来。在经过多次的卷积+池化之后是全连接层(Fully Connected Layer,简称FC),最后是输出层(Output Layer)。

3. Pytorch介绍:

PytorchTorch7团队开发的,与Torch的不同之处在于Pytorch使用了Python作为开发语言,同样说明它是一个以Python优先的深度学习框架,它不仅能够实现强大的GPU加速,同时还支持动态神经网络,这是TensorFlow等很多主流框架不支持的。而且Pytorch可以轻松扩展。

Pytorch中有两种变量类型,一种是Tensor,一种是Variable。并且TensorNumpy之间可以自由转换。

有了这些基础概念,我们可以接下来手动写一个典型的CNN网络——Mnist网络:

要实现这个网络可以分为以下几个步骤:

1. 数据下载和预处理

2. 定义网络模型,即Mnist网络

3. 训练网络

4. 测试网络

代码实现:

#1.数据预处理

data_tf = torchvision.transforms.Compose(

        [torchvision.transforms.ToTensor(),#将输入转换为Tensor的格式

         torchvision.transforms.Normalize([0.5],[0.5])] #归一化处理[-1,1],因为黑白图片的depth1,如果是彩色图片,输入depth,则torchvision.transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])

        )

# 2.下载(读取)数据

train_data = torchvision.datasets.MNIST(

        root = 'W:/pic_data',#下载的图片存放的路径

        train = True,

        transform = data_tf,

        download = True #True代表下载,如果已经下载完成可以设置为False

        )

train_dataloader = DataLoader(train_data,batch_size = Batch_size,shuffle = True)

 

 

test_data = torchvision.datasets.MNIST(

        root = 'W:/pic_data',

        train = False,

        transform = data_tf

        )

test_dataloader = DataLoader(test_data,batch_size = Batch_size,shuffle =False)

2. 定义网络模型:

class my_mnist(nn.Module):

    def __init__(self):

        super(my_mnist,self).__init__()

        self.layer1 = nn.Sequential(

                nn.Conv2d(1,16,5,1,2),#输入是1,输出是16,卷积核是5*5,每次移动1步,每一条边补充2/0,经过这一步之后,数据由1*28*28,变成了16*28*28

                nn.ReLU(),#激活函数

                nn.MaxPool2d(2)#卷积核是2*2,即每2*2的矩阵中的4个数据选取一个最大值,这样就由16*28*28,变成了16*14*14

                )

        self.layer2 = nn.Sequential(

                nn.Conv2d(16,32,5,1,2),#16*14*14 --> 32*14*14

                nn.ReLU(),

                nn.MaxPool2d(2)#32*14*14 -->32*7*7

                )

        self.layer3 = nn.Linear(32*7*7,10)#output = 10,是因为0-910个数,代表输出有10种可能。

    def forward(self,x):

        x = self.layer1(x)

        x = self.layer2(x)

        x = x.view(x.size(0),-1)#经过layer2之后xsize是(n,c,h,w),这一步的作用可以理解为将图片碾压成平面,即(1,32,7,7-->1,32*7*7

        out = self.layer3(x)

        return out

#注意:模型的建立是在forward()中实现的,之前只是在堆建框架及设置参数。

‘’’

Class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

Parameters:

· in_channels(int) – 输入信号的通道

· out_channels(int) – 卷积产生的通道可以理解为有多少个采集器

· kerner_size(int or tuple) - 卷积核的尺寸

· stride(int or tupleoptional) - 卷积步长卷积每次移动的距离

· padding(int or tupleoptional) - 输入的每一条边补充0的层数

· dilation(int or tupleoptional) – 卷积核元素之间的间距

· groups(intoptional) – 从输入通道到输出通道的阻塞连接数

· bias(booloptional) - 如果bias=True,添加偏置

class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

参数:

· kernel_size(int or tuple) - max pooling的窗口大小

· stride(int or tupleoptional) - max pooling的窗口移动的步长。默认值是kernel_size

· padding(int or tupleoptional) - 输入的每一条边补充0的层数

· dilation(int or tupleoptional) – 一个控制窗口中元素步幅的参数

· return_indices - 如果等于True,会返回输出最大值的序号,对于上采样操作会有帮助

· ceil_mode - 如果等于True,计算输出信号大小的时候,会使用向上取整,代替默认的向下取整的操作

 

‘’’

#接着导入网络,定义损失函数和优化方法:

net = my_mnist()

#print(net)

 

loss_func = nn.CrossEntropyLoss()#定义损失函数

optimizer = torch.optim.Adam(net.parameters(),lr = lean_rate)#定义优化器

3. 训练网络:

for epoch in range(500):

    running_loss = 0

    running_acc = 0

    for (x,y) in train_dataloader:

        

        x_input = Variable(x)

        y_target = Variable(y)

        output = net(x_input)

        loss = loss_func(output,y_target)

        optimizer.zero_grad()

        loss.backward()

        optimizer.step()

        running_loss += loss.data[0]

        _, predict = torch.max(output, 1)#1代表在行这个维度,最大的数

        correct_num = (predict == y_target).sum()

        running_acc += correct_num.data[0]

 

    running_loss /= len(train_data)

    running_acc /= len(train_data)

 

    print("[%d] Loss: %.5f, Acc: %.2f" %(epoch, running_loss, 100*running_acc))

    if running_loss <0.002:

        Break

4. 测试网络:

net.eval()#将网络改成测试模式

 

for (img,label) in test_dataloader:

    test_img = Variable(img)

    label = Variable(label)

    

    test_out = net(test_img)

    _, predict = torch.max(test_out, 1)

    print('test_out:',predict,

          'label:',label)

 

总结代码如下:

import torch

from torch.autograd import Variable

import torch.nn as nn

import torchvision

import matplotlib.pyplot as plt

from torch.utils.data import DataLoader

Epoch = 1

Batch_size = 32

lean_rate = 0.001

Download_Minist = False

 

#1.数据预处理

data_tf = torchvision.transforms.Compose(

        [torchvision.transforms.ToTensor(),

         torchvision.transforms.Normalize([0.5],[0.5])] #归一化处理[-1,1]

        )

# 2.下载(读取)数据

train_data = torchvision.datasets.MNIST(

        root = 'W:/pic_data',

        train = True,

        transform = data_tf,

        download = Download_Minist

        )

train_dataloader = DataLoader(train_data,batch_size = Batch_size,shuffle = True)

 

 

test_data = torchvision.datasets.MNIST(

        root = 'W:/pic_data',

        train = False,

        transform = data_tf

        )

test_dataloader = DataLoader(test_data,batch_size = Batch_size,shuffle =False)

 

 

'''

#打印第一张图片

print(train_data.train_data.size())

print(train_data.train_labels.size())

plt.imshow(train_data.train_data[0].numpy(),cmap = 'gray')

plt.title('%i'%(train_data.train_labels[0]))

plt.show()

 

'''

#3.自定义训练网络模型

class my_mnist(nn.Module):

    def __init__(self):

        super(my_mnist,self).__init__()

        self.layer1 = nn.Sequential(

                nn.Conv2d(1,16,5,1,2),

                nn.ReLU(),

                nn.MaxPool2d(2)

                )

        self.layer2 = nn.Sequential(

                nn.Conv2d(16,32,5,1,2),

                nn.ReLU(),

                nn.MaxPool2d(2)

                )

        self.layer3 = nn.Linear(32*7*7,10)

    def forward(self,x):

        x = self.layer1(x)

        x = self.layer2(x)

        x = x.view(x.size(0),-1)

        out = self.layer3(x)

        return out

 

net = my_mnist()

#print(net)

 

loss_func = nn.CrossEntropyLoss()

optimizer = torch.optim.Adam(net.parameters(),lr = lean_rate)

 

#5.训练网络

 

for epoch in range(500):

    running_loss = 0

    running_acc = 0

    for (x,y) in train_dataloader:

        

        x_input = Variable(x)

        y_target = Variable(y)

        output = net(x_input)

        loss = loss_func(output,y_target)

        optimizer.zero_grad()

        loss.backward()

        optimizer.step()

        running_loss += loss.data[0]

        _, predict = torch.max(output, 1)#1代表在行这个维度,最大的数

        correct_num = (predict == y_target).sum()

        running_acc += correct_num.data[0]

 

    running_loss /= len(train_data)

    running_acc /= len(train_data)

 

    print("[%d] Loss: %.5f, Acc: %.2f" %(epoch, running_loss, 100*running_acc))

    if running_loss <0.002:

        break

 

#测试网络

net.eval()

 

for (img,label) in test_dataloader:

    test_img = Variable(img)

    label = Variable(label)

    

    test_out = net(test_img)

    _, predict = torch.max(test_out, 1)

    print('test_out:',predict,

          'label:',label)

PS:第一次写博客,欢迎大神指教。允许转载,请注明作者和出处。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页