0


快速了解机器视觉(CV)基础知识

最近再查一些基础知识的时候看见了几篇文章写得很棒(在这篇文章的结束我会给出参考链接),然后我把他们整合了一下,跟大家分享,希望能有帮助:

1.计算机视觉领域四大基本任务中的应用:

a.图片分类
b.目标定位
c.语义分割
d.实例分割
在这里插入图片描述

2.机器视觉中基本常识:

①语义鸿沟(semantic gap) 人类可以轻松地从图像中识别出目标,而计算机看到的图像只是一组0到255之间的整数。

②计算机视觉任务的其他困难 拍摄视角变化、目标占据图像的比例变化、光照变化、背景融合、目标形变、遮挡等。

③计算机视觉的顶级会议和期刊顶级会议有CVPR、ICCV、和ECCV,此外ICLR也有不少计算机视觉论文。顶级期刊有IJCV和TPAMI。由于计算机视觉领域发展十分迅速,不论身处学术界或产业界,通过阅读顶级会议和期刊论文了解计算机视觉的最近研究成果都十分必要。

④FPS
是图像领域中的定义bai: FPS (Frames Per Second):每秒传输帧数(考察实时性)。 Frames Per Second更确切的解释是“每秒钟填充图像的帧数(帧/秒)”。 FPS 是测量用于保存、显示动态视频的信息数量。通俗来讲就是指动画或视频的画面数。例如在电影视频及数字视频上,每一帧都是静止的图象;快速连续地显示帧便形成了运动的假象。每秒钟帧数 ( FPS ) 愈多,所显示的动作就会愈流畅。通常,要避免动作不流畅的最低 FPS 是30。某些计算机视频格式,每秒只能提供15帧。 这里的“ FPS ”也可以理解为我们常说的“刷新率(单位为Hz)”,例如我们常在CS游戏里说的“ FPS 值”。我们在装机选购显卡和显示器的时候,都会注意到“刷新率”。一般我们设置缺省刷新率都在75Hz(即75帧/秒)以上。例如:75Hz的刷新率刷也就是指屏幕一秒内只扫描75次,即75帧/秒。而当刷新率太低时我们肉眼都能感觉到屏幕的闪烁,不连贯,对图像显示效果和视觉感观产生不好的影响。 电影以每秒24张画面的速度播放,也就是一秒钟内在屏幕上连续投射出24张静止画面。有关动画播放速度的单位是fps,其中的f就是英文单词Frame(画面、帧),p就是Per(每),s就是Second(秒)。用中文表达就是多少帧每秒,或每秒多少帧。电影是24fps,通常简称为24帧。

⑤TP、FP、TN、FN
概念:
在这里插入图片描述
考虑一个二分类的问题,系统需要将样本分为真(positive),假(negative)两类。

下图的方框代表所有需要预测的样本,黄色圆圈内代表系统预测是真(positive)的样本,绿色圆圈内代表实际情况为真(positive)的样本。

所以黄绿交叉的部分是系统预测为真,实际情况也是真,系统预测正确(True)的True Positive,TP;

黄色圆圈以外的绿色部分是系统预测为假而实际上为真的样本,系统预测错误(False)的False Negatives,FN;

绿色圆圈以外的黄色部分即为系统预测为真,然而实际为假的样本,系统预测错误(False)的False Positives,FP;

最后,灰色部分为系统预测为假,实际也为假,系统预测正确(True)的True Negatives,TN。

⑥什么是conv+relu+pooling,他们的作用是什么?
1.conv:卷积神经网络,抽取特征,进行复现
2.relu:修正线性单元,克服梯度消失问题,加快训练速度
3.pooling:池化,保留主要的特征,同时减少下一层的参数和计算量,防止过拟合;保持某种不变性,包括translation(平移),rotation(旋转),scale(尺度),常用的有mean-pooling和max-pooling。
过拟合:
在这里插入图片描述
补充mean-pooling和max-pooling:
mean-pooling:
在这里插入图片描述
max-pooling:
在这里插入图片描述

他们的作用是让图片复现的更加清晰

⑦AP/MAP

AP衡量的是系统在单个类别上的好坏,MAP衡量的是学出的模型在所有类别上的好坏,得到各个类别上的AP后,MAP就是取所有AP的平均值。
在这里插入图片描述
⑧IOU
在这里插入图片描述
举例如下:绿色框是准确值,红色框是预测值。
在这里插入图片描述

3.卷积神经网络(convolutional neural networks, CNN)

一般的卷积神经网络由以下几个层组成:卷积层,池化层,全连接层,Softmax层。这四者构成了常见的卷积神经网络。
1.卷积层。 卷积层是一个卷积神经网络最重要的部分,也是卷积神经网络得名的缘由。卷积层中每一个节点的输入是上一层神经网络的一小块,卷积层试图将神经网络中的每一个小块进行更加深入地分析从而得到抽象程度更高的特征,其作用是捕获图像的局部信息。通过多层卷积层堆叠,各层提取到特征逐渐由边缘、纹理、方向等低层级特征过度到文字、车轮、人脸等高层级特征。

2.池化层。池化层的神经网络不会改变三维矩阵的深度,但是它将缩小矩阵的大小。池化层操作将分辨率较高的图片转化为分辨率较低的图片。

3.全连接层。 经过多轮的卷积层和池化层处理后,卷积神经网络一般会接1到2层全连接层来给出最后的分类结果。

4.Softmax层。Softmax层主要用于分类问题。

在卷积层中,卷积核所处理的节点矩阵的长、宽都是人工指定的,这个节点矩阵的尺寸称之为卷积核的尺寸。卷积核处理的深度和当前层的神经网络节点矩阵的深度是一致的,即便节点矩阵是三维的,卷积核的尺寸只需指定两个维度。一般地,卷积核的尺寸是3×3和5×5。在图中,左边表示输入的数据,输入数据的尺寸为3×32×32(注意:在PyTorch中,数据输入形式表示3×32×32),中间表示卷积核,右边每一个小圆点表示一个神经元,图中有5个神经元。假设卷积核尺寸为5×5,卷积层中每个神经元会有输入数据中3×5×5区域的权重,一共75个权重。这里再次强调下卷积核的深度必须为3,和输入数据保持一致。
在这里插入图片描述
在卷积层,还需说明神经元的数量它们的排列方式滑动步长、以及边界填充

首先,神经元的数量,就是卷积层的输出深度,如图所示有5个神经元,该参数是用户指定的,它和使用的滤波器数量一致。

其次,卷积核进行运算时,必须指定滑动步长。比如步长为1,说明卷积核每次移动1个像素点。当步长为2,卷积核会滑动2个像素点。滑动的操作使得输出的数据变得更少。

最后,介绍边界填充。边界填充如果为0,可以保证输入和输出在空间上尺寸一致;如果边界填充大于0,可以确保在进行卷积操作时,不损失边界信息。

①卷积层:

那么,输出的尺寸最终如何计算?在PyTorch中,可以用一个公式来计算,就是floor((W-F+2P)/ S + 1)。其中,floor 表示下取整操作,W表示输入数据的大小,F表示卷积层中卷积核的尺寸,S表示步长,P表示边界填充的数量。比如输入是5×5,卷积核是3×3,步长是1,填充的数量是0,那么根据公式,就能得到(2+2×0)/ 1 + 1 = 3,输出的空间大小为3×3;如果步长为2,那么(3+2×0)/ 2 + 1 = 2,输出的空间大小为2×2。

在PyTorch中, 类nn.Conv2d()是卷积核模块。卷积核及其调用例子如下:

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

一般地,其调用如下:

# With square kernels and equal stride
m = nn.Conv2d(16,33,3, stride=2)# non-square kernels and unequal stride and with padding
m = nn.Conv2d(16,33,(3,5), stride=(2,1), padding=(4,2))# non-square kernels and unequal stride and with padding and dilation
m = nn.Conv2d(16,33,(3,5), stride=(2,1), padding=(4,2), dilation=(3,1))
nput = autograd.Variable(torch.randn(20,16,50,100))
output = m(input)

nn.Conv2d中参数含义:in_channels表示输入数据体的深度;out_channels表示输出数据体的深度;kernel_size 表示卷积核的大小;stride表示滑动的步长;padding表示边界0填充的个数;dilation表示输入数据体的空间间隔;groups 表示输入数据体和输出数据体在深度上的关联;bias 表示偏置。

②池化层:

通常会在卷积层后面插入池化层,其作用是逐渐降低网络的空间尺寸,达到减少网络中参数的数量,减少计算资源的使用的目的,同时也能有效地控制过拟合。

池化层一般有两次方式:Max Pooling 和 Mean Pooling。以下以Max Pooling来说明池化层的具体内容。池化层操作不改变模型的深度,对输入数据体在深度上的切片作为输入,不断地滑动窗口,取这些窗口的最大值作为输出结果,减少它的空间尺寸。
在这里插入图片描述
池化层的具体计算,以窗口大小是2,滑动步长是2为例:每次都从2x2的窗口中选择最大的数值,同时每次滑动2个步长进入新的窗口。
在这里插入图片描述
池化层为什么有效?图片特征具有局部不变性,也就是说,即便通过下采样也不会丢失图片拥有的特征。由于这种特性,可以将图片缩小再进行卷积处理,这样能够大大地降低卷积计算的时间。最常用的池化层尺寸是2x2,滑动步长为2,对图像进行下采样,将其中75%的信息丢弃,选择其中最大的保留下来,这样也达到去除一些噪声信息的目的。

在PyTorch中,池化层是包括在类nn.MaxPool2d和nn.AvgPoo2d。下面介绍一下nn.MaxPool2d及其调用例子。其调用如下:

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

# pool of square window of size=3, stride=2
m = nn.MaxPool2d(3, stride=2)# pool of non-square window
m = nn.MaxPool2d((3,2), stride=(2,1))input= autograd.Variable(torch.randn(20,16,50,32))
output = m(input)

nn.MaxPool2d中各个参数的含义。其中,kernel_size, stride,padding, dilation在nn.Conv2d中已经解释过。return_indices表示是否返回最大值所处的下标;ceil_model表示使用方格代替层结构。

③SoftMax:

SoftMax与HardMax:HardMax最大的特点就是只选出其中一个最大值,即非黑即白,而这往往并非是我们的需求,我们需要的是置信度(概率值),故而用的是SoftMax,为每个输出分类赋予一个概率值,表示每种分类的可能性。

4.网络模型

基本架构 我们用conv代表卷积层、bn代表批量归一层、pool代表池化层。最常见的网络结构顺序是conv -> bn -> relu -> pool,其中卷积层用于提取特征、池化层用于减少空间大小。随着网络深度的进行,图像的空间大小将越来越小,而通道数会越来越大。
下面简单的介绍一下几种最简单的网络模型:
1.LeNet-5 60k参数。网络基本架构为:conv1 (6) -> pool1 -> conv2 (16) -> pool2 -> fc3 (120) -> fc4 (84) -> fc5 (10) -> softmax。括号中的数字代表通道数,网络名称中有5表示它有5层conv/fc层。当时,LeNet-5被成功用于ATM以对支票中的手写数字进行识别。LeNet取名源自其作者姓LeCun。
在这里插入图片描述

classLeNet(nn.Module):def__init__(self):super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(3,6,5)
        self.conv2 = nn.Conv2d(6,16,5)
        self.fc1   = nn.Linear(16*5*5,120)
        self.fc2   = nn.Linear(120,84)
        self.fc3   = nn.Linear(84,10)defforward(self, x):
        out = F.relu(self.conv1(x))
        out = F.max_pool2d(out,2)
        out = F.relu(self.conv2(out))
        out = F.max_pool2d(out,2)
        out = out.view(out.size(0),-1)
        out = F.relu(self.fc1(out))
        out = F.relu(self.fc2(out))
        out = self.fc3(out)return out

2.AlexNet 60M参数,ILSVRC 2012的冠军网络。网络基本架构为:conv1 (96) -> pool1 -> conv2 (256) -> pool2 -> conv3 (384) -> conv4 (384) -> conv5 (256) -> pool5 -> fc6 (4096) -> fc7 (4096) -> fc8 (1000) -> softmax。AlexNet有着和LeNet-5相似网络结构,但更深、有更多参数。conv1使用11×11的滤波器、步长为4使空间大小迅速减小(227×227 -> 55×55)。AlexNet的关键点是:(1). 使用了ReLU激活函数,使之有更好的梯度特性、训练更快。(2). 使用了随机失活(dropout)。(3). 大量使用数据扩充技术。AlexNet的意义在于它以高出第二名10%的性能取得了当年ILSVRC竞赛的冠军,这使人们意识到卷积神经网络的优势。此外,AlexNet也使人们意识到可以利用GPU加速卷积神经网络训练。AlexNet取名源自其作者名Alex。
在这里插入图片描述

classAlexNet(nn.Module):def__init__(self, num_classes):super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3,96, kernel_size=11, stride=4, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(64,256, kernel_size=5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.Conv2d(192,384, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384,256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256,256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),)
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(256*6*6,4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096,4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes),)defforward(self, x):
        x = self.features(x)
        x = x.view(x.size(0),256*6*6)
        x = self.classifier(x)return x

3.VGG-16/VGG-19 138M参数,ILSVRC 2014的亚军网络。VGG-16的基本架构为:conv1^2 (64) -> pool1 -> conv2^2 (128) -> pool2 -> conv3^3 (256) -> pool3 -> conv4^3 (512) -> pool4 -> conv5^3 (512) -> pool5 -> fc6 (4096) -> fc7 (4096) -> fc8 (1000) -> softmax。 ^3代表重复3次。VGG网络的关键点是:(1). 结构简单,只有3×3卷积和2×2汇合两种配置,并且重复堆叠相同的模块组合。卷积层不改变空间大小,每经过一次汇合层,空间大小减半。(2). 参数量大,而且大部分的参数集中在全连接层中。网络名称中有16表示它有16层conv/fc层。(3). 合适的网络初始化和使用批量归一(batch normalization)层对训练深层网络很重要。在原论文中无法直接训练深层VGG网络,因此先训练浅层网络,并使用浅层网络对深层网络进行初始化。在BN出现之后,伴随其他技术,后续提出的深层网络可以直接得以训练。VGG-19结构类似于VGG-16,有略好于VGG-16的性能,但VGG-19需要消耗更大的资源,因此实际中VGG-16使用得更多。由于VGG-16网络结构十分简单,并且很适合迁移学习,因此至今VGG-16仍在广泛使用。VGG-16和VGG-19取名源自作者所处研究组名(Visual Geometry Group)。
在这里插入图片描述

cfg ={'VGG11':[64,'M',128,'M',256,256,'M',512,512,'M',512,512,'M'],'VGG13':[64,64,'M',128,128,'M',256,256,'M',512,512,'M',512,512,'M'],'VGG16':[64,64,'M',128,128,'M',256,256,256,'M',512,512,512,'M',512,512,512,'M'],'VGG19':[64,64,'M',128,128,'M',256,256,256,256,'M',512,512,512,512,'M',512,512,512,512,'M'],}classVGG(nn.Module):def__init__(self, vgg_name):super(VGG, self).__init__()
        self.features = self._make_layers(cfg[vgg_name])
        self.classifier = nn.Linear(512,10)defforward(self, x):
        out = self.features(x)
        out = out.view(out.size(0),-1)
        out = self.classifier(out)return out
    def_make_layers(self, cfg):
        layers =[]
        in_channels =3for x in cfg:if x =='M':
                layers +=[nn.MaxPool2d(kernel_size=2, stride=2)]else:
                layers +=[nn.Conv2d(in_channels, x, kernel_size=3, padding=1),
                           nn.BatchNorm2d(x),
                           nn.ReLU(inplace=True)]
                in_channels = x
        layers +=[nn.AvgPool2d(kernel_size=1, stride=1)]return nn.Sequential(*layers)

4.GoogLeNet 5M参数,ILSVRC 2014的冠军网络。GoogLeNet试图回答在设计网络时究竟应该选多大尺寸的卷积、或者应该选汇合层。其提出了Inception模块,同时用1×1、3×3、5×5卷积和3×3汇合,并保留所有结果。网络基本架构为:conv1 (64) -> pool1 -> conv2^2 (64, 192) -> pool2 -> inc3 (256, 480) -> pool3 -> inc4^5 (512, 512, 512, 528, 832) -> pool4 -> inc5^2 (832, 1024) -> pool5 -> fc (1000)。GoogLeNet的关键点是:(1). 多分支分别处理,并级联结果。(2). 为了降低计算量,用了1×1卷积降维。GoogLeNet使用了全局平均汇合替代全连接层,使网络参数大幅减少。GoogLeNet取名源自作者所处单位(Google),其中L大写是为了向LeNet致敬,而Inception的名字来源于盗梦空间中的"we need to go deeper"梗。
在这里插入图片描述
5.Inception v3/v4 在GoogLeNet的基础上进一步降低参数。其和GoogLeNet有相似的Inception模块,但将7×7和5×5卷积分解成若干等效3×3卷积,并在网络中后部分把3×3卷积分解为1×3和3×1卷积。这使得在相似的网络参数下网络可以部署到42层。此外,Inception v3使用了批量归一层。Inception v3是GoogLeNet计算量的2.5倍,而错误率较后者下降了3%。Inception v4在Inception模块基础上结合了residual模块(见下文),进一步降低了0.4%的错误率。

在这里插入图片描述
6.ResNet ILSVRC 2015的冠军网络。ResNet旨在解决网络加深后训练难度增大的现象。其提出了residual模块,包含两个3×3卷积和一个短路连接(左图)。短路连接可以有效缓解反向传播时由于深度过深导致的梯度消失现象,这使得网络加深之后性能不会变差。短路连接是深度学习又一重要思想,除计算机视觉外,短路连接也被用到了机器翻译、语音识别/合成领域。此外,具有短路连接的ResNet可以看作是许多不同深度而共享参数的网络的集成,网络数目随层数指数增加。ResNet的关键点是:(1). 使用短路连接,使训练深层网络更容易,并且重复堆叠相同的模块组合。(2). ResNet大量使用了批量归一层。(3). 对于很深的网络(超过50层),ResNet使用了更高效的瓶颈(bottleneck)结构(右图)。ResNet在ImageNet上取得了超过人的准确率。
在这里插入图片描述
下图对比上述几种网络框架:
在这里插入图片描述
7.preResNet ResNet的改进。preResNet整了residual模块中各层的顺序。相比经典residual模块(a),(b)将BN共享会更加影响信息的短路传播,使网络更难训练、性能也更差;©直接将ReLU移到BN后会使该分支的输出始终非负,使网络表示能力下降;(d)将ReLU提前解决了(e)的非负问题,但ReLU无法享受BN的效果;(e)将ReLU和BN都提前解决了(d)的问题。preResNet的短路连接(e)能更加直接的传递信息,进而取得了比ResNet更好的性能。

在这里插入图片描述
8.ResNeXt ResNet的另一改进。传统的方法通常是靠加深或加宽网络来提升性能,但计算开销也会随之增加。ResNeXt旨在不改变模型复杂度的情况下提升性能。受精简而高效的Inception模块启发,ResNeXt将ResNet中非短路那一分支变为多个分支。和Inception不同的是,每个分支的结构都相同。ResNeXt的关键点是:(1). 沿用ResNet的短路连接,并且重复堆叠相同的模块组合。(2). 多分支分别处理。(3). 使用1×1卷积降低计算量。其综合了ResNet和Inception的优点。此外,ResNeXt巧妙地利用分组卷积进行实现。ResNeXt发现,增加分支数是比加深或加宽更有效地提升网络性能的方式。ResNeXt的命名旨在说明这是下一代(next)的ResNet。
在这里插入图片描述
9.随机深度 ResNet的改进。旨在缓解梯度消失和加速训练。类似于随机失活(dropout),其以一定概率随机将residual模块失活。失活的模块直接由短路分支输出,而不经过有参数的分支。在测试时,前馈经过全部模块。随机深度说明residual模块是有信息冗余的。
在这里插入图片描述
10.DenseNet 其目的也是避免梯度消失。和residual模块不同,dense模块中任意两层之间均有短路连接。也就是说,每一层的输入通过级联(concatenation)包含了之前所有层的结果,即包含由低到高所有层次的特征。和之前方法不同的是,DenseNet中卷积层的滤波器数很少。DenseNet只用ResNet一半的参数即可达到ResNet的性能。实现方面,作者在大会报告指出,直接将输出级联会占用很大GPU存储。后来,通过共享存储,可以在相同的GPU存储资源下训练更深的DenseNet。但由于有些中间结果需要重复计算,该实现会增加训练时间。

在这里插入图片描述
11.SENet ILSVRC 2017的冠军网络。SENet通过额外的分支(gap-fc-fc-sigm)来得到每个通道的[0, 1]权重,自适应地校正原各通道激活值响应。以提升有用的通道响应并抑制对当前任务用处不大的通道响应。

在这里插入图片描述
针对你的任务,如何设计网络? 当面对你的实际任务时,如果你的目标是解决该任务而不是发明新算法,那么不要试图自己设计全新的网络结构,也不要试图从零复现现有的网络结构。找已经公开的实现和预训练模型进行微调。去掉最后一个全连接层和对应softmax,加上对应你任务的全连接层和softmax,再固定住前面的层,只训练你加的部分。如果你的训练数据比较多,那么可以多微调几层,甚至微调所有层。

5.目标定位(object localization)

在图像分类的基础上,我们还想知道图像中的目标具体在图像的什么位置,通常是以包围盒的(bounding box)形式。

基本思路 多任务学习,网络带有两个输出分支。一个分支用于做图像分类,即全连接+softmax判断目标类别,和单纯图像分类区别在于这里还另外需要一个“背景”类。另一个分支用于判断目标位置,即完成回归任务输出四个数字标记包围盒位置(例如中心点横纵坐标和包围盒长宽),该分支输出结果只有在分类分支判断不为“背景”时才使用。

6.目标检测(object detection)

在目标定位中,通常只有一个或固定数目的目标,而目标检测更一般化,其图像中出现的目标种类和数目都不定。因此,目标检测是比目标定位更具挑战性的任务。

mAP (mean average precision) 目标检测中的常用评价指标,计算方法如下。当预测的包围盒和真实包围盒的交并比大于某一阈值(通常为0.5),则认为该预测正确。对每个类别,我们画出它的查准率-查全率(precision-recall)曲线,平均准确率是曲线下的面积。之后再对所有类别的平均准确率求平均,即可得到mAP,其取值为[0, 100%]。

交并比(intersection over union, IoU) 算法预测的包围盒和真实包围盒交集的面积除以这两个包围盒并集的面积,取值为[0, 1]。交并比度量了算法预测的包围盒和真实包围盒的接近程度,交并比越大,两个包围盒的重叠程度越高。

7.MNIST数据集上卷积神经网络的实现

讲解如何使用PyTorch实现一个简单的卷积神经网络,使用的数据集是MNIST,预期可以达到97.05%左右的准确率。该神经网络由2个卷积层和3个全连接层构建,读者通过这个例子可以掌握设计卷积神经网络的特征以及参数的配置。

1. 配置库和配置参数

#coding=utf-8#配置库import torch
from torch import nn, optim
import torch.nn.functional as F
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets

# 配置参数
torch.manual_seed(1)#设置随机数种子,确保结果可重复  
batch_size =128#批处理大小
learning_rate =1e-2#学习率
num_epoches =10#训练次数 

2. 加载MINSIT数据

# 下载训练集 MNIST 手写数字训练集
train_dataset = datasets.MNIST(
    root='./data',#数据保持的位置
    train=True,# 训练集 
    transform=transforms.ToTensor(),# 一个取值范围是[0,255]的PIL.Image# 转化为取值范围是[0,1.0]的torch.FloadTensor
    download=True)#下载数据

test_dataset = datasets.MNIST(
    root='./data', 
    train=False,# 测试集
    transform=transforms.ToTensor())

3. 数据的批处理

#数据的批处理,尺寸大小为batch_size, #在训练集中,shuffle 必须设置为True, 表示次序是随机的
train_loader =
  DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader =
  DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

4. 创建CNN模型

# 定义卷积神经网络模型classCnn(nn.Module):def__init__(self, in_dim, n_class):# 1x28x28super(Cnn, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_dim,6,3, stride=1, padding=1),#28 x 28 
            nn.ReLU(True),
            nn.MaxPool2d(2,2),# 14 x 14
            nn.Conv2d(6,16,5, stride=1, padding=0),# 16 x 10 x 10
            nn.ReLU(True), nn.MaxPool2d(2,2))# 16x5x5

        self.fc = nn.Sequential(
            nn.Linear(400,120),# 400 = 16 x 5 x 5 
            nn.Linear(120,84),
            nn.Linear(84, n_class))defforward(self, x):
        out = self.conv(x)
        out = out.view(out.size(0),400)# 400 = 16 x 5 x 5  
        out = self.fc(out)return out

model = Cnn(1,10)# 图片大小是28x28, 10是数据的种类

5.打印模型,呈现网络结构

print(model)

6.训练

下面我们开始训练, 将 img, label 都用 Variable 包起来, 然后放入 model 中计算 out, 最后再计算less和正确率.

# 定义loss和optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate)# 开始训练for epoch inrange(num_epoches):
    running_loss =0.0
    running_acc =0.0for i, data inenumerate(train_loader,1):#批处理
        img, label = data
        img = Variable(img)
        label = Variable(label)# 前向传播 
        out = model(img)
        loss = criterion(out, label)# loss 
        running_loss += loss.data[0]* label.size(0)# total loss , 由于loss 是batch 取均值的,需要把batch size 乘回去
        _, pred = torch.max(out,1)# 预测结果
        num_correct =(pred == label).sum()#正确结果的num#accuracy = (pred == label).float().mean() #正确率
        running_acc += num_correct.data[0]# 正确结果的总数# 后向传播
        optimizer.zero_grad()#梯度清零,以免影响其他batch
        loss.backward()# 后向传播,计算梯度
        optimizer.step()#利用梯度更新 W ,b参数#打印一个循环后,训练集合上的loss 和正确率print('Train {} epoch, Loss: {:.6f}, Acc: {:.6f}'.format(
        epoch +1, running_loss /(len(train_dataset)), running_acc /(len(
            train_dataset))))

7. 在测试集测试识别率

#模型测试, 
model.eval()#由于训练和测试 BatchNorm, Dropout配置不同,需要说明是否模型测试
eval_loss =0
eval_acc =0for data in test_loader:#test set 批处理
    img, label = data
 
    img = Variable(img, volatile=True)# volatile 确定你是否不调用.backward(), 测试中不需要
    label = Variable(label, volatile=True)
    out = model(img)# 前向算法 
    loss = criterion(out, label)# 计算 loss
    eval_loss += loss.data[0]* label.size(0)# total loss
    _, pred = torch.max(out,1)# 预测结果
    num_correct =(pred == label).sum()# 正确结果
    eval_acc += num_correct.data[0]#正确结果总数print('Test Loss: {:.6f}, Acc: {:.6f}'.format(eval_loss /(len(
            test_dataset)), eval_acc *1.0/(len(test_dataset))))

参考博文:半小时学会卷积神经网络
计算机视觉四大基本任务(分类、定位、检测、分割)
深度学习中的性能参数名称
什么是卷积和它的作用
Selective Search


本文转载自: https://blog.csdn.net/qq_45104603/article/details/127619230
版权归原作者 小学生玩编程 所有, 如有侵权,请联系我们删除。

“快速了解机器视觉(CV)基础知识”的评论:

还没有评论