每月笔记之2019年11月

1、信息量用来衡量一个事件的不确定度,熵则用来衡量一个系统(也就是所有事件)的不确定度。
对于一个随机变量X,它所有可能取值的信息量的期望E[I(x)]就称为熵。
相对熵的意义就很明确了:DKL(p||q)表示在真实分布为p的前提下,使用q分布进行编码相对于使用真实分布p进行编码(即最优编码)所多出来的bit数。

2、YOLOv3中网络结构(Darknet-53)一方面基本采用全卷积(YOLO v2中采用pooling层做feature map的sample,这里都换成卷积层来做了),另一方面引入了residual结构(YOLO v2中还是类似VGG那样直筒型的网络结构,层数太多训起来会有梯度问题,所以Darknet-19也就19层,因此得益于ResNet的residual结构,训深层网络难度大大减小,因此这里可以将网络做到53层,精度提升比较明显)。

3、yolo_v2的做法是既有保守又有激进,x和y直接暴力预测,而w和h通过bounding box prior的调整来确定。

4、anchor机制只是试验性在yolo_v2上铺设,一旦有了dimension priors就把anchor抛弃了。最后达到78.6mAP的成熟模型上也没用anchor boxes。

5、python中双冒号用法::
关于[::]操作,在list中可以用在元素层面,在numpy的数学数据中可以用在任何层面。
使用方法[start: end : step ],也就是[ 起始下标 : 终止下标 : 间隔距离 ]
切片范围是: start <= x < end, (注:一个带等于一个不带等于) [::2]是指从0开始间隔为2取数一直到最后
定义一:在list里面,只存在元素,不存在元素中的元素;list里元素就是最小的成分,不可以再切片。 (比如2行2列,2行是该倆元素)
定义二:在array中(numpy的数据都可以)最后一个维度的数据才可以叫做元素,同样元素不可切分。

6、 eps = np.finfo(height.dtype).eps 取符合height.dtype类型的最小正数,保证分母不为零 以及 log内不为负

7、numpy.prod()这个函数吧,这个函数是连乘操作,将里面所有的元素相乘。
比如:a = numpy.array([1,2,3,4])
那么:numpy.prod(a) = 24
还有:numpy.prod(a[2:3]) = 3#所有的区间都是左闭右开的,所以只有3了
同理:numpy.prod(a[1:3]) = 6。
有这三个例子,就应该可以对这个函数有个大概的理解了

8、语法:X,Y = numpy.meshgrid(x, y) #用来快速生成坐标矩阵,大X,Y的数量是相同的,一个表示所有点的横坐标,一个表示所有点的纵坐标。 矩阵大小也就是图的大小
输入的x,y,就是网格点的横纵坐标列向量(非矩阵)
输出的X,Y,就是坐标矩阵。

9、Python中列表list,元祖tuple和numpy中的array
列表是可以改变的,能够增加或减少,(append和del函数),且其中数据类型可以不一样,而array的中的类型必须全部相同,在list中的数据类型保存的是数据的存放的地址,简单的说就是指针,并非数据,这样保存一个list就太麻烦了,例如list1=[1,2,3,‘a’]需要4个指针和四个数据,增加了存储和消耗cpu。
元祖tuple和列表十分相似,不过元组是不可变的。即你不能修改元组。元组通过圆括号中用逗号分隔的项目定义。元组通常用在使语句或用户定义的函数能够安全的采用一组值的时候,即被使用的元组的值不会改变。元组可以嵌套。
Numpy中封装的array有很强大的功能,里面存放的都是相同的数据类型

10、在一开始阅读源码的时候,我常常把Faster RCNN中用到的三个Creator弄混。
AnchorTargetCreator : 负责在训练RPN的时候,从上万个anchor中选择一些(比如256)进行训练,以使得正负样本比例大概是1:1. 同时给出训练的位置参数目标。 即返回gt_rpn_loc和gt_rpn_label。
ProposalTargetCreator: 负责在训练RoIHead/Fast R-CNN的时候,从RoIs选择一部分(比如128个)用以训练。同时给定训练目标, 返回(sample_RoI, gt_RoI_loc, gt_RoI_label)
ProposalCreator: 在RPN中,从上万个anchor中,选择一定数目(2000或者300),调整大小和位置,生成RoIs,用以Fast R-CNN训练或者测试。

其中AnchorTargetCreator和ProposalTargetCreator是为了生成训练的目标,只在训练阶段用到,ProposalCreator是RPN为Fast R-CNN生成RoIs,在训练和测试阶段都会用到。三个共同点在于他们都不需要考虑反向传播(因此不同框架间可以共享numpy实现)

11、###Numpy 中clip函数的使用
numpy.clip(a, a_min, a_max, out=None) 用过之后,a这个数组中值最大为a_max,最小为a_min

12、Python 函数 -slice(),,slice() 函数实现切片对象
class slice(start, stop, step)

13、argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y
注:输出的是索引

np.argsort()[num]
ps:这里的num的绝对值小于等于x中元素的个数
当num>=0时,np.argsort()[num]就可以理解为y[num];
当num<0时,np.argsort()[num]就是把数组y的元素反向输出,如有y[-1] 即输出最大值的索引

14、numpy中np.max和np.maximum
np.max(a, axis=None, out=None, keepdims=False)
求序列的最值:最少接受一个参数,axis默认为axis=0即列向,如果axis=1即横向

np.maximum(X, Y, out=None)
X和Y逐位进行比较,选择最大值:最少接受两个参数

15、
Python中的 // 与 / 的区别
" / " 表示浮点数除法,返回浮点结果;
" // " 表示整数除法,返回不大于结果的一个最大的整数   
(6 // 4 = 1 , 6 / 4 =1.5)

16、pytorch中卷积层和全连接层的初始化
for m in model.modules():
if isinstance(m,nn.Conv2d):
nn.init.normal(m.weight.data)
nn.init.xavier_normal(m.weight.data)
nn.init.kaiming_normal(m.weight.data)#卷积层参数初始化
m.bias.data.fill_(0)
elif isinstance(m,nn.Linear):
m.weight.data.normal_()#全连接层参数初始化

17、voc评价指标: iou_thresh (float): A prediction is correct if its Intersection over
Union with the ground truth is above this value. (一般为0.5)

18、numpy关于copy有三种情况,完全不复制、视图(view)或者叫浅复制(shallow copy)和深复制(deep copy)

b = a 和 b = a[:] 的差别就在于后者会创建新的对象,前者不会。两种方式都会导致 a 和 b 的数据相互影响。

要想不让 a 的改动影响到 b,可以使用深复制:
unique_b = a.copy()

19、a = np.unique(A)
对于一维数组或者列表,unique函数去除其中重复的元素,并按元素由大到小返回一个新的无元素重复的元组或者列表

20、我们知道python 本来就是用c写的,最近刚好看过源码(一切皆对象)由于其本身特性和高级语言等原因,运行速度是一直是一个问题。虽然pytorch是用C加速和CUDA运算,但是NMS这一块需要我们自己写,用python速度很慢,这里作者结合了Cupy cuda编程 和Cython结合,写出了nms.
Cupy是numpy的一个加速cuda计算库,可以将Numpy放到gpu计算,Cython则是将python代码编译成C语言,C编译器将.c文件编译链接成pyd拓展模块,这样对象的类型大小在编译时就可以确定,会加速很多。官网是这样说的
A .pyx file is compiled by Cython to a .c file, containing the code of a Python extension module.
The .c file is compiled by a C compiler to a .so file (or .pyd on Windows) which can be import-ed directly into a Python session.
win上生成pyd linux生成.so 动态链接库 可以被python直接导入(实际上好多库的函数都是这么干的…python实在太慢了)

21、cupy与numpy函数库无太大差异,np.函数 在cp上也都有,用法也一样 只不过一个在gpu计算 一个在本地计算

22、Cython写法 与python没什么不同 声明一些变量类型而已
Cpython会自动帮我们依据半python代码(pyx)将此pyx编译成.c c编译器会再次编译.c文件生成我们要的动态链接库.so

23、Python中@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

@property的实现比较复杂,把一个getter方法变成属性,只需要加上@property就可以了,此时@property本身又会创建另外一个装饰器@score.setter,负责把set方法变成给属性赋值,这么做完后,我们调用起来既可控又方便,这样调用时候不用使用类内的get函数调用,而是直接当成属性调用,如s.score

24、 score经过softmax后就是这个框的prob

25、voc中AP的计算:
方法一:在VOC2010以前,只需要选取当Recall >= 0, 0.1, 0.2, …, 1共11个点时的Precision最大值,然后AP就是这11个Precision的平均值。

方法二:在VOC2010及以后,需要针对每一个不同的Recall值(包括0和1),选取其大于等于这些Recall值时的Precision最大值,然后计算PR曲线下面积作为AP值。

26、卡阈值作为正负样本的判定依据,阈值较高时,Precision比较大,阈值较低时,Recall较大。(推荐的话,想Precision较大,用户希望排名靠前的推荐是自己想要的,刑侦的话希望Recall较大,不错过一个犯人)

27、机器翻译,自然语言处理,计算机视觉领域的注意力机制差不多,但是其实仔细推敲起来,这三者的注意力机制是有明显区别的。
在机器翻译领域,翻译人员需要把已有的一句话翻译成另外一种语言的一句话。例如把一句话从英文翻译到中文,把中文翻译到法语。在这种情况下,输入语言和输出语言的词语之间的先后顺序其实是相对固定的,是具有一定的语法规则的;
在视频分类或者情感识别领域,视频的先后顺序是由时间戳和相应的片段组成的,输入的就是一段视频里面的关键片段,也就是一系列具有先后顺序的图片的组合。NLP 中的情感识别问题也是一样的,语言本身就具有先后顺序的特点;
图像识别,物体检测领域与前面两个有本质的不同。因为物体检测其实是在一幅图里面挖掘出必要的物体结构或者位置信息,在这种情况下,它的输入就是一幅图片,并没有非常明显的先后顺序,而且从人脑的角度来看,由于个体的差异性,很难找到一个通用的观察图片的方法。由于每个人都有着自己观察的先后顺序,因此很难统一成一个整体。

28、计算机视觉里的注意力机制:
在门牌识别里面,该网络是按照从左到右的顺序来进行图片扫描的,这与人类识别物品的方式极其相似。除了门牌识别之外,该论文也对手写字体进行了识别,同样取得了不错的效果。

29、通过ReLU实现稀疏后的模型能够更好地挖掘相关特征,拟合训练数据。
(猜想:可能正是因为用的是relu激活函数,导致feature map中的大部分值为0 处于不激活状态,那想要加注意力机制的话是不是应该换一个激活函数)

30、首先有一个共识必须先提出:神经网络如果保持每层的信息流动是同一方差,那么会更加有利于优化。不然大家也不会去争先恐后地研究各种normalization方法。
不过,Xavier Glorot认为还不够,应该增强这个条件,好的初始化应该使得各层的激活值和梯度的方差在传播过程中保持一致,这个被称为Glorot条件。
如果反向传播每层梯度保持近似的方差,则信息能反馈到各层。而前向传播激活值方差近似相等,有利于平稳地学习。

31、Xavier初始化虽然美妙,但它是针对tanh函数设计的,而激活函数现在是ReLU的天下,ReLU只有一半的激活,
另一半是不激活的,relu激活函数对应He初始化。

32、数据经过归一化和标准化后可以加快梯度下降的求解速度,这就是Batch Normalization等技术非常流行的原因,它使得可以使用更大的学习率更稳定地进行梯度传播,甚至增加网络的泛化能力。

33、在深度学习中,因为网络的层数非常多,如果数据分布在某一层开始有明显的偏移,随着网络的加深这一问题会加剧(这在BN的文章中被称之为internal covariate shift),进而导致模型优化的难度增加,甚至不能优化。所以,归一化就是要减缓这个问题。

34、在深度学习中,因为网络的层数非常多,如果数据分布在某一层开始有明显的偏移,随着网络的加深这一问题会加剧(这在BN的文章中被称之为internal covariate shift),进而导致模型优化的难度增加,甚至不能优化。所以,归一化就是要减缓这个问题。

35、如果输出的blob大小为(N,C,H,W),那么BN在每一层normalization就是基于NHW个数值进行求平均以及方差的操作,记住这里我们后面会进行比较。(通道分离操作)
BN带来的好处:
(1) 减轻了对参数初始化的依赖,这是利于调参的朋友们的。
(2) 训练更快,可以使用更高的学习率。
(3) BN一定程度上增加了泛化能力,dropout等技术可以去掉。

36、这么多的Normalization怎么使用呢?有一些基本的建议吧,不一定是正确答案。
(1) 正常的处理图片的CNN模型都应该使用Batch Normalization。只要保证batch size较大(不低于32),并且打乱了输入样本的顺序。如果batch太小,则优先用Group Normalization替代。
(2)对于RNN等时序模型,有时候同一个batch内部的训练实例长度不一(不同长度的句子),则不同的时态下需要保存不同的统计量,无法正确使用BN层,只能使用Layer Normalization。
(3) 对于图像生成以及风格迁移类应用,使用Instance Normalization更加合适。

37、之所以只说Batch Normalization,是因为上面的这些方法的差异主要在于计算normalization的元素集合不同。Batch Normalization是NHW,
Layer Normalization是CHW,
Instance Normalization是HW,
Group Normalization是G
H*W。

38、除了极大极小值,还有一类值为“鞍点”,简单来说,它就是在某一些方向梯度下降,另一些方向梯度上升,形状似马鞍,对于深度学习模型的优化来说,鞍点比局部极大值点或者极小值点带来的问题更加严重。
目前常用的优化方法分为一阶和二阶,这里的阶对应导数,一阶方法只需要一阶导数,二阶方法需要二阶导数。
常用的一阶算法就是:随机梯度下降SGD及其各类变种了。
常用的二阶算法就是:牛顿法等。

39、下面我们要形成共识,说sgd算法,实际上指的就是mini-batch gradient descent算法,没有人会去一次拿整个数据集或者一个样本进行优化。

40、深度学习中的优化方法:看起来好像都不如SGD算法,实际上这是一个很普遍的现象,各类开源项目和论文[3-4]都能够印证这个结论。
总体上来说,改进方法降低了调参工作量,只要能够达到与精细调参的SGD相当的性能,就很有意义了,这也是Adam流行的原因。但是,改进策略带来的学习率和步长的不稳定还是有可能影响算法的性能,因此这也是一个研究的方向,不然哪来这么多Adam的变种呢。

41、在这个基础上,他们就做实验了,结果如下,c表示卷积,p表示pooling,aug表示数据增强,所以这里就是比较pooling和aug对性能的影响,结果表明池化不池化的,好像没有什么用,而数据增强做不做得好,才是关键。结果说明CNN本身没什么平移不变性,是靠数据学来的。
暂且先总结一下吧:池化什么的不重要了,搞数据增强才是正道。

42、这是我们最熟悉的,通常认为如果选取区域均值(mean pooling),往往能保留整体数据的特征,较好的突出背景信息;如果选取区域最大值(max pooling),则能更好保留纹理特征。

43、带步长的卷积虽然不需要池化,却没有了灵活的激活机制。平均池化稳扎稳打,却丢失了细节。最大池化克服了平均池化的缺点,却打断了梯度回传。
最终发现,池化也还是要学的好,所谓随机应变,盖莫如此。另外,如何选择好用于池化的区域,也是一门学问。

44、式子中的R(f),正是为了约束模型的表达能力,f是模型,R是一个跟模型复杂度相关的函数,单调递增。
有同学可能会说,模型的表达能力跟模型大小,也就是参数量有关,限制模型的表达能力不是应该去调整模型大小吗?这里咱们从另一个角度来看模型的能力问题。
如果我们限制一层神经网络的参数只能为0或者1,它的表达能力肯定不如不做限制,所以同样的参数量,模型的表达能力与参数本身也有关系,正则项就可以在参数上做文章。(袁彦博那个是不是相当于限制了参数,加入了正则化???)
所以说正则化就用于提高模型的泛化能力,这里所说的仅仅是狭义上的参数正则化,而广义上的正则化方法众多,第3部分进行介绍。
正则化的最终目标用一句土话来说,就是让网络学的不要太死,否则变成僵硬的书呆子。

45、实验表明,隐式的方法比显式的方法(显示是指 dropout L1/L2正则化等方法)更强,从batch normalization的使用替换掉了dropout,以及数据扩增碾压一切trick就可以看出。另外,批量随机梯度算法本身,也可以算是一种隐式的正则化方法,它随机选择批量样本而不是整个数据集,与上面的dropout方法其实也有异曲同工之妙。
这么看来,其实data dependent方法更好,咱们前面的几期都说过,不要闷着头设计,从数据中学习才是王道。

46、我一直觉得直接比较不同batch size下的绝对收敛精度来衡量batch size的好坏是没有太大意义的,因为不同的batch size要配合不同的调参策略用才能达到其最佳效果,而要想在每个batch size下都找到合适的调参策略那可太难了,所以用这种方法来决定batch size未免有点武断。
链接:https://zhuanlan.zhihu.com/p/86529347

47、Cascade R-CNN中提到的mismatch问题:
我们可以明显的看到training阶段和inference阶段,bbox回归器的输入分布是不一样的,training阶段的输入proposals质量更高(被采样过,IoU>threshold),inference阶段的输入proposals质量相对较差(没有被采样过,可能包括很多IoU<threshold的),这就是论文中提到mismatch问题,这个问题是固有存在的,通常threshold取0.5时,mismatch问题还不会很严重。

48、RON的anchor attention机制是啥??

49、这里稍微对比下RefineDet与frcnn的区别:
(1) frcnn通过1-stage的RPN对anchor做了第一次调整,再通过2-stage的Fast RCNN做2-stage的调整,anchor的分类、回归是在两个分支上,独立地完成的;1、2-stage间的特征通过RoI pooling衔接;
(2) RefineDet中ARM的操作与RPN类似,但ARM上的特征通过TCB传至ODM(TCB在操作上与DSSD、FPN类似,top-down地融合了高低层feature map特征),并通过ARM上输出的anchor objectness得分,避免了在ODM上预测所有anchor,达到了文中提到的减少anchor搜索空间之目的(有点类似RON中的objectness attention操作),并做了1-stage的anchor调整;ODM上的操作就与SSD类似了,输出目标位置和分类,做了2-stage的anchor调整,且ARM指导了ODM没必要对所有anchor都做此类预测;

训练阶段,对于一个refined anchor,且其gt label为负样本,如果ARM中预测其objectness得分小于某阈值(“真实” 负样本轻易地被模型判定为non-object,太容易了,还是不要给模型训练为好,不然模型容易骄傲~~~),在ODM训练阶段就直接舍弃之;也即,只有ARM输出的refined 难分负样本 + 所有正样本参与到ODM的训练;
注:这点作者讲得不详细,其实跟OHEM策略类似,目标就是为了找到难分负样本,一方面使得正负样本数量均衡,另一方面在易分负样本上训练没啥意思,自然需要找到难分负样本,给模型的训练带来挑战;那么ARM中所有参与训练的负样本,我们自然希望找到objectness得分高的负样本(objectness得分高,就意味着该负样本被模型误判为object了,自然得进一步训练,以纠正模型的这种误操作),过滤objectness得分低的负样本(模型轻易就判别出该负样本是non-object了,可以不用再学了);

Inference
测试阶段,ARM首先对所有密集采样的anchor,通过objectness得分过滤到判别为背景的anchor(filters out the regularly tiled anchors with the negative confidence scores > thres),对剩余anchor做位置、尺度refine(第一次refine);TCB转换特征后,ODM进一步利用剩余的anchor采用SSD这种直接预测具体类别 + bbox位置的方式操作一波(第二次refine),最终输出top400置信度得分的bboxes,再通过IoU = 0.45的NMS操作,并保留最多200个bboxes作为最终检测结果;

50、2019年目标检测还可以做的方向:
(1)改Conv,Conv不一定最适合目标检测这个任务,它对旋转和尺寸变换不鲁邦啊
(2)要不attention走起来,我不是说加几层网络然后乘起来那种,是不是可以 shape bias ,part-aware,relation of part and whole,怼遮挡,视角,光照?
(3)改训练方法啊,gradient-based BP算法一定好么?搞个二阶的?

如果我理解没错,lecun bengio hinton就是做这些拿的图灵奖,所以:如果真的做纯目标检测,必须去硬啃骨头了。
(转载:https://www.zhihu.com/question/351254577/answer/861582672)

51、Rethink Anchor思考与总结(参考链接:https://zhuanlan.zhihu.com/p/91261916)
(1)Anchor based中通过设置IoU阈值来进行正负样本的判定,这是否是最合适的方法。首先它是一个待调的超参,并不是用一个0.5,或者0.3和0.7就可以cover所有cases。Cascade R-CNN,Guide Anchor中已经明确指出,当生成了更高质量的proposal/(2)Anchor时,需要增大正样本的IoU阈值,才可获得好的效果。
将不同scale的物体指定到不同level的feature上进行检测是否是最合适的方法。TridentNet为解决multi-scale提供了一个非常好的思路,显式的将scale剥离开来,与不同的layer做严格的align,同时尽量去学习一些common knowledge。其实SNIP也是在做align。
(3)Anchor free框架可以说是极其优美了。以FCOS为例,将检测完全转换为了 per-pixel prediction框架,更加适应multi-task,PolarMask便是一篇结合instance seg的尝试。
(4)Anchor free虽说性能好,但是离cascade的detector还是有一定差距。此外,速度上优势也不够明显。为保证高Recall,要使用高分辨率feature map,引入FPN使得在边缘端使用变得更加困难。

52、

发布了71 篇原创文章 · 获赞 56 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/j879159541/article/details/103326669