MNIST 数据集详析:使用残差网络RESNET识别手写数字(文末送书)_数字识别用的数据集

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!

王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。

对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!

【完整版领取方式在文末!!】

93道网络安全面试题

需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)

内容实在太多,不一一截图了

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

1️⃣零基础入门
① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


如果出现这种错误:



> 
> SyntaxError: Non-UTF-8 code starting with \xca in fileD:\PycharmProjects\model-fuxian\data set\MNIST t.py on line 2, but noencoding declared; see http://python.org/dev/peps/pep-0263/ fordetails
> 
> 
> 


大概率是你没加:`# coding:gbk`,为什么呢?由于 Python 默认使用 ASCII 编码来解析源代码,因此如果源文件中包含了非 ASCII 编码的字符(比如中文字符),那么解释器就可能会抛出 SyntaxError 异常。加上# -*- coding: gbk -*-这样的注释语句可以告诉解释器当前源文件的字符编码格式是 GBK,从而避免源文件中文字符被错误地解析。


如果成功运行会出现这种结果,表示已经开始下载了:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0f0103e175db4cd7818862e3e669806d.png)  
 输出结果:



> 
> Dataset MNIST  
>  Number of datapoints: 60000  
>  Root location: ./MNIST  
>  Split: Train  
>  StandardTransform  
>  Transform: ToTensor()  
>  Dataset MNIST  
>  Number of datapoints: 10000  
>  Root location: ./MNIST  
>  Split: Test  
>  StandardTransform  
>  Transform: ToTensor()
> 
> 
> 


## 3.数据集可视化



import torchvision
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import numpy as np
import matplotlib.pyplot as plt

train_data = datasets.MNIST(root=“model-fuxian/data set/MNIST/MNIST/raw/MNIST”,
train=True,
transform=transforms.ToTensor(),
download=False)

train_loader = DataLoader(dataset=train_data,
batch_size=64,
shuffle=True)

for num, (image, label) in enumerate(train_loader):
image_batch = torchvision.utils.make_grid(image, padding=2)
plt.imshow(np.transpose(image_batch.numpy(), (1, 2, 0)), vmin=0, vmax=255)
plt.show()
print(label)


得到图片:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9e40e4dca3a547ca8f5b0e75924ab119.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0175491ea2b646c689891a96292045de.png)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e858194b569746c49a86f557d177daaf.png)


这是标签:



tensor([2, 1, 7, 7, 2, 4, 2, 2, 0, 1, 7, 1, 5, 7, 9, 0, 2, 7, 4, 7, 0, 2, 7, 1,
6, 9, 1, 1, 1, 5, 4, 3, 8, 0, 1, 0, 1, 3, 8, 0, 1, 4, 5, 1, 8, 4, 7, 3,
8, 3, 2, 2, 0, 0, 4, 0, 2, 9, 7, 1, 8, 3, 2, 3])
tensor([6, 6, 7, 2, 5, 4, 0, 3, 4, 6, 1, 4, 1, 9, 2, 2, 8, 7, 5, 7, 9, 6, 6, 7,
1, 9, 9, 5, 5, 6, 9, 6, 8, 5, 5, 7, 8, 9, 8, 3, 1, 0, 1, 4, 6, 1, 8, 6,
1, 4, 6, 7, 1, 9, 5, 4, 3, 4, 6, 1, 7, 3, 7, 6])
tensor([7, 1, 5, 1, 4, 0, 9, 2, 2, 0, 1, 5, 2, 3, 6, 4, 6, 9, 3, 3, 2, 8, 1, 5,
8, 0, 1, 4, 5, 6, 2, 6, 4, 9, 2, 0, 7, 2, 0, 1, 2, 4, 4, 6, 5, 9, 1, 2,
5, 3, 3, 8, 8, 3, 4, 5, 2, 6, 0, 0, 8, 7, 1, 7])


## 4.使用残差网络RESNET识别手写数字


### 残差网络:


残差网络(Residual Network,ResNet)是在神经网络模型中给非线性层增加直连边的方式来缓解梯度消失问题,从而使训练深度神经网络变得更加容易。在残差网络中,最基本的单位为残差单元。


### 算子ResBlock:


首先实现一个算子ResBlock来构建残差单元,其中定义了use\_residual参数,用于在后续实验中控制是否使用残差连接:



class ResBlk(nn.Module): # 定义Resnet Block模块
“”"
resnet block
“”"

def \_\_init\_\_(self, ch_in, ch_out, stride=1):  # 进入网络前先得知道传入层数和传出层数的设定
    """

:param ch_in:
:param ch_out:
“”"
super(ResBlk, self).init() # 初始化

    # we add stride support for resbok, which is distinct from tutorials.
    # 根据resnet网络结构构建2个(block)块结构 第一层卷积 卷积核大小3\*3,步长为1,边缘加1
    self.conv1 = nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=stride, padding=1)
    # 将第一层卷积处理的信息通过BatchNorm2d
    self.bn1 = nn.BatchNorm2d(ch_out)
    # 第二块卷积接收第一块的输出,操作一样
    self.conv2 = nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1)
    self.bn2 = nn.BatchNorm2d(ch_out)

    # 确保输入维度等于输出维度
    self.extra = nn.Sequential()  # 先建一个空的extra
    if ch_out != ch_in:
        # [b, ch\_in, h, w] => [b, ch\_out, h, w]
        self.extra = nn.Sequential(
            nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=stride),
            nn.BatchNorm2d(ch_out)
        )

def forward(self, x):  # 定义局部向前传播函数
    out = F.relu(self.bn1(self.conv1(x)))  # 对第一块卷积后的数据再经过relu操作
    out = self.bn2(self.conv2(out))  # 第二块卷积后的数据输出
    out = self.extra(x) + out  # 将x传入extra经过2块(block)输出后与原始值进行相加
    out = F.relu(out)  # 调用relu
    return out

### ResNet18结构及六个模块:


残差网络就是将很多个残差单元串联起来构成的一个非常深的网络。ResNet18 的网络结构如图所示:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/8191042540344963a887594b23d62533.png)  
 其中为了便于理解,可以将ResNet18网络划分为6个模块:


第一模块:包含了一个步长为2,大小为7 × 7 的卷积层,卷积层的输出通道数为64,卷积层的输出经过批量归一化、ReLU激活函数的处理后,接了一个步长为2的3 × 3 的最大汇聚层;  
 第二模块:包含了两个残差单元,经过运算后,输出通道数为64,特征图的尺寸保持不变;  
 第三模块:包含了两个残差单元,经过运算后,输出通道数为128,特征图的尺寸缩小一半;  
 第四模块:包含了两个残差单元,经过运算后,输出通道数为256,特征图的尺寸缩小一半;  
 第五模块:包含了两个残差单元,经过运算后,输出通道数为512,特征图的尺寸缩小一半;  
 第六模块:包含了一个全局平均汇聚层,将特征图变为1 × 1 的大小,最终经过全连接层计算出最后的输出。


### 定义完整网络:



class ResNet18(nn.Module): # 构建resnet18层

def \_\_init\_\_(self):
    super(ResNet18, self).__init__()

    self.conv1 = nn.Sequential(  # 首先定义一个卷积层
        nn.Conv2d(1, 32, kernel_size=3, stride=3, padding=0),
        nn.BatchNorm2d(32)
    )
    # followed 4 blocks 调用4次resnet网络结构,输出都是输入的2倍
    self.blk1 = ResBlk(32, 64, stride=1)
    self.blk2 = ResBlk(64, 128, stride=1)
    self.blk3 = ResBlk(128, 256, stride=1)
    self.blk4 = ResBlk(256, 256, stride=1)
    self.outlayer = nn.Linear(256 \* 1 \* 1, 10)  # 最后是全连接层

def forward(self, x):  # 定义整个向前传播

    x = F.relu(self.conv1(x))  # 先经过第一层卷积

    x = self.blk1(x)  # 然后通过4次resnet网络结构
    x = self.blk2(x)
    x = self.blk3(x)
    x = self.blk4(x)

    x = F.adaptive_avg_pool2d(x, [1, 1])
    # print('after pool:', x.shape)
    x = x.view(x.size(0), -1)  # 平铺一维值
    x = self.outlayer(x)  # 全连接层

    return x

完整代码:



coding=gbk

1.加载必要的库

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms
import argparse

2.超参数

BATCH_SIZE = 32#每批处理的数据 一次性多少个
DEVICE = torch.device(“cuda”)#使用GPU

DEVICE = torch.device(“cuda” if torch.cuda.is_available() else “cpu”)#使用GPU

EPOCHS =4 #训练数据集的轮次

3.图像处理

pipeline = transforms.Compose([transforms.ToTensor(), #将图片转换为Tensor
])

4.下载,加载数据

from torch.utils.data import DataLoader
#下载
train_set = datasets.MNIST(“data”,train=True,download=True,transform=pipeline)
test_set = datasets.MNIST(“data”,train=False,download=True,transform=pipeline)
#加载 一次性加载BATCH_SIZE个打乱顺序的数据
train_loader = DataLoader(train_set,batch_size=BATCH_SIZE,shuffle=True)
test_loader = DataLoader(test_set,batch_size=BATCH_SIZE,shuffle=True)

5.构建网络模型

class ResBlk(nn.Module): # 定义Resnet Block模块
“”"
resnet block
“”"

def \_\_init\_\_(self, ch_in, ch_out, stride=1):  # 进入网络前先得知道传入层数和传出层数的设定
    """

:param ch_in:
:param ch_out:
“”"
super(ResBlk, self).init() # 初始化

    # we add stride support for resbok, which is distinct from tutorials.
    # 根据resnet网络结构构建2个(block)块结构 第一层卷积 卷积核大小3\*3,步长为1,边缘加1
    self.conv1 = nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=stride, padding=1)
    # 将第一层卷积处理的信息通过BatchNorm2d
    self.bn1 = nn.BatchNorm2d(ch_out)
    # 第二块卷积接收第一块的输出,操作一样
    self.conv2 = nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1)
    self.bn2 = nn.BatchNorm2d(ch_out)

    # 确保输入维度等于输出维度
    self.extra = nn.Sequential()  # 先建一个空的extra
    if ch_out != ch_in:
        # [b, ch\_in, h, w] => [b, ch\_out, h, w]
        self.extra = nn.Sequential(
            nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=stride),
            nn.BatchNorm2d(ch_out)
        )

def forward(self, x):  # 定义局部向前传播函数
    out = F.relu(self.bn1(self.conv1(x)))  # 对第一块卷积后的数据再经过relu操作
    out = self.bn2(self.conv2(out))  # 第二块卷积后的数据输出
    out = self.extra(x) + out  # 将x传入extra经过2块(block)输出后与原始值进行相加
    out = F.relu(out)  # 调用relu
    return out

class ResNet18(nn.Module): # 构建resnet18层

def \_\_init\_\_(self):
    super(ResNet18, self).__init__()

    self.conv1 = nn.Sequential(  # 首先定义一个卷积层
        nn.Conv2d(1, 32, kernel_size=3, stride=3, padding=0),
        nn.BatchNorm2d(32)
    )
    # followed 4 blocks 调用4次resnet网络结构,输出都是输入的2倍
    self.blk1 = ResBlk(32, 64, stride=1)
    self.blk2 = ResBlk(64, 128, stride=1)
    self.blk3 = ResBlk(128, 256, stride=1)
    self.blk4 = ResBlk(256, 256, stride=1)
    self.outlayer = nn.Linear(256 \* 1 \* 1, 10)  # 最后是全连接层

def forward(self, x):  # 定义整个向前传播

    x = F.relu(self.conv1(x))  # 先经过第一层卷积

    x = self.blk1(x)  # 然后通过4次resnet网络结构
    x = self.blk2(x)
    x = self.blk3(x)
    x = self.blk4(x)

    x = F.adaptive_avg_pool2d(x, [1, 1])
    # print('after pool:', x.shape)
    x = x.view(x.size(0), -1)  # 平铺一维值
    x = self.outlayer(x)  # 全连接层

    return x

6.定义优化器

model = ResNet18().to(DEVICE)#创建模型并将模型加载到指定设备上

optimizer = optim.Adam(model.parameters(),lr=0.001)#优化函数

criterion = nn.CrossEntropyLoss()

7.训练

def train_model(model,device,train_loader,optimizer,epoch):
# Training settings
parser = argparse.ArgumentParser(description=‘PyTorch MNIST Example’)
parser.add_argument(‘–batch-size’, type=int, default=64, metavar=‘N’,
help=‘input batch size for training (default: 64)’)
parser.add_argument(‘–test-batch-size’, type=int, default=1000, metavar=‘N’,
help=‘input batch size for testing (default: 1000)’)
parser.add_argument(‘–epochs’, type=int, default=14, metavar=‘N’,
help=‘number of epochs to train (default: 14)’)
parser.add_argument(‘–lr’, type=float, default=1.0, metavar=‘LR’,
help=‘learning rate (default: 1.0)’)
parser.add_argument(‘–gamma’, type=float, default=0.7, metavar=‘M’,
help=‘Learning rate step gamma (default: 0.7)’)
parser.add_argument(‘–no-cuda’, action=‘store_true’, default=False,
help=‘disables CUDA training’)
parser.add_argument(‘–dry-run’, action=‘store_true’, default=False,
help=‘quickly check a single pass’)
parser.add_argument(‘–seed’, type=int, default=1, metavar=‘S’,
help=‘random seed (default: 1)’)
parser.add_argument(‘–log-interval’, type=int, default=10, metavar=‘N’,
help=‘how many batches to wait before logging training status’)
parser.add_argument(‘–save-model’, action=‘store_true’, default=False,
help=‘For Saving the current Model’)
args = parser.parse_args()

model.train()#模型训练
for batch_index,(data ,target) in enumerate(train_loader):
    data,target = data.to(device),target.to(device)#部署到DEVICE上去
    optimizer.zero_grad()#梯度初始化为0
    output = model(data)#训练后的结果
    loss = criterion(output,target)#多分类计算损失
    loss.backward()#反向传播 得到参数的梯度值
    optimizer.step()#参数优化
    if batch_index % args.log_interval == 0:
        print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
            epoch, batch_index \* len(data), len(train_loader.dataset),
                   100. \* batch_index / len(train_loader), loss.item()))
        if args.dry_run:
            break

8.测试

def test_model(model,device,text_loader):
model.eval()#模型验证
correct = 0.0#正确率
global Accuracy
text_loss = 0.0
with torch.no_grad():#不会计算梯度,也不会进行反向传播
for data,target in text_loader:
data,target = data.to(device),target.to(device)#部署到device上
output = model(data)#处理后的结果
text_loss += criterion(output,target).item()#计算测试损失
pred = output.argmax(dim=1)#找到概率最大的下标
correct += pred.eq(target.view_as(pred)).sum().item()#累计正确的值
text_loss /= len(test_loader.dataset)#损失和/加载的数据集的总数
Accuracy = 100.0*correct / len(text_loader.dataset)
print(“Test__Average loss: {:4f},Accuracy: {:.3f}\n”.format(text_loss,Accuracy))

9.调用

for epoch in range(1,EPOCHS+1):
train_model(model,DEVICE,train_loader,optimizer,epoch)
test_model(model,DEVICE,test_loader)

torch.save(model.state_dict(),‘model.ckpt’)


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7978d065191a4e3ea99af97b14f43305.png)


### 精确度


**Test\_\_Average loss: 0.000808,Accuracy: 99.150**  
 最后可以发现准确度达到了99%还高,可以看出来残差网络识别手写数字的准确性还是很高的。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e8cd576e28e048639247ea075be3ff99.png)  
 没有GPU的可以使用CPU,不过速度会大打折扣:`DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")`,最好是可以使用`GPU`,这样速度会快很多: `torch.device("cuda")#使用GPU`




### 一、网安学习成长路线图


网安所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/aa7be04dc8684d7ea43acc0151aebbf1.png)


### 二、网安视频合集


观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f0aeee2eec7a48f4ad7d083932cb095d.png)


### 三、精品网安学习书籍

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/078ea1d4cda342f496f9276a4cda5fcf.png)


### 四、网络安全源码合集+工具包

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。  
 **需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)**

![在这里插入图片描述](https://img-blog.csdnimg.cn/e54c0bac8f3049928b488dc1e5080fc5.png)


### 五、网络安全面试题


最后就是大家最关心的网络安全面试题板块  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/15c1192cad414044b4dd41f3df44433d.png)![在这里插入图片描述](https://img-blog.csdnimg.cn/b07abbfab1fd4edc800d7db3eabb956e.png)  



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值