经典卷积架构:GoogLeNet
GoogLeNetGoogLeNet,也叫做Inception,没错,翻译过来就是《盗梦空间》。
相较于之前的网络,GoogLeNet网络层数更多,网络变得更深,网络结构也变得更加复杂。
不过,虽然网络结构复杂,但由于使用了1*1卷积来减少通道数,GoogLeNet所包含的参数不增反减,这也是GoogLeNet表现如此出众的重要原因之一。
GoogleNet的网络结构参数表如下:
type:网络层类型patch size/stride:(卷积核or池化窗口)尺寸/(卷积/池化)步长output size:该层输出特征图的shape
GoogLeNet重复使用了inception,和NiN基础块一样,它也是一个单独的块,不妨记作inception block,蓝色框起来的是便是inception block需要的参数。
inception block结构如下:
inception block使用了4个并行的分支,最后在通道维度上将4个分支的结果做了concat融合。这样,网络变宽了,我们无需考虑到底是用卷积层还是池化层,卷积核的尺寸是3x3还是5x5比较好,这一切,都交给模型,让模型自己 ...
语义分割中的IoU理论讲解+PyTorch实现
语义分割中的IoU之前的文章介绍过目标检测中的IoU,它等于预测框与真实框的交集区域面积除以并集区域面积。
在语义分割问题中,IoU经常被作为指标来评估模型学习的好坏。和目标检测中的IoU一样,语义分割中的IoU也是用预测结果和真实结果的交集除以并集。
只不过,语义分割问题并不像目标检测问题那样存在所谓的框,它通常是对每个像素进行分类,然后根据分类结果分别计算每个类别的交集和并集,从而进一步计算得到IoU。
因此,语义分割问题的IoU计算方式会与目标检测中IoU的计算方式会有所不同(两者思想一样,具体计算方式不一样)。
计算IoU需要预测类别和真实类别,后者是已知的,而前者需要模型去预测,再经过一些后处理得到。将模型预测值转为我们需要的预测类别的步骤(即:后处理过程)如下:
输入1张shape为C*H*W的图片,输出的shape为C'*H*W。C表示图片通道数,一般是3,C'表示语义分割问题的总类别数,比如一共有4类,那么C'=4。在C'所在维度上做个切片,比如C'[:,3,3]取了坐标为[3,3]的像素点在C'维度上的取值,该取值是一个 ...
经典卷积架构:NiN
NiNNiN在已有网络的基础上进行了改进,并且这些改进影响了后续网络模型的发展。经典之作,值得回味,今天我们就来一起实现它~
NiN的网络结构主要由多个NiN基础块堆叠而成。
1*1卷积NiN基础块含有3个卷积层,除了第一个卷积层,其余两个卷积层的卷积核尺寸都是1*1的,这种卷积核不会改变特征图的尺寸,并且可以在不增加太多参数量的前提下,实现通道数的变化,相当于是将每个通道上的特征图做了一个融合(比如,卷之前,维度是[C,224*224],卷之后,维度是[D,224*224],看吧,只有通道数发生了变化)。
全局平均池化在网络尾部进行分类结果输出时,NiN使用了全局平均池化层来代替之前的网络中使用的全连接层,这种提取全局信息的方式极大的减少了网络参数量,同时也不会像全连接层那样容易导致模型过拟合。你可以对比之前介绍的AlexNet,它在最后使用全连接层来输出分类结果,而这里的NiN使用的是全局平均池化。
NiN将网络最后一个NiN基础块的输出通道数设置为总类别数,紧接其后的全局平均池化层会在通道维度上对每张特征图求平均。假设总类别为10,那么就会有10个通道,经过全局平均池化层就能得到 ...
经典卷积架构:VGG系列
VGGVGG的提出者所在实验室名字为Visual Geometry Group ,因此就地取名,VGG诞生了。
VGG通过堆叠大量的VGG块,实现了更深的网络结构。
这里的VGG块,包含了多个卷积层一个池化层:
卷积层的卷积核尺寸为3*3,stride为1,padding为1;这种结构保证了输入图片(或特征图)经过卷积后得到的特征图的尺寸与输入尺寸是一样的。也就是或,卷积仅仅改变通道数,而不改变图像(特征图)的尺寸。
池化层的池化窗口尺寸和stride都是2,从而使得特征图的尺寸减半。
在堆叠的多个VGG块之后,是一些全连接层,负责最后的分类结果输出。
根据网络层数的不同,VGG有多个版本,如下图:
可以看出,不同版本之间的差异体现在卷积层(VGG 块个数不同),而全连接层是通用的。
在代码实现时,我们将写一个基本通用的框架,它可以帮助我们快捷实现不同版本的VGG。
注意:
我们将忽略现在已经不怎么使用的LRN,并且会添加一些现在常用的网络层,如ReLU,BN等。
对于图中的第4列(C),该框架不是通用的,因为含有1*1卷积。不过这对于实现来说完全不是问题,比如将全部层堆叠 ...
经典卷积架构:AlexNet
AlexNet在2012年的Imagenet竞赛中,AlexNet以低于第二名10.8个百分点的top-5错误率赢得了冠军,自此以后,基于CNN的图像分类算法开始流行起来,深度学习时代到来了。
AlexNet的网络结构如上图所示。相比于之前的LeNet-5,AlexNet堆叠了更多的卷积块,从而网络更深。同时,它还引入了Dropout的技巧,以及ReLU激活函数等。
在AlexNet刚被提出时,受限于当时的算力,作者采用了多个GPU进行训练。而随着技术的发展,现在的算力已经可以在单卡上训练AlexNet了,且显存绰绰有余。
更多细节,将在代码实现中体现。
PyTorch 实现AlexNet代码实现时,去除了现在已经很少被使用的LRN(局部响应归一化);并且将最后一个池化层由最大池化改为自适应平均池化,这种池化方法可以将不同尺寸的输入图片固定到特定尺寸,于是就可以固定住该池化层后面紧挨着的第一个全连接层的参数(最后一个池化层到第一个全连接之间有一个flatten操作,由于池化层输出的尺寸是固定的,因此flatten后再输入到这个全连接层的神经元个数也是固定的),使用起来更加方便。
12 ...
经典卷积架构:LeNet-5
LeNet-5LeNet-5作为CNN的开山之作,在如今看来并不复杂,但在当时可以称得上是开创性的成就,并且其之后出现的许多卷积架构基本遵循LeNet-5的思想。LeNet-5的网络结构如上图所示,它最开始被用于解决手写数字识别问题。
对于一张32*32单通道手写数字图片,首先经过卷积(kernel_size: 5)得到6张28*28的特征图,然后做下采样(池化,kernel_size=2,stride=2)将特征图尺寸减半;接着经过一顿卷,得到120张1*1的特征图;将其展平,得到120维的向量,经过两个全连接层,输出10维的向量,代表该图片中的数字取值的概率(取值集合为0到9)。
当然,卷积与池化操作之间做了激活操作,在当时用的Simoid和Tanh。在稍后的代码实现中,我们会改成现在更常用的ReLU。更多细节,将在代码实现中体现。
PyTorch 实现LeNet-5123456789101112131415161718192021222324252627282930import torchimport torch.nn as nnclass LeNet(nn.Module): ...
图像数据的标准化
对于一份图像数据集,在送入模型之前,往往需要做些预处理操作,标准化便是常用的一种预处理操作,它能够起到加速模型收敛的作用。
标准化公式为:$$\frac{X-X_{mean}}{X_{std}}$$其中,$X$是原数据集,$X_{mean}$和$X_{std}$分别代表原数据的均值和标准差。
从表格数据的标准化说起对于表格数据,只需分别计算每列的均值和标准差即可。举个栗子,假设某数据集X如下:
.
feature1
feature2
样本1
1
30
样本2
1.5
45
样本3
0.9
35
则:
第一个特征的均值为$$(1+1.5+0.9)/3=1.133$$第二个特征的均值为$$(30+45+35)/3=36.66$$第一个特征的标准差为$$\sqrt{[(1-1.133)^2+(1.5-1.133)^2+(0.9-1.133)^2]/3}=0.2624$$第二个特征的标准差为$$\sqrt{[(30-36.66)^2+(45-36.66)^2+(35-36.66)^2]/3}=6.236$$
于是,该数据集的均值为$[1.133,36.66]$,标准差为 ...
目标检测中的非极大抑制+PyTorch实现
什么是非极大抑制?在目标检测中,为了提升召回率,通常的检测结果中会出现一个目标对应多个框的结果。
每个框对应的数字代表置信度,通俗来说,就是代表有多大把握确定框内有目标,取值越大,说明越有把握。
但是,对于我们来说,每个目标只需要一个对应框就足够了,因此需要从这么多框中选出最好的,非极大抑制(NMS)就是用来解决这个问题的。
对于只含有一类目标的图片来说,非极大抑制的步骤如下:
(0)设定一个置信度阈值thres和一个IoU阈值iou_thres,删除置信度小于thres的框;
(1)按照置信度对这些框从大到小排序;
(2)取出置信度最大的框放在一边,并将此框与其余的框求IoU,对于其余的框,只保留IoU小于IoU_thres的框;
(3) 重复(1)(2),最后剩余的框(也就是取出来的框)就是非极大抑制得到的结果。
注意,以上步骤中,最后得到的结果可能不止一个,因为一张图片中可能有多个同类别目标。
如果是一张图片中含有不止一个类别的目标,只需分别对每个类别的目标重复上面的步骤即可。
下面通过代码实现来加深下理解。
非极大抑制的PyTorch实现12345678910111213141 ...
目标检测中的IoU理论讲解+代码实现
IoU 理论讲解在计算机中,图像的坐标系是以左上角为原点,原点向右(x轴)和向下(y轴)分别作为两个坐标轴构成的,分别代表图像的宽度(width)和高度(height)。
下面的图片中,红色框是标注好的框(Ground Truth),蓝色框是预测出来的。
那么这两个框的交集就是下面黄色填充的区域:
而两个框的并集,就是把两个框的区域合并(重叠部分+不重叠部分),就像下面这样:
IoU就是交集区域面积与并集区域面积的比值,其计算公式如下:$$IoU=\frac{交集}{并集}$$
假设已知每个框的左上角坐标和右下角坐标,具体地,用[x1,y1,x2,y2]代表蓝色框的坐标,用[xx1,yy1,xx2,yy2]代表红色框的坐标:
现在来确定交集的左上角和右下角的坐标:
左上角坐标为$(max(x1,xx1),max(y1,yy1))$右下角坐标为$(min(x2,xx2),min(y2,yy2))$
那么两者的交集区域面积为:$$[min(y2,yy2)-max(y1,yy1)]*[min(x2,xx2)-max(x1,xx1)]$$
当两者无交集时,上式的乘法中有一项为负数,我们可以规定 ...
手把手教你打造一个汽车检测器!
本文将带你打造一个汽车检测器,使用的算法是PyTorch版本的YOLOV3。本文不会讲解该算法的细节,而是专注于如何去实现自己的汽车检测器,主要包括数据下载,数据清洗,数据集制作以及训练和检测(图片检测,视频检测)等过程。即使你不知道YOLOV3是什么也没关系,这对于阅读本文几乎毫无影响。
数据集下载为了检测汽车,首先需要获取含有汽车的标注好的数据集,这里我选择了KITTI。由于官网下载太慢,推荐使用下面的百度云链接进行下载。
下载KITTI数据集:https://pan.baidu.com/s/1t3TXXkqVR4NGqZwQiGEIzg提取码:cw35
源码来自Github开源项目https://github.com/eriklindernoren/PyTorch-YOLOv3,为了适应本文的内容,我将其做了些许更改,一并上传到了百度云,在公众号后台回复"detect"直达下载地址。
数据清洗在主目录PyTorch-YOLOv3-master下新建文件夹datasets,在datasets中新建四个文件夹:train_image,train_label,pr ...