一文看尽物体检测中的各种FPN

早期的物体检测算法,无论是一步式的,还是两步式的,通常都是在Backbone的最后一个stage(特征图分辨率相同的所有卷积层归类为一个stage)最后一层的特征图,直接外接检测头做物体检测。此种物体检测算法,可以称之为单stage物体检测算法。

由于单stage物体检测算法中,Backbone的最后一个stage的stride通常是32,导致输出的特征图分辨率是输入图片分辨率的1/32,太小,不利于物体检测,因此单stage的物体检测算法,一般会将最后一个stage的MaxPooling去掉或者将stride为2的conv改为stride为1的conv,以增大最后一个分辨率。

后来研究发现,单stage物体检测算法中,无法用单一stage的特征图同时有效的表征各个尺度的物体,因此,后来物体检测算法,就逐渐发展为利用不同stage的特征图,形成特征金字塔网络(feature parymid network),表征不同scale的物体,然后再基于特征金字塔做物体检测,也就是进入了FPN时代。

本文将认真梳理物体检测中常用的各种FPN。

解构物体检测各个阶段

我们常见的物体检测算法,其实可以分解为三个递进的阶段:

1)Backbone生成特征阶段

计算机视觉任务一般都是基于常用预训练的Backbone,生成抽象的语义特征,再进行特定任务微调。物体检测也是如此。

Backbone生成的特征,一般按stage划分,分别记作C1、C2、C3、C4、C5、C6、C7等,其中的数字与stage的编号相同,代表的是分辨率减半的次数,如C2代表stage2输出的特征图,分辨率为输入图片的1/4,C5代表,stage5输出的特征图,分辨率为输入图片的1/32。

2)特征融合阶段

这个是FPN特有的阶段,FPN一般将上一步生成的不同分辨率特征作为输入,输出经过融合后的特征。输出的特征一般以P作为编号标记。如FPN的输入是,C2、C3、C4、C5、C6,经过融合后,输出为P2、P3、P4、P5、P6。这个过程可以用数学公式表达:

3)检测头输出bounding box
FPN输出融合后的特征后,就可以输入到检测头做具体的物体检测。

大致可以由下图表达。

FPN的演进

物体检测性能提升,一般主要通过数据增强、改进Backbone、改进FPN、改进检测头、改进loss、改进后处理等6个常用手段。

其中FPN自从被提出来,先后迭代了不少版本。大致迭代路径如下图:

1)无融合

无融合,又利用多尺度特征的典型代表就是2016年日出的鼎鼎有名的SSD,它直接利用不同stage的特征图分别负责不同scale大小物体的检测。

2)自上而下单向融合

自上而下单向融合的FPN,事实上仍然是当前物体检测模型的主流融合模式。如我们常见的Faster RCNNMask RCNNYolov3RetinaNetCascade RCNN等,具体各个FPN的内部细节如下图。

a)Faster/Master/Cascade RCNN中的FPN

Faster/Master/Cascade RCNN中的FPN,利用了C2-C6五个stage的特征,其中C6是从C5直接施加1x1/2的MaxPooling操作得到。FPN融合后得到P2-P6,其中P6直接等于C6,P5是先经过1x1Conv,再经过3x3Conv得到,P2-P4均是先经过1x1Conv,再融合上一层2xUpsample的特征,再经过3x3Conv得到。具体过程可以看上图。

b)RetinaNet中的FPN

RetinaNet中的FPN,利用了C3-C7五个stage的特征,其中C6是从C5直接施加3x3/2的Conv操作得到,C7是从C6直接施加3x3/2的Conv操作得到。FPN融合后得到P3-P7,其中P6、P7直接等于C6、C7,P5是先经过1x1Conv,再经过3x3Conv得到,P3-P4均是先经过1x1Conv,再融合上一层2xUpsample的特征,再经过3x3Conv得到。具体过程可以看上图。

可以看出,RetinaNet基本与Faster/Master/Cascade RCNN中的FPN一脉相承。只是利用的stage的特征略有差别,Faster/Master/Cascade RCNN利用了高分辨率低语义的C2,RetinaNet利用了更低分辨率更高语义的C7。其他都是细微的差别。

c)Yolov3中的FPN

Yolov3中的FPN与上述两个有比较大的区别。首先,Yolov3中的FPN只利用到了C3-C5三个stage的特征;其次,从C5征到P5特征,会先经过5层Conv,然后再经过一层3x3Conv;最后,C3-C4到P3-P4特征,上一层特征会先经过1x1Conv+2xUpsample,然后先与本层特征concatenate,再经过5层Conv,之后经过一层3x3Conv。看图最清楚。

可以看图仔细对比Yolov3与Faster/Master/Cascade RCNN以及RetinaNet细节上的区别。

3)简单双向融合

FPN自从提出来以后,均是只有从上向下的融合,PANet是第一个提出从下向上二次融合的模型,并且PANet就是在Faster/Master/Cascade RCNN中的FPN的基础上,简单增了从下而上的融合路径。看下图。

4)复杂的双向融合

PANet的提出证明了双向融合的有效性,而PANet的双向融合较为简单,因此不少文章在FPN的方向上更进一步,尝试了更复杂的双向融合,如ASFFNAS-FPNBiFPN

ASFF
ASFF(论文:Learning Spatial Fusion for Single-Shot Object Detection)作者在YOLOV3的FPN的基础上,研究了每一个stage再次融合三个stage特征的效果。如下图。其中不同stage特征的融合,采用了注意力机制,这样就可以控制其他stage对本stage特征的贡献度。

NAS-FPN和BiFPN
NAS-FPN和BiFPN,都是google出品,思路也一脉相承,都是在FPN中寻找一个有效的block,然后重复叠加,这样就可以弹性的控制FPN的大小。

其中BiFPN的具体细节如下图。

Recursive-FPN
递归FPN是此文写作之时前两周刚刚新出炉的(原论文是DetectoRS: Detecting Objects with Recursive Feature Pyramid and Switchable Atrous Convolution),效果之好令人惊讶,使用递归FPN的DetectoRS是目前物体检测(COCO mAP 54.7)、实体分割和全景分割的SOTA,太强悍了。

递归FPN理解起来很容易,就是将传统FPN的融合后的输出,再输入给Backbone,进行二次循环,如下图。

下图给出了FPN与Recursive-FPN的区别,并且把一个2层的递归FPN展开了,非常简单明了,不做过多介绍。

5)M2det中的SFAM

M2det中的SFAM,比较复杂,它是先把C3与C5两个stage的特征融合成一个与C3分辨率相同的特征图(下图中的FFM1模块),然后再在此特征图上叠加多个UNet(下图中的TUM模块),最后将每个UNet生成的多个分辨率中相同分辨率特征一起融合(下图中的SFAM模块),从而生成最终的P3、P4、P5、P6特征,以供检测头使用。具体如下图。

每一个模块的详细细节如下图。

思考

FPN的优化会显著带来物体检测的性能提升,当前最好的FPN是递归FPN,期待将来更有效的FPN出现。

最近Facebook出了一篇文章object detection by transformer,如果transformer与各种强大的FPN结合,效果如何还是值得期待。

参考文献

  1. SSD: Single Shot Multibox Detector
  2. Faster RCNN: Towards Real-Time Object Detection with Region Proposal Networks
  3. Mask RCNN
  4. Yolov3: An Incremental Improvement
  5. RetinaNet: Focal Loss for Dense Object Detection
  6. Cascade RCNN: Delving into High Quality Object Detection
  7. PANet: Path Aggregation Network for Instance Segmentation
  8. ASFF: Learning Spatial Fusion for Single-Shot Object Detection
  9. NAS-FPN: Learning Scalable Feature Pyramid Architecture for Object Detection
    10.BiFPN: (EfficientDet: Scalable and Efficient Object Detection)
    11.DetectoRS: Detecting Objects with Recursive Feature Pyramid and Switchable Atrous Convolution
    12.SFAM(M2det: A single-shot object detector based on multi-level feature pyramid network)

一劳永逸的财富观

面对每天为生计奔波操劳,动辄996、997,我想不少人曾梦想着不劳而获。希望在家躺着,工资照发,希望周游世界,工资照发。也曾幻想有一天老爸突然一通打电话过来,悄悄地告诉自己其实是个富二代,并以命令的口吻说“少爷回家接班”。然而面对残酷的现实,该996还是得996。

完完全全的不劳而获,其实就是踩狗屎运,如中彩票了,家里拆迁了,突然爆红了,公司要上市了等等,这种可遇不可求。我们普通人能够通过努力获得的不劳而获,其实叫做「一劳永逸」。不是不付出就获得收获,而是努力一次,从此均有收获。

我曾经听过最佳的「一劳永逸」获得财富的例子,就是考证。一级注册结构工程师证,挂靠价格大约13万一年,一级注册岩土工程师证,14万一年,等等。一次考证,终生受用。真正的一劳永逸,或者真正的不劳而获。前些年,证书挂靠不严格的时候,如果一身多证,每年能有大几十万的不需要任何付出的收入,也难怪那么多考证狂魔,我也心生羡慕。近些年,证书挂靠市场被整治,然而影响其实不大,咱们中国人不缺的就是投机取巧的办法。然而证书,不是想考就能考的。

其实「一劳永逸」的机会非常多,有些甚至就在我们身边,只是被大家有意或者无意的忽视了。比如上大学,只要大学毕业了,大学生的身份足以让你一辈子受用。比如曾经做过很复杂很成功的项目,导致你的能力上了台阶,那么走到哪里均会一直吃这次项目的红利,毕竟能力上去了就很难下来了。比如你的微博成了大V,那么无论你怎么折腾,粉丝都很难离你而去。比如你读了某本书,茅塞顿开,你的价值观从此得到改变,那这个价值观会一直影响你的人生。

「一劳永逸」讲的是缓慢积累的成长后的突破,讲的是不可逆的变化。这提示我们,在职业生涯中,如果有些坎一定要突破,那么要竭尽全力去加速突破,一旦突破了,获得的是一种新生,别磨磨蹭蹭,天天划水,让自己经常处于劳而无获的状态。

证券类投资领域的「一劳永逸」,我认为是找到一个优质标的,等着它高速成长,给自己带来显著的财富。而不是整天盯着做波段,追涨杀跌。如果把自己注意力,一直放在行情波动上,投入过多的精力,当然有可能有所得,但对于像我这样的普通人,更多的是劳而大亏,连劳而无获都做不到。

我是比特币死忠粉,我当前在比特币领域的投资策略是,定投+等待抄底。我认为最好买入策略是别人特别恐慌的时候抄底,如313,而非定投。但定投可以保证获得基本收益,而且可以让我保持关注度。现在我很少盯盘,很少操作,主要精力还是放在工作上,当前收益尚可,我想这就是所谓的一劳永逸吧!

都看到这里了,还不关注和转发一个!

当前深度学习算法工程师的职业天花板

从事一个职业方向一定要仔细思考这个职业方向的未来和天花板,方便自己的职业规划,甚至是职业选择。今天我想好好聊聊我当前正在从事的深度学习算法工程师这个非常热门的职业方向的天花板。

我认为,一个职业方向的天花板,根本取决于这个职业方向所能创造或者带动的社会价值,其次才取决于它在它所属的产品形态中所占据的地位。比如后端,因为每一个跟网络相关的产品,都需要强大的后端支撑,后端能创造出巨大的社会价值,同时后端在具体的互联网产品中占据数据中心的核心地位,因此后端的天花板很高,CEO大多出自后端。又比如iOS移动端,移动互联网的崛起,让iOS也创造出了巨大的社会价值,但iOS在移动端的产品形态中,只是偏于一端,不具有全局统筹的作用,因此天花板就稍微低一点,一般上限可能就是iOS团队负责人。

深度学习是一个比较尴尬的职业方向,我一直认为AI是一个大骗局,原因在于当前深度学习有以下几大明显缺陷,限制了它的落地。

1)性能瓶颈
别看各大模型在公开数据集上的成绩有多惊艳,一旦遇到真实复杂多变的环境,都歇菜,准确度会显著下降。这是深度学习本身固有缺陷所导致的。而很多应用对准确度的要求非常高。
深度学习本质是拟合训练样本分布。我们一般假设训练样本充分采样于真实的应用场景,这样训练样本分布基本与真实应用场景的同分布。然而事实上训练样本对于真实世界都是欠采样的,不能充分代表真实世界的数据分布,因此在真实复杂多变的环境,性能就会比较差。至于为啥是欠采样,本质还是因为数据是高维的,高维采样非常困难,或者换个说法,组合爆炸。
还有一点,深度学习学习不到规则,导致对输入的变化非常敏感,略微调整一个像素值,结果可能会发生翻天覆地的变化。而现实世界的变化是非常复杂的。
当然我不排除,在特定环境特定领域,深度学习有非常优异的表现。比如人脸、机器翻译等。我这里说的是更普遍的场景。

2)需要大规模准确标注的数据
如果想落地一个深度学习算法,通常需要大规模的标注数据,如人脸这种特殊的应用场景,确实会有公司耗费巨资去采集并标注数据,但普通公司想落地一个普通的算法,比如抽烟检测,则需要他们去建立数据集,难度是很大的。

3)速度
深度学习算法高度依赖显卡的算力,离开了显卡,深度学习龟速。即使有显卡,一般也做不到实时分析。比如我做过一个加油站项目,一个板子要跑8路摄像头,怎么可能实时分析?

4)稍微复杂的场景深度学习搞不定
深度学习并不是万能的,一般只能解决一些简单的问题。稍微复杂一点的场景,基本就搞不定。我曾经遇到过一个需求,要自动检测加油站的加油枪的线有没有拉断?深度学习怎么搞?

由于AI落地很难,所以当前AI能创造的社会价值比较有限,这会导致深度学习的岗位需求终究会由当前的过热,回归到与其价值产出匹配的位置,也就是说,会有相当一批以AI为噱头的企业倒闭,这也是我不怎么建议非科研目的去选择此方向的原因。

虽然价值有限,但对于能落地的场景,深度学习算法工程师在整个项目落地中,还是处于核心地位,但这个核心地位,只是关乎项目能不能落地,不关乎是否由深度学习算法工程师统筹全局,所以天花板基本跟移动端等类似,都是部门负责人已经到头了。虽然同样是部门负责人级别的天花板,深度学习工程师在非纯AI大公司中通常做的是锦上添花的性能优化,也就是说自我稀缺性其实是不足的,所以建议深度学习从业者,要有足够的危机意识。毕竟一个人在公司的价值,是你为公司创造了什么。

如果单论创业,深度学习方向的机会我认为也不多。

我之前由移动端转到图像识别方向,以为获得了更大的天地,如今身在其中,忽然发现,自立牢笼。

不过我依然坚持奋斗在深度学习或者机器学习方向,一大部分原因是我热爱,我热爱搞点研究,也热爱知识更新频繁的领域。况且AI当前还处于高速发展阶段,每一年都会有一些令人耳目一新的突破,参与其中,有种与时代脉搏共舞的感觉,很奇妙。

以上只是我个人片面之词,必有偏颇之处,望大家谅解。

要做短线投机之前,先做一个简单的数学题

假设任何一只新上市股票第一周,一半可能性上涨80%,一半可能性下跌60%。

现在我们搞个投资策略,每周一买一只新上市的股票,周五把它卖了。然后不断重复。

假设我们有1万本金,请问一年下来能赚多少钱?

一般会采用两种极端的策略,
a)均匀定投
把1万块等分52份,每周只用1份的钱买入新上市股票。
b)all in策略
每周均把所有的钱买入新上市股票。

你一般会采用哪种策略?All in策略看似极端,我想大部人看到上涨收益大于下跌损失,都会这么干。

我们来粗略算算,
1)对于均匀定投
期望收益: $1万\times 0.5\times (1+80\%)+1万\times 0.5\times (1-60\%)=1.1万$

2)对于all in
期望收益:每周期望收益率10%,一年下来利滚利,就是1.1的52次方,$1.1^{52}=142.0429$万。
然而你的实际回报,应该是:

52周下来,你还剩下1.95元,归零了。

这是怎么回事?

我也是看到上述非常反直觉的结果后,起了强烈的兴趣,进行了一番严谨的数学推导和研究后,方搞明白。我看到有网络文章分析说,这是遍历性的问题。这压根不是遍历性问题,这就是胜率问题。

后文有详细推导,但我想大部分人看到数学公式就眼晕,这里直接给出结论:
1)定投
对于定投,期望收益确实是1.1万,而且收益率大于0,也即最终剩下1万以上的概率是83.41%,这是相当高的胜率,也即基本不会亏钱。收益率大于期望收益率10%,也即最终剩下1.1万以上的概率是44.49%,也是相当高的。

定投的收益上限是每周都盈利,计算下来是1.8万。

2)all in
对于all in策略,你是不是怀疑期望收益计算错了?我一开始也是怀疑期望收益计算错误,然而经过严密的数学推导后发现,期望收益确实是$1.1^{52}=142.0429$万,这符合大家的直觉认知。

然而出问题的是,收益大于0,也即最终剩下1万以上的概率是6.32%,也就是亏钱概率93.68%,请问你还敢投吗?收益等于期望收益,也即最终剩下142万以上的概率是0.88%,也就是99.12%的概率你剩下的钱少于142万,请问你还敢投吗?

更进一步研究发现,亏损90%以上,也就是最终只剩下0.1万以下的概率是89.42%。亏损99%以上,也就是最终只剩下0.01万元以下的概率是75.58%,也就是说极大概率归零了。请问你还敢投吗?

为什么平均收益很高,却又大概率会归零?这是因为贫富差距过大,比如连续52次都是盈利的最终收益是$1.8^{52}=18.8$万亿倍。你我都是被平均了。这其实就是买彩票。

all in收益上限是18.8万万亿,你心动了吗?

————————————以下是详细公式推导———————————————-
————————————以下是详细公式推导———————————————-
————————————以下是详细公式推导———————————————-

如果用$x_{i}$记录第${i}$次投资,取值为1,表示盈利,取值为0,表示亏损,那么$52$次投资表示为:

一次投资如果盈利了,也即$x_{i}=1$,则收益为$(1+80\%)$,如果亏损了,也即$x_{i}=0$,则收益为$(1-60\%)$,可以统一成以下收益公式:

定投策略分析

1)期望收益

把资本按52均分,然后每一次只投入总本的1/52,这种策略俗称定投策略,这种策略的收益公式是:

那么,定投策略的最终收益期望:

也即总收益期望等于每一次投资收益期望的之和,我们计算单次投资收益期望:

那么定投策略的最终收益期望是:

2)胜率

假如52次投资中,记盈利的次数为$n$,则亏损的次数为$52-n$,那么定投策略的总收益$R(x_{1},x_{1},…,x_{52})$可以进一步简化为:

下面我们计算下对于目标收益$r_{0}$,需要盈利的次数n:

我们可以算出,当目标收益是正的,也即$r_{0}>=1.0$,那么可以算出盈利的次数至少是23。当目标收益大于期望收益$1.1$时,可以算出盈利的次数至少是27。

当知道了大于等于目标收益,所需要的盈利的次数时,我们可以计算对应的概率:

那么,如果目标收益是正的,则对应的概率:

如果想达到期望收益即1.1以上,则对应的概率:

all in策略分析

1)期望收益

每次都all in应该是挺多投资者实际采用,或者倾向于采用的投资策略,这种策略的收益公式是

那么,all in策略的最终收益期望:

也即总收益期望等于每一次投资收益期望的乘积,我们单独计算每一次投资收益期望:

那么all in策略的最终收益期望是:

可以看出all in策略的收益是指数级的,最终的平均收益是142.0429万,相当高啊。

2)胜率

假如52次投资中,记盈利的次数为$n$,则亏损的次数为$52-n$,那么all in策略的总收益$R(x_{1},x_{1},…,x_{52})$可以进一步简化为:

下面我们计算下对于目标收益$r_{0}$,需要盈利的次数n:

上式中的log可以是自然对数,也可以是以10为底的对数。

我们可以算出,当目标收益是正的,也即$r_{0}>=1.0$,那么可以算出盈利的次数至少是32。当目标收益大于期望收益$1.1^{52}=142.0429$时,可以算出盈利的次数至少是35。

当知道了大于等于目标收益,所需要的盈利的次数时,我们可以计算对应的概率:

那么,如果目标收益是正的,则对应的概率:

如果想达到期望收益即142.0429,则对应的概率:

可以进一步计算:

3)代码模拟

all in策略的平均收益过高,我一开始怀疑数学推导的可靠性,就写了python脚本做了验证。

import numpy as np
import math


def cal_profit(events, pos_earning=0.8, neg_earning=0.6):
    r = 1
    for i in events:
        r = r * ((1 + pos_earning) ** i) * ((1 - neg_earning) ** (1 - i))
    return r


def factorial(n):
    if n == 0 or n == 1:
        return 1
    else:
        return (n * factorial(n - 1))


def count_days_more_than(n, total=52):
    c = 0
    for i in range(n, total+1):
        c = c + factorial(total) / (factorial(total - i) * factorial(i))
    return c


def cal_winning_least_days(events_count=52, pos_earning=0.8, neg_earning=0.6, winning_ratio=1.0):
    winning_earning = 1 + pos_earning
    losing_earning = 1 - neg_earning
    r = (math.log(winning_ratio) - events_count *
         math.log(losing_earning)) / math.log(winning_earning / losing_earning)
    return math.ceil(r)


def cal_winning_prob(least_winning_days, events_count=52, pos_earning=0.8, neg_earning=0.6):
    return count_days_more_than(least_winning_days, total=events_count) / 2 ** events_count


if __name__ == "__main__":
    profits = []
    for _ in range(20):
        events = np.random.randint(2, size=52)
        profit = cal_profit(events)
        profits.append(profit)

    profits = np.array(profits)
    avg = profits.mean()
    var = profits - avg
    var = var * var
    var = math.sqrt(var.sum())
    print("mean: {:0.4f}, var: {:0.4f} theoretical: {:0.4f}".format(
        avg, var, 1.1**52))

    n = cal_winning_least_days(winning_ratio=0.1)
    p = cal_winning_prob(n)

    print(n, p)
    print(1.8**52)

如果把模拟次数设置成1亿次,会发现最终的均值就是数学上的理论期望收益。

下面是我们模拟20次的最终收益,可以看到大部分时候收益基本归零。

0.08007
0.08007
0.00000
0.00001
0.00004
7.29680
0.00020
0.00000
0.00020
0.00000
0.00395
0.00020
7.29680
0.36034
0.00004
0.00004
0.01779
0.00088
0.00000
0.00001

我也会在微信公众号「慢投ZI」分享个人的投资感悟,欢迎大家扫码关注。

细说EfficientNet

EfficientNet发布于2019年5月28日,发布之初就以其在图片分类上各种SOTA结果而惊艳整个CV届。有多惊艳,且看下图,简直是在各个角度吊打现有的算法模型,完全做到了又快又准。

那是不是作者做出了一些令人叹为观止的创新呢?非也,作者的思路十分朴素,四两拨千斤。

1. 利用NAS(神经网络搜索)搜索出一个更好的Backbone,也即上图中的EfficientNet-B0。
2. 对B0模型的宽度、深度和图片分辨率同时缩放,便得到了令人惊艳的B1-B7。

为什么简单缩放就能得到极其优异的模型呢?

这就是作者的核心创新,作者核心探讨了如何对模型的宽度、深度和图片分辨率等三个维度做缩放,可以得到最佳的性能提升。

模型缩放

当我们得到一个基础模型后,为了提高模型的复杂度,进而提高模型的性能,我们一般会对模型做适当的缩放。常用的缩放方法是
1)增大模型的宽度
也就是增加每一个卷积层的通道数
2)增大模型的深度
将每一个stage重复的单元增加多一些,如resnet50到resnet101的扩展
3) 增大输入图片的分辨率

如下图。

如果单一缩放这三个维度,模型精度都有提升,但很快都饱和了,如下图。这里有个重要问题,大家要思考,为什么饱和了?模型参数不是变多了,为啥新增加的参数不起效果?我以前阅读resnet论文时,非常疑惑为啥ResNet1000和ResNet101的性能几乎一样。作者这里就给出了部分答案,模型的宽度、深度和图片分辨率三者是互相关联的,当深度增加时,模型的宽度、输入图片的分辨率都要跟着增加才会得到最好的效果。

直观上也很好理解,当深度增加时,需要更高的输入图片分辨率,来保证感受野的有效性,也需要更宽的网络,保证能捕捉更多的特征。是不是有点拗口,反过来说可能更好理解,大分辨率的图片,需要更深的网络,来增加感受野,从而捕捉有效语义,也需要更宽的网络捕捉更精细的特征。

组合缩放系数

当计算资源增加时,如果彻底的去搜索宽度、深度、图片分辨率这三个变量的各种组合,那么搜索空间将无限大,搜索效率会非常低。

因此作者提出了组合缩放的方法:

用单一的组合缩放系数$\phi$,同时缩放宽度、深度和图片分辨率,缩放公式如上图。而深度、宽度和分辨率的缩放基数$\alpha、\beta、\gamma$,由在基准模型上取$\phi = 1$做参数搜索得到,作者在Efficient-B0上搜索的最终结果是$\alpha =1.2、\beta =1.1、\gamma =1.15$。

需要解释一下,为啥要做如下约束:

当对模型的深度、宽度和分辨率分别做$\alpha^{\phi}、\beta^{\phi}、\gamma^{\phi}$缩放时,对应的计算量,大约增加为:

这是因为当模型深度增加时,计算量成线性增加,当模型宽度和分辨率增加时,计算量以二次方增加。
因此,如果约束$\alpha \cdot \beta^{2} \cdot \gamma^{2} = 2$,则当模型深度、宽度和分辨率统一缩放$\phi$时,最终的计算量大约增加为$2^{\phi}$,这就很好计算。有了这个关系,就可以根据计算资源的变化来反推组合缩放系数$\phi$的大小。

简单举个例子,假如当前算力增加到原来的10倍,那么组合缩放系数$\phi$计算公式如下:

得到$\phi = 3.32$,然后按$\alpha^{\phi}、\beta^{\phi}、\gamma^{\phi}$缩放模型的深度、宽度和分辨率即可。

我们直观感受下B0-B7缩放的尺度。

# Coefficients:   width,depth,res,dropout
'efficientnet-b0': (1.0, 1.0, 224, 0.2),
'efficientnet-b1': (1.0, 1.1, 240, 0.2),
'efficientnet-b2': (1.1, 1.2, 260, 0.3),
'efficientnet-b3': (1.2, 1.4, 300, 0.3),
'efficientnet-b4': (1.4, 1.8, 380, 0.4),
'efficientnet-b5': (1.6, 2.2, 456, 0.4),
'efficientnet-b6': (1.8, 2.6, 528, 0.5),
'efficientnet-b7': (2.0, 3.1, 600, 0.5),

如何评价EfficientNet

EfficientNet之所以被众人所知,唯一原因就是其又快又准的SOTA结果。

而能够有如此结果,其实是组合缩放+更好的Backbone(EfficientNet-B0)双重作用的结果。而Efficient-B0是用NAS搜索出来的,这也意味着即使你和作者有相同的创意idea,如果没有足够的计算资源,你也做不出EfficientNet,作为普通的科研人员,是不是有点忧伤。

而更让EfficientNet大放异彩的是,基于EfficientNet的目标检测算法EfficientDet也屠榜,有时间我们再一起研究研究。

问题思考

这里我给出几个问题供大家思考,如果能解决,说不定能发论文。

  1. 即使是组合缩放,为什么最终的性能仍然会饱和?
  2. 对于不同的backbone,是不是组合缩放的最佳缩放基数$\alpha、\beta、\gamma$是否相同?

文献

  1. EfficientNet论文

投资是一种信仰

对于投资,无论何种流派,最终的目的都是高收益。

但选择不同的流派,其实等同于选择不同的生活状态和心理状态。

如果选择了技术流,实时盯盘基本就变成了生活的一部分,或者说生活的全部。痴迷或者紧要的时候,吃饭睡觉走路可能想的是K线走势。如果某一次上涨精准抓住了,那么这一天见到谁都会笑一笑,如果某一次下跌没精准撤出,一整天哭丧着脸是必然的。总体对一时涨跌很敏感。

如果选择了价值流,按照价值低估的时候买进,价值高估的时候沽出操作,那么平时的主要工作就是等待。见到暴跌,喜上眉梢,终于可以买进。见到暴涨,如果没到买入点,也无所谓。价值流对一时涨跌看的比较淡,看的是总体相对于价值的变化。

如果选择了定投派,那就更无所谓了,平时看都不看,到点定投即可。

细思之,投资流派的选择,非常类似信仰选择,对个人的影响是全方位的。如果不是自己性格实在做不到,技术流是非常不建议的,因为技术流不但耗费巨大的精力,往往最终还成了韭菜。而且价投或者定投的收益也是很可观的。

但可悲的是,价投和定投看似简单,却是最难的,一般人基本都做不到,而技术流是人的天然选择,所以上苍注定,大部人都是韭菜,如果你曾经大幅度亏损过,不要不服而下更大的赌注,接收自己是韭菜即可,然后好好调整自己的投资流派选择,或许那才是止损的最快方式。

我也会在微信公众号「慢投ZI」分享个人的投资感悟,欢迎大家扫码关注。

从一个demo学习AdaBoost

前言

提升算法(boost算法)是组合多个仅比随机猜测好一些的弱学习器,形成一个性能很好的强学习器。听起来很不可思议,但已经有学者证明,一个问题可由单个强学习器学习的充分必要条件是,这个问题可由多个弱学习器组合的学习器学习。这也是提升算法可行的根本依据。

提升算法直观上也很好理解,如果多个弱学习器各自擅长解决问题的某一些互相不同的场景,那么多个弱学习器有可能比单个擅长任何场景的学习性能好,三个臭皮匠胜过一个诸葛亮。

具体怎么学习和组合这一系列的弱学习器,各个boost算法着重点不同,常用的是三大boost算法,AdaBoost、GBDT和XGBoost。

提升算法的性能取决于各个弱分类器的多样性,AdaBoost通过改变训练数据的权重,来增强各个基本分类器的多样性。

本文以一个demo为例,庖丁解牛式的学习AdaBoost。

AsyncDisplayKit近一年的使用体会及疑难点

一个第三方库能做到像新产品一样,值得大家去写写使用体会的,并不多见,AsyncDisplayKit却完全可以,因为AsyncDisplayKit不仅仅是一个工具,它更像一个系统UI框架,改变整个编码体验。也正是这种极强的侵入性,导致不少听过、star过,甚至下过demo跑过AsyncDisplayKit的你我,望而却步,驻足观望。但列表界面稍微复杂时,烦人的高度计算,因为性能不得不放弃Autolayout而选择上古时代的frame layout,令人精疲力尽,这时AsyncDisplayKit总会不自然浮现眼前,让你跃跃欲试。

去年10月份,我们入坑了。

当时还只是拿简单的列表页试水,基本上手后,去年底在稍微空闲的时候用AsyncDisplayKit重构了帖子详情,今年三月份,又借着公司聊天增加群聊的契机,用AsyncDisplayKit重构整个聊天。林林总总,从简单到复杂,踩过的坑大大小小,将近一年的时光转眼飞逝,可以写写总结了。

学习曲线

先说说学习曲线,这是大家都比较关心的问题。

iOS两个客户端代码复用小技巧

一般一个App只有一个客户端,因此也只有一份代码仓库,也就无所谓复用不复用。但两个客户端也不是没有,美团、饿了么等就分商家版和买家版,贝聊App也分为老师版和家长版两个客户端。有两个客户端代码复用就在所难免,比如基本的工具类,比如一些共用的业务。本文就以贝聊App为例,分享当有两个客户端时代码复用的小技巧。

repository仓库划分

贝聊APP远程仓库划分为三个,一个家长端repository,一个老师端repository,一个两端共用的BLKit repository


生命的惯性

生命好似被上帝精心编排的话剧,年少时学习,长大了工作,然后结婚生子,抚养小孩,照看父母,最后垂垂老去。一幕接着一幕,一幕赶着一幕。貌似自由意志,其实我们只有润色生活这么一点点权限。

而在某一幕中,比如工作,我们也只是尽己所能完成每一日的事情。当然随着日复一日,年复一年,薪水逐年递增,职位越干越大,工作内容也渐进宏观。从小白程序员,到编程资深程序员,到项目负责人,到CTO。没有什么会一成不变,但也没有什么会突如其来。

循序渐进,是我们的一生,也是我们的每一天,每一秒,循序渐进就是我们生命的惯性。

这没啥不好,途中会有焦虑,会有进步,会有责罚,会有掌声,会有层出不穷的新事物。但总觉得有点烦闷,因为一切都是可期的。

我们渴望着惊喜,因为惊喜让生命充盈、丰厚。

或在某个小巷,遇到一个丁香一样的姑娘,或在某个不经意的抬头,看见散落满天的星,或在某次与人会谈时,获得生命的顿悟,或在举步维艰之际,遇到一生的贵人。

生命难逃惯性,我们总期望着惊喜。惊喜也总会不期而至,但并不是无缘无故。今日生命的惊喜大多是我们昨日努力种下的种。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×