基于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:第一次写博客,欢迎大神指教。允许转载,请注明作者和出处。

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是一个基于PyTorchMNIST识别的代码示例: 首先,导入必要的库和模块: ``` import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms ``` 然后,定义网络模型。这里我们定义了一个简单的卷积神经网络,包含两个卷积层和两个全连接层: ``` class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 4 * 4, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = self.pool(nn.functional.relu(self.conv1(x))) x = self.pool(nn.functional.relu(self.conv2(x))) x = x.view(-1, 16 * 4 * 4) x = nn.functional.relu(self.fc1(x)) x = nn.functional.relu(self.fc2(x)) x = self.fc3(x) return x net = Net() ``` 接着,定义损失函数和优化器: ``` criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) ``` 然后,加载MNIST数据集,并进行预处理: ``` transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True, num_workers=2) testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False, num_workers=2) ``` 最后,开始训练模型: ``` for epoch in range(5): # 训练5轮 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 % 100 == 99: # 每100个batch输出一次训练状态 print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100)) running_loss = 0.0 print('Finished Training') ``` 最后,计算测试集上的准确率: ``` correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, 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)) ``` 这就是一个基于PyTorchMNIST识别的完整代码示例。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

think_three

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值