0%

量化投资

量化投资定义

量化投资是指通过数量化模型建立科学投资体系,以获取稳定收益。

量化投资优势

量化投资的优势在于纪律性、系统性、及时性和分散化。

  • 纪律性:严格执行投资策略,不随投资者情侣的变化而随意更改,这样可以克服人性的弱点,也可以克服认知偏差。
  • 系统性:量化投资的系统性特征包括多层次的量化模型、多角度的观察及海量数据的观察。多层次模型包括大类资产配置模型、行业选择模型、精选个股模型等。多角度观察主要包括对宏观周期、市场结构、估值、成长、盈利质量、市场情绪等多个角度分析。此外,海量数据处理能力能够更好地在广大资本市场捕捉到更多的投资机会,拓展更大的投资机会。
  • 及时性:及时快速地跟踪市场变化,不断发现能够提供超额收益的新的统计模型,寻找新的交易机会。
  • 准确性:准确客观评价交易机会,克服主观情绪偏差从而盈利。
  • 分散化:在控制风险的条件下,量化投资可以充当分散化投资的工具。表现为两个方面:一是量化投资不断地从历史中挖掘有望在未来重复的历史规律并且加以利用,这些历史规律都是较大概率取胜的策略;二是依靠筛选出股票组合来取胜,而不是一只或几只股票取胜。

    量化策略

    使用量化策略是进行量化投资的有效方式,通过客观准确的交易规则构建策略,并在历史数据上进行回测,当回测结果通过评估审核后才可以称得上是一个可进行实盘交易得量化策略,许多私募在实盘前还有一个模拟交易阶段。

    AI量化投资策略构建流程

  • 第一步:确定数据(如股票池),划分训练集、测试集;
  • 第二步:明确目标,进行数据标注;
    • 目标:人为定义的模型预测目标,例如未来N日收益率、未来N日波动率、未来N日的收益率排序等统计量;
    • 标注:计算训练集数据所在时间阶段的每日目标值。
  • 第三步:找因子;构建可能影响目标的特征(量化策略中可称为因子)
    • 特征:反映事物在某方面的表现或性质的事项,在AI量化策略中,特征可以是换手率、市盈率、KDJ技术指标等;
  • 第四步:数据连接+缺失数据处理;将上述每只股票的标注数据与特征数据注意链接,以便模型的学习和使用;
  • 第五步:模型训练+股票预测
  • 第六步:回测;将验证集的预测结果放入历史真实数据中检测。

    量化结果分析

    当我们策略回测完成时,系统会输出包含各种指标的收益曲线图,如收益概括、交易详情、每日持仓和收益、输出日志等。
    回测结果

    收益率

    Total Return: 策略整个回测时间段上的总收益率。比如,如果收益率为30%,表明起始时间是1万本金,结束时间本金变成1.3万。计算公式如下,该值越大越好。

    其中,$PV{end} = 策略最终股票和现金总价值, PV{start} = 策略开始股票和现金总价值$。

    年化收益率

    Total Annualized Returns: 该策略每一年的收益率。比如,如果回测时间段为2年,总收益率为30%,那么每年的年化率就在15%附近(不考虑复利)。计算公式如下,该值越大越好。

    其中,$P=策略总收益率,n=策略执行天数$

    基准收益率

    Benchmark Returns: 策略需要有一个比较基准,比较基准为沪深300。若基准收益率为15%,表明在整个回测时间段,大盘本身就上涨了15%,如果策略收益率小于基准收益率,说明策略表现并不好,连大盘都没有跑赢。计算公式如下:

    其中,$M{end}=基准最终价值, M{start}=基准开始价值$

    Alpha

    投资中面临着系统性风险(即Beta)和非系统性风险(即Alpha),Alpha是投资者获得与市场波动无关的回报。比如投资者获得了15%的回报,其基准获得了10%的回报,那么Alpha或者价值增值的部分就是5%,计算公式如下,该值越大越好。

    其中,$R_p=策略年化收益率, R_m=基准年化收益率, R_f=无风险利率(默认0.03), \beta_p=策略Beta值$

  • $\alpha>0$时,策略相对于市场获得了超额收益;

  • $\alpha=0$时,策略相对于市场获得了适当收益;
  • $\alpha<0$时,策略相对于市场获得了较少收益;

    Beta

    表示投资的系统性风险,反映了策略对大盘变化的敏感性。例如一个策略的Beta为1.5,则大盘涨1%的时候,策略可能涨1.5%,反之亦然;如果一个策略的Beta为-1.5,寿命大盘涨1%的时候,策略可能跌1.5%,反之亦然。计算公式如下,该值的绝对值越小越好。

    其中,$D_p=策略每日收益, D_m=基准每日收益, Cov(D_p, D_m)=策略每日收益与基准每日收益的协方差, Var(D_m)=基准每日收益的方差$

  • $\beta<0$ 投资组合和基准的走向通常反方向,如空头头寸类;

  • $\beta=0$ 投资组合和基准的走向没有相关性,如固定收益类;
  • $0<\beta<1$ 投资组合和基准的走向相同,但是比基准的移动幅度更小;
  • $\beta=1$ 投资组合和基准的走向相同,并且和基准的移动幅度贴近;
  • $\beta>1$ 投资组合和基准的走向相同,但是比基准的移动幅度更大。

    夏普比率

    表示每承受一单位总风险,会产生多少的超额报酬,可以同时对策略的收益与风险进行综合考虑,也可以理解为经过风险调整后收益率。计算公式如下,该值越大越好。其中,$R_p=策略年化收益率, R_f=无风险利率(默认0.03), \sigma_p=策略年化波动率$

    胜率

    winning percentage: 衡量策略盈利指标。比如10次投资中8次获利,胜率就是80%。计算公式如下,该值越大越好。

    盈亏比

    The profit and cross ratio: 盈亏比是在投资市场里每次交易得盈利和亏损的比例。计算公式如下,该值越大越好。

    收益波动率

    收益率的标准差,用来衡量策略的风险性,波动越大代表策略风险越高。计算公式如下,该值越小越好。其中,$R_p=策略每日收益率, \overline{R_p}=策略每日收益率的平均值=\frac{1}{n}\sum_i^nR_p, n=策略执行天数$

    信息比率

    衡量单位超额风险带来的超额收益。信息比率越大,说明该策略单位跟踪误差所获得的超额收益越高,因此,信息比率较大的策略的表现要优于信息比率较低的基准。合理的投资目标应该是在承担适度风险下,尽可能追求高信息比率。计算公式如下,该值越大越好。其中,$R_p=策略年化收益率,R_m=基准年化收益率,\theta_t=策略与基准每日收益差值的年化标准差$

    最大回撤

    策略在整个时间段上亏损最严重的时候相比净值最高值下跌的百分比。如果最大回撤为20%,表明策略在某个时间点上,相比之前的净值最高。其中,$P_x,P_y=策略某日股票和现金的总价值,y>x$。

    交易详情

    交易详情主要显示了策略在整个回测过程中每个交易日的买卖信息,包括买卖时间、股票代码、交易方向、交易数量、成交价格、交易成本。具体见下图:

    每日持仓及收益

    每日持仓及收益主要呈现每日持有股票代码、当日收盘价、持仓股票数量、持仓金额、收益等指标。具体见下图:

    输出日志

    输出日志主要为策略运行过程中的一些日志。包括涨跌停股票不能交易、停牌估计不能交易等。该日志可以便于我们检查回测结果的正确性。

[TOC]

第四章 经典网络解读

4.1 LeNet-5

4.1.1 模型介绍

​ LeNet-5是由$LeCun$ 提出的一种用于识别手写数字和机器印刷字符的卷积神经网络(Convolutional Neural Network,CNN)$^{[1]}$,其命名来源于作者$LeCun$的名字,5则是其研究成果的代号,在LeNet-5之前还有LeNet-4和LeNet-1鲜为人知。LeNet-5阐述了图像中像素特征之间的相关性能够由参数共享的卷积操作所提取,同时使用卷积、下采样(池化)和非线性映射这样的组合结构,是当前流行的大多数深度图像识别网络的基础。

4.1.2 模型结构

​ 图4.1 LeNet-5网络结构图

​ 如图4.1所示,LeNet-5一共包含7层(输入层不作为网络结构),分别由2个卷积层、2个下采样层和3个连接层组成,网络的参数配置如表4.1所示,其中下采样层和全连接层的核尺寸分别代表采样范围和连接矩阵的尺寸(如卷积核尺寸中的$“5\times5\times1/1,6”$表示核大小为$5\times5\times1$、步长为$1​$且核个数为6的卷积核)。

​ 表4.1 LeNet-5网络参数配置

网络层 输入尺寸 核尺寸 输出尺寸 可训练参数量
卷积层$C_1$ $32\times32\times1$ $5\times5\times1/1,6$ $28\times28\times6$ $(5\times5\times1+1)\times6$
下采样层$S_2$ $28\times28\times6$ $2\times2/2$ $14\times14\times6$ $(1+1)\times6$ $^*$
卷积层$C_3$ $14\times14\times6$ $5\times5\times6/1,16$ $10\times10\times16$ $1516^*$
下采样层$S_4$ $10\times10\times16$ $2\times2/2$ $5\times5\times16$ $(1+1)\times16$
卷积层$C_5$$^*$ $5\times5\times16$ $5\times5\times16/1,120$ $1\times1\times120$ $(5\times5\times16+1)\times120$
全连接层$F_6$ $1\times1\times120$ $120\times84$ $1\times1\times84$ $(120+1)\times84$
输出层 $1\times1\times84$ $84\times10$ $1\times1\times10$ $(84+1)\times10$

​ $^*$ 在LeNet中,下采样操作和池化操作类似,但是在得到采样结果后会乘以一个系数和加上一个偏置项,所以下采样的参数个数是$(1+1)\times6​$而不是零。

​ $^*$ $C_3$卷积层可训练参数并未直接连接$S_2$中所有的特征图(Feature Map),而是采用如图4.2所示的采样特征方式进行连接(稀疏连接),生成的16个通道特征图中分别按照相邻3个特征图、相邻4个特征图、非相邻4个特征图和全部6个特征图进行映射,得到的参数个数计算公式为$6\times(25\times3+1)+6\times(25\times4+1)+3\times(25\times4+1)+1\times(25\times6+1)=1516$,在原论文中解释了使用这种采样方式原因包含两点:限制了连接数不至于过大(当年的计算能力比较弱);强制限定不同特征图的组合可以使映射得到的特征图学习到不同的特征模式。

FeatureMap

​ 图4.2 $S_2$与$C_3$之间的特征图稀疏连接

​ $^*$ $C_5$卷积层在图4.1中显示为全连接层,原论文中解释这里实际采用的是卷积操作,只是刚好在$5\times5$卷积后尺寸被压缩为$1\times1​$,输出结果看起来和全连接很相似。

4.1.3 模型特性

  • 卷积网络使用一个3层的序列组合:卷积、下采样(池化)、非线性映射(LeNet-5最重要的特性,奠定了目前深层卷积网络的基础)
  • 使用卷积提取空间特征
  • 使用映射的空间均值进行下采样
  • 使用$tanh$或$sigmoid$进行非线性映射
  • 多层神经网络(MLP)作为最终的分类器
  • 层间的稀疏连接矩阵以避免巨大的计算开销

4.2 AlexNet

4.2.1 模型介绍

​ AlexNet是由$Alex$ $Krizhevsky $提出的首个应用于图像分类的深层卷积神经网络,该网络在2012年ILSVRC(ImageNet Large Scale Visual Recognition Competition)图像分类竞赛中以15.3%的top-5测试错误率赢得第一名$^{[2]}$。AlexNet使用GPU代替CPU进行运算,使得在可接受的时间范围内模型结构能够更加复杂,它的出现证明了深层卷积神经网络在复杂模型下的有效性,使CNN在计算机视觉中流行开来,直接或间接地引发了深度学习的热潮。

4.2.2 模型结构

​ 图4.3 AlexNet网络结构图

​ 如图4.3所示,除去下采样(池化层)和局部响应规范化操作(Local Responsible Normalization, LRN),AlexNet一共包含8层,前5层由卷积层组成,而剩下的3层为全连接层。网络结构分为上下两层,分别对应两个GPU的操作过程,除了中间某些层($C3$卷积层和$F{6-8}$全连接层会有GPU间的交互),其他层两个GPU分别计算结 果。最后一层全连接层的输出作为$softmax$的输入,得到1000个图像分类标签对应的概率值。除去GPU并行结构的设计,AlexNet网络结构与LeNet十分相似,其网络的参数配置如表4.2所示。

​ 表4.2 AlexNet网络参数配置

网络层 输入尺寸 核尺寸 输出尺寸 可训练参数量
卷积层$C_1$ $^*$ $224\times224\times3$ $11\times11\times3/4,48(\times2_{GPU})$ $55\times55\times48(\times2_{GPU})$ $(11\times11\times3+1)\times48\times2$
下采样层$S_{max}$$^*$ $55\times55\times48(\times2_{GPU})$ $3\times3/2(\times2_{GPU})$ $27\times27\times48(\times2_{GPU})$ 0
卷积层$C_2$ $27\times27\times48(\times2_{GPU})$ $5\times5\times48/1,128(\times2_{GPU})$ $27\times27\times128(\times2_{GPU})$ $(5\times5\times48+1)\times128\times2$
下采样层$S_{max}$ $27\times27\times128(\times2_{GPU})$ $3\times3/2(\times2_{GPU})$ $13\times13\times128(\times2_{GPU})$ 0
卷积层$C_3$ $^*$ $13\times13\times128\times2_{GPU}$ $3\times3\times256/1,192(\times2_{GPU})$ $13\times13\times192(\times2_{GPU})$ $(3\times3\times256+1)\times192\times2$
卷积层$C_4$ $13\times13\times192(\times2_{GPU})$ $3\times3\times192/1,192(\times2_{GPU})$ $13\times13\times192(\times2_{GPU})$ $(3\times3\times192+1)\times192\times2$
卷积层$C_5$ $13\times13\times192(\times2_{GPU})$ $3\times3\times192/1,128(\times2_{GPU})$ $13\times13\times128(\times2_{GPU})$ $(3\times3\times192+1)\times128\times2$
下采样层$S_{max}$ $13\times13\times128(\times2_{GPU})$ $3\times3/2(\times2_{GPU})$ $6\times6\times128(\times2_{GPU})$ 0
全连接层$F_6$ $^*$ $6\times6\times128\times2_{GPU}$ $9216\times2048(\times2_{GPU})$ $1\times1\times2048(\times2_{GPU})$ $(9216+1)\times2048\times2$
全连接层$F_7$ $1\times1\times2048\times2_{GPU}$ $4096\times2048(\times2_{GPU})$ $1\times1\times2048(\times2_{GPU})$ $(4096+1)\times2048\times2$
全连接层$F_8$ $1\times1\times2048\times2_{GPU}$ $4096\times1000$ $1\times1\times1000$ $(4096+1)\times1000\times2$

卷积层$C_1$输入为$224\times224\times3$的图片数据,分别在两个GPU中经过核为$11\times11\times3$、步长(stride)为4的卷积卷积后,分别得到两条独立的$55\times55\times48$的输出数据。

下采样层$S{max}$实际上是嵌套在卷积中的最大池化操作,但是为了区分没有采用最大池化的卷积层单独列出来。在$C{1-2}$卷积层中的池化操作之后(ReLU激活操作之前),还有一个LRN操作,用作对相邻特征点的归一化处理。

卷积层$C3$ 的输入与其他卷积层不同,$13\times13\times192\times2{GPU}$表示汇聚了上一层网络在两个GPU上的输出结果作为输入,所以在进行卷积操作时通道上的卷积核维度为384。

全连接层$F_{6-8}$中输入数据尺寸也和$C_3$类似,都是融合了两个GPU流向的输出结果作为输入。

4.2.3 模型特性

  • 所有卷积层都使用ReLU作为非线性映射函数,使模型收敛速度更快
  • 在多个GPU上进行模型的训练,不但可以提高模型的训练速度,还能提升数据的使用规模
  • 使用LRN对局部的特征进行归一化,结果作为ReLU激活函数的输入能有效降低错误率
  • 重叠最大池化(overlapping max pooling),即池化范围z与步长s存在关系$z>s$(如$S_{max}$中核尺度为$3\times3/2$),避免平均池化(average pooling)的平均效应
  • 使用随机丢弃技术(dropout)选择性地忽略训练中的单个神经元,避免模型的过拟合

4.3 ZFNet

4.3.1 模型介绍

​ ZFNet是由$Matthew$ $D. Zeiler$和$Rob$ $Fergus$在AlexNet基础上提出的大型卷积网络,在2013年ILSVRC图像分类竞赛中以11.19%的错误率获得冠军(实际上原ZFNet所在的队伍并不是真正的冠军,原ZFNet以13.51%错误率排在第8,真正的冠军是$Clarifai$这个队伍,而$Clarifai$这个队伍所对应的一家初创公司的CEO又是$Zeiler$,而且$Clarifai$对ZFNet的改动比较小,所以通常认为是ZFNet获得了冠军)$^{[3-4]}​$。ZFNet实际上是微调(fine-tuning)了的AlexNet,并通过反卷积(Deconvolution)的方式可视化各层的输出特征图,进一步解释了卷积操作在大型网络中效果显著的原因。

4.3.2 模型结构

​ 图4.4 ZFNet网络结构图(原始结构图与AlexNet风格结构图)

​ 如图4.4所示,ZFNet与AlexNet类似,都是由8层网络组成的卷积神经网络,其中包含5层卷积层和3层全连接层。两个网络结构最大的不同在于,ZFNet第一层卷积采用了$7\times7\times3/2$的卷积核替代了AlexNet中第一层卷积核$11\times11\times3/4$的卷积核。图4.5中ZFNet相比于AlexNet在第一层输出的特征图中包含更多中间频率的信息,而AlexNet第一层输出的特征图大多是低频或高频的信息,对中间频率特征的缺失导致后续网络层次如图4.5(c)能够学习到的特征不够细致,而导致这个问题的根本原因在于AlexNet在第一层中采用的卷积核和步长过大。

​ 图4.5 (a)ZFNet第一层输出的特征图(b)AlexNet第一层输出的特征图(c)AlexNet第二层输出的特征图(d)ZFNet第二层输出的特征图

​ 表4.3 ZFNet网络参数配置
| 网络层 | 输入尺寸 | 核尺寸 | 输出尺寸 | 可训练参数量 |
| :—————————-: | :—————————————————: | :———————————————————: | :—————————————————: | :——————————————————-: |
| 卷积层$C1$ $^*$ | $224\times224\times3$ | $7\times7\times3/2,96$ | $110\times110\times96$ | $(7\times7\times3+1)\times96$ |
| 下采样层$S
{max}$ | $110\times110\times96$ | $3\times3/2$ | $55\times55\times96$ | 0 |
| 卷积层$C2$ $^*$ | $55\times55\times96$ | $5\times5\times96/2,256$ | $26\times26\times256$ | $(5\times5\times96+1)\times256$ |
| 下采样层$S
{max}$ | $26\times26\times256$ | $3\times3/2$ | $13\times13\times256$ | 0 |
| 卷积层$C3$ | $13\times13\times256$ | $3\times3\times256/1,384$ | $13\times13\times384$ | $(3\times3\times256+1)\times384$ |
| 卷积层$C_4$ | $13\times13\times384$ | $3\times3\times384/1,384$ | $13\times13\times384$ | $(3\times3\times384+1)\times384$ |
| 卷积层$C_5$ | $13\times13\times384$ | $3\times3\times384/1,256$ | $13\times13\times256$ | $(3\times3\times384+1)\times256$ |
| 下采样层$S
{max}$ | $13\times13\times256$ | $3\times3/2$ | $6\times6\times256$ | 0 |
| 全连接层$F_6$ | $6\times6\times256$ | $9216\times4096$ | $1\times1\times4096$ | $(9216+1)\times4096$ |
| 全连接层$F_7$ | $1\times1\times4096$ | $4096\times4096$ | $1\times1\times4096$ | $(4096+1)\times4096$ |
| 全连接层$F_8$ | $1\times1\times4096$ | $4096\times1000$ | $1\times1\times1000$ | $(4096+1)\times1000$ |

卷积层$C_1$与AlexNet中的$C_1$有所不同,采用$7\times7\times3/2$的卷积核代替$11\times11\times3/4​$,使第一层卷积输出的结果可以包含更多的中频率特征,对后续网络层中多样化的特征组合提供更多选择,有利于捕捉更细致的特征。

卷积层$C_2$采用了步长2的卷积核,区别于AlexNet中$C_2$的卷积核步长,所以输出的维度有所差异。

4.3.3 模型特性

​ ZFNet与AlexNet在结构上几乎相同,此部分虽属于模型特性,但准确地说应该是ZFNet原论文中可视化技术的贡献。

  • 可视化技术揭露了激发模型中每层单独的特征图。
  • 可视化技术允许观察在训练阶段特征的演变过程且诊断出模型的潜在问题。
  • 可视化技术用到了多层解卷积网络,即由特征激活返回到输入像素空间。
  • 可视化技术进行了分类器输出的敏感性分析,即通过阻止部分输入图像来揭示那部分对于分类是重要的。
  • 可视化技术提供了一个非参数的不变性来展示来自训练集的哪一块激活哪个特征图,不仅需要裁剪输入图片,而且自上而下的投影来揭露来自每块的结构激活一个特征图。
  • 可视化技术依赖于解卷积操作,即卷积操作的逆过程,将特征映射到像素上。

4.4 Network in Network

4.4.1 模型介绍

​ Network In Network (NIN)是由$Min Lin$等人提出,在CIFAR-10和CIFAR-100分类任务中达到当时的最好水平,因其网络结构是由三个多层感知机堆叠而被成为NIN$^{[5]}$。NIN以一种全新的角度审视了卷积神经网络中的卷积核设计,通过引入子网络结构代替纯卷积中的线性映射部分,这种形式的网络结构激发了更复杂的卷积神经网络的结构设计,其中下一节中介绍的GoogLeNet的Inception结构就是来源于这个思想。

4.4.2 模型结构


​ 图 4.6 NIN网络结构图

​ NIN由三层的多层感知卷积层(MLPConv Layer)构成,每一层多层感知卷积层内部由若干层的局部全连接层和非线性激活函数组成,代替了传统卷积层中采用的线性卷积核。在网络推理(inference)时,这个多层感知器会对输入特征图的局部特征进行划窗计算,并且每个划窗的局部特征图对应的乘积的权重是共享的,这两点是和传统卷积操作完全一致的,最大的不同在于多层感知器对局部特征进行了非线性的映射,而传统卷积的方式是线性的。NIN的网络参数配置表4.4所示(原论文并未给出网络参数,表中参数为编者结合网络结构图和CIFAR-100数据集以$3\times3$卷积为例给出)。

​ 表4.4 NIN网络参数配置(结合原论文NIN结构和CIFAR-100数据给出)

网络层 输入尺寸 核尺寸 输出尺寸 参数个数
局部全连接层$L_{11}$ $^*$ $32\times32\times3$ $(3\times3)\times16/1$ $30\times30\times16$ $(3\times3\times3+1)\times16$
全连接层$L_{12}$ $^*$ $30\times30\times16$ $16\times16$ $30\times30\times16$ $((16+1)\times16)$
局部全连接层$L_{21}$ $30\times30\times16$ $(3\times3)\times64/1$ $28\times28\times64$ $(3\times3\times16+1)\times64$
全连接层$L_{22}$ $28\times28\times64$ $64\times64$ $28\times28\times64$ $((64+1)\times64)$
局部全连接层$L_{31}$ $28\times28\times64$ $(3\times3)\times100/1$ $26\times26\times100$ $(3\times3\times64+1)\times100$
全连接层$L_{32}$ $26\times26\times100$ $100\times100$ $26\times26\times100$ $((100+1)\times100)$
全局平均采样$GAP$ $^*$ $26\times26\times100$ $26\times26\times100/1$ $1\times1\times100$ $0$

局部全连接层$L{11}$实际上是对原始输入图像进行划窗式的全连接操作,因此划窗得到的输出特征尺寸为$30\times30$($\frac{32-3_k+1}{1{stride}}=30$)
全连接层$L{12}$是紧跟$L{11}$后的全连接操作,输入的特征是划窗后经过激活的局部响应特征,因此仅需连接$L{11}$和$L{12}$的节点即可,而每个局部全连接层和紧接的全连接层构成代替卷积操作的多层感知卷积层(MLPConv)。
全局平均采样层或全局平均池化层$GAP$(Global Average Pooling)将$L_{32}$输出的每一个特征图进行全局的平均池化操作,直接得到最后的类别数,可以有效地减少参数量。

4.4.3 模型特点

  • 使用多层感知机结构来代替卷积的滤波操作,不但有效减少卷积核数过多而导致的参数量暴涨问题,还能通过引入非线性的映射来提高模型对特征的抽象能力。
  • 使用全局平均池化来代替最后一个全连接层,能够有效地减少参数量(没有可训练参数),同时池化用到了整个特征图的信息,对空间信息的转换更加鲁棒,最后得到的输出结果可直接作为对应类别的置信度。

4.5 VGGNet

4.5.1 模型介绍

​ VGGNet是由牛津大学视觉几何小组(Visual Geometry Group, VGG)提出的一种深层卷积网络结构,他们以7.32%的错误率赢得了2014年ILSVRC分类任务的亚军(冠军由GoogLeNet以6.65%的错误率夺得)和25.32%的错误率夺得定位任务(Localization)的第一名(GoogLeNet错误率为26.44%)$^{[5]}$,网络名称VGGNet取自该小组名缩写。VGGNet是首批把图像分类的错误率降低到10%以内模型,同时该网络所采用的$3\times3$卷积核的思想是后来许多模型的基础,该模型发表在2015年国际学习表征会议(International Conference On Learning Representations, ICLR)后至今被引用的次数已经超过1万4千余次。

4.5.2 模型结构

​ 图 4.7 VGG16网络结构图

​ 在原论文中的VGGNet包含了6个版本的演进,分别对应VGG11、VGG11-LRN、VGG13、VGG16-1、VGG16-3和VGG19,不同的后缀数值表示不同的网络层数(VGG11-LRN表示在第一层中采用了LRN的VGG11,VGG16-1表示后三组卷积块中最后一层卷积采用卷积核尺寸为$1\times1$,相应的VGG16-3表示卷积核尺寸为$3\times3$),本节介绍的VGG16为VGG16-3。图4.7中的VGG16体现了VGGNet的核心思路,使用$3\times3$的卷积组合代替大尺寸的卷积(2个$3\times3卷积即可与$$5\times5$卷积拥有相同的感受视野),网络参数设置如表4.5所示。

​ 表4.5 VGG16网络参数配置

网络层 输入尺寸 核尺寸 输出尺寸 参数个数
卷积层$C_{11}$ $224\times224\times3$ $3\times3\times64/1$ $224\times224\times64$ $(3\times3\times3+1)\times64$
卷积层$C_{12}$ $224\times224\times64$ $3\times3\times64/1$ $224\times224\times64$ $(3\times3\times64+1)\times64$
下采样层$S_{max1}$ $224\times224\times64$ $2\times2/2$ $112\times112\times64$ $0$
卷积层$C_{21}$ $112\times112\times64$ $3\times3\times128/1$ $112\times112\times128$ $(3\times3\times64+1)\times128$
卷积层$C_{22}$ $112\times112\times128$ $3\times3\times128/1$ $112\times112\times128$ $(3\times3\times128+1)\times128$
下采样层$S_{max2}$ $112\times112\times128$ $2\times2/2$ $56\times56\times128$ $0$
卷积层$C_{31}$ $56\times56\times128$ $3\times3\times256/1$ $56\times56\times256$ $(3\times3\times128+1)\times256$
卷积层$C_{32}$ $56\times56\times256$ $3\times3\times256/1$ $56\times56\times256$ $(3\times3\times256+1)\times256$
卷积层$C_{33}$ $56\times56\times256$ $3\times3\times256/1$ $56\times56\times256$ $(3\times3\times256+1)\times256$
下采样层$S_{max3}$ $56\times56\times256$ $2\times2/2$ $28\times28\times256$ $0$
卷积层$C_{41}$ $28\times28\times256$ $3\times3\times512/1$ $28\times28\times512$ $(3\times3\times256+1)\times512$
卷积层$C_{42}$ $28\times28\times512$ $3\times3\times512/1$ $28\times28\times512$ $(3\times3\times512+1)\times512$
卷积层$C_{43}$ $28\times28\times512$ $3\times3\times512/1$ $28\times28\times512$ $(3\times3\times512+1)\times512$
下采样层$S_{max4}$ $28\times28\times512$ $2\times2/2$ $14\times14\times512$ $0$
卷积层$C_{51}$ $14\times14\times512$ $3\times3\times512/1$ $14\times14\times512$ $(3\times3\times512+1)\times512$
卷积层$C_{52}$ $14\times14\times512$ $3\times3\times512/1$ $14\times14\times512$ $(3\times3\times512+1)\times512$
卷积层$C_{53}$ $14\times14\times512$ $3\times3\times512/1$ $14\times14\times512$ $(3\times3\times512+1)\times512$
下采样层$S_{max5}$ $14\times14\times512$ $2\times2/2$ $7\times7\times512$ $0$
全连接层$FC_{1}$ $7\times7\times512$ $(7\times7\times512)\times4096$ $1\times4096$ $(7\times7\times512+1)\times4096$
全连接层$FC_{2}$ $1\times4096$ $4096\times4096$ $1\times4096$ $(4096+1)\times4096$
全连接层$FC_{3}$ $1\times4096$ $4096\times1000$ $1\times1000$ $(4096+1)\times1000$

4.5.3 模型特性

  • 整个网络都使用了同样大小的卷积核尺寸$3\times3$和最大池化尺寸$2\times2$。
  • $1\times1$卷积的意义主要在于线性变换,而输入通道数和输出通道数不变,没有发生降维。
  • 两个$3\times3$的卷积层串联相当于1个$5\times5$的卷积层,感受野大小为$5\times5$。同样地,3个$3\times3$的卷积层串联的效果则相当于1个$7\times7$的卷积层。这样的连接方式使得网络参数量更小,而且多层的激活函数令网络对特征的学习能力更强。
  • VGGNet在训练时有一个小技巧,先训练浅层的的简单网络VGG11,再复用VGG11的权重来初始化VGG13,如此反复训练并初始化VGG19,能够使训练时收敛的速度更快。
  • 在训练过程中使用多尺度的变换对原始数据做数据增强,使得模型不易过拟合。

4.6 GoogLeNet

4.6.1 模型介绍

​ GoogLeNet作为2014年ILSVRC在分类任务上的冠军,以6.65%的错误率力压VGGNet等模型,在分类的准确率上面相比过去两届冠军ZFNet和AlexNet都有很大的提升。从名字GoogLeNet可以知道这是来自谷歌工程师所设计的网络结构,而名字中GoogLeNet更是致敬了LeNet$^{[0]}$。GoogLeNet中最核心的部分是其内部子网络结构Inception,该结构灵感来源于NIN,至今已经经历了四次版本迭代(Inception$_{v1-4}$)。


​ 图 4.8 Inception性能比较图

4.6.2 模型结构


​ 图 4.9 GoogLeNet网络结构图
​ 如图4.9中所示,GoogLeNet相比于以前的卷积神经网络结构,除了在深度上进行了延伸,还对网络的宽度进行了扩展,整个网络由许多块状子网络的堆叠而成,这个子网络构成了Inception结构。图4.9为Inception的四个版本:$Inception{v1}​$在同一层中采用不同的卷积核,并对卷积结果进行合并;$Inception{v2}​$组合不同卷积核的堆叠形式,并对卷积结果进行合并;$Inception{v3}​$则在$v_2​$基础上进行深度组合的尝试;$Inception{v4}​$结构相比于前面的版本更加复杂,子网络中嵌套着子网络。

$Inception_{v1}$

$Inception_{v2}$

$Inception_{v3}$

$Inception_{v4}$

​ 图 4.10 Inception$_{v1-4}$结构图

​ 表 4.6 GoogLeNet中Inception$_{v1}$网络参数配置

网络层 输入尺寸 核尺寸 输出尺寸 参数个数
卷积层$C_{11}$ $H\times{W}\times{C_1}$ $1\times1\times{C_2}/2$ $\frac{H}{2}\times\frac{W}{2}\times{C_2}$ $(1\times1\times{C_1}+1)\times{C_2}$
卷积层$C_{21}$ $H\times{W}\times{C_2}$ $1\times1\times{C_2}/2$ $\frac{H}{2}\times\frac{W}{2}\times{C_2}$ $(1\times1\times{C_2}+1)\times{C_2}$
卷积层$C_{22}$ $H\times{W}\times{C_2}$ $3\times3\times{C_2}/1$ $H\times{W}\times{C_2}/1$ $(3\times3\times{C_2}+1)\times{C_2}$
卷积层$C_{31}$ $H\times{W}\times{C_1}$ $1\times1\times{C_2}/2$ $\frac{H}{2}\times\frac{W}{2}\times{C_2}$ $(1\times1\times{C_1}+1)\times{C_2}$
卷积层$C_{32}$ $H\times{W}\times{C_2}$ $5\times5\times{C_2}/1$ $H\times{W}\times{C_2}/1$ $(5\times5\times{C_2}+1)\times{C_2}$
下采样层$S_{41}$ $H\times{W}\times{C_1}$ $3\times3/2$ $\frac{H}{2}\times\frac{W}{2}\times{C_2}$ $0$
卷积层$C_{42}$ $\frac{H}{2}\times\frac{W}{2}\times{C_2}$ $1\times1\times{C_2}/1$ $\frac{H}{2}\times\frac{W}{2}\times{C_2}$ $(3\times3\times{C_2}+1)\times{C_2}$
合并层$M$ $\frac{H}{2}\times\frac{W}{2}\times{C_2}(\times4)$ 拼接 $\frac{H}{2}\times\frac{W}{2}\times({C_2}\times4)$ $0$

4.6.3 模型特性

  • 采用不同大小的卷积核意味着不同大小的感受野,最后拼接意味着不同尺度特征的融合;

  • 之所以卷积核大小采用1、3和5,主要是为了方便对齐。设定卷积步长stride=1之后,只要分别设定pad=0、1、2,那么卷积之后便可以得到相同维度的特征,然后这些特征就可以直接拼接在一起了;

  • 网络越到后面,特征越抽象,而且每个特征所涉及的感受野也更大了,因此随着层数的增加,3x3和5x5卷积的比例也要增加。但是,使用5x5的卷积核仍然会带来巨大的计算量。 为此,文章借鉴NIN2,采用1x1卷积核来进行降维。

Restnet

Densenet

4.7 为什么现在的CNN模型都是在GoogleNet、VGGNet或者AlexNet上调整的?

  • 评测对比:为了让自己的结果更有说服力,在发表自己成果的时候会同一个标准的baseline及在baseline上改进而进行比较,常见的比如各种检测分割的问题都会基于VGG或者Resnet101这样的基础网络。
  • 时间和精力有限:在科研压力和工作压力中,时间和精力只允许大家在有限的范围探索。
  • 模型创新难度大:进行基本模型的改进需要大量的实验和尝试,并且需要大量的实验积累和强大灵感,很有可能投入产出比比较小。
  • 资源限制:创造一个新的模型需要大量的时间和计算资源,往往在学校和小型商业团队不可行。
  • 在实际的应用场景中,其实是有大量的非标准模型的配置。

参考文献

[1] Y. LeCun, L. Bottou, Y. Bengio, and P. Haffner. Gradient-based learning applied to document recognition. Proceedings of the IEEE, november 1998.

[2] A. Krizhevsky, I. Sutskever and G. E. Hinton. ImageNet Classification with Deep Convolutional Neural Networks. Advances in Neural Information Processing Systems 25. Curran Associates, Inc. 1097–1105.

[3] LSVRC-2013. http://www.image-net.org/challenges/LSVRC/2013/results.php

[4] M. D. Zeiler and R. Fergus. Visualizing and Understanding Convolutional Networks. European Conference on Computer Vision.

[5] M. Lin, Q. Chen, and S. Yan. Network in network. Computing Research Repository, abs/1312.4400, 2013.

[6] K. Simonyan and A. Zisserman. Very Deep Convolutional Networks for Large-Scale Image Recognition. International Conference on Machine Learning, 2015.

[7] Bharath Raj. a-simple-guide-to-the-versions-of-the-inception-network, 2018.

[8] Christian Szegedy, Sergey Ioffe, Vincent Vanhoucke, Alex Alemi. Inception-v4, Inception-ResNet and
the Impact of Residual Connections on Learning
, 2016.

[9] Sik-Ho Tsang. review-inception-v4-evolved-from-googlenet-merged-with-resnet-idea-image-classification, 2018.

[10] Zbigniew Wojna, Christian Szegedy, Vincent Vanhoucke, Sergey Ioffe, Jonathon Shlens. Rethinking the Inception Architecture for Computer Vision, 2015.

[11] Christian Szegedy, Wei Liu, Yangqing Jia, Pierre Sermanet, Scott Reed, Dragomir Anguelov, Dumitru Erhan, Vincent Vanhoucke, Andrew Rabinovich. Going deeper with convolutions, 2014.

[TOC]

https://morvanzhou.github.io/tutorials/machine-learning/reinforcement-learning/

第十章 强化学习

10.1 强化学习的主要特点?

其他许多机器学习算法中学习器都是学得怎样做,而RL是在尝试的过程中学习到在特定的情境下选择哪种行动可以得到最大的回报。在很多场景中,当前的行动不仅会影响当前的rewards,还会影响之后的状态和一系列的rewards。RL最重要的3个特定在于:
(1) 基本是以一种闭环的形式;
(2) 不会直接指示选择哪种行动(actions);
(3) 一系列的actions和奖励信号(reward signals)都会影响之后较长的时间。

10.1.1 定义

强化学习是机器学习的一个重要分支,是多学科多领域交叉的一个产物,它的本质是解决 decision making 问题,即自动进行决策,并且可以做连续决策。
它主要包含四个元素,agent,环境状态,行动,奖励, 强化学习的目标就是获得最多的累计奖励。
我们列举几个形象的例子:
小孩想要走路,但在这之前,他需要先站起来,站起来之后还要保持平衡,接下来还要先迈出一条腿,是左腿还是右腿,迈出一步后还要迈出下一步。
小孩就是 agent,他试图通过采取行动(即行走)来操纵环境(行走的表面),并且从一个状态转变到另一个状态(即他走的每一步),当他完成任务的子任务(即走了几步)时,孩子得到奖励(给巧克力吃),并且当他不能走路时,就不会给巧克力。

上图中agent代表自身,如果是自动驾驶,agent就是车;如果你玩游戏它就是你当前控制的游戏角色,如马里奥,马里奥往前走时环境就一直在发生变化,有小怪物或者障碍物出现,它需要通过跳跃来进行躲避,就是要做action(如向前走和跳起的动作);无人驾驶的action就是车左转、右转或刹车等等,它无时无刻都在与环境产生交互,action会反馈给环境,进而改变环境,如果自动驾驶的车行驶目标是100米,它向前开了10米,那环境就发生了变化,所以每次产生action都会导致环境改变,环境的改变会反馈给自身(agent),就是这样的一个循环;反馈又两种方式:1、做的好(reward)即正反馈,2、做得不好(punishment惩罚)即负反馈。Agent可能做得好,也可能做的不好,环境始终都会给它反馈,agent会尽量去做对自身有利的决策,通过反反复复这样的一个循环,agent会越来越做的好,就像孩子在成长过程中会逐渐明辨是非,这就是强化学习。

10.2 强化学习应用实例

(1)Manufacturing

例如一家日本公司 Fanuc,工厂机器人在拿起一个物体时,会捕捉这个过程的视频,记住它每次操作的行动,操作成功还是失败了,积累经验,下一次可以更快更准地采取行动。

(2)Inventory Management

在库存管理中,因为库存量大,库存需求波动较大,库存补货速度缓慢等阻碍使得管理是个比较难的问题,可以通过建立强化学习算法来减少库存周转时间,提高空间利用率。

(3)Dynamic pricing

强化学习中的 Q-learning 可以用来处理动态定价问题。

(4)Customer Delivery

制造商在向各个客户运输时,想要在满足客户的所有需求的同时降低车队总成本。通过 multi-agents 系统和 Q-learning,可以降低时间,减少车辆数量。

(5)ECommerce Personalization

在电商中,也可以用强化学习算法来学习和分析顾客行为,定制产品和服务以满足客户的个性化需求。

(6)Ad Serving

例如算法 LinUCB (属于强化学习算法 bandit 的一种算法),会尝试投放更广范围的广告,尽管过去还没有被浏览很多,能够更好地估计真实的点击率。
再如双 11 推荐场景中,阿里巴巴使用了深度强化学习与自适应在线学习,通过持续机器学习和模型优化建立决策引擎,对海量用户行为以及百亿级商品特征进行实时分析,帮助每一个用户迅速发现宝贝,提高人和商品的配对效率。还有,利用强化学习将手机用户点击率提升了 10-20%。

(7)Financial Investment Decisions

例如这家公司 Pit.ai,应用强化学习来评价交易策略,可以帮助用户建立交易策略,并帮助他们实现其投资目标。

(8)Medical Industry

动态治疗方案(DTR)是医学研究的一个主题,是为了给患者找到有效的治疗方法。 例如癌症这种需要长期施药的治疗,强化学习算法可以将患者的各种临床指标作为输入 来制定治疗策略。

10.3 强化学习和监督式学习、非监督式学习的区别

在机器学习中,我们比较熟知的是监督式学习,非监督学习,此外还有一个大类就是强化学习:
当前的机器学习算法可以分为3种:有监督的学习(Supervised Learning)、无监督的学习(Unsupervised Learning)和强化学习(Reinforcement Learning),结构图如下所示:

10.3.1 强化学习和监督式学习的区别:

监督式学习就好比你在学习的时候,有一个导师在旁边指点,他知道怎么是对的怎么是错的,但在很多实际问题中,例如 chess,go,这种有成千上万种组合方式的情况,不可能有一个导师知道所有可能的结果。

而这时,强化学习会在没有任何标签的情况下,通过先尝试做出一些行为得到一个结果,通过这个结果是对还是错的反馈,调整之前的行为,就这样不断的调整,算法能够学习到在什么样的情况下选择什么样的行为可以得到最好的结果。

就好比你有一只还没有训练好的小狗,每当它把屋子弄乱后,就减少美味食物的数量(惩罚),每次表现不错时,就加倍美味食物的数量(奖励),那么小狗最终会学到一个知识,就是把客厅弄乱是不好的行为。

两种学习方式都会学习出输入到输出的一个映射,监督式学习出的是之间的关系,可以告诉算法什么样的输入对应着什么样的输出,强化学习出的是给机器的反馈 reward function,即用来判断这个行为是好是坏。
另外强化学习的结果反馈有延时,有时候可能需要走了很多步以后才知道以前的某一步的选择是好还是坏,而监督学习做了比较坏的选择会立刻反馈给算法。

而且强化学习面对的输入总是在变化,每当算法做出一个行为,它影响下一次决策的输入,而监督学习的输入是独立同分布的。

通过强化学习,一个 agent 可以在探索和开发(exploration and exploitation)之间做权衡,并且选择一个最大的回报。

exploration 会尝试很多不同的事情,看它们是否比以前尝试过的更好。

exploitation 会尝试过去经验中最有效的行为。

一般的监督学习算法不考虑这种平衡,就只是是 exploitative。

10.3.2 强化学习和非监督式学习的区别:

非监督式不是学习输入到输出的映射,而是模式。例如在向用户推荐新闻文章的任务中,非监督式会找到用户先前已经阅读过类似的文章并向他们推荐其一,而强化学习将通过向用户先推荐少量的新闻,并不断获得来自用户的反馈,最后构建用户可能会喜欢的文章的“知识图”。

对非监督学习来说,它通过对没有概念标记的训练例进行学习,以发现训练例中隐藏的结构性知识。这里的训练例的概念标记是不知道的,因此训练样本的歧义性最高。对强化学习来说,它通过对没有概念标记、但与一个延迟奖赏或效用(可视为延迟的概念标记)相关联的训练例进行学习,以获得某种从状态到行动的映射。这里本来没有概念标记的概
念,但延迟奖赏可被视为一种延迟概念标记,因此其训练样本的歧义性介于监督学习和非监督学习之间。

需要注意的是,监督学习和非监督学习从一开始就是相对的,而强化学习在提出时并没有从训练样本歧义性的角度考虑其与监督学习和非监督学习的区别,因此,一些早期的研究中把强化学习视为一种特殊的非监督学习。事实上,对强化学习的定位到目前仍然是有争议的,有的学者甚至认为它是与“从例子中学习”同一级别的概念。

从训练样本歧义性角度进行的分类体系,在近几年可望有一些扩展,例如多示例学习(multi-instancelearning)等从训练样本歧义性方面来看很特殊的新的学习框架有可能会进入该体系。但到目前为止,没有任何新的框架得到了公认的地位。另外,半监督学习(semi-supervisedlearning)也有一定希望,它的障碍是半监督学习中的歧义性并不是与生俱来的,而是人为的,即用户期望用未标记的样本来辅助对已标记样本的学习。这与监督学习、非监督学习、强化学习等天生的歧义性完全不同。半监督学习中人为的歧义性在解决工程问题上是需要的、有用的(对大量样本进行标记的代价可能是极为昂贵的),但可能不太会导致方法学或对学习问题视点的大的改变。

强化学习和前二者的本质区别:没有前两者具有的明确数据概念,它不知道结果,只有目标。数据概念就是大量的数据,有监督学习、无监督学习需要大量数据去训练优化你建立的模型,就像猫狗识别,用n多张猫狗图片去训练模型,经过训练优化后,你用一张崭新的猫狗图片让模型作出判断,这个模型就知道是猫还是狗。

10.4 强化学习主要有哪些算法?

强化学习不需要监督信号,可以在模型未知的环境中平衡探索和利用, 其主要算法有蒙特卡罗强化学习, 时间差分(temporal difference: TD)学习, 策略梯度等。典型的深度强化学习算法特点及性能比较如下图所示:

除了上述深度强化学习算法,还有深度迁移强化学习、分层深度强化学习、深度记忆强化学习以及多智能体强化学习等算法。

10.5 深度迁移强化学习算法

传统深度强化学习算法每次只能解决一种游戏任务, 无法在一次训练中完成多种任务. 迁移学习和强化学习的结合也是深度强化学习的一种主要思路。

Parisotto等提出了一种基于行为模拟的深度迁移强化学习算法. 该算法通过监督信号的指导, 使得单一的策略网络学习各自的策略, 并将知识迁移到新任务中. Rusa等提出策略蒸馏(policy distillation)深度迁移强化学习算法. 策略蒸馏算法中分为学习网络和指导网络, 通过这两个网络Q值的偏差来确定目标函数,引导学习网络逼近指导网络的值函数空间. 此后,Rusa等又提出了一种基于渐进神经网络(progressive neural networks, PNN)的深度迁移强化学习算法.PNN是一种把神经网络和神经网络连起来的算法. 它在一系列序列任务中, 通过渐进的方式来存储知识和提取特征, 完成了对知识的迁移. PNN最终实现多个独立任务的训练, 通过迁移加速学习过程, 避免灾难性遗忘. Fernando 等提出了路径网络(PathNet)[45].PathNet可以说是PNN的进阶版. PathNet把网络中每一层都看作一个模块, 把构建一个网络看成搭积木,也就是复用积木. 它跟PNN非常类似, 只是这里不再有列, 而是不同的路径. PathNet将智能体嵌入到神经网络中, 其中智能体的任务是为新任务发现网络中可以复用的部分. 智能体是网络之中的路径, 其决定了反向传播过程中被使用和更新的参数范围. 在一系列的Atari强化学习任务上, PathNet都实现了正迁移, 这表明PathNet在训练神经网络上具有通用性应用能力.PathNet也可以显著提高A3C算法超参数选择的鲁棒性. Schaul等提出了一种通用值函数逼近器(universalvalue function approximators, UVFAs)来泛化状态和目标空间.UVFAs可以将学习到的知识迁移到环境动态特性相同但目标不同的新任务中.

10.6 分层深度强化学习算法

分层强化学习可以将最终目标分解为多个子任务来学习层次化的策略, 并通过组合多个子任务的策略形成有效的全局策略. Kulkarni等提出了分层DQN(hierarchical deep Q-network, h—DQN) 算法. h—DQN基于时空抽象和内在激励分层, 通过在不同的时空尺度上设置子目标对值函数进行层次化处理. 顶层的值函数用于确定宏观决策, 底层的值函数用于确定具体行动.Krishnamurthy等在h—DQN的基础上提出了基于内部选择的分层深度强化学习算法. 该模型结合时空抽象和深度神经网络, 自动地完成子目标的学习, 避免了特定的内在激励和人工设定中间目标,加速了智能体的学习进程, 同时也增强了模型的泛化能力. Kulkarni等基于后续状态表示法提出了深度后续强化学习(deep successor reinforcement learning,DSRL).DSRL通过阶段性地分解子目标和学习子目标策略, 增强了对未知状态空间的探索, 使得智能体更加适应那些存在延迟反馈的任务.Vezhnevets等受封建(feudal)强化学习算法的启发, 提出一种分层深度强化学习的架构FeUdal网络(FuNs)[49]. FuNs框架使用一个管理员模块和一个工人模块. 管理员模块在较低的时间分辨率下工作, 设置抽象目标并传递给工人模块去执行. FuNs框架创造了一个稳定的自然层次结构, 并且允许两个模块以互补的方式学习. 实验证明, FuNs有助于处理长期信用分配和记忆任务,在Atari视频游戏和迷宫游戏中都取得了不错的效果。

10.7 深度记忆强化学习算法

传统的深度强化学习模型不具备记忆、认知、推理等高层次的能力, 尤其是在面对状态部分可观察和延迟奖赏的情形时. Junhyuk等通过在传统的深度强化学习模型中加入外部的记忆网络部件和反馈控制机制, 提出反馈递归记忆Q网络(feedback recurrent memory Q-network, FRMQN)). FRMQN模型具备了一定的记忆与推理功能, 通过反馈控制机制,FRMQN整合过去存储的有价值的记忆和当前时刻的上下文状态, 评估动作值函数并做出决策. FRMQN初步模拟了人类的主动认知与推理能力, 并完成了一些高层次的认知任务. 在一些未经过训练的任务中,FRMQN模型表现出了很强的泛化能力.Blundell等设计出一种模型无关的情节控制算法(model-free episode control, MFEC). MFEC可以快速存储和回放状态转移序列, 并将回放的序列整合到结构化知识系统中, 使得智能体在面对一些复杂的决策任务时, 能快速达到人类玩家的水平.MFEC通过反向经验回放, 使智能体拥有初步的情节记忆. 实验表明, 基于MFEC算法的深度强化学习不仅可以在Atari游戏中学习到有效策略, 还可以处理一些三维场景的复杂任务. Pritzel等在MFEC的基础上进一步提出了神经情节控制(neural episodic control, NEC),有效提高了深度强化学习智能体的记忆能力和学习效率[53]. NEC能快速吸收新经验并依据新经验来采取行动. 价值函数包括价值函数渐变状态表示和价值函数快速更新估计两部分. 大量场景下的研究表明,NEC的学习速度明显快于目前最先进的通用深度强化学习智能体.

10.8 多智能体深度强化学习算法

在一些复杂场景中, 涉及到多智能体的感知决策问题, 这时需要将单一模型扩展为多个智能体之间相互合作、通信及竞争的多智能体深度强化学习系统.Foerster等提出了一种称为分布式深度递归Q网络(deep distributed recurrent Q-networks, DDRQN) 的模型, 解决了状态部分可观测状态下的多智能体通信与合作的挑战性难题[54]. 实验表明, 经过训练的DDRQN模型最终在多智能体之间达成了一致的通信协1536 控制理论与应用第34 卷议, 成功解决了经典的红蓝帽子问题.让智能体学会合作与竞争一直以来都是人工智能领域内的一项重要研究课题, 也是实现通用人工智能的必要条件. Lowe等提出了一种用于合作–竞争混合环境的多智能体actor-critic 算法(multi-agent deepdeterministic policy gradient, MADDPG)[55]. MADDPG对DDPG强化学习算法进行了延伸, 可实现多智能体的集中式学习和分布式执行, 让智能体学习彼此合作和竞争. 在多项测试任务中, MADDPG的表现都优于DDPG.

10.9 强化学习开源框架

谷歌TensorFlow Agents —-TensorFlow的加强版,它提供许多工具,通过强化学习可以实现各类智能应用程序的构建与训练。这个框架能够将OpoenAI Gym接口扩展至多个并行环境,并允许各代理立足TensorFlow之内实现以执行批量计算。其面向OpoenAI Gy环境的批量化接口可与TensorFlow实现全面集成,从而高效执行各类算法。该框架还结合有BatchPPO,一套经过优化的近端策略优化算法实现方案。其核心组件包括一个环境打包器,用于在外部过程中构建OpenAI Gym环境; 一套批量集成,用于实现TensorFlow图步并以强化学习运算的方式重置函数; 外加用于将TensorFlow图形批处理流程与强化学习算法纳入训练特内单一却步的组件。

Roboschool:Roboschool 提供开源软件以通过强化学习构建并训练机器人模拟。其有助于在同一环境当中对多个代理进行强化学习训练。通过多方训练机制,您可以训练同一代理分别作为两方玩家(因此能够自我对抗)、使用相同算法训练两套代理,或者设置两种算法进行彼此对抗。Roboschool由OpenAI开发完成,这一非营利性组织的背后赞助者包括Elon Musk、Sam Altman、Reid Hoffman以及Peter Thiel。其与OpenAI Gym相集成,后者是一套用于开发及评估强化学习算法的开源工具集。OpenAI Gym与TensorFlow、Theano以及其它多种深度学习库相兼容。OpenAI Gym当中包含用于数值计算、游戏以及物理引擎的相关代码。Roboschool基于Bullet物理引擎,这是一套开源许可物理库,并被其它多种仿真软件——例如Gazebo与Virtual Robot Experimentation Platform(简称V-REP)所广泛使用。其中包含多种强化学习算法,具体以怨报德 异步深度强化学习方法、Actor-Critic with Experience Replay、Actor- Critic using Kronecker-Factored Trust Region、深度确定性策略梯度、近端策略优化以及信任域策略优化等等。

Coach:英特尔公司的开源强化学习框架,可以对游戏、机器人以及其它基于代理的智能应用进行智能代理的建模、训练与评估。Coach 提供一套模块化沙箱、可复用组件以及用于组合新强化学习算法并在多种应用领域内训练新智能应用的Python API。该框架利用OpenAI Gym作为主工具,负责与不同强化学习环境进行交换。其还支持其它外部扩展,具体包括Roboschool、gym-extensions、PyBullet以及ViZDoom。Coach的环境打包器允许用户向其中添加自定义强化学习环境,从而解决其它学习问题。该框架能够在桌面计算机上高效训练强化学习代理,并利用多核CPU处理相关任务。其能够为一部分强化学习算法提供单线程与多线程实现能力,包括异步优势Actor-Critic、深度确定性策略梯度、近端策略优化、直接未来预测以及规范化优势函数。所有算法皆利用面向英特尔系统作出优化的TensorFLow完成,其中部分算法亦适用于英特尔的Neon深度学习框架。Coach 当中包含多种强化学习代理实现方案,具体包括从单线程实现到多线程实现的转换。其能够开发出支持单与多工作程序(同步或异步)强化学习实现方法的新代理。此外,其还支持连续与离散操作空间,以及视觉观察空间或仅包含原始测量指标的观察空间。

10.10 深度强化学习算法小结

基于值函数概念的DQN及其相应的扩展算法在离散状态、离散动作的控制任务中已经表现了卓越的性能, 但是受限于值函数离散型输出的影响, 在连续型控制任务上显得捉襟见肘. 基于策略梯度概念的,以DDPG, TRPO等为代表的策略型深度强化学习算法则更适用于处理基于连续状态空间的连续动作的控制输出任务, 并且算法在稳定性和可靠性上具有一定的理论保证, 理论完备性较强. 采用actor-critic架构的A3C算法及其扩展算法, 相比于传统DQN算法, 这类算法的数据利用效率更高, 学习速率更快, 通用性、可扩展应用性更强, 达到的表现性能更优, 但算法的稳定性无法得到保证. 而其他的如深度迁移强化学习、分层深度强化学习、深度记忆强化学习和多智能体深度强化学习等算法都是现在的研究热点, 通过这些算法能应对更为复杂的场景问题、系统环境及控制任务, 是目前深度强化学习算法研究的前沿领域.

展望未来,人工智能开发者们需要尽可能掌握上述框架以及其中所使用的各类强化学习算法。此外,还需要强化自身对于多代理强化学习架构的理解,因为其中多种框架都大量利用前沿博弈论研究成果。最后,还需要熟悉深度强化学习知识。

[TOC]

第十二章 网络搭建及训练

12.1 TensorFlow

12.1.1 TensorFlow是什么?

  TensorFlow支持各种异构平台,支持多CPU/GPU、服务器、移动设备,具有良好的跨平台的特性;TensorFlow架构灵活,能够支持各种网络模型,具有良好的通用性;此外,TensorFlow架构具有良好的可扩展性,对OP的扩展支持,Kernel特化方面表现出众。

  TensorFlow最初由Google大脑的研究员和工程师开发出来,用于机器学习和神经网络方面的研究,于2015.10宣布开源,在众多深度学习框架中脱颖而出,在Github上获得了最多的Star量。

12.1.2 TensorFlow的设计理念是什么?

TensorFlow的设计理念主要体现在两个方面:

(1)将图定义和图运算完全分开。
  TensorFlow 被认为是一个“符号主义”的库。我们知道,编程模式通常分为命令式编程(imperative style programming)和符号式编程(symbolic style programming)。命令式编程就是编写我们理解的通常意义上的程序,很容易理解和调试,按照原有逻辑执行。符号式编程涉及很多的嵌入和优化,不容易理解和调试,但运行速度相对有所提升。现有的深度学习框架中,Torch 是典型的命令式的,Caffe、MXNet 采用了两种编程模式混合的方法,而 TensorFlow 完全采用符号式编程。

  符号式计算一般是先定义各种变量,然后建立一个数据流图,在数据流图中规定各个变量间的计算关系,最后需要对据流图进行编译,但此时的数据流图还是一个空壳儿,里面没有任何实际数据,只有把需要运算的输入放进去后,才能在整个模型中形成数据流,从而形成输出值。

  例如:

1
2
t = 8 + 9
print(t)

  在传统的程序操作中,定义了 t 的运算,在运行时就执行了,并输出 17。而在 TensorFlow中,数据流图中的节点,实际上对应的是 TensorFlow API 中的一个操作,并没有真正去运行:

1
2
3
4
5
import tensorflow as tf
t = tf.add(8,9)
print(t)

#输出 Tensor{"Add_1:0",shape={},dtype=int32}

  (2)TensorFlow 中涉及的运算都要放在图中,而图的运行只发生在会话(session)中。开启会话后,就可以用数据去填充节点,进行运算;关闭会话后,就不能进行计算了。因此,会话提供了操作运行和 Tensor 求值的环境。

  例如:

1
2
3
4
5
6
7
8
9
10
import tensorflow as tf
#创建图
a = tf.constant([4.0,5.0])
b = tf.constant([6.0,7.0])
c = a * b
#创建会话
sess = tf.Session()
#计算c
print(sess.run(c)) #进行矩阵乘法,输出[24.,35.]
sess.close()

12.1.3 TensorFlow特点有哪些?

1.高度的灵活性

  TensorFlow 并不仅仅是一个深度学习库,只要可以把你的计算过程表示称一个数据流图的过程,我们就可以使用 TensorFlow 来进行计算。TensorFlow 允许我们用计算图的方式建立计算网络,同时又可以很方便的对网络进行操作。用户可以基于 TensorFlow 的基础上用 python 编写自己的上层结构和库,如果TensorFlow没有提供我们需要的API的,我们也可以自己编写底层的 C++ 代码,通过自定义操作将新编写的功能添加到 TensorFlow 中。

2.真正的可移植性

  TensorFlow 可以在 CPU 和 GPU 上运行,可以在台式机、服务器、移动设备上运行。你想在你的笔记本上跑一下深度学习的训练,或者又不想修改代码,想把你的模型在多个CPU上运行, 亦或想将训练好的模型放到移动设备上跑一下,这些TensorFlow都可以帮你做到。

3.多语言支持

  TensorFlow采用非常易用的python来构建和执行我们的计算图,同时也支持 C++ 的语言。我们可以直接写python和C++的程序来执行TensorFlow,也可以采用交互式的ipython来方便的尝试我们的想法。当然,这只是一个开始,后续会支持更多流行的语言,比如Lua,JavaScript 或者R语言。

4.丰富的算法库

  TensorFlow提供了所有开源的深度学习框架里,最全的算法库,并且在不断的添加新的算法库。这些算法库基本上已经满足了大部分的需求,对于普通的应用,基本上不用自己再去自定义实现基本的算法库了。

5.完善的文档

  TensorFlow的官方网站,提供了非常详细的文档介绍,内容包括各种API的使用介绍和各种基础应用的使用例子,也包括一部分深度学习的基础理论。

  自从宣布开源以来,大量人员对TensorFlow做出贡献,其中包括Google员工,外部研究人员和独立程序员,全球各地的工程师对TensorFlow的完善,已经让TensorFlow社区变成了Github上最活跃的深度学习框架。

12.1.4 TensorFlow的系统架构是怎样的?

  整个系统从底层到上层可分为七层:

  设备层:硬件计算资源,支持CPU、GPU

  网络层:支持两种通信协议

  数值计算层:提供最基础的计算,有线性计算、卷积计算

  高维计算层:数据的计算都是以数组的形式参与计算

  计算图层:用来设计神经网络的结构

  工作流层:提供轻量级的框架调用

  构造层:最后构造的深度学习网络可以通过TensorBoard服务端可视化

12.1.5 TensorFlow编程模型是怎样的?

TensorFlow的编程模型:让向量数据在计算图里流动。那么在编程时至少有这几个过程:1.构建图,2.启动图,3.给图输入数据并获取结果。

1.构建图

TensorFlow的图的类型是tf.Graph,它包含着计算节点和tensor的集合。

  这里引用了两个新概念:tensor和计算节点。
  我们先介绍tensor,一开始我们就介绍了,我们需要把数据输入给启动的图才能获取计算结果。那么问题来了,在构建图时用什么表示中间计算结果?这个时候tensor的概念就需要引入了。
  类型是tf.Tensor,代表某个计算节点的输出,一定要看清楚是“代表”。它主要有两个作用:

1.构建不同计算节点之间的数据流

2.在启动图时,可以设置某些tensor的值,然后获取指定tensor的值。这样就完成了计算的输入输出功能。

如下代码所示:

1
2
inImage = tf.placeholder(tf.float32,[32,32,3],"inputImage")
processedImage = tf.image.per_image_standardization(inImage,"processedImage")

  这里inImage和processedImage都是tensor类型。它们代表着计算节点输出的数据,数据的值具体是多少在启动图的时候才知道。上面两个方法调用都传递了一个字符串,它是计算节点的名字,最好给节点命名,这样我们可以在图上调用get_tensor_by_name(name)获取对应的tensor对象,十分方便。(tensor名字为“<计算节点名字>:”)

  创建tensor时,需要指定类型和shape。对不同tensor进行计算时要求类型相同,可以使用 tf.cast 进行类型转换。同时也要求 shape (向量维度)满足运算的条件,我们可以使用 tf.reshape 改变shape。

  现在了解计算节点的概念,其功能是对tensor进行计算、创建tensor或进行其他操作,类型是tf.Operation。获取节点对象的方法为get_operation_by_name(name)。

构建图,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
g=tf.Graph()

with g.as_default():
input_data=tf.placeholder(tf.float32,[None,2],"input_data")
input_label=tf.placeholder(tf.float32,[None,2],"input_label")

W1=tf.Variable(tf.truncated_normal([2,2]),name="W1")
B1=tf.Variable(tf.zeros([2]),name="B1")

output=tf.add(tf.matmul(input_data,W1),B1,name="output")
cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=output,labels=input_label)

train_step=tf.train.AdamOptimizer().minimize(cross_entropy,name="train_step")

initer=tf.global_variables_initializer()

  上面的代码中我们创建了一个图,并在上面添加了很多节点。我们可以通过调用get_default_graph()获取默认的图。

  Input_data,input_label,W1,B1,output,cross_entropy都是tensor类型,train_step,initer,是节点类型。

有几类tensor或节点比较重要,下面介绍一下:

1.placeholder

  Tensorflow,顾名思义, tensor代表张量数据,flow代表流,其最初的设计理念就是构建一张静态的数据流图。图是有各个计算节点连接而成,计算节点之间流动的便是中间的张量数据。要想让张量数据在我们构建的静态计算图中流动起来,就必须有最初的输入数据流。而placeholder,翻译过来叫做占位符,顾名思义,是给我们的输入数据提供一个接口,也就是说我们的一切输入数据,例如训练样本数据,超参数数据等都可以通过占位符接口输送到数据流图之中。使用实例如下代码:

1
2
3
4
5
6
7
8
import tensorflow as tf
x = tf.placeholder(dtype=tf.float32,shape=[],name='x')
y = tf.placeholder(dtpe=tf.float32,shape=[],nmae='y')
z = x*y
with tf.Session() as sess:
prod = sess.run(z,feed_dict={x:1.,y:5.2})
print(prod)
[out]:5.2

2. variable

  无论是传统的机器学习算法,例如线性支持向量机(Support Vector Machine, SVM),其数学模型为y = + b,还是更先进的深度学习算法,例如卷积神经网络(Convolutional Neural Network, CNN)单个神经元输出的模型y = w*x + b。可以看到,w和b就是我们要求的模型,模型的求解是通过优化算法(对于SVM,使用
SMO[1]算法,对于CNN,一般基于梯度下降法)来一步一步更新w和b的值直到满足停止条件。因此,大多数机器学习的模型中的w和b实际上是以变量的形式出现在代码中的,这就要求我们在代码中定义模型变量。

1
2
3
4
5
6
7
import tensorflow as tf
a = tf.Variable(2.)
b = tf.Variable(3.)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer()) #变量初始化
print(sess.run(a*b))
[out]:6.

[1] Platt, John. “Sequential minimal optimization: A fast algorithm for training support vector machines.” (1998).

3. initializer

  由于tensorflow构建的是静态的计算流图,在开启会话之前,所有的操作都不会被执行。因此为了执行在计算图中所构建的赋值初始化计算节点,需要在开启会话之后,在会话环境下运行初始化。如果计算图中定义了变量,而会话环境下为执行初始化命令,则程序报错,代码如下:

1
2
3
4
5
6
7
import tensorflow as tf
a = tf.Variable(2.)
b = tf.Variable(3.)
with tf.Session() as sess:
#sess.run(tf.global_variables_initializer()) #注释掉初始化命令
print(sess.run(a*b))
[Error]: Attempting to use uninitialized value Variable

2.启动图

  先了解session的概念,然后才能更好的理解图的启动。
  图的每个运行实例都必须在一个session里,session为图的运行提供环境。Session的类型是tf.Session,在实例化session对象时我们需要给它传递一个图对象,如果不显示给出将使用默认的图。Session有一个graph属性,我们可以通过它获取session对应的图。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
numOfBatch=5
datas=np.zeros([numOfBatch,2],np.float32)
labels=np.zeros([numOfBatch,2],np.float32)

sess=tf.Session(graph=g)
graph=sess.graph
sess.run([graph.get_operation_by_name("initer")])

dataHolder=graph.get_tensor_by_name("input_data:0")
labelHolder=graph.get_tensor_by_name("input_label:0")
train=graph.get_operation_by_name("train_step")
out=graph.get_tensor_by_name("output:0")

for i inrange(200):
result=sess.run([out,train],feed_dict={dataHolder:datas,labelHolder:labels})
if i%100==0:
saver.save(sess,"./moules")

sess.close()

代码都比较简单,就不介绍了。不过要注意2点:1.别忘记运行初始化节点,2.别忘记close掉session对象以释放资源。

3.给图输入数据并获取结果

代码:

1
2
for i inrange(200):
result=sess.run([out,train],feed_dict={dataHolder:datas,labelHolder:labels})

  这里主要用到了session对象的run方法,它用来运行某个节点或tensor并获取对应的值。我们一般会一次传递一小部分数据进行mini-batch梯度下降来优化模型。

  我们需要把我们需要运行的节点或tensor放入一个列表,然后作为第一个参数(不考虑self)传递给run方法,run方法会返回一个计算结果的列表,与我们传递的参数一一对应。

  如果我们运行的节点依赖某个placeholder,那我们必须给这个placeholder指定值,怎么指定代码里面很清楚,给关键字参数feed_dict传递一个字典即可,字典里的元素的key是placeholder对象,value是我们指定的值。值的数据的类型必须和placeholder一致,包括shape。值本身的类型是numpy数组。

这里再解释一个细节,在定义placeholder时代码如下:

1
2
input_data=tf.placeholder(tf.float32,[None,2],"input_data")
input_label=tf.placeholder(tf.float32,[None,2],"input_label")

  shape为[None,2],说明数据第一个维度是不确定的,然后TensorFlow会根据我们传递的数据动态推断第一个维度,这样我们就可以在运行时改变batch的大小。比如一个数据是2维,一次传递10个数据对应的tensor的shape就是[10,2]。可不可以把多个维度指定为None?理论上不可以!

12.1.6 如何基于tensorflow搭建VGG16

​ 介绍完关于tensorflow的基础知识,是时候来一波网络搭建实战了。虽然网上有很多相关教程,但我想从最标准的tensorflow代码和语法出发(而不是调用更高级的API,失去了原来的味道),向大家展示如何搭建其标准的VGG16网络架构。话不多说,上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import numpy as np
import tensorflow as tf

def get_weight_variable(shape):
return tf.get_variable('weight', shape=shape, initializer=tf.truncated_normal_initializer(stddev=0.1))

def get_bias_variable(shape):
return tf.get_variable('bias', shape=shape, initializer=tf.constant_initializer(0))

def conv2d(x, w, padding = 'SAME', s=1):
x = tf.nn.conv2d(x, w, strides=[1, s, s, 1], padding = padding)
return x

def maxPoolLayer(x):
return tf.nn.max_pool(x, ksize = [1, 2, 2, 1],
strides = [1, 2, 2, 1], padding = 'SAME')

def conv2d_layer(x,in_chs, out_chs, ksize, layer_name):
with tf.variable_scope(layer_name):
w = get_weight_variable([ksize, ksize, in_chs, out_chs])
b = get_bias_variable([out_chs])
y = tf.nn.relu(tf.bias_add(conv2d(x,w,padding = 'SAME', s=1), b))
return y

def fc_layer(x,in_kernels, out_kernels, layer_name):
with tf.variable_scope(layer_name):
w = get_weight_variable([in_kernels,out_kernels])
b = get_bias_variable([out_kernels])
y = tf.nn.relu(tf.bias_add(tf.matmul(x,w),b))
return y

def VGG16(x):
conv1_1 = conv2d_layer(x,tf.get_shape(x).as_list()[-1], 64, 3, 'conv1_1')
conv1_2 = conv2d_layer(conv1_1,64, 64, 3, 'conv1_2')
pool_1 = maxPoolLayer(conv1_2)

conv2_1 = conv2d_layer(pool1,64, 128, 3, 'conv2_1')
conv2_2 = conv2d_layer(conv2_1,128, 128, 3, 'conv2_2')
pool2 = maxPoolLayer(conv2_2)

conv3_1 = conv2d_layer(pool2,128, 256, 3, 'conv3_1')
conv3_2 = conv2d_layer(conv3_1,256, 256, 3, 'conv3_2')
conv3_3 = conv2d_layer(conv3_2,256, 256, 3, 'conv3_3')
pool3 = maxPoolLayer(conv3_3)

conv4_1 = conv2d_layer(pool3,256, 512, 3, 'conv4_1')
conv4_2 = conv2d_layer(conv4_1,512, 512, 3, 'conv4_2')
conv4_3 = conv2d_layer(conv4_2,512, 512, 3, 'conv4_3')
pool4 = maxPoolLayer(conv4_3)

conv5_1 = conv2d_layer(pool4,512, 512, 3, 'conv5_1')
conv5_2 = conv2d_layer(conv5_1,512, 512, 3, 'conv5_2')
conv5_3 = conv2d_layer(conv5_1,512, 512, 3, 'conv5_3')
pool5 = maxPoolLayer(conv5_3)

pool5_flatten_dims = int(np.prod(pool5.get_shape().as_list()[1:]))
pool5_flatten = tf.reshape(pool5,[-1,pool5_flatten_dims])

fc_6 = fc_layer(pool5_flatten, pool5_flatten_dims, 4096, 'fc6')
fc_7 = fc_layer(fc_6, 4096, 4096, 'fc7')
fc_8 = fc_layer(fc_7, 4096, 10, 'fc8')

return fc_8

12.2 Pytorch

12.2.1 Pytorch是什么?

  Pytorch是torch的python版本,是由Facebook开源的神经网络框架,专门针对 GPU 加速的深度神经网络(DNN)编程。Torch 是一个经典的对多维矩阵数据进行操作的张量(tensor )库,在机器学习和其他数学密集型应用有广泛应用。与Tensorflow的静态计算图不同,pytorch的计算图是动态的,可以根据计算需要实时改变计算图。但由于Torch语言采用 Lua,导致在国内一直很小众,并逐渐被支持 Python 的 Tensorflow 抢走用户。作为经典机器学习库 Torch 的端口,PyTorch 为 Python 语言使用者提供了舒适的写代码选择。

12.2.2 为什么选择 Pytorch?

1.简洁:

  PyTorch的设计追求最少的封装,尽量避免重复造轮子。不像 TensorFlow 中充斥着session、graph、operation、name_scope、variable、tensor、layer等全新的概念,PyTorch 的设计遵循tensor→variable(autograd)→nn.Module 三个由低到高的抽象层次,分别代表高维数组(张量)、自动求导(变量)和神经网络(层/模块),而且这三个抽象之间联系紧密,可以同时进行修改和操作。
简洁的设计带来的另外一个好处就是代码易于理解。PyTorch的源码只有TensorFlow的十分之一左右,更少的抽象、更直观的设计使得PyTorch的源码十分易于阅读。

2.速度:

  PyTorch 的灵活性不以速度为代价,在许多评测中,PyTorch 的速度表现胜过 TensorFlow和Keras 等框架。框架的运行速度和程序员的编码水平有极大关系,但同样的算法,使用PyTorch实现的那个更有可能快过用其他框架实现的。

3.易用:

  PyTorch 是所有的框架中面向对象设计的最优雅的一个。PyTorch的面向对象的接口设计来源于Torch,而Torch的接口设计以灵活易用而著称,Keras作者最初就是受Torch的启发才开发了Keras。PyTorch继承了Torch的衣钵,尤其是API的设计和模块的接口都与Torch高度一致。PyTorch的设计最符合人们的思维,它让用户尽可能地专注于实现自己的想法,即所思即所得,不需要考虑太多关于框架本身的束缚。

4.活跃的社区:

  PyTorch 提供了完整的文档,循序渐进的指南,作者亲自维护的论坛 供用户交流和求教问题。Facebook 人工智能研究院对 PyTorch 提供了强力支持,作为当今排名前三的深度学习研究机构,FAIR的支持足以确保PyTorch获得持续的开发更新,不至于像许多由个人开发的框架那样昙花一现。

12.2.3 PyTorch 的架构是怎样的?

  PyTorch(Caffe2) 通过混合前端,分布式训练以及工具和库生态系统实现快速,灵活的实验和高效生产。PyTorch 和 TensorFlow 具有不同计算图实现形式,TensorFlow 采用静态图机制(预定义后再使用),PyTorch采用动态图机制(运行时动态定义)。PyTorch 具有以下高级特征:

  混合前端:新的混合前端在急切模式下提供易用性和灵活性,同时无缝转换到图形模式,以便在C ++运行时环境中实现速度,优化和功能。
  分布式训练:通过利用本地支持集合操作的异步执行和可从Python和C ++访问的对等通信,优化了性能。
  Python优先: PyTorch为了深入集成到Python中而构建的,因此它可以与流行的库和Cython和Numba等软件包一起使用。
  丰富的工具和库:活跃的研究人员和开发人员社区建立了丰富的工具和库生态系统,用于扩展PyTorch并支持从计算机视觉到强化学习等领域的开发。
  本机ONNX支持:以标准ONNX(开放式神经网络交换)格式导出模型,以便直接访问与ONNX兼容的平台,运行时,可视化工具等。
  C++前端:C++前端是PyTorch的纯C++接口,它遵循已建立的Python前端的设计和体系结构。它旨在实现高性能,低延迟和裸机C++应用程序的研究。
使用GPU和CPU优化的深度学习张量库。

12.2.4 Pytorch 与 tensorflow 之间的差异在哪里?

  上面也将了PyTorch 最大优势是建立的神经网络是动态的, 对比静态的 Tensorflow, 它能更有效地处理一些问题, 比如说 RNN 变化时间长度的输出。各有各的优势和劣势。两者都是大公司发布的, Tensorflow(Google)宣称在分布式训练上下了很大的功夫, 那就默认 Tensorflow 在分布式训练上要超出 Pytorch(Facebook),还有tensorboard可视化工具, 但是 Tensorflow 的静态计算图使得在 RNN 上有一点点被动 (虽然它用其他途径解决了), 不过用 PyTorch 的时候, 会对这种动态的 RNN 有更好的理解。而且 Tensorflow 的高度工业化, 它的底层代码很难看懂, Pytorch 好那么一点点, 如果深入 PytorchAPI, 至少能比看 Tensorflow 多看懂一点点 Pytorch 的底层在干啥。

12.2.5 Pytorch有哪些常用工具包?

  torch :类似 NumPy 的张量库,强 GPU 支持 ;
  torch.autograd :基于 tape 的自动区别库,支持 torch 之中的所有可区分张量运行;
  torch.nn :为最大化灵活性未涉及、与 autograd 深度整合的神经网络库;
  torch.optim:与 torch.nn 一起使用的优化包,包含 SGD、RMSProp、LBFGS、Adam 等标准优化方式;
  torch.multiprocessing: python 多进程并发,进程之间 torch Tensors 的内存共享;
  torch.utils:数据载入器。具有训练器和其他便利功能;
  torch.legacy(.nn/.optim) :处于向后兼容性考虑,从 Torch 移植来的 legacy 代码;

12.3 Caffe

12.3.1 什么是 Caffe?

  Caffe的全称应该是Convolutional Architecture for Fast Feature Embedding,它是一个清晰、高效的深度学习框架,它是开源的,核心语言是C++,它支持命令行、Python和Matlab接口,它既可以在CPU上运行也可以在GPU上运行。它的license是BSD 2-Clause。

12.3.2 Caffe的特点是什么?

(1)、模块化:Caffe从一开始就设计得尽可能模块化,允许对新数据格式、网络层和损失函数进行扩展。

(2)、表示和实现分离:Caffe的模型(model)定义是用Protocol Buffer语言写进配置文件的。以任意有向无环图的形式,Caffe支持网络架构。Caffe会根据网络的需要来正确占用内存。通过一个函数调用,实现CPU和GPU之间的切换。

(3)、测试覆盖:在Caffe中,每一个单一的模块都对应一个测试。

(4)、python和Matlab接口:同时提供Python和Matlab接口。

(5)、预训练参考模型:针对视觉项目,Caffe提供了一些参考模型,这些模型仅应用在学术和非商业领域,它们的license不是BSD。

12.3.3 Caffe的设计思想是怎样的?

  基本上,Caffe 沿用了神经网络的一个简单假设——所有的计算都是以layer的形式表示的,layer做的事情就是take一些数据,然后输出一些计算以后的结果,比如说卷积,就是输入一个图像,然后和这一层的参数(filter)做卷积,然后输出卷积的结果。每一个layer需要做两个计算:forward是从输入计算输出,然后backward是从上面给的gradient来计算相对于输入的gradient,只要这两个函数实现了以后,我们就可以把很多层连接成一个网络,这个网络做的事情就是输入我们的数据(图像或者语音或者whatever),然后来计算我们需要的输出(比如说识别的label),在training的时候,我们可以根据已有的label来计算loss和gradient,然后用gradient来update网络的参数,这个就是Caffe的一个基本流程。

  基本上,最简单地用Caffe上手的方法就是先把数据写成Caffe的格式,然后设计一个网络,然后用Caffe提供的solver来做优化看效果如何,如果你的数据是图像的话,可以从现有的网络,比如说alexnet或者googlenet开始,然后做fine tuning,如果你的数据稍有不同,比如说是直接的float vector,你可能需要做一些custom的configuration,Caffe的logistic regression example兴许会很有帮助。

  Fine tune方法:fine tuning的想法就是说,在imagenet那么大的数据集上train好一个很牛的网络了,那别的task上肯定也不错,所以我们可以把pretrain的网络拿过来,然后只重新train最后几层,重新train的意思是说,比如我以前需要classify imagenet的一千类,现在我只想识别是狗还是猫,或者是不是车牌,于是我就可以把最后一层softmax从一个40961000的分类器变成一个40962的分类器,这个strategy在应用中非常好使,所以我们经常会先在imagenet上pretrain一个网络,因为我们知道imagenet上training的大概过程会怎么样。

12.3.4 Caffe架构是怎样的?

  Caffe的架构与其它的深度学习框架稍微不同,它没有根据算法实现过程的方式来进行编码,而是以系统级的抽象作为整体架构,逐层的封装实现细节,使得上层的架构变得很清晰。Caffe的整体架构如下:

1. SyncedMem

  这个类的主要功能是封装CPU和GPU的数据交互操作。一般来说,数据的流动形式都是:硬盘->CPU内存->GPU内存->CPU内存->(硬盘),所以在写代码的过程中经常会写CPU/GPU之间数据传输的代码,同时还要维护CPU和GPU两个处理端的内存指针。这些事情处理起来不会很难,但是会很繁琐。因此SyncedMem的出现就是把CPU/GPU的数据传输操作封装起来,只需要调用简单的接口就可以获得两个处理端同步后的数据。

2. Blob

  Blob是用于存储数据的对象,在Caffe中各种数据(图像输入、模型参数)都是以Blob的形式在网络中传输的,Blob提供统一的存储操作接口,可用来保存训练数据、模型参数等,同时Blob还能在CPU和GPU之间进行同步以支持CPU/GPU的混合运算。
  这个类做了两个封装:一个是操作数据的封装,使用Blob可以操纵高维的数据,快速访问其中的数据,变换数据的维度等;另一个是对原始数据和更新量的封装,每一个Blob中都有data和diff两个数据指针,data用于存储原始数据,diff 用于存储反向传播(Backpropagation)的梯度更新值。Blob使用了SyncedMem,这样便于访问不同的处理端。Blob基本实现了整个Caffe数据结构部分的封装,在Net类中可以看到所有的前后向数据和参数都用Blob来表示就足够了。数据的抽象到这个就可以了,接下来作层级的抽象。神经网络的前后向计算可以做到层与层之间完全独立,只要每个层按照一定的接口规则实现,就可以确保整个网络的正确性。

3. Layer

  Layer是网络Net的基本单元,也是Caffe中能在外部进行调整的最小网络结构单元,每个Layer都有输入Blob和输出Blob。Layer(层)是Caffe中最庞大最繁杂的模块,它是神经网络的基本计算单元。由于Caffe强调模块化设计,因此只允许每个layer完成一类特定的计算,例如convolution操作、pooling、非线性变换、内积运算,以及数据加载、归一化和损失计算等。Caffe中layer的种类有很多,具体的种类及功能请看官方文档。在创建一个Caffe模型的时候,也是以Layer为基础进行的。Layer是一个父类,它的下面还有各种实现特定功能的子类,例如data_layer,conv_layer,loss_layer等。Layer是通过LayFactory来创建的。

4. Net

  Net是一个完整的深度网络,包含输入层、隐藏层、输出层,在Caffe中一般是一个卷积神经网络(Convolution Neural Networ,CNN)。通过定义不同类型的Layer,并用Blob将不同的Layer连接起来,就能产生一个Net。Net将数据Blob和层Layer组合起来做进一步的封装,对外提供了初始化和前后传播的接口,使得整体看上去和一个层的功能类似,但内部的组合可以是多种多样的。值得一提的是,每一层的输入输出数据统一保存在Net中,同时每个层内的参数指针也保存在Net中,不同的层可以通过WeightShare共享相同的参数,因此可以通过配置来实现多个神经网络层之间共享参数的功能。一个Net由多个Layer组成。一个典型的网络从data layer(从磁盘中载入数据)出发到loss layer结束。

5. Solver

  有了Net就可以进行神经网络的前后向传播计算了,但是还缺少神经网络的训练和预测功能,Solver类进一步封装了训练和预测相关的一些功能。它还提供了两个接口:一个是更新参数的接口,继承Solver可以实现不同的参数更新方法,如Momentum,Nesterov,Adagrad等,因此可以使用不同的优化算法。另一个接口是训练过程中每一轮特定状态下的可注入的一些回调函数,在代码中这个回调点的直接使用者就是多GPU训练算法。Solver定义了针对Net网络模型的求解方法,记录网络的训练过程,保存网络模型参数,中断并恢复网络的训练过程。自定义Solver能够实现不同的神经网络求解方式。阅读Solver的代码可以了解网络的求解优化过程。Solver是一个父类,它下面还有实现不同优化方法的子类,例如sgd_solver,adagrad_sovler等,Solver是通过SolverFactory来创建的。

6. Proto

  caffe.proto位于…/src/caffe/proto目录下,在这个文件夹下还有一个.pb.cc和一个.pb.h文件,这两个文件都是由caffe.proto编译而来的。 在caffe.proto中定义了很多结构化数据,包括:
BlobProto、Datum、FillerParameter、NetParameter、SolverParameter、SolverState、LayerParameter、ConcatParameter、ConvolutionParameter、DataParameter、DropoutParameter、HDF5DataParameter、HDF5OutputParameter、ImageDataParameter、InfogainLossParameter、InnerProductParameter、LRNParameter、MemoryDataParameter、PoolingParameter、PowerParameter、WindowDataParameter、V0LayerParameter。

7. IO

  除了上面的东西之外,还需要输入数据和参数。DataReader和DataTransformer帮助准备输入数据,Filler对参数进行初始化,一些Snapshot方法可以对模型进行持久化。

12.3.5 Caffe的有哪些接口?

  Caffe深度学习框架支持多种编程接口,包括命令行、Python和Matlab,下面将介绍如何使用这些接口。

1. Caffe Python接口

  Caffe提供 Python 接口,即Pycaffe,具体实现在caffe、python文件夹内。在Python代码中import caffe,可以load models(导入模型)、forward and backward (前向、反向迭代)、handle IO(数据输入输出)、visualize networks(绘制net)和instrument model solving(自定义优化方法)。所有的模型数据、计算参数都是暴露在外、可供读写的。
  (1)caffe.Net 是主要接口,负责导入数据、校验数据、计算模型。
  (2)caffe.Classsifier 用于图像分类。
  (3)caffe.Detector 用于图像检测。
  (4)caffe.SGDSolver 是露在外的 solver 的接口。
  (5)caffe.io 处理输入输出,数据预处理。
  (6)caffe.draw 可视化 net 的结构。
  (7)caffe blobs 以 numpy ndarrys 的形式表示,方便而且高效。

2. Caffe MATLAB接口

  MATLAB接口(Matcaffe)在 caffe/matlab 目录的 caffe 软件包。在 matcaffe 的基础上,可将Caffe整合到MATLAB代码中。
  MATLAB接口包括:
  (1)MATLAB 中创建多个网络结构。
  (2)网络的前向传播(Forward)与反向传播(Backward)计算。
  (3)网络中的任意一层以及参数的存取。
  (4)网络参数保存至文件或从文件夹加载。
  (5)blob 和 network 形状调整。
  (6)网络参数编辑和调整。
  (7)创建多个 solvers 进行训练。
  (8)从solver 快照(Snapshots)恢复并继续训练。
  (9)访问训练网络(Train nets)和测试网络(Test nets)。
  (10)迭代后网络交由 MATLAB 控制。
  (11)MATLAB代码融合梯度算法。

3. Caffe 命令行接口

  命令行接口 Cmdcaffe 是 Caffe 中用来训练模型、计算得分以及方法判断的工具。Cmdcaffe 存放在 caffe/build/tools 目录下。

1. caffe train

  caffe train 命令用于模型学习,具体包括:
  (1)caffe train 带 solver.prototxt 参数完成配置。
  (2)caffe train 带 snapshot mode_iter_1000.solverstate 参数加载 solver snapshot。
  (3)caffe train 带 weights 参数 model.caffemodel 完成 Fine-tuning 模型初始化。

2. caffe test

  caffe test 命令用于测试运行模型的得分,并且用百分比表示网络输出的最终结果,比如 accuracyhuoloss 作为其结果。测试过程中,显示每个 batch 的得分,最后输出全部 batch 的平均得分值。

3. caffe time

  caffe time 命令用来检测系统性能和测量模型相对执行时间,此命令通过逐层计时与同步,执行模型检测。

参考文献:
1.深度学习:Caffe之经典模型讲解与实战/ 乐毅,王斌

10.4 网络搭建有什么原则?

10.4.1新手原则。

刚入门的新手不建议直接上来就开始搭建网络模型。比较建议的学习顺序如下:

  • 1.了解神经网络工作原理,熟悉基本概念及术语。
  • 2.阅读经典网络模型论文+实现源码(深度学习框架视自己情况而定)。
  • 3.找数据集动手跑一个网络,可以尝试更改已有的网络模型结构。
  • 4.根据自己的项目需要设计网络。

10.4.2深度优先原则。

通常增加网络深度可以提高准确率,但同时会牺牲一些速度和内存。但深度不是盲目堆起来的,一定要在浅层网络有一定效果的基础上,增加深度。深度增加是为了增加模型的准确率,如果浅层都学不到东西,深了也没效果。

10.4.3卷积核size一般为奇数。

卷积核为奇数有以下好处:

  • 1 保证锚点刚好在中间,方便以 central pixel为标准进行滑动卷积,避免了位置信息发生偏移 。
  • 2 保证在填充(Padding)时,在图像之间添加额外的零层,图像的两边仍然对称。

10.4.4卷积核不是越大越好。

AlexNet中用到了一些非常大的卷积核,比如11×11、5×5卷积核,之前人们的观念是,卷积核越大,感受野越大,看到的图片信息越多,因此获得的特征越好。但是大的卷积核会导致计算量的暴增,不利于模型深度的增加,计算性能也会降低。于是在VGG、Inception网络中,利用2个3×3卷积核的组合比1个5×5卷积核的效果更佳,同时参数量(3×3×2+1=19<26=5×5×1+1)被降低,因此后来3×3卷积核被广泛应用在各种模型中。

10.5 有哪些经典的网络模型值得我们去学习的?

提起经典的网络模型就不得不提起计算机视觉领域的经典比赛:ILSVRC .其全称是 ImageNet Large Scale Visual Recognition Challenge.正是因为ILSVRC 2012挑战赛上的AlexNet横空出世,使得全球范围内掀起了一波深度学习热潮。这一年也被称作“深度学习元年”。而在历年ILSVRC比赛中每次刷新比赛记录的那些神经网络也成为了人们心中的经典,成为学术界与工业届竞相学习与复现的对象,并在此基础上展开新的研究。

序号 年份 网络名称 获得荣誉
1 2012 AlexNet ILSVRC图像分类冠军
2 2014 VGGNet ILSVRC图像分类亚军
3 2014 GoogLeNet ILSVRC图像分类冠军
4 2015 ResNet ILSVRC图像分类冠军
5 2017 SeNet ILSVRC图像分类冠军
  • 1 AlexNet
    论文:ImageNet Classification with Deep Convolutional Neural Networks
    代码实现:tensorflow
    主要特点:

    • 1.第一次使用非线性激活函数ReLU。
    • 2.增加防加过拟合方法:Droupout层,提升了模型鲁棒性。
    • 3.首次使用数据增强。
    • 4.首次使用GPU加速运算。
  • 2 VGGNet
    论文:Very Deep Convolutional Networks for Large-Scale Image Recognition
    代码实现:tensorflow
    主要特点:

    • 1.网络结构更深。
    • 2.普遍使用小卷积核。
  • 3 GoogLeNet
    论文:Going Deeper with Convolutions
    代码实现:tensorflow
    主要特点:

    • 1.增强卷积模块功能。
      主要的创新在于他的Inception,这是一种网中网(Network In Network)的结构,即原来的结点也是一个网络。Inception一直在不断发展,目前已经V2、V3、V4。其中1*1卷积主要用来降维,用了Inception之后整个网络结构的宽度和深度都可扩大,能够带来2-3倍的性能提升。
    • 2.连续小卷积代替大卷积,保证感受野不变的同时,减少了参数数目。
  • 4 ResNet
    论文:Deep Residual Learning for Image Recognition
    代码实现:tensorflow
    主要特点:

    解决了“退化”问题,即当模型的层次加深时,错误率却提高了。

  • 5 SeNet
    论文:Squeeze-and-Excitation Networks
    代码实现:tensorflow
    主要特点:

    提出了feature recalibration,通过引入 attention 重新加权,可以得到抑制无效特征,提升有效特征的权重,并很容易地和现有网络结合,提升现有网络性能,而计算量不会增加太多。

CV领域网络结构演进历程:
CV领域网络结构演进历程

ILSVRC挑战赛历年冠军:
ILSVRC挑战赛历年冠军

此后,ILSVRC挑战赛的名次一直是衡量一个研究机构或企业技术水平的重要标尺。
ILSVRC 2017 已是最后一届举办.2018年起,将由WebVision竞赛(Challenge on Visual Understanding by Learning from Web Data)来接棒。因此,即使ILSVRC挑战赛停办了,但其对深度学习的深远影响和巨大贡献,将永载史册。

10.6 网络训练有哪些技巧吗?

10.6.1.合适的数据集。

  • 1 没有明显脏数据(可以极大避免Loss输出为NaN)。
  • 2 样本数据分布均匀。

10.6.2.合适的预处理方法。

关于数据预处理,在Batch Normalization未出现之前预处理的主要做法是减去均值,然后除去方差。在Batch Normalization出现之后,减均值除方差的做法已经没有必要了。对应的预处理方法主要是数据筛查、数据增强等。

10.6.3.网络的初始化。

网络初始化最粗暴的做法是参数赋值为全0,这是绝对不可取的。因为如果所有的参数都是0,那么所有神经元的输出都将是相同的,那在back propagation的时候同一层内所有神经元的行为也是相同的,这可能会直接导致模型失效,无法收敛。吴恩达视频中介绍的方法是将网络权重初始化均值为0、方差为1符合的正态分布的随机数据。

10.6.4.小规模数据试练。

在正式开始训练之前,可以先用小规模数据进行试练。原因如下:

  • 1 可以验证自己的训练流程对否。
  • 2 可以观察收敛速度,帮助调整学习速率。
  • 3 查看GPU显存占用情况,最大化batch_size(前提是进行了batch normalization,只要显卡不爆,尽量挑大的)。

10.6.5.设置合理Learning Rate。

  • 1 太大。Loss爆炸、输出NaN等。
  • 2 太小。收敛速度过慢,训练时长大大延长。
  • 3 可变的学习速率。比如当输出准确率到达某个阈值后,可以让Learning Rate减半继续训练。

10.6.6.损失函数

损失函数主要分为两大类:分类损失和回归损失

1.回归损失:

  • 1 均方误差(MSE 二次损失 L2损失)
    它是我们的目标变量与预测值变量差值平方。
  • 2 平均绝对误差(MAE L1损失)
    它是我们的目标变量与预测值变量差值绝对值。
    关于MSE与MAE的比较。MSE更容易解决问题,但是MAE对于异常值更加鲁棒。更多关于MAE和MSE的性能,可以参考L1vs.L2 Loss Function

2.分类损失:

  • 1 交叉熵损失函数。
    是目前神经网络中最常用的分类目标损失函数。
  • 2 合页损失函数
    合页损失函数广泛在支持向量机中使用,有时也会在损失函数中使用。缺点:合页损失函数是对错误越大的样本施以更严重的惩罚,但是这样会导致损失函数对噪声敏感。

[TOC]

第六章 循环神经网络(RNN)

6.1 为什么需要RNN?

​ 时间序列数据是指在不同时间点上收集到的数据,这类数据反映了某一事物、现象等随时间的变化状态或程度。一般的神经网络,在训练数据足够、算法模型优越的情况下,给定特定的x,就能得到期望y。其一般处理单个的输入,前一个输入和后一个输入完全无关,但实际应用中,某些任务需要能够更好的处理序列的信息,即前面的输入和后面的输入是有关系的。比如:

​ 当我们在理解一句话意思时,孤立的理解这句话的每个词不足以理解整体意思,我们通常需要处理这些词连接起来的整个序列; 当我们处理视频的时候,我们也不能只单独的去分析每一帧,而要分析这些帧连接起来的整个序列。为了解决一些这样类似的问题,能够更好的处理序列的信息,RNN就由此诞生了。

6.2 图解RNN基本结构

6.2.1 基本的单层网络结构

​ 在进一步了解RNN之前,先给出最基本的单层网络结构,输入是,经过变换Wx+b和激活函数f得到输出y

6.2.2 图解经典RNN结构

​ 在实际应用中,我们还会遇到很多序列形的数据,如:

  • 自然语言处理问题。x1可以看做是第一个单词,x2可以看做是第二个单词,依次类推。

  • 语音处理。此时,x1、x2、x3……是每帧的声音信号。

  • 时间序列问题。例如每天的股票价格等等。

    其单个序列如下图所示:

    前面介绍了诸如此类的序列数据用原始的神经网络难以建模,基于此,RNN引入了隐状态$h$(hidden state),$h​$可对序列数据提取特征,接着再转换为输出。

    为了便于理解,先计算$h_1​$:

    注:图中的圆圈表示向量,箭头表示对向量做变换。

    RNN中,每个步骤使用的参数​相同,的计算方式和类似,其计算结果如下:

    计算$h_3$,$h_4​$也相似,可得:

    接下来,计算RNN的输出$y_1$,采用$Softmax$作为激活函数,根据$y_n=f(Wx+b)$,得$y_1​$:

    使用和$y_1​$相同的参数$V,c​$,得到$y_1,y_2,y_3,y_4​$的输出结构:

    以上即为最经典的RNN结构,其输入为$x_1,x_2,x_3,x_4$,输出为$y_1,y_2,y_3,y_4$,当然实际中最大值为$y_n$,这里为了便于理解和展示,只计算4个输入和输出。从以上结构可看出,RNN结构的输入和输出等长。

6.2.3 vector-to-sequence结构

​ 有时我们要处理的问题输入是一个单独的值,输出是一个序列。此时,有两种主要建模方式:

​ 方式一:可只在其中的某一个序列进行计算,比如序列第一个进行输入计算,其建模方式如下:

​ 方式二:把输入信息X作为每个阶段的输入,其建模方式如下:

6.2.4 sequence-to-vector结构

​ 有时我们要处理的问题输入是一个序列,输出是一个单独的值,此时通常在最后的一个序列上进行输出变换,其建模如下所示:

6.2.5 Encoder-Decoder结构

​ 原始的sequence-to-sequence结构的RNN要求序列等长,然而我们遇到的大部分问题序列都是不等长的,如机器翻译中,源语言和目标语言的句子往往并没有相同的长度。

​ 其建模步骤如下:

步骤一:将输入数据编码成一个上下文向量$c$,这部分称为Encoder,得到$c$有多种方式,最简单的方法就是把Encoder的最后一个隐状态赋值给$c$,还可以对最后的隐状态做一个变换得到$c$,也可以对所有的隐状态做变换。其示意如下所示:

步骤二:用另一个RNN网络(我们将其称为Decoder)对其进行编码,方法一是将步骤一中的$c​$作为初始状态输入到Decoder,示意图如下所示:

方法二是将$c$作为Decoder的每一步输入,示意图如下所示:

6.2.6 以上三种结构各有怎样的应用场景

网络结构 结构图示 应用场景举例
1 vs N 1、从图像生成文字,输入为图像的特征,输出为一段句子
2、根据图像生成语音或音乐,输入为图像特征,输出为一段语音或音乐
N vs 1 1、输出一段文字,判断其所属类别
2、输入一个句子,判断其情感倾向
3、输入一段视频,判断其所属类别
N vs M 1、机器翻译,输入一种语言文本序列,输出另外一种语言的文本序列
2、文本摘要,输入文本序列,输出这段文本序列摘要
3、阅读理解,输入文章,输出问题答案
4、语音识别,输入语音序列信息,输出文字序列

6.2.7 图解RNN中的Attention机制

​ 在上述通用的Encoder-Decoder结构中,Encoder把所有的输入序列都编码成一个统一的语义特征$c​$再解码,因此,$c​$中必须包含原始序列中的所有信息,它的长度就成了限制模型性能的瓶颈。如机器翻译问题,当要翻译的句子较长时,一个$c​$可能存不下那么多信息,就会造成翻译精度的下降。Attention机制通过在每个时间输入不同的$c​$来解决此问题。

​ 引入了Attention机制的Decoder中,有不同的$c$,每个$c​$会自动选择与当前输出最匹配的上下文信息,其示意图如下所示:

举例,比如输入序列是“我爱中国”,要将此输入翻译成英文:

​ 假如用$a{ij}$衡量Encoder中第$j$阶段的$h_j$和解码时第$i$阶段的相关性,$a{ij}$从模型中学习得到,和Decoder的第$i-1$阶段的隐状态、Encoder 第$j$个阶段的隐状态有关,比如$a_{3j}​$的计算示意如下所示:

最终Decoder中第$i$阶段的输入的上下文信息 $ci$来自于所有$h_j$对$a{ij}$的加权和。

其示意图如下图所示:

​ 在Encoder中,$h1,h_2,h_3,h_4$分别代表“我”,“爱”,“中”,“国”所代表信息。翻译的过程中,$c_1$会选择和“我”最相关的上下午信息,如上图所示,会优先选择$a{11}$,以此类推,$c2$会优先选择相关性较大的$a{22}$,$c3$会优先选择相关性较大的$a{33},a_{34}$,这就是attention机制。

6.3 RNNs典型特点?

  1. RNNs主要用于处理序列数据。对于传统神经网络模型,从输入层到隐含层再到输出层,层与层之间一般为全连接,每层之间神经元是无连接的。但是传统神经网络无法处理数据间的前后关联问题。例如,为了预测句子的下一个单词,一般需要该词之前的语义信息。这是因为一个句子中前后单词是存在语义联系的。
  2. RNNs中当前单元的输出与之前步骤输出也有关,因此称之为循环神经网络。具体的表现形式为当前单元会对之前步骤信息进行储存并应用于当前输出的计算中。隐藏层之间的节点连接起来,隐藏层当前输出由当前时刻输入向量和之前时刻隐藏层状态共同决定。
  3. 标准的RNNs结构图,图中每个箭头代表做一次变换,也就是说箭头连接带有权值。
  4. 在标准的RNN结构中,隐层的神经元之间也是带有权值的,且权值共享。
  5. 理论上,RNNs能够对任何长度序列数据进行处理。但是在实践中,为了降低复杂度往往假设当前的状态只与之前某几个时刻状态相关,下图便是一个典型的RNNs

输入单元(Input units):输入集$\bigr{x0,x_1,…,x_t,x{t+1},…\bigr}$,

输出单元(Output units):输出集$\bigr{y0,y_1,…,y_t,y{y+1},…\bigr}$,

隐藏单元(Hidden units):输出集$\bigr{s0,s_1,…,s_t,s{t+1},…\bigr}$。

图中信息传递特点:

  1. 一条单向流动的信息流是从输入单元到隐藏单元。
  2. 一条单向流动的信息流从隐藏单元到输出单元。
  3. 在某些情况下,RNNs会打破后者的限制,引导信息从输出单元返回隐藏单元,这些被称为“Back Projections”。
  4. 在某些情况下,隐藏层的输入还包括上一时刻隐藏层的状态,即隐藏层内的节点可以自连也可以互连。
  5. 当前单元(cell)输出是由当前时刻输入和上一时刻隐藏层状态共同决定。

6.4 CNN和RNN的区别 ?

类别 特点描述
相同点 1、传统神经网络的扩展。
2、前向计算产生结果,反向计算模型更新。
3、每层神经网络横向可以多个神经元共存,纵向可以有多层神经网络连接。
不同点 1、CNN空间扩展,神经元与特征卷积;RNN时间扩展,神经元与多个时间输出计算
2、RNN可以用于描述时间上连续状态的输出,有记忆功能,CNN用于静态输出

6.5 RNNs和FNNs有什么区别?

  1. 不同于传统的前馈神经网络(FNNs),RNNs引入了定向循环,能够处理输入之间前后关联问题。
  2. RNNs可以记忆之前步骤的训练信息。
    定向循环结构如下图所示

6.6 RNNs训练和传统ANN训练异同点?

相同点

  1. RNNs与传统ANN都使用BP(Back Propagation)误差反向传播算法。

不同点

  1. RNNs网络参数W,U,V是共享的(具体在本章6.2节中已介绍),而传统神经网络各层参数间没有直接联系。
  2. 对于RNNs,在使用梯度下降算法中,每一步的输出不仅依赖当前步的网络,还依赖于之前若干步的网络状态。

6.7 为什么RNN 训练的时候Loss波动很大

​ 由于RNN特有的memory会影响后期其他的RNN的特点,梯度时大时小,learning rate没法个性化的调整,导致RNN在train的过程中,Loss会震荡起伏,为了解决RNN的这个问题,在训练的时候,可以设置临界值,当梯度大于某个临界值,直接截断,用这个临界值作为梯度的大小,防止大幅震荡。

6.8 标准RNN前向输出流程

​ 以$x$表示输入,$h$是隐层单元,$o$是输出,$L$为损失函数,$y$为训练集标签。$t$表示$t$时刻的状态,$V,U,W$是权值,同一类型的连接权值相同。以下图为例进行说明标准RNN的前向传播算法:

对于$t$时刻:

其中$\phi()$为激活函数,一般会选择tanh函数,$b$为偏置。

$t$时刻的输出为:

模型的预测输出为:

其中$\sigma​$为激活函数,通常RNN用于分类,故这里一般用softmax函数。

6.9 BPTT算法推导

​ BPTT(back-propagation through time)算法是常用的训练RNN的方法,其本质还是BP算法,只不过RNN处理时间序列数据,所以要基于时间反向传播,故叫随时间反向传播。BPTT的中心思想和BP算法相同,沿着需要优化的参数的负梯度方向不断寻找更优的点直至收敛。需要寻优的参数有三个,分别是U、V、W。与BP算法不同的是,其中W和U两个参数的寻优过程需要追溯之前的历史数据,参数V相对简单只需关注目前,那么我们就来先求解参数V的偏导数。

RNN的损失也是会随着时间累加的,所以不能只求t时刻的偏导。

​ W和U的偏导的求解由于需要涉及到历史数据,其偏导求起来相对复杂。为了简化推导过程,我们假设只有三个时刻,那么在第三个时刻 L对W,L对U的偏导数分别为:

可以观察到,在某个时刻的对W或是U的偏导数,需要追溯这个时刻之前所有时刻的信息。根据上面两个式子得出L在t时刻对W和U偏导数的通式:

整体的偏导公式就是将其按时刻再一一加起来。

6.9 RNN中为什么会出现梯度消失?

首先来看tanh函数的函数及导数图如下所示:

sigmoid函数的函数及导数图如下所示:

从上图观察可知,sigmoid函数的导数范围是(0,0.25],tanh函数的导数范围是(0,1],他们的导数最大都不大于1。

​ 基于6.8中式(9-10)中的推导,RNN的激活函数是嵌套在里面的,如果选择激活函数为$tanh$或$sigmoid$,把激活函数放进去,拿出中间累乘的那部分可得:

梯度消失现象:基于上式,会发现累乘会导致激活函数导数的累乘,如果取tanh或sigmoid函数作为激活函数的话,那么必然是一堆小数在做乘法,结果就是越乘越小。随着时间序列的不断深入,小数的累乘就会导致梯度越来越小直到接近于0,这就是“梯度消失“现象。

​ 实际使用中,会优先选择tanh函数,原因是tanh函数相对于sigmoid函数来说梯度较大,收敛速度更快且引起梯度消失更慢。

6.10 如何解决RNN中的梯度消失问题?

​ 上节描述的梯度消失是在无限的利用历史数据而造成,但是RNN的特点本来就是能利用历史数据获取更多的可利用信息,解决RNN中的梯度消失方法主要有:

​ 1、选取更好的激活函数,如Relu激活函数。ReLU函数的左侧导数为0,右侧导数恒为1,这就避免了“梯度消失“的发生。但恒为1的导数容易导致“梯度爆炸“,但设定合适的阈值可以解决这个问题。

​ 2、加入BN层,其优点包括可加速收敛、控制过拟合,可以少用或不用Dropout和正则、降低网络对初始化权重不敏感,且能允许使用较大的学习率等。

​ 2、改变传播结构,LSTM结构可以有效解决这个问题。下面将介绍LSTM相关内容。

6.11 LSTM

6.11.1 LSTM的产生原因

​ RNN在处理长期依赖(时间序列上距离较远的节点)时会遇到巨大的困难,因为计算距离较远的节点之间的联系时会涉及雅可比矩阵的多次相乘,会造成梯度消失或者梯度膨胀的现象。为了解决该问题,研究人员提出了许多解决办法,例如ESN(Echo State Network),增加有漏单元(Leaky Units)等等。其中最成功应用最广泛的就是门限RNN(Gated RNN),而LSTM就是门限RNN中最著名的一种。有漏单元通过设计连接间的权重系数,从而允许RNN累积距离较远节点间的长期联系;而门限RNN则泛化了这样的思想,允许在不同时刻改变该系数,且允许网络忘记当前已经累积的信息。

6.11.2 图解标准RNN和LSTM的区别

​ 所有 RNN 都具有一种重复神经网络模块的链式的形式。在标准的 RNN 中,这个重复的模块只有一个非常简单的结构,例如一个 tanh 层,如下图所示:

​ LSTM 同样是这样的结构,但是重复的模块拥有一个不同的结构。不同于单一神经网络层,这里是有四个,以一种非常特殊的方式进行交互。

注:上图图标具体含义如下所示:

​ 上图中,每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。粉色的圈代表 pointwise 的操作,诸如向量的和,而黄色的矩阵就是学习到的神经网络层。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。

6.11.3 LSTM核心思想图解

​ LSTM 的关键就是细胞状态,水平线在图上方贯穿运行。细胞状态类似于传送带。直接在整个链上运行,只有一些少量的线性交互。信息在上面流传保持不变会很容易。示意图如下所示:

LSTM 有通过精心设计的称作为“门”的结构来去除或者增加信息到细胞状态的能力。门是一种让信息选择式通过的方法。他们包含一个 sigmoid 神经网络层和一个 pointwise 乘法操作。示意图如下:

LSTM 拥有三个门,分别是忘记层门,输入层门和输出层门,来保护和控制细胞状态。

忘记层门

​ 作用对象:细胞状态 。

​ 作用:将细胞状态中的信息选择性的遗忘。

​ 操作步骤:该门会读取$h{t-1}$和$x_t$,输出一个在 0 到 1 之间的数值给每个在细胞状态$C{t-1}​$中的数字。1 表示“完全保留”,0 表示“完全舍弃”。示意图如下:

输入层门

​ 作用对象:细胞状态

​ 作用:将新的信息选择性的记录到细胞状态中。

​ 操作步骤:

​ 步骤一,sigmoid 层称 “输入门层” 决定什么值我们将要更新。

​ 步骤二,tanh 层创建一个新的候选值向量$\tilde{C}_t$加入到状态中。其示意图如下:

​ 步骤三:将$c{t-1}$更新为$c{t}$。将旧状态与$f_t$相乘,丢弃掉我们确定需要丢弃的信息。接着加上$i_t * \tilde{C}_t$得到新的候选值,根据我们决定更新每个状态的程度进行变化。其示意图如下:

输出层门
作用对象:隐层$h_t$

​ 作用:确定输出什么值。

​ 操作步骤:

​ 步骤一:通过sigmoid 层来确定细胞状态的哪个部分将输出。

​ 步骤二:把细胞状态通过 tanh 进行处理,并将它和 sigmoid 门的输出相乘,最终我们仅仅会输出我们确定输出的那部分。

其示意图如下所示:

6.11.4 LSTM流行的变体

增加peephole 连接

​ 在正常的LSTM结构中,Gers F A 等人提出增加peephole 连接,可以门层接受细胞状态的输入。示意图如下所示:

对忘记门和输入门进行同时确定

​ 不同于之前是分开确定什么忘记和需要添加什么新的信息,这里是一同做出决定。示意图如下所示:

Gated Recurrent Unit

​ 由Kyunghyun Cho等人提出的Gated Recurrent Unit (GRU),其将忘记门和输入门合成了一个单一的更新门,同样还混合了细胞状态和隐藏状态,和其他一些改动。其示意图如下:

最终的模型比标准的 LSTM 模型要简单,也是非常流行的变体。

6.12 LSTMs与GRUs的区别

LSTMs与GRUs的区别如图所示:

从上图可以看出,二者结构十分相似,不同在于

  1. new memory都是根据之前state及input进行计算,但是GRUs中有一个reset gate控制之前state的进入量,而在LSTMs里没有类似gate;
  2. 产生新的state的方式不同,LSTMs有两个不同的gate,分别是forget gate (f gate)和input gate(i gate),而GRUs只有一种update gate(z gate);
  3. LSTMs对新产生的state可以通过output gate(o gate)进行调节,而GRUs对输出无任何调节。

6.13 RNNs在NLP中典型应用?

(1)语言模型与文本生成(Language Modeling and Generating Text)

​ 给定一组单词序列,需要根据前面单词预测每个单词出现的可能性。语言模型能够评估某个语句正确的可能性,可能性越大,语句越正确。另一种应用便是使用生成模型预测下一个单词的出现概率,从而利用输出概率的采样生成新的文本。

(2)机器翻译(Machine Translation)

​ 机器翻译是将一种源语言语句变成意思相同的另一种源语言语句,如将英语语句变成同样意思的中文语句。与语言模型关键的区别在于,需要将源语言语句序列输入后,才进行输出,即输出第一个单词时,便需要从完整的输入序列中进行获取。

(3)语音识别(Speech Recognition)

​ 语音识别是指给定一段声波的声音信号,预测该声波对应的某种指定源语言语句以及计算该语句的概率值。

(4)图像描述生成 (Generating Image Descriptions)

​ 同卷积神经网络一样,RNNs已经在对无标图像描述自动生成中得到应用。CNNs与RNNs结合也被应用于图像描述自动生成。

6.13 常见的RNNs扩展和改进模型

6.13.1 Simple RNNs(SRNs)

  1. SRNs是一个三层网络,其在隐藏层增加了上下文单元。下图中的y是隐藏层,u是上下文单元。上下文单元节点与隐藏层中节点的连接是固定的,并且权值也是固定的。上下文节点与隐藏层节点一一对应,并且值是确定的。
  2. 在每一步中,使用标准的前向反馈进行传播,然后使用学习算法进行学习。上下文每一个节点保存其连接隐藏层节点上一步输出,即保存上文,并作用于当前步对应的隐藏层节点状态,即隐藏层的输入由输入层的输出与上一步的自身状态所决定。因此SRNs能够解决标准多层感知机(MLP)无法解决的对序列数据进行预测的问题。
    SRNs网络结构如下图所示:

6.13.2 Bidirectional RNNs

​ Bidirectional RNNs(双向网络)将两层RNNs叠加在一起,当前时刻输出(第t步的输出)不仅仅与之前序列有关,还与之后序列有关。例如:为了预测一个语句中的缺失词语,就需要该词汇的上下文信息。Bidirectional RNNs是一个相对较简单的RNNs,是由两个RNNs上下叠加在一起组成的。输出由前向RNNs和后向RNNs共同决定。如下图所示:

6.13.3 Deep RNNs

​ Deep RNNs与Bidirectional RNNs相似,其也是又多层RNNs叠加,因此每一步的输入有了多层网络。该网络具有更强大的表达与学习能力,但是复杂性也随之提高,同时需要更多的训练数据。Deep RNNs的结构如下图所示:

6.13.4 Echo State Networks(ESNs)

ESNs特点

  1. 它的核心结构为一个随机生成、且保持不变的储备池(Reservoir)。储备池是大规模随机生成稀疏连接(SD通常保持1%~5%,SD表示储备池中互相连接的神经元占总神经元个数N的比例)的循环结构;
  2. 从储备池到输出层的权值矩阵是唯一需要调整的部分;
  3. 简单的线性回归便能够完成网络训练;

ESNs基本思想

​ 使用大规模随机连接的循环网络取代经典神经网络中的中间层,从而简化网络的训练过程。
网络中的参数包括:
(1)W - 储备池中节点间连接权值矩阵;
(2)Win - 输入层到储备池之间连接权值矩阵,表明储备池中的神经元之间是相互连接;
(3)Wback - 输出层到储备池之间的反馈连接权值矩阵,表明储备池会有输出层来的反馈;
(4)Wout - 输入层、储备池、输出层到输出层的连接权值矩阵,表明输出层不仅与储备池连接,还与输入层和自己连接。
(5)Woutbias - 输出层的偏置项。

​ ESNs的结构如下图所示:

6.13.4 Gated Recurrent Unit Recurrent Neural Networks

GRUs是一般的RNNs的变型版本,其主要是从以下两个方面进行改进。

  1. 以语句为例,序列中不同单词处的数据对当前隐藏层状态的影响不同,越前面的影响越小,即每个之前状态对当前的影响进行了距离加权,距离越远,权值越小。

  2. 在产生误差error时,其可能是由之前某一个或者几个单词共同造成,所以应当对对应的单词weight进行更新。GRUs的结构如下图所示。GRUs首先根据当前输入单词向量word vector以及前一个隐藏层状态hidden state计算出update gate和reset gate。再根据reset gate、当前word vector以及前一个hidden state计算新的记忆单元内容(new memory content)。当reset gate为1的时候,new memory content忽略之前所有memory content,最终的memory是由之前的hidden state与new memory content一起决定。

6.13.5 Bidirectional LSTMs

  1. 与bidirectional RNNs 类似,bidirectional LSTMs有两层LSTMs。一层处理过去的训练信息,另一层处理将来的训练信息。
  2. 在bidirectional LSTMs中,通过前向LSTMs获得前向隐藏状态,后向LSTMs获得后向隐藏状态,当前隐藏状态是前向隐藏状态与后向隐藏状态的组合。

6.13.6 Stacked LSTMs

  1. 与deep rnns 类似,stacked LSTMs 通过将多层LSTMs叠加起来得到一个更加复杂的模型。
  2. 不同于bidirectional LSTMs,stacked LSTMs只利用之前步骤的训练信息。

6.13.7 Clockwork RNNs(CW-RNNs)

​ CW-RNNs是RNNs的改良版本,其使用时钟频率来驱动。它将隐藏层分为几个块(组,Group/Module),每一组按照自己规定的时钟频率对输入进行处理。为了降低RNNs的复杂度,CW-RNNs减少了参数数量,并且提高了网络性能,加速网络训练。CW-RNNs通过不同隐藏层模块在不同时钟频率下工作来解决长时依赖问题。将时钟时间进行离散化,不同的隐藏层组将在不同时刻进行工作。因此,所有的隐藏层组在每一步不会全部同时工作,这样便会加快网络的训练。并且,时钟周期小组的神经元不会连接到时钟周期大组的神经元,只允许周期大的神经元连接到周期小的(组与组之间的连接以及信息传递是有向的)。周期大的速度慢,周期小的速度快,因此是速度慢的神经元连速度快的神经元,反之则不成立。

​ CW-RNNs与SRNs网络结构类似,也包括输入层(Input)、隐藏层(Hidden)、输出层(Output),它们之间存在前向连接,输入层到隐藏层连接,隐藏层到输出层连接。但是与SRN不同的是,隐藏层中的神经元会被划分为若干个组,设为$g​$,每一组中的神经元个数相同,设为$k​$,并为每一个组分配一个时钟周期$T_i\epsilon{T_1,T_2,…,T_g}​$,每一组中的所有神经元都是全连接,但是组$j​$到组$i​$的循环连接则需要满足$T_j​$大于$T_i​$。如下图所示,将这些组按照时钟周期递增从左到右进行排序,即$T_1<T_2<…<T_g​$,那么连接便是从右到左。例如:隐藏层共有256个节点,分为四组,周期分别是[1,2,4,8],那么每个隐藏层组256/4=64个节点,第一组隐藏层与隐藏层的连接矩阵为64$\times​$64的矩阵,第二层的矩阵则为64$\times​$128矩阵,第三组为64$\times​$(3$\times​$64)=64$\times​$192矩阵,第四组为64$\times​$(4$\times​$64)=64$\times​$256矩阵。这就解释了上一段中速度慢的组连接到速度快的组,反之则不成立。

CW-RNNs的网络结构如下图所示

6.13.8 CNN-LSTMs

  1. 为了同时利用CNN以及LSTMs的优点,CNN-LSTMs被提出。在该模型中,CNN用于提取对象特征,LSTMs用于预测。CNN由于卷积特性,其能够快速而且准确地捕捉对象特征。LSTMs的优点在于能够捕捉数据间的长时依赖性。

参考文献

[1] 何之源.https://zhuanlan.zhihu.com/p/28054589.

[2] http://colah.github.io/posts/2015-08-Understanding-LSTMs/

[3] https://blog.csdn.net/zhaojc1995/article/details/80572098

[4] Graves A. Supervised Sequence Labelling with Recurrent Neural Networks[J]. Studies in Computational Intelligence, 2008, 385.

[5] Graves A. Generating Sequences With Recurrent Neural Networks[J]. Computer Science, 2013.

[6] Greff K , Srivastava R K , Koutník, Jan, et al. LSTM: A Search Space Odyssey[J]. IEEE Transactions on Neural Networks & Learning Systems, 2015, 28(10):2222-2232.

[7] Lanchantin J, Singh R, Wang B, et al. DEEP MOTIF DASHBOARD: VISUALIZING AND UNDERSTANDING GENOMIC SEQUENCES USING DEEP NEURAL NETWORKS.[J]. Pacific Symposium on Biocomputing Pacific Symposium on Biocomputing, 2016, 22:254.

[8] Pascanu R , Mikolov T , Bengio Y . On the difficulty of training Recurrent Neural Networks[J]. 2012.

[9] Hochreiter S. The Vanishing Gradient Problem During Learning Recurrent Neural Nets and Problem Solutions[J]. International Journal of Uncertainty, Fuzziness and Knowledge-Based Systems, 1998, 06(02):-.

[10] Dyer C, Kuncoro A, Ballesteros M, et al. Recurrent Neural Network Grammars[C]// Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies. 2016.

[11] Mulder W D , Bethard S , Moens M F . A survey on the application of recurrent neural networks to statistical language modeling.[M]. Academic Press Ltd. 2015.

[12] Graves A. Generating Sequences With Recurrent Neural Networks[J]. Computer Science, 2013.

[13] Zhang B, Xiong D, Su J. Neural Machine Translation with Deep Attention[J]. IEEE Transactions on Pattern Analysis and Machine Intelligence, 2018, PP(99):1-1.

[14] https://github.com/xuanyuansen/scalaLSTM

[15] Deep Learning,Ian Goodfellow Yoshua Bengio and Aaron Courville,Book in preparation for MIT Press,2016;

[16] http://colah.github.io/posts/2015-08-Understanding-LSTMs/

[17] Greff K, Srivastava R K, Koutník J, et al. LSTM: A Search Space Odyssey[J]. IEEE Transactions on Neural Networks & Learning Systems, 2016, 28(10):2222-2232.

[18] Yao K , Cohn T , Vylomova K , et al. Depth-Gated Recurrent Neural Networks[J]. 2015.

[19] Koutník J, Greff K, Gomez F, et al. A Clockwork RNN[J]. Computer Science, 2014:1863-1871.

[20] Gers F A , Schmidhuber J . Recurrent nets that time and count[C]// Neural Networks, 2000. IJCNN 2000, Proceedings of the IEEE-INNS-ENNS International Joint Conference on. IEEE, 2000.

[21] Li S, Wu C, Hai L, et al. FPGA Acceleration of Recurrent Neural Network Based Language Model[C]// IEEE International Symposium on Field-programmable Custom Computing Machines. 2015.

[22] Mikolov T , Kombrink S , Burget L , et al. Extensions of recurrent neural network language model[C]// Acoustics, Speech and Signal Processing (ICASSP), 2011 IEEE International Conference on. IEEE, 2011.

[23] Graves A . Generating Sequences With Recurrent Neural Networks[J]. Computer Science, 2013.

[24] Sutskever I , Vinyals O , Le Q V . Sequence to Sequence Learning with Neural Networks[J]. 2014.

[25] Liu B, Lane I. Joint Online Spoken Language Understanding and Language Modeling with Recurrent Neural Networks[J]. 2016.

[26] Graves A, Mohamed A R, Hinton G. Speech recognition with deep recurrent neural networks[C]// IEEE International Conference on Acoustics. 2013.

[27] https://cs.stanford.edu/people/karpathy/deepimagesent/

[28] Cho K, Van Merriënboer B, Gulcehre C, et al. Learning phrase representations using RNN encoder-decoder for statistical machine translation[J]. arXiv preprint arXiv:1406.1078, 2014.

[TOC]

第八章 目标检测

8.1 基本概念

8.1.1 什么是目标检测?

​ 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。

​ 计算机视觉中关于图像识别有四大类任务:

分类-Classification:解决“是什么?”的问题,即给定一张图片或一段视频判断里面包含什么类别的目标。

定位-Location:解决“在哪里?”的问题,即定位出这个目标的的位置。

检测-Detection:解决“是什么?在哪里?”的问题,即定位出这个目标的的位置并且知道目标物是什么。

分割-Segmentation:分为实例的分割(Instance-level)和场景分割(Scene-level),解决“每一个像素属于哪个目标物或场景”的问题。

图像识别四大类任务,图像来源于cs231n 2016课件Lecture 8

8.1.2 目标检测要解决的核心问题?

除了图像分类之外,目标检测要解决的核心问题是:

1.目标可能出现在图像的任何位置。

2.目标有各种不同的大小。

3.目标可能有各种不同的形状。

8.1.3 目标检测算法分类?

基于深度学习的目标检测算法主要分为两类:

1.Two stage目标检测算法

​ 先进行区域生成(region proposal,RP)(一个有可能包含待检物体的预选框),再通过卷积神经网络进行样本分类。

​ 任务:特征提取—>生成RP—>分类/定位回归。

​ 常见的two stage目标检测算法有:R-CNN、SPP-Net、Fast R-CNN、Faster R-CNN和R-FCN等。

2.One stage目标检测算法

​ 不用RP,直接在网络中提取特征来预测物体分类和位置。

​ 任务:特征提取—>分类/定位回归。

​ 常见的one stage目标检测算法有:OverFeat、YOLOv1、YOLOv2、YOLOv3、SSD和RetinaNet等。

8.1.4 目标检测有哪些应用?

​ 目标检测具有巨大的实用价值和应用前景。应用领域包括人脸检测、行人检测、车辆检测、飞机航拍或卫星图像中道路的检测、车载摄像机图像中的障碍物检测、医学影像在的病灶检测等。还有在安防领域中,可以实现比如安全帽、安全带等动态检测,移动侦测、区域入侵检测、物品看护等功能。

8.2 Two Stage目标检测算法

8.2.1 R-CNN

R-CNN有哪些创新点?

  1. 使用CNN(ConvNet)对 region proposals 计算 feature vectors。从经验驱动特征(SIFT、HOG)到数据驱动特征(CNN feature map),提高特征对样本的表示能力。
  2. 采用大样本下(ILSVRC)有监督预训练和小样本(PASCAL)微调(fine-tuning)的方法解决小样本难以训练甚至过拟合等问题。

注:ILSVRC其实就是众所周知的ImageNet的挑战赛,数据量极大;PASCAL数据集(包含目标检测和图像分割等),相对较小。

R-CNN 介绍

​ R-CNN作为R-CNN系列的第一代算法,其实没有过多的使用“深度学习”思想,而是将“深度学习”和传统的“计算机视觉”的知识相结合。比如R-CNN pipeline中的第二步和第四步其实就属于传统的“计算机视觉”技术。使用selective search提取region proposals,使用SVM实现分类。

原论文中R-CNN pipeline只有4个步骤,光看上图无法深刻理解R-CNN处理机制,下面结合图示补充相应文字

  1. 预训练模型。选择一个预训练 (pre-trained)神经网络(如AlexNet、VGG)。

  2. 重新训练全连接层。使用需要检测的目标重新训练(re-train)最后全连接层(connected layer)。

  3. 提取 proposals并计算CNN 特征。利用选择性搜索(Selective Search)算法提取所有proposals(大约2000幅images),调整(resize/warp)它们成固定大小,以满足 CNN输入要求(因为全连接层的限制),然后将feature map 保存到本地磁盘。

  4. 训练SVM。利用feature map 训练SVM来对目标和背景进行分类(每个类一个二进制SVM)

  5. 边界框回归(Bounding boxes Regression)。训练将输出一些校正因子的线性回归分类器

R-CNN 实验结果

R-CNN在VOC 2007测试集上mAP达到58.5%,打败当时所有的目标检测算法。

8.2.2 Fast R-CNN

Fast R-CNN有哪些创新点?

  1. 只对整幅图像进行一次特征提取,避免R-CNN中的冗余特征提取
  2. 用RoI pooling层替换最后一层的max pooling层,同时引入建议框数据,提取相应建议框特征
  3. Fast R-CNN网络末尾采用并行的不同的全连接层,可同时输出分类结果和窗口回归结果,实现了end-to-end的多任务训练【建议框提取除外】,也不需要额外的特征存储空间【R-CNN中的特征需要保持到本地,来供SVM和Bounding-box regression进行训练】
  4. 采用SVD对Fast R-CNN网络末尾并行的全连接层进行分解,减少计算复杂度,加快检测速度。

Fast R-CNN 介绍

​ Fast R-CNN是基于R-CNN和SPPnets进行的改进。SPPnets,其创新点在于计算整幅图像的the shared feature map,然后根据object proposal在shared feature map上映射到对应的feature vector(就是不用重复计算feature map了)。当然,SPPnets也有缺点:和R-CNN一样,训练是多阶段(multiple-stage pipeline)的,速度还是不够”快”,特征还要保存到本地磁盘中。

将候选区域直接应用于特征图,并使用RoI池化将其转化为固定大小的特征图块。以下是Fast R-CNN的流程图

RoI Pooling层详解

因为Fast R-CNN使用全连接层,所以应用RoI Pooling将不同大小的ROI转换为固定大小。

RoI Pooling 是Pooling层的一种,而且是针对RoI的Pooling,其特点是输入特征图尺寸不固定,但是输出特征图尺寸固定(如7x7)。

什么是RoI呢?

RoI是Region of Interest的简写,一般是指图像上的区域框,但这里指的是由Selective Search提取的候选框。

往往经过RPN后输出的不止一个矩形框,所以这里我们是对多个RoI进行Pooling。

RoI Pooling的输入

输入有两部分组成:

  1. 特征图(feature map):指的是上面所示的特征图,在Fast RCNN中,它位于RoI Pooling之前,在Faster RCNN中,它是与RPN共享那个特征图,通常我们常常称之为“share_conv”;
  2. RoIs,其表示所有RoI的N*5的矩阵。其中N表示RoI的数量,第一列表示图像index,其余四列表示其余的左上角和右下角坐标。

在Fast RCNN中,指的是Selective Search的输出;在Faster RCNN中指的是RPN的输出,一堆矩形候选框,形状为1x5x1x1(4个坐标+索引index),其中值得注意的是:坐标的参考系不是针对feature map这张图的,而是针对原图的(神经网络最开始的输入)。其实关于ROI的坐标理解一直很混乱,到底是根据谁的坐标来。其实很好理解,我们已知原图的大小和由Selective Search算法提取的候选框坐标,那么根据”映射关系”可以得出特征图(featurwe map)的大小和候选框在feature map上的映射坐标。至于如何计算,其实就是比值问题,下面会介绍。所以这里把ROI理解为原图上各个候选框(region proposals),也是可以的。

注:说句题外话,由Selective Search算法提取的一系列可能含有object的bounding box,这些通常称为region proposals或者region of interest(ROI)。

RoI的具体操作

  1. 根据输入image,将ROI映射到feature map对应位置

    注:映射规则比较简单,就是把各个坐标除以“输入图片与feature map的大小的比值”,得到了feature map上的box坐标

  2. 将映射后的区域划分为相同大小的sections(sections数量与输出的维度相同)

  3. 对每个sections进行max pooling操作

这样我们就可以从不同大小的方框得到固定大小的相应 的feature maps。值得一提的是,输出的feature maps的大小不取决于ROI和卷积feature maps大小。RoI Pooling 最大的好处就在于极大地提高了处理速度。

RoI Pooling的输出

输出是batch个vector,其中batch的值等于RoI的个数,vector的大小为channel w h;RoI Pooling的过程就是将一个个大小不同的box矩形框,都映射成大小固定(w * h)的矩形框。

RoI Pooling示例

8.2.3 Faster R-CNN

Faster R-CNN有哪些创新点?

Fast R-CNN依赖于外部候选区域方法,如选择性搜索。但这些算法在CPU上运行且速度很慢。在测试中,Fast R-CNN需要2.3秒来进行预测,其中2秒用于生成2000个ROI。Faster R-CNN采用与Fast R-CNN相同的设计,只是它用内部深层网络代替了候选区域方法。新的候选区域网络(RPN)在生成ROI时效率更高,并且以每幅图像10毫秒的速度运行。

图8.1.13 Faster R-CNN的流程图
Faster R-CNN的流程图与Fast R-CNN相同,采用外部候选区域方法代替了内部深层网络。

图8.1.14
候选区域网络

候选区域网络(RPN)将第一个卷积网络的输出特征图作为输入。它在特征图上滑动一个3×3的卷积核,以使用卷积网络(如下所示的ZF网络)构建与类别无关的候选区域。其他深度网络(如VGG或ResNet)可用于更全面的特征提取,但这需要以速度为代价。ZF网络最后会输出256个值,它们将馈送到两个独立的全连接层,以预测边界框和两个objectness分数,这两个objectness分数度量了边界框是否包含目标。我们其实可以使用回归器计算单个objectness分数,但为简洁起见,Faster R-CNN使用只有两个类别的分类器:即带有目标的类别和不带有目标的类别。

图8.1.15
对于特征图中的每一个位置,RPN会做k次预测。因此,RPN将输出4×k个坐标和每个位置上2×k个得分。下图展示了8×8的特征图,且有一个3×3的卷积核执行运算,它最后输出8×8×3个ROI(其中k=3)。下图(右)展示了单个位置的3个候选区域。

图8.1.16
假设最好涵盖不同的形状和大小。因此,Faster R-CNN不会创建随机边界框。相反,它会预测一些与左上角名为锚点的参考框相关的偏移量(如x, y)。我们限制这些偏移量的值,因此我们的猜想仍然类似于锚点。

图8.1.17
要对每个位置进行k个预测,我们需要以每个位置为中心的k个锚点。每个预测与特定锚点相关联,但不同位置共享相同形状的锚点。

图8.1.18
这些锚点是精心挑选的,因此它们是多样的,且覆盖具有不同比例和宽高比的现实目标。这使得我们可以用更好的猜想来指导初始训练,并允许每个预测专门用于特定的形状。该策略使早期训练更加稳定和简便。

图8.1.19
Faster R-CNN使用更多的锚点。它部署9个锚点框:3个不同宽高比的3个不同大小的锚点(Anchor)框。每一个位置使用9个锚点,每个位置会生成2×9个objectness分数和4×9个坐标。

8.2.4 R-FCN

R-FCN有哪些创新点?

R-FCN 仍属于two-stage 目标检测算法:RPN+R-FCN

  1. Fully convolutional
  2. 位置敏感得分图(position-sentive score maps)

our region-based detector is fully convolutional with almost all computation shared on the entire image. To achieve this goal, we propose position-sensitive score maps to address a dilemma between translation-invariance in image classification and translation-variance in object detection.

R-FCN backbone:ResNet

ResNet-101+R-FCN:83.6% in PASCAL VOC 2007 test datasets

既提高了mAP,又加快了检测速度

假设我们只有一个特征图用来检测右眼。那么我们可以使用它定位人脸吗?应该可以。因为右眼应该在人脸图像的左上角,所以我们可以利用这一点定位整个人脸。如果我们还有其他用来检测左眼、鼻子或嘴巴的特征图,那么我们可以将检测结果结合起来,更好地定位人脸。现在我们回顾一下所有问题。在Faster R-CNN中,检测器使用了多个全连接层进行预测。如果有2000个ROI,那么成本非常高。R-FCN通过减少每个ROI所需的工作量实现加速。上面基于区域的特征图与ROI是独立的,可以在每个ROI之外单独计算。剩下的工作就比较简单了,因此R-FCN的速度比Faster R-CNN快。

图8.2.1 人脸检测
现在我们来看一下5×5的特征图M,内部包含一个蓝色方块。我们将方块平均分成3×3个区域。现在,我们在M中创建了一个新的特征图,来检测方块的左上角(TL)。这个新的特征图如下图(右)所示。只有黄色的网格单元[2,2]处于激活状态。在左侧创建一个新的特征图,用于检测目标的左上角。

图8.2.2 检测示例
我们将方块分成9个部分,由此创建了9个特征图,每个用来检测对应的目标区域。这些特征图叫做位置敏感得分图(position-sensitive score map),因为每个图检测目标的子区域(计算其得分)。

图8.2.3生成9个得分图
下图中红色虚线矩形是建议的ROI。我们将其分割成3×3个区域,并询问每个区域包含目标对应部分的概率是多少。例如,左上角ROI区域包含左眼的概率。我们将结果存储成3×3 vote数组,如下图(右)所示。例如,vote_array[0][0]包含左上角区域是否包含目标对应部分的得分。

图8.2.4
将ROI应用到特征图上,输出一个3x3数组。将得分图和ROI映射到vote数组的过程叫做位置敏感ROI池化(position-sensitive ROI-pool)。该过程与前面讨论过的ROI池化非常接近。

图8.2.5
将ROI的一部分叠加到对应的得分图上,计算V[i][j]。在计算出位置敏感ROI池化的所有值后,类别得分是其所有元素得分的平均值。

图8.2.6 ROI池化
假如我们有C个类别要检测。我们将其扩展为C+1个类别,这样就为背景(非目标)增加了一个新的类别。每个类别有3×3个得分图,因此一共有(C+1)×3×3个得分图。使用每个类别的得分图可以预测出该类别的类别得分。然后我们对这些得分应用 softmax 函数,计算出每个类别的概率。以下是数据流图,在本案例中,k=3。

图8.2.7

8.2.5 FPN

FPN有哪些创新点?

  1. 多层特征
  2. 特征融合

解决目标检测中的多尺度问题,通过简单的网络连接改变,在基本不增加原有模型计算量的情况下,大幅度提升小物体(small object)检测的性能。

在物体检测里面,有限计算量情况下,网络的深度(对应到感受野)与 stride 通常是一对矛盾的东西,常用的网络结构对应的 stride 一般会比较大(如 32),而图像中的小物体甚至会小于 stride 的大小,造成的结果就是小物体的检测性能急剧下降。传统解决这个问题的思路包括:

  1. 图像金字塔(image pyramid),即多尺度训练和测试。但该方法计算量大,耗时较久。
  2. 特征分层,即每层分别预测对应的scale分辨率的检测结果,如SSD算法。该方法强行让不同层学习同样的语义信息,但实际上不同深度对应于不同层次的语义特征,浅层网络分辨率高,学到更多是细节特征,深层网络分辨率低,学到更多是语义特征。

因而,目前多尺度的物体检测主要面临的挑战为:

  1. 如何学习具有强语义信息的多尺度特征表示?
  2. 如何设计通用的特征表示来解决物体检测中的多个子问题?如 object proposal, box localization, instance segmentation.
  3. 如何高效计算多尺度的特征表示?

FPN网络直接在Faster R-CNN单网络上做修改,每个分辨率的 feature map 引入后一分辨率缩放两倍的 feature map 做 element-wise 相加的操作。通过这样的连接,每一层预测所用的 feature map 都融合了不同分辨率、不同语义强度的特征,融合的不同分辨率的 feature map 分别做对应分辨率大小的物体检测。这样保证了每一层都有合适的分辨率以及强语义(rich semantic)特征。同时,由于此方法只是在原网络基础上加上了额外的跨层连接,在实际应用中几乎不增加额外的时间和计算量。作者接下来实验了将 FPN 应用在 Faster RCNN 上的性能,在 COCO 上达到了 state-of-the-art 的单模型精度。在RPN上,FPN增加了8.0个点的平均召回率(average recall,AR);在后面目标检测上,对于COCO数据集,FPN增加了2.3个点的平均精确率(average precision,AP),对于VOC数据集,FPN增加了3.8个点的AP。

FPN算法主要由三个模块组成,分别是:

  1. Bottom-up pathway(自底向上线路)
  2. Lareral connections(横向链接)
  3. Top-down path(自顶向下线路)

Bottom-up pathway

FPN是基于Faster R-CNN进行改进,其backbone是ResNet-101,FPN主要应用在Faster R-CNN中的RPN(用于bouding box proposal generation)和Fast R-CNN(用于object detection)两个模块中。

其中 RPN 和 Fast RCNN 分别关注的是召回率(recall)和精确率(precision),在这里对比的指标分别为 Average Recall(AR) 和 Average Precision(AP)。

注:Bottom-up可以理解为自底向上,Top-down可以理解为自顶向下。这里的下是指low-level,上是指high-level,分别对应于提取的低级(浅层)特征和高级语义(高层)特征。

Bottom-up pathway 是卷积网络的前向传播过程。在前向传播过程中,feature map的大小可以在某些层发生改变。一些尺度(scale)因子为2,所以后一层feature map的大小是前一层feature map大小的二分之一,根据此关系进而构成了feature pyramid(hierarchy)。

然而还有很多层输出的feature map是一样的大小(即不进行缩放的卷积),作者将这些层归为同一 stage。对于feature pyramid,作者为每个stage定义一个pyramid level。

作者将每个stage的最后一层的输出作为feature map,然后不同stage进行同一操作,便构成了feature pyramid。

具体来说,对于ResNets-101,作者使用了每个stage的最后一个残差结构的特征激活输出。将这些残差模块输出表示为{C2, C3, C4, C5},对应于conv2,conv3,conv4和conv5的输出,并且注意它们相对于输入图像具有{4, 8, 16, 32}像素的步长。考虑到内存占用,没有将conv1包含在金字塔中。

Top-down pathway and lateral connections

Top-town pathway是上采样(upsampling)过程。而later connection(横向连接)是将上采样的结果和bottom-up pathway生成的相同大小的feature map进行融合(merge)。

注:上采样尺度因子为2,因为为了和之前下采样卷积的尺度因子=2一样。上采样是放大,下采样是缩小。

具体操作如下图所示,上采样(2x up)feature map与相同大小的bottom-up feature map进行逐像素相加融合(element-wise addition),其中bottom-up feature先要经过1x1卷积层,目的是为了减少通道维度(reduce channel dimensions)。

注:减少通道维度是为了将bottom-up feature map的通道数量与top-down feature map的通道数量保持一致,又因为两者feature map大小一致,所以可以进行对应位置像素的叠加(element-wise addition)。

8.2.6 Mask R-CNN

Mask R-CNN有哪些创新点?

  1. Backbone:ResNeXt-101+FPN
  2. RoI Align替换RoI Pooling

Mask R-CNN是一个实例分割(Instance segmentation)算法,主要是在目标检测的基础上再进行分割。Mask R-CNN算法主要是Faster R-CNN+FCN,更具体一点就是ResNeXt+RPN+RoI Align+Fast R-CNN+FCN。

Mask R-CNN算法步骤

  1. 输入一幅你想处理的图片,然后进行对应的预处理操作,或者预处理后的图片;
  2. 将其输入到一个预训练好的神经网络中(ResNeXt等)获得对应的feature map;
  3. 对这个feature map中的每一点设定预定个的RoI,从而获得多个候选RoI;
  4. 将这些候选的RoI送入RPN网络进行二值分类(前景或背景)和BB回归,过滤掉一部分候选的RoI;
  5. 对这些剩下的RoI进行RoI Align操作(即先将原图和feature map的pixel对应起来,然后将feature map和固定的feature对应起来);
  6. 对这些RoI进行分类(N类别分类)、BB回归和MASK生成(在每一个RoI里面进行FCN操作)。

RoI Pooling和RoI Align有哪些不同?

ROI Align 是在Mask-RCNN中提出的一种区域特征聚集方式,很好地解决了RoI Pooling操作中两次量化造成的区域不匹配(mis-alignment)的问题。实验显示,在检测测任务中将 RoI Pooling 替换为 RoI Align 可以提升检测模型的准确性。

在常见的两级检测框架(比如Fast-RCNN,Faster-RCNN,RFCN)中,RoI Pooling 的作用是根据预选框的位置坐标在特征图中将相应区域池化为固定尺寸的特征图,以便进行后续的分类和包围框回归操作。由于预选框的位置通常是由模型回归得到的,一般来讲是浮点数,而池化后的特征图要求尺寸固定。故RoI Pooling这一操作存在两次量化的过程。

  • 将候选框边界量化为整数点坐标值。
  • 将量化后的边界区域平均分割成 $k\times k$ 个单元(bin),对每一个单元的边界进行量化。

事实上,经过上述两次量化,此时的候选框已经和最开始回归出来的位置有一定的偏差,这个偏差会影响检测或者分割的准确度。在论文里,作者把它总结为“不匹配问题(misalignment)”。

下面我们用直观的例子具体分析一下上述区域不匹配问题。如下图所示,这是一个Faster-RCNN检测框架。输入一张$800\times 800$的图片,图片上有一个$665\times 665$的包围框(框着一只狗)。图片经过主干网络提取特征后,特征图缩放步长(stride)为32。因此,图像和包围框的边长都是输入时的1/32。800正好可以被32整除变为25。但665除以32以后得到20.78,带有小数,于是RoI Pooling 直接将它量化成20。接下来需要把框内的特征池化$7\times 7$的大小,因此将上述包围框平均分割成$7\times 7$个矩形区域。显然,每个矩形区域的边长为2.86,又含有小数。于是ROI Pooling 再次把它量化到2。经过这两次量化,候选区域已经出现了较明显的偏差(如图中绿色部分所示)。更重要的是,该层特征图上0.1个像素的偏差,缩放到原图就是3.2个像素。那么0.8的偏差,在原图上就是接近30个像素点的差别,这一差别不容小觑。

为了解决RoI Pooling的上述缺点,作者提出了RoI Align这一改进的方法(如图2)。

RoI Align的思路很简单:取消量化操作,使用双线性内插的方法获得坐标为浮点数的像素点上的图像数值,从而将整个特征聚集过程转化为一个连续的操作。值得注意的是,在具体的算法操作上,RoI Align并不是简单地补充出候选区域边界上的坐标点,然后将这些坐标点进行池化,而是重新设计了一套比较优雅的流程,如下图所示:

  1. 遍历每一个候选区域,保持浮点数边界不做量化。

  2. 将候选区域分割成$k\times k$个单元,每个单元的边界也不做量化。

  3. 在每个单元中计算固定四个坐标位置,用双线性内插的方法计算出这四个位置的值,然后进行最大池化操作。

这里对上述步骤的第三点作一些说明:这个固定位置是指在每一个矩形单元(bin)中按照固定规则确定的位置。比如,如果采样点数是1,那么就是这个单元的中心点。如果采样点数是4,那么就是把这个单元平均分割成四个小方块以后它们分别的中心点。显然这些采样点的坐标通常是浮点数,所以需要使用插值的方法得到它的像素值。在相关实验中,作者发现将采样点设为4会获得最佳性能,甚至直接设为1在性能上也相差无几。事实上,RoI Align 在遍历取样点的数量上没有RoI Pooling那么多,但却可以获得更好的性能,这主要归功于解决了mis alignment的问题。值得一提的是,我在实验时发现,RoI Align在VOC 2007数据集上的提升效果并不如在COCO上明显。经过分析,造成这种区别的原因是COCO上小目标的数量更多,而小目标受mis alignment问题的影响更大(比如,同样是0.5个像素点的偏差,对于较大的目标而言显得微不足道,但是对于小目标,误差的影响就要高很多)。

8.2.7 DetNet(贡献者:北京理工大学—明奇)

DetNet是发表在ECCV2018的论文,比较新,出发点是现有的检测任务backbone都是从分类任务衍生而来的,因此作者想针对检测专用的backbone做一些讨论和研究而设计了DetNet,思路比较新奇。

  1. Introduction
      很多backbone的提出都是用于挑战ImageNet分类任务后被应用到检测上来,而鲜有单独针对检测任务设计的backbone

  检测和分类有明显的区别:(1)不仅需要分类,还需要精确的定位 (2)最近的检测器都是基于类似FPN结构,在分类网络基础上加额外多尺度特征进行检测,应对不同尺度变化的目标。这两点又是相互补充,共同协助网络完成分类到检测任务的转变。例如分类任务是检测的一环所以必不可少,但是传统分类采用的最高级特征定位细节不够,因此很多最近网络设法用类似FPN的结构去处理尺度变化的问题,就将分类较好地过渡到检测任务上了。

  1. DetNet

    2.1 Motivation
      主要着眼点是分辨率,从大目标和小目标分别阐述保持分辨率的重要性。所以DetNet也是从分辨率的保持着手,解决多尺度物体的识别问题。

  • Weak visibility of large objects
      网络在较深层如P6(FPN)P7(RetinaNet)大目标的边界不明确使精确定位困难。

  • Invisibility of small objects
      小目标就很惨了,降采样容易丢。这个就不赘述了,所以只要避开降采样就能防止目标丢失,但是这种方法又会导致抽象能力不够

​ 2.2 DetNet Design
  保持分辨率有两个麻烦的问题:(1)内存消耗大,计算大 (2)降采样减少导致高层的抽象特征不足以很好地进行分类任务。下面设计时会同时考虑时间和高层抽象信息两点。
  先放出DetNet的多尺度各stage的尺寸如下图, 可以看到,相比前两种方式,DetNet在P4之后就不再进一步降采样了,进行分辨率的保持。

  实现细节如下图:

  • 采用的backbone是ResNet-50,改进设计了DetNet-59。
  • 对bottlenecks进行了改进,传统的其实不止C,也包含两种,即将AB的膨胀卷积换成普通卷积。AB是新的基础模块。
  • 为了减少分辨率保持带来的时间和内存成本消耗,通道数固定为256(思考:降采样和膨胀卷积都会有信息丢失,这里可以想想)。
  • DetNet也可以加FPN结构,方法类似。
  1. Experiments
      检测和训练的细节配置就不看了。

    3.1 Main Results

  • 在FPN基础上明显有大物体涨点,同时由于高分辨率,小物体也有不错的提升。
  • 膨胀卷积提供的大感受野使得分类也不逊色

​ 3.2 Results analysis

  • 从AP50看出,高好1.7;从AP80看出,高了3.7。由此可以看出确实提高了检测性能。(
  • 从定位性能来看,大物体的提升比小物体更多。作者认为是高分辨率解决了大物体边界模糊的问题。其实有一种解释:小目标没有大目标明显,因为膨胀卷积核降采样都会丢失小目标,只是膨胀卷积可能离散采样不至于像降采样直接给到后面没了,但是没有根本性的解决,所以小目标不大。

  • AR指标也有类似结论

  • AR50体现了小目标的查全率更好,这也印证上面分析的:相对降采样,膨胀卷积丢失会好点。此下大目标效果虽然提升不大但是也很高了,作者表示DetNet擅长找到更精确的定位目标,在AR85的高指标就能看出。
  • AR85看大目标丢失少,说明能够像 VGG一样对大目标效果优良。关于小目标的效果平平,作者认为没有必要太高,因为FPN结构对小目标已经利用地很充分了,这里即使不高也没事。

3.3 Discussion

  • 关于stage
      为了研究backbone对检测的影响,首先研究stage的作用。前4个还好说,和ResNet一样,但是P5 P6就不同,没有尺度的变化,和传统意义的stage不一样了,需要重新定义。这里DetNet也是类似ResNet的方法,虽然没有尺度变化,但是AB模块的位置还是保持了,B开启一个stage(听上去有点牵强)。如下图,认为新加的仍属于P5。

  验证方法是做了实验,将P6开始的block换成上图所示的A模块对比效果如下图。 发现还是加了B效果更好。(但是这个stage和传统意义很不一样,所以很多性质不能相提并论,只是B模块的改变也不好判定什么)

8.2.8 CBNet

本部分介绍一篇在COCO数据集达到最高单模型性能——mAP 53.3的网络,论文于2019.9.3发布在ArXiv,全名是CBNet: A Novel Composite Backbone Network Architecture for Object Detection

  1. Introduction

  名义上是单模型,实际是多模型的特征融合,只是和真正的多模型策略略有不同。作者的起点是,设计新的模型往往需要在ImageNet上进行预训练,比较麻烦。因而提出的Composite Backbone Network (CBNet),采用经典网络的多重组合的方式构建网络,一方面可以提取到更有效的特征,另一方面也能够直接用现成的预训练参数(如ResNet,ResNeXt等)比较简单高效。

  1. Proposed method

    2.1 Architecture of CBNet

  如上图,模型中采用K个(K>1)相同的结构进行紧密联结。其中两个相同backbone的叫Dual-Backbone (DB),三个叫Triple- Backbone (TB);L代表backbone的stage数目,这里统一设置为L=5。其中,和前任工作不同的地方在于,这里将不同的stage信息进行复用回传,以便获取更好的特征(为什么work不好说)。

2.2 Other possible composite styles

  相关工作的其他类似结构,大同小异。要么是前面backbone的stage往后传播,要么是往前一个传播,每个都有一篇论文,应该都会给出不同的解释;第四个结构不太一样,是类似densnet的结构,但是密集连接+多backbone assemble的内存消耗不出意外会非常大。但是脱离这些体系来看,多backbone的结构类似多模型的assemble,和单模型有点不公平。

  1. Experiment
  • result

COCO数据集上的结果。看来提升还是有的。但是也能看出,大趋势上,三阶级联效果不如两阶的提升大,也是这部分的特征提升空间有限的缘故,到底哪部分在work不好说。下图的研究就更说明这一点了,斜率逐渐减小。

  • Comparisons of different composite styles

他的级联网络相比,作者的阐述点只落脚于特征的利用情况,但是这个东西本身就很玄乎,不好说到底怎么算利用得好。硬要说这种做法的解释性,大概就是将backbone方向的后面高级语义特征传播回前面进行加强,相当于横向的FPN传播。

  • Number of backbones in CBNet

速度慢是必然的,FPN+ResNeXt为8fps,加上两个backboen后为5.5FPS;如果减去backbone的前两个stage,可以节省部分参数达到6.9FPS,而精度下降不大(整体速度太低,这个实验意义不大)

  • Sharing weights for CBNet
  • 从中可以看出其实权重是否share区别不大, 不到一个点的降幅,参数量减少。
  • Effectiveness of basic feature enhancement by CBNet

从中可以看出激活响应效果更好,确实是能够提取到更为有效的特征,对物体的响应更加敏感。

8.3 One Stage目标检测算法

我们将对单次目标检测器(包括SSD系列和YOLO系列等算法)进行综述。我们将分析FPN以理解多尺度特征图如何提高准确率,特别是小目标的检测,其在单次检测器中的检测效果通常很差。然后我们将分析Focal loss和RetinaNet,看看它们是如何解决训练过程中的类别不平衡问题的。

8.3.1 SSD

SSD有哪些创新点?

  1. 基于Faster R-CNN中的Anchor,提出了相似的先验框(Prior box)
  2. 从不同比例的特征图(多尺度特征)中产生不同比例的预测,并明确地按长宽比分离预测。

不同于前面的R-CNN系列,SSD属于one-stage方法。SSD使用 VGG16 网络作为特征提取器(和 Faster R-CNN 中使用的 CNN 一样),将后面的全连接层替换成卷积层,并在之后添加自定义卷积层,并在最后直接采用卷积进行检测。在多个特征图上设置不同缩放比例和不同宽高比的先验框以融合多尺度特征图进行检测,靠前的大尺度特征图可以捕捉到小物体的信息,而靠后的小尺度特征图能捕捉到大物体的信息,从而提高检测的准确性和定位的准确性。如下图是SSD的网络结构图。

1. 怎样设置default boxes?
SSD中default box的概念有点类似于Faster R-CNN中的anchor。不同于Faster R-CNN只在最后一个特征层取anchor, SSD在多个特征层上取default box,可以得到不同尺度的default box。在特征图的每个单元上取不同宽高比的default box,一般宽高比在{1,2,3,1/2,1/3}中选取,有时还会额外增加一个宽高比为1但具有特殊尺度的box。如下图所示,在8x8的feature map和4x4的feature map上的每个单元取4个不同的default box。原文对于300x300的输入,分别在conv4_3, conv7,conv8_2,conv9_2,conv10_2,conv11_2的特征图上的每个单元取4,6,6,6,4,4个default box. 由于以上特征图的大小分别是38x38,19x19,10x10,5x5,3x3,1x1,所以一共得到38x38x4+19x19x6+10x10x6+5x5x6+
3x3x4+1x1x4=8732个default box.对一张300x300的图片输入网络将会针对这8732个default box预测8732个边界框。

2. 怎样对先验框进行匹配?
SSD在训练的时候只需要输入图像和图像中每个目标对应的ground truth. 先验框与ground truth 的匹配遵循两个原则:

(1)对图片中的每个ground truth, 在先验框中找到与其IOU最大的先验框,则该先验框对应的预测边界框与ground truth 匹配。

(2)对于(1)中每个剩下的没有与任何ground truth匹配到的先验框,找到与其IOU最大的ground truth,若其与该ground truth的IOU值大于某个阈值(一般设为0.5),则该先验框对应的预测边界框与该ground truth匹配。

按照这两个原则进行匹配,匹配到ground truth的先验框对应的预测边界框作为正样本,没有匹配到ground truth的先验框对应的预测边界框作为负样本。尽管一个ground truth可以与多个先验框匹配,但是ground truth的数量相对先验框还是很少,按照上面的原则进行匹配还是会造成负样本远多于正样本的情况。为了使正负样本尽量均衡(一般保证正负样本比例约为1:3),SSD采用hard negative mining, 即对负样本按照其预测背景类的置信度进行降序排列,选取置信度较小的top-k作为训练的负样本。

3. 怎样得到预测的检测结果?

最后分别在所选的特征层上使用3x3卷积核预测不同default boxes所属的类别分数及其预测的边界框location。由于对于每个box需要预测该box属于每个类别的置信度(假设有c类,包括背景,例如20class的数据集合,c=21)和该box对应的预测边界框的location(包含4个值,即该box的中心坐标和宽高),则每个box需要预测c+4个值。所以对于某个所选的特征层,该层的卷积核个数为(c+4)x 该层的default box个数.最后将每个层得到的卷积结果进行拼接。对于得到的每个预测框,取其类别置信度的最大值,若该最大值大于置信度阈值,则最大值所对应的类别即为该预测框的类别,否则过滤掉此框。对于保留的预测框根据它对应的先验框进行解码得到其真实的位置参数(这里还需注意要防止预测框位置超出图片),然后根据所属类别置信度进行降序排列,取top-k个预测框,最后进行NMS,过滤掉重叠度较大的预测框,最后得到检测结果。

SSD优势是速度比较快,整个过程只需要一步,首先在图片不同位置按照不同尺度和宽高比进行密集抽样,然后利用CNN提取特征后直接进行分类与回归,所以速度比较快,但均匀密集采样会造成正负样本不均衡的情况使得训练比较困难,导致模型准确度有所降低。另外,SSD对小目标的检测没有大目标好,因为随着网络的加深,在高层特征图中小目标的信息丢失掉了,适当增大输入图片的尺寸可以提升小目标的检测效果。

8.3.2 DSSD

DSSD有哪些创新点?

  1. Backbone:将ResNet替换SSD中的VGG网络,增强了特征提取能力
  2. 添加了Deconvolution层,增加了大量上下文信息

为了解决SSD算法检测小目标困难的问题,DSSD算法将SSD算法基础网络从VGG-16更改为ResNet-101,增强网络特征提取能力,其次参考FPN算法思路利用去Deconvolution结构将图像深层特征从高维空间传递出来,与浅层信息融合,联系不同层级之间的图像语义关系,设计预测模块结构,通过不同层级特征之间融合特征输出预测物体类别信息。

DSSD算法中有两个特殊的结构:Prediction模块;Deconvolution模块。前者利用提升每个子任务的表现来提高准确性,并且防止梯度直接流入ResNet主网络。后者则增加了三个Batch Normalization层和三个3×3卷积层,其中卷积层起到了缓冲的作用,防止梯度对主网络影响太剧烈,保证网络的稳定性。

SSD和DSSD的网络模型如下图所示:

Prediction Module

SSD直接从多个卷积层中单独引出预测函数,预测量多达7000多,梯度计算量也很大。MS-CNN方法指出,改进每个任务的子网可以提高准确性。根据这一思想,DSSD在每一个预测层后增加残差模块,并且对于多种方案进行了对比,如下图所示。结果表明,增加残差预测模块后,高分辨率图片的检测精度比原始SSD提升明显。

Deconvolution模块

为了整合浅层特征图和deconvolution层的信息,作者引入deconvolution模块,如下图所示。作者受到论文Learning to Refine Object Segments的启发,认为用于精细网络的deconvolution模块的分解结构达到的精度可以和复杂网络一样,并且更有效率。作者对其进行了一定的修改:其一,在每个卷积层后添加批归一化(batch normalization)层;其二,使用基于学习的deconvolution层而不是简单地双线性上采样;其三,作者测试了不同的结合方式,元素求和(element-wise sum)与元素点积(element-wise product)方式,实验证明元素点积计算能得到更好的精度。

8.3.3 YOLOv1

YOLOv1有哪些创新点?

  1. 将整张图作为网络的输入,直接在输出层回归bounding box的位置和所属的类别
  2. 速度快,one stage detection的开山之作

YOLOv1介绍

YOLO(You Only Look Once: Unified, Real-Time Object Detection)是one-stage detection的开山之作。之前的物体检测方法首先需要产生大量可能包含待检测物体的先验框, 然后用分类器判断每个先验框对应的边界框里是否包含待检测物体,以及物体所属类别的概率或者置信度,同时需要后处理修正边界框,最后基于一些准则过滤掉置信度不高和重叠度较高的边界框,进而得到检测结果。这种基于先产生候选区再检测的方法虽然有相对较高的检测准确率,但运行速度较慢。

YOLO创造性的将物体检测任务直接当作回归问题(regression problem)来处理,将候选区和检测两个阶段合二为一。只需一眼就能知道每张图像中有哪些物体以及物体的位置。下图展示了各物体检测系统的流程图。

事实上,YOLO也并没有真正的去掉候选区,而是直接将输入图片划分成7x7=49个网格,每个网格预测两个边界框,一共预测49x2=98个边界框。可以近似理解为在输入图片上粗略的选取98个候选区,这98个候选区覆盖了图片的整个区域,进而用回归预测这98个候选框对应的边界框。

1. 网络结构是怎样的?

YOLO网络借鉴了GoogLeNet分类网络结构,不同的是YOLO使用1x1卷积层和3x3卷积层替代inception module。如下图所示,整个检测网络包括24个卷积层和2个全连接层。其中,卷积层用来提取图像特征,全连接层用来预测图像位置和类别概率值。

2. YOLO的输入、输出、损失函数分别是什么?

前面说到YOLO将输入图像分成7x7的网格,最后输出是7x7xk的张量。YOLO网络最后接了两个全连接层,全连接层要求输入是固定大小的,所以YOLO要求输入图像有固定大小,论文中作者设计的输入尺寸是448x448。

YOLO将输入图像分成7x7的网格,每个网格预测2个边界框。若某物体的ground truth的中心落在该网格,则该网格中与这个ground truth IOU最大的边界框负责预测该物体。对每个边界框会预测5个值,分别是边界框的中心x,y(相对于所属网格的边界),边界框的宽高w,h(相对于原始输入图像的宽高的比例),以及这些边界框的confidencescores(边界框与ground truth box的IOU值)。同时每个网格还需要预测c个类条件概率 (是一个c维向量,表示某个物体object在这个网格中,且该object分别属于各个类别的概率,这里的c类物体不包含背景)。论文中的c=20,则每个网格需要预测2x5+20=30个值,这些值被映射到一个30维的向量。
为了让边界框坐标损失、分类损失达到很好的平衡,损失函数设计如下图所示。

如上图所示,损失函数分为坐标预测(蓝色框)、含有物体的边界框的confidence预测(红色框)、不含有物体的边界框的confidence预测(黄色框)、分类预测(紫色框)四个部分。

由于不同大小的边界框对预测偏差的敏感度不同,小的边界框对预测偏差的敏感度更大。为了均衡不同尺寸边界框对预测偏差的敏感度的差异。作者巧妙的对边界框的w,h取均值再求L2 loss. YOLO中更重视坐标预测,赋予坐标损失更大的权重,记为 coord,在pascal voc训练中coodd=5 ,classification error部分的权重取1。

某边界框的置信度定义为:某边界框的confidence = 该边界框存在某类对象的概率pr(object)*该边界框与该对象的ground truth的IOU值 ,若该边界框存在某个对象pr(object)=1 ,否则pr(object)=0 。由于一幅图中大部分网格中是没有物体的,这些网格中的边界框的confidence置为0,相比于有物体的网格,这些不包含物体的网格更多,对梯度更新的贡献更大,会导致网络不稳定。为了平衡上述问题,YOLO损失函数中对没有物体的边界框的confidence error赋予较小的权重,记为 noobj,对有物体的边界框的confidence error赋予较大的权重。在pascal VOC训练中noobj=0.5 ,有物体的边界框的confidence error的权重设为1.

3. YOLO怎样预测?

YOLO最后采用非极大值抑制(NMS)算法从输出结果中提取最有可能的对象和其对应的边界框。

输入一张图片到YOLO网络将输出一个7730的张量表示图片中每个网格对应的可能的两个边界框以及每个边界框的置信度和包含的对象属于各个类别的概率。由此可以计算某对象i属于类别 同时在第j个边界框中的得分:

每个网格有20个类条件概率,2个边界框置信度,相当于每个网格有40个得分,7x7个网格有1960个得分,每类对象有1960/20=98个得分,即98个候选框。

NMS步骤如下:

1.设置一个Score的阈值,一个IOU的阈值;

2.对于每类对象,遍历属于该类的所有候选框,

①过滤掉Score低于Score阈值的候选框;

②找到剩下的候选框中最大Score对应的候选框,添加到输出列表;

③进一步计算剩下的候选框与②中输出列表中每个候选框的IOU,若该IOU大于设置的IOU阈值,将该候选框过滤掉,否则加入输出列表中;

④最后输出列表中的候选框即为图片中该类对象预测的所有边界框

3.返回步骤2继续处理下一类对象。

YOLO将识别与定位合二为一,结构简便,检测速度快,更快的Fast YOLO可以达到155FPS。相对于R-CNN系列, YOLO的整个流程中都能看到整张图像的信息,因此它在检测物体时能很好的利用上下文信息,从而不容易在背景上预测出错误的物体信息。同时YOLO可以学习到高度泛化的特征,能将一个域上学到的特征迁移到不同但相关的域上,如在自然图像上做训练的YOLO,在艺术图片上可以得到较好的测试结果。

由于YOLO网格设置比较稀疏,且每个网格只预测2个边界框,其总体预测精度不高,略低于Fast RCNN。其对小物体的检测效果较差,尤其是对密集的小物体表现比较差。

8.3.4 YOLOv2

YOLOv2 有哪些创新点?

YOLOv1虽然检测速度快,但在定位方面不够准确,并且召回率较低。为了提升定位准确度,改善召回率,YOLOv2在YOLOv1的基础上提出了几种改进策略,如下图所示,可以看到,一些改进方法能有效提高模型的mAP。

  1. 大尺度预训练分类
  2. New Network:Darknet-19
  3. 加入anchor

YOLOv2 介绍

(1)Batch Normalization

YOLOv2中在每个卷积层后加Batch Normalization(BN)层,去掉dropout. BN层可以起到一定的正则化效果,能提升模型收敛速度,防止模型过拟合。YOLOv2通过使用BN层使得mAP提高了2%。
(2)High Resolution Classifier

目前的大部分检测模型都会使用主流分类网络(如vgg、resnet)在ImageNet上的预训练模型作为特征提取器,
而这些分类网络大部分都是以小于256x256的图片作为输入进行训练的,低分辨率会影响模型检测能力。YOLOv2将输入图片的分辨率提升至448x448,为了使网络适应新的分辨率,YOLOv2先在ImageNet上以448x448的分辨率对网络进行10个epoch的微调,让网络适应高分辨率的输入。通过使用高分辨率的输入,YOLOv2的mAP提升了约4%。

(3)Convolutional With Anchor Boxes

YOLOv1利用全连接层直接对边界框进行预测,导致丢失较多空间信息,定位不准。YOLOv2去掉了YOLOv1中的全连接层,使用Anchor Boxes预测边界框,同时为了得到更高分辨率的特征图,YOLOv2还去掉了一个池化层。由于图片中的物体都倾向于出现在图片的中心位置,若特征图恰好有一个中心位置,利用这个中心位置预测中心点落入该位置的物体,对这些物体的检测会更容易。所以总希望得到的特征图的宽高都为奇数。YOLOv2通过缩减网络,使用416x416的输入,模型下采样的总步长为32,最后得到13x13的特征图,然后对13x13的特征图的每个cell预测5个anchor boxes,对每个anchor box预测边界框的位置信息、置信度和一套分类概率值。使用anchor
boxes之后,YOLOv2可以预测13x13x5=845个边界框,模型的召回率由原来的81%提升到88%,mAP由原来的69.5%降低到69.2%.召回率提升了7%,准确率下降了0.3%。

(4)Dimension Clusters

在Faster R-CNN和SSD中,先验框都是手动设定的,带有一定的主观性。YOLOv2采用k-means聚类算法对训练集中的边界框做了聚类分析,选用boxes之间的IOU值作为聚类指标。综合考虑模型复杂度和召回率,最终选择5个聚类中心,得到5个先验框,发现其中中扁长的框较少,而瘦高的框更多,更符合行人特征。通过对比实验,发现用聚类分析得到的先验框比手动选择的先验框有更高的平均IOU值,这使得模型更容易训练学习。

(5)New Network:Darknet-19

YOLOv2采用Darknet-19,其网络结构如下图所示,包括19个卷积层和5个max pooling层,主要采用3x3卷积和1x1卷积,这里1x1卷积可以压缩特征图通道数以降低模型计算量和参数,每个卷积层后使用BN层以加快模型收敛同时防止过拟合。最终采用global avg pool 做预测。采用YOLOv2,模型的mAP值没有显著提升,但计算量减少了。

(6)Direct location prediction

Faster R-CNN使用anchor boxes预测边界框相对先验框的偏移量,由于没有对偏移量进行约束,每个位置预测的边界框可以落在图片任何位置,会导致模型不稳定,加长训练时间。YOLOv2沿用YOLOv1的方法,根据所在网格单元的位置来预测坐标,则Ground Truth的值介于0到1之间。网络中将得到的网络预测结果再输入sigmoid函数中,让输出结果介于0到1之间。设一个网格相对于图片左上角的偏移量是cx,cy。先验框的宽度和高度分别是pw和ph,则预测的边界框相对于特征图的中心坐标(bx,by)和宽高bw、bh的计算公式如下图所示。

YOLOv2结合Dimention Clusters, 通过对边界框的位置预测进行约束,使模型更容易稳定训练,这种方式使得模型的mAP值提升了约5%。

(7)Fine-Grained Features

YOLOv2借鉴SSD使用多尺度的特征图做检测,提出pass through层将高分辨率的特征图与低分辨率的特征图联系在一起,从而实现多尺度检测。YOLOv2提取Darknet-19最后一个max pool层的输入,得到26x26x512的特征图。经过1x1x64的卷积以降低特征图的维度,得到26x26x64的特征图,然后经过pass through层的处理变成13x13x256的特征图(抽取原特征图每个2x2的局部区域组成新的channel,即原特征图大小降低4倍,channel增加4倍),再与13x13x1024大小的特征图连接,变成13x13x1280的特征图,最后在这些特征图上做预测。使用Fine-Grained Features,YOLOv2的性能提升了1%.

(8)Multi-Scale Training

YOLOv2中使用的Darknet-19网络结构中只有卷积层和池化层,所以其对输入图片的大小没有限制。YOLOv2采用多尺度输入的方式训练,在训练过程中每隔10个batches,重新随机选择输入图片的尺寸,由于Darknet-19下采样总步长为32,输入图片的尺寸一般选择32的倍数{320,352,…,608}。采用Multi-Scale Training, 可以适应不同大小的图片输入,当采用低分辨率的图片输入时,mAP值略有下降,但速度更快,当采用高分辨率的图片输入时,能得到较高mAP值,但速度有所下降。

YOLOv2借鉴了很多其它目标检测方法的一些技巧,如Faster R-CNN的anchor boxes, SSD中的多尺度检测。除此之外,YOLOv2在网络设计上做了很多tricks,使它能在保证速度的同时提高检测准确率,Multi-Scale Training更使得同一个模型适应不同大小的输入,从而可以在速度和精度上进行自由权衡。

YOLOv2的训练

YOLOv2的训练主要包括三个阶段。
第一阶段:先在ImageNet分类数据集上预训练Darknet-19,此时模型输入为$224\times 224$,共训练160个epochs。
第二阶段:将网络的输入调整为$448\times 448$,继续在ImageNet数据集上finetune分类模型,训练10个epochs,此时分类模型的top-1准确度为76.5%,而top-5准确度为93.3%。
第三个阶段:修改Darknet-19分类模型为检测模型,并在检测数据集上继续finetune网络。
网络修改包括(网路结构可视化):移除最后一个卷积层、global avgpooling层以及softmax层,并且新增了三个$3\times 3 \times 2014$卷积层,同时增加了一个passthrough层,最后使用$1\times 1$卷积层输出预测结果。

8.3.5 YOLO9000

github:http://pjreddie.com/yolo9000/

YOLO9000是在YOLOv2的基础上提出的一种联合训练方法,可以检测超过9000个类别的模型。YOLOv2混合目标检测数据集和分类数据集,用目标检测数据集及其类别标记信息和位置标注信息训练模型学习预测目标定位和分类,用分类数据集及其类别标记信息进一步扩充模型所能识别的物体类别同时能增强模型鲁棒性。

1. YOLO9000是怎么组织数据的?

YOLO9000根据各个类别之间的从属关系建立一种树结WordTree, 将COCO数据集和ImageNet数据集组织起来。

WordTree的生成方式如下:

①首先遍历ImageNet中的类别名词。

②对每个名词,在WordNet(一种结构化概念及概念之间关系的语言数据库)上找到从它所在位置到根节点(设根节点为实体对象physical object)的最短路径,由于在WordNet中大多数同义词只有一个路径,所以先把将该路径上的词全都加到树中。

③迭代地检查剩下的名词,取它到根节点的最短路径,将该最短路径上的还没出现在层次树中的词加入到树中。
混合后的数据集形成一个有9418类的WordTree.生成的WordTree模型如下图所示。另外考虑到COCO数据集相对于ImageNet数据集数据量太少了,为了平衡两个数据集,作者进一步对COCO数据集过采样,使COCO数据集与ImageNet数据集的数据量比例接近1:4。

对于物体的标签,采用one-hot编码的形式,数据集中的每个物体的类别标签被组织成1个长度为9418的向量,向量中除在WordTree中从该物体对应的名词到根节点的路径上出现的词对应的类别标号处为1,其余位置为0。

2. YOLO9000是怎么进行联合训练的?

YOLO9000采用YOLOv2的结构,anchorbox由原来的5调整到3,对每个anchorbox预测其对应的边界框的位置信息x,y,w,h和置信度以及所包含的物体分别属于9418类的概率,所以每个anchorbox需要预测4+1+9418=9423个值。每个网格需要预测3x9423=28269个值。在训练的过程中,当网络遇到来自检测数据集的图片时,用完整的YOLOv2loss进行反向传播计算,当网络遇到来自分类数据集的图片时,只用分类部分的loss进行反向传播。

3. YOLO9000是怎么预测的?

WordTree中每个节点的子节点都属于同一个子类,分层次的对每个子类中的节点进行一次softmax处理,以得到同义词集合中的每个词的下义词的概率。当需要预测属于某个类别的概率时,需要预测该类别节点的条件概率。即在WordTree上找到该类别名词到根节点的路径,计算路径上每个节点的概率之积。预测时,YOLOv2得到置信度,同时会给出边界框位置以及一个树状概率图,沿着根节点向下,沿着置信度最高的分支向下,直到达到某个阈值,最后到达的节点类别即为预测物体的类别。

YOLO9000使用WordTree混合目标检测数据集和分类数据集,并在其上进行联合训练,使之能实时检测出超过9000个类别的物体,其强大令人赞叹不已。YOLO9000尤其对动物的识别效果很好,但是对衣服或者设备等类别的识别效果不是很好,可能的原因是与目标检测数据集中的数据偏向有关。

8.3.6 YOLOv3

YOLOv3总结了自己在YOLOv2的基础上做的一些尝试性改进,有的尝试取得了成功,而有的尝试并没有提升模型性能。其中有两个值得一提的亮点,一个是使用残差模型,进一步加深了网络结构;另一个是使用FPN架构实现多尺度检测。

YOLOv3有哪些创新点?

  1. 新网络结构:DarkNet-53
  2. 融合FPN
  3. 用逻辑回归替代softmax作为分类器

1. YOLOv3对网络结构做了哪些改进?

YOLOv3在之前Darknet-19的基础上引入了残差块,并进一步加深了网络,改进后的网络有53个卷积层,取名为Darknet-53,网络结构如下图所示(以256*256的输入为例)。

为了比较Darknet-53与其它网络结构的性能,作者在TitanX上,采用相同的实验设置,将256x256的图片分别输入以Darknet-19,ResNet-101,ResNet-152和Darknet-53为基础网络的分类模型中,实验得到的结果如下图所示。可以看到Darknet-53比ResNet-101的性能更好,而且速度是其1.5倍,Darknet-53与ResNet-152性能相似但速度几乎是其2倍。注意到,Darknet-53相比于其它网络结构实现了每秒最高的浮点计算量,说明其网络结构能更好的利用GPU。

2.YOLOv3中怎样实现多尺度检测?

YOLOv3借鉴了FPN的思想,从不同尺度提取特征。相比YOLOv2,YOLOv3提取最后3层特征图,不仅在每个特征图上分别独立做预测,同时通过将小特征图上采样到与大的特征图相同大小,然后与大的特征图拼接做进一步预测。用维度聚类的思想聚类出9种尺度的anchor box,将9种尺度的anchor box均匀的分配给3种尺度的特征图.如下图是在网络结构图的基础上加上多尺度特征提取部分的示意图(以在COCO数据集(80类)上256x256的输入为例):

从YOLOv1到YOLOv2再到YOLO9000、YOLOv3, YOLO经历三代变革,在保持速度优势的同时,不断改进网络结构,同时汲取其它优秀的目标检测算法的各种trick,先后引入anchor box机制、引入FPN实现多尺度检测等。

8.3.7 RetinaNet

研究背景

  • Two-Stage检测器(如Faster R-CNN、FPN)效果好,但速度相对慢
  • One-Stage检测器(如YOLO、SSD)速度快,但效果一般

作者对one-stage检测器准确率不高的问题进行探究,发现主要问题在于正负类别不均衡(简单-难分类别不均衡)。

We discover that the extreme foreground-background class imbalance encountered during training of dense detectors is the central cause.

作者建议通过重新设计标准的交叉熵损失(cross entropy loss)来解决这种类别不平衡(class inbalance)问题,即提出Focal Loss。

We propose to address this class imbalance by reshaping the standard cross entropy loss such that it down-weights the loss assigned to well-classified examples. Our novel Focal Loss focuses training on a sparse set of hard examples and prevents the vast number of easy negatives from overwhelming the detector during training.

结合Focal Loss的one-stage检测器称为RetinaNet,该检测器在COCO上mAP可以和特征金字塔网络(feature pyramid network,FPN)或者Mask R-CNN接近,

问:什么是类别不均衡(class imbalance)?

答:负样本的数量极大于正样本的数量,比如包含物体的区域(正样本)很少,而不包含物体的区域(负样本)很多。比如检测算法在早期会生成一大波的bbox。而一幅常规的图片中,顶多就那么几个object。这意味着,绝大多数的bbox属于background。

问:样本的类别不均衡会带来什么问题?

答:由于大多数都是简单易分的负样本(属于背景的样本),使得训练过程不能充分学习到属于那些有类别样本的信息;其次简单易分的负样本太多,可能掩盖了其他有类别样本的作用(这些简单易分的负样本仍产生一定幅度的loss,见下图蓝色曲线,数量多会对loss起主要贡献作用,因此就主导了梯度的更新方向,掩盖了重要的信息)

This imbalance causes two problems: (1) training is inefficient as most locations are easy negatives that contribute no useful learning signal; (2) en masse, the easy negatives can overwhelm training and lead to degenerate models.

简单来说,因为bbox数量爆炸。 正是因为bbox中属于background的bbox太多了,所以如果分类器无脑地把所有bbox统一归类为background,accuracy也可以刷得很高。于是乎,分类器的训练就失败了。分类器训练失败,检测精度自然就低了。

问:为什么在two-stage检测器中,没有出现类别不均衡(class imbalamce)问题呢?

答:因为通过RPN阶段可以减少候选目标区域,而在分类阶段,可以固定前景与背景比值(foreground-to-background ratio)为1:3,或者使用OHEM(online hard example mining)使得前景和背景的数量达到均衡。

RetinaNet有哪些创新点?

概述:

  • New loss:提出Focal Loss函数解决class imbalance
  • New detector:RetinaNet = ResNet + FPN + Two sub-networks + Focal Loss

Focal Loss更加聚焦在困难样本(hard examples)上的训练。

将Focal Loss与ResNet-101-FPN backbone结合提出RetinaNet(one-stage检测器),RetinaNet在COCO test-dev上达到39.1mAP,速度为5FPS。

RetinaNet检测器与当时最佳的其它检测器进行比较,无论是速度上还是准确率上都是最佳:

详解:

作者提出一种新的损失函数,思路是希望那些hard examples对损失的贡献变大,使网络更倾向于从这些样本上学习。

作者以二分类为例进行说明:

交叉熵函数CE

首先是我们常使用的交叉熵损失函数:

上式中,y=+1或者y=-1。p∈[0,1]是y=+1的估计概率。作者定义pt为:

注:对交叉熵函数不了解的,可以参考理解交叉熵作为损失函数在神经网络中的作用

均衡交叉熵函数

要对类别不均衡问题对loss的贡献进行一个控制,即加上一个控制权重即可,最初作者的想法即如下这样,对于属于少数类别的样本,增大α即可

但这样有一个问题,它仅仅解决了正负样本之间的平衡问题,并没有区分易分/难分样本,按作者的话说:

While α balances the importance of positive/negative examples, it does not differentiate between easy/hard examples. Instead, we propose to reshape the loss function to down-weight easy examples and thus focus training on hard negatives.

问:为什么公式(3)只解决正负样本不均衡问题?

答:增加了一个系数αt,跟pt的定义类似,当label=1的时候,αt=a;当label=-1的时候,αt=1-a,a的范围也是0到1。因此可以通过设定a的值(一般而言假如1这个类的样本数比-1这个类的样本数多很多,那么a会取0到0.5来增加-1这个类的样本的权重)来控制正负样本对总的loss的共享权重。

Focal Loss

作者一开始给交叉熵损失函数添加modulating factor:

显然,样本越易分,pt就越大(pt—>1),modulating factor趋近于0,则贡献的loss就越小,同样地,样本越难分,其pt就越小,modulating factor接近于1,则贡献的loss不受影响。

问:为什么pt越大,FL值越小?

答:根据公式(4)可知,FL与log(pt)中的pt成反比,与1-pt成正比,因此FL与pt的关系成反比。这是交叉熵函数的基本性质。当pt很大时(接近于1),FL值很小;而当pt很小时(接近于0),FL值会很大。

注:这里有个超参数—focusing parameter γ。

γ 放大了modulating factor的作用。

举原文中的一个例子,当pt=0.9时,带有modulating factor的focal loss是CE loss的100分之一,即进一步减小了正确分类的损失。

For instance, with γ = 2, an example classified with pt = 0.9 would have 100× lower loss compared with CE and with pt ≈ 0.968 it would have 1000× lower loss. This in turn increases the importance of correcting misclassified examples (whose loss is scaled down by at most 4× for pt ≤ .5 and γ = 2).

在实际中,作者采用如下公式,即综合了公式(3)和公式(4)的形式,这样机能调整正负样本的权重,又能控制难易分类样本的权重:

这里的两个参数 α和γ 来控制,在实验中a的选择范围也很广,一般而言当γ增加的时候,a需要减小一点,本文作者采用α=0.25,γ=2效果最好。

RetinaNet Detector

RetinaNet是由backbone网络和两个特殊任务的子网络(subnet)组成(属于one-stage检测器)。Backbone用来计算feature map;第一个子网络用来object classification,第二个子网络用来bounding box regression。

Feature Pyramid Network Backbone

Anchor

Classification Subnet

Box Regression Subnet

RetinaNet结构注意内容:

  1. 训练时FPN每一级的所有example都被用于计算Focal Loss,loss值加到一起用来训练;
  2. 测试时FPN每一级只选取score最大的1000个example来做nms;
  3. 整个结构不同层的head部分(上图中的c和d部分)共享参数,但分类和回归分支间的参数不共享;
  4. 分类分支的最后一级卷积的bias初始化成前面提到的-log((1-π)/π);

作者:张磊_0503 链接:https://www.jianshu.com/p/204d9ad9507f 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

实验结果

Table1是关于RetinaNet和Focal Loss的一些实验结果。(a)是在交叉熵的基础上加上参数a,a=0.5就表示传统的交叉熵,可以看出当a=0.75的时候效果最好,AP值提升了0.9。(b)是对比不同的参数γ和a的实验结果,可以看出随着γ的增加,AP提升比较明显。(d)通过和OHEM的对比可以看出最好的Focal Loss比最好的OHEM提高了3.2AP。这里OHEM1:3表示在通过OHEM得到的minibatch上强制positive和negative样本的比例为1:3,通过对比可以看出这种强制的操作并没有提升AP。(e)加入了运算时间的对比,可以和前面的Figure2结合起来看,速度方面也有优势!注意这里RetinaNet-101-800的AP是37.8,当把训练时间扩大1.5倍同时采用scale jitter,AP可以提高到39.1,这就是全文和table2中的最高的39.1AP的由来。

8.3.8 RFBNet

RFBNet有哪些创新点?

  1. 提出RF block(RFB)模块

RFBNet主要想利用一些技巧使得轻量级模型在速度和精度上达到很好的trade-off的检测器。灵感来自人类视觉的感受野结构Receptive Fields (RFs) ,提出了新奇的RF block(RFB)模块,来验证感受野尺寸和方向性的对提高有鉴别鲁棒特征的关系。RFBNet是以主干网络(backbone)为VGG16的SSD来构建的,主要是在Inception的基础上加入了dilated卷积层(dilated convolution),从而有效增大了感受野(receptive field)。整体上因为是基于SSD网络进行改进,所以检测速度还是比较快,同时精度也有一定的保证。

RFB介绍

RFB是一个类似Inception模块的多分支卷积模块,它的内部结构可分为两个组件:多分支卷积层和dilated卷积层。如下图:

1.多分支卷积层
​ 根据RF的定义,用多种尺寸的卷积核来实现比固定尺寸更好。具体设计:1.瓶颈结构,1x1-s2卷积减少通道特征,然后加上一个nxn卷积。2.替换5x5卷积为两个3x3卷积去减少参数,然后是更深的非线性层。有些例子,使用1xn和nx1代替nxn卷积;shortcut直连设计来自于ResNet和Inception ResNet V2。3.为了输出,卷积经常有stride=2或者是减少通道,所以直连层用一个不带非线性激活的1x1卷积层。

2.Dilated 卷积层

设计灵感来自Deeplab,在保持参数量和同样感受野的情况下,用来获取更高分辨率的特征。下图展示两种RFB结构:RFB和RFB-s。每个分支都是一个正常卷积后面加一个dilated卷积,主要是尺寸和dilated因子不同。(a)RFB。整体结构上借鉴了Inception的思想,主要不同点在于引入3个dilated卷积层(比如3x3conv,rate=1),这也是RFBNet增大感受野的主要方式之一;(b)RFB-s。RFB-s和RFB相比主要有两个改进,一方面用3x3卷积层代替5x5卷积层,另一方面用1x3和3x1卷积层代替3x3卷积层,主要目的应该是为了减少计算量,类似Inception后期版本对Inception结构的改进。

RFBNet300的整体结构如下图所示,基本上和SSD类似。RFBNet和SSD不同的是:1、主干网上用两个RFB结构替换原来新增的两层。2、conv4_3和conv7_fc在接预测层之前分别接RFB-s和RFB结构。

8.3.9 M2Det

M2Det有哪些创新点?

  1. 提出了多层次特征金字塔网络(MLFPN)来构建更有效的特征金字塔,用于检测不同尺度的对象。

M2Det的整体架构如下所示。M2Det使用backbone和多级特征金字塔网络(MLFPN)从输入图像中提取特征,然后类似于SSD,根据学习的特征生成密集的边界框和类别分数,最后是非最大抑制(NMS)操作以产生最终结果。 MLFPN由三个模块组成:特征融合模块(FFM),简化的U形模块(TUM)和按基于尺度的特征聚合模块(SFAM)。 FFMv1通过融合骨干网络的特征图,将语义信息丰富为基本特征。每个TUM生成一组多尺度特征,然后交替连接的TUM和FFMv2提取多级多尺度特征。此外,SFAM通过按比例缩放的特征连接操作和自适应注意机制将特征聚合到多级特征金字塔中。下面介绍有关M2Det中三个核心模块和网络配置的更多详细信息。

FFMs

FFM融合了M2Det中不同层次的特征,这对于构建最终的多级特征金字塔至关重要。它们使用1x1卷积层来压缩输入特征的通道,并使用连接操作来聚合这些特征图。特别是,由于FFMv1以backbone中不同比例的两个特征图作为输入,因此它采用一个上采样操作,在连接操作之前将深度特征重新缩放到相同的尺度。同时,FFMv2采用基本特征和前一个TUM的最大输出特征图 - 这两个具有相同的比例 - 作为输入,并产生下一个TUM的融合特征。 FFMv1和FFMv2的结构细节分别如下图(a)和(b)所示。

TUMs

TUM不同于FPN和RetinaNet,TUM采用简化的U形结构,如上图(c)所示。编码器是一系列3x3,步长为2的卷积层.并且解码器将这些层的输出作为其参考特征集,而原始FPN选择ResNet主干网络中每个阶段的最后一层的输出。此外,在解码器分支的上采样层后添加1x1卷积层和按元素求和的操作,以增强学习能力并保持特征的平滑性。每个TUM的解码器中的所有输出形成当前级别的多尺度特征。整体而言,堆叠TUM的输出形成多层次多尺度特征,而前TUM主要提供浅层特征,中间TUM提供中等特征,后TUM提供深层特征。

SFAM

SFAM旨在将由TUM生成的多级多尺度特征聚合成多级特征金字塔,如下图所示。SFAM的第一阶段是沿着信道维度将等效尺度的特征连接在一起。聚合特征金字塔可以表示为$X = [X_1,X_2,…,X_i,…,X_L]$,其中

指的是尺度第i个最大的特征。这里,聚合金字塔中的每个比例都包含来自多级深度的特征。但是,简单的连接操作不太适合。在第二阶段,引入了通道注意模块,以促使特征集中在最有益的通道。在SE区块之后,使用全局平均池化来在挤压步骤中生成通道统计z∈RC。

8.4 人脸检测

在目标检测领域可以划分为了人脸检测与通用目标检测,往往人脸这方面会有专门的算法(包括人脸检测、人脸识别、人脸其他属性的识别等等),并且和通用目标检测(识别)会有一定的差别,着主要来源于人脸的特殊性(有时候目标比较小、人脸之间特征不明显、遮挡问题等),下面将从人脸检测和通用目标检测两个方面来讲解目标检测。

8.4.1 目前主要有人脸检测方法分类?

目前人脸检测方法主要包含两个区域:传统人脸检测算法和基于深度学习的人脸检测算法。传统人脸检测算法主要可以分为4类:

(1)基于知识的人脸检测方法;

(2)基于模型的人脸检测方法;

(3)基于特征的人脸检测方法;

(4)基于外观的人脸检测方法。

由于本书着重关注深度学习,下面会着重介绍基于深度学习的人脸检测方法。

2006年Hinton首次提出深度学习(Deep Learning)的概念,它是通过组合低层的特征形成更高层的抽象特征。随后研究者将深度学习应用在人脸检测领域,主要集中在基于卷积神经网络(CNN)的人脸检测研究,如基于级联卷积神经网络的人脸检测(cascade cnn)、 基于多任务卷积神经网络的人脸检测(MTCNN)、Facebox等,很大程度上提高了人脸检测的鲁棒性。当然通用目标检测算法像Faster-rcnn、yolo、ssd等也有用在人脸检测领域,也可以实现比较不错的结果,但是和专门人脸检测算法比还是有差别。下面部分主要介绍基于深度学习的的人脸检测算法,基于深度学习的通用目标检测算法将在第二大节介绍。

8.4.2 如何检测图片中不同大小的人脸?

传统人脸检测算法中针对不同大小人脸主要有两个策略:

(1)缩放图片的大小(图像金字塔如图8.4.1所示);

(2)缩放滑动窗的大小(如图8.4.2所示)。

图 8.1 图像金字塔

图 8.2 缩放滑动窗口

​ 基于深度学习的人脸检测算法中针对不同大小人脸主要也有两个策略,但和传统人脸检测算法有点区别,主要包括:

(1)缩放图片大小。(不过也可以通过缩放滑动窗的方式,基于深度学习的滑动窗人脸检测方式效率会很慢存在多次重复卷积,所以要采用全卷积神经网络(FCN),用FCN将不能用滑动窗的方法。)

(2)通过anchor box的方法(如图8.3所示,不要和图8.2混淆,这里是通过特征图预测原图的anchor box区域,具体在facebox中有描述)。

图 8.3 anchor box

8.4.3 如何设定算法检测最小人脸尺寸?

主要是看滑动窗的最小窗口和anchorbox的最小窗口。

(1)滑动窗的方法

假设通过12×12的滑动窗,不对原图做缩放的话,就可以检测原图中12×12的最小人脸。但是往往通常给定最小人脸a=40、或者a=80,以这么大的输入训练CNN进行人脸检测不太现实,速度会很慢,并且下一次需求最小人脸a=30*30又要去重新训练,通常还会是12×12的输入,为满足最小人脸框a,只需要在检测的时候对原图进行缩放即可:w=w×12/a。

(2)anchorbox的方法

原理类似,这里主要看anchorbox的最小box,通过可以通过缩放输入图片实现最小人脸的设定。

8.4.4 如何定位人脸的位置?

(1)滑动窗的方式:

滑动窗的方式是基于分类器识别为人脸的框的位置确定最终的人脸,

图 8.4 滑动窗

(2)FCN的方式:

​ FCN的方式通过特征图映射到原图的方式确定最终识别为人脸的位置,特征图映射到原图人脸框是要看特征图相比较于原图有多少次缩放(缩放主要查看卷积的步长和池化层),假设特征图上(2,3)的点,可粗略计算缩放比例为8倍,原图中的点应该是(16,24);如果训练的FCN为12*12的输入,对于原图框位置应该是(16,24,12,12),当然这只是估计位置,具体的再构建网络时要加入回归框的预测,主要是相对于原图框的一个平移与缩放。

(3)通过anchor box的方式:

​ 通过特征图映射到图的窗口,通过特征图映射到原图到多个框的方式确定最终识别为人脸的位置。

8.4.5 如何通过一个人脸的多个框确定最终人脸框位置?

图 8.5 通过NMS得到最终的人脸位置

NMS改进版本有很多,最原始的NMS就是判断两个框的交集,如果交集大于设定的阈值,将删除其中一个框,那么两个框应该怎么选择删除哪一个呢? 因为模型输出有概率值,一般会优选选择概率小的框删除。

8.4.6 基于级联卷积神经网络的人脸检测(Cascade CNN)

  1. cascade cnn的框架结构是什么?

级联结构中有6个CNN,3个CNN用于人脸非人脸二分类,另外3个CNN用于人脸区域的边框校正。给定一幅图像,12-net密集扫描整幅图片,拒绝90%以上的窗口。剩余的窗口输入到12-calibration-net中调整大小和位置,以接近真实目标。接着输入到NMS中,消除高度重叠窗口。下面网络与上面类似。

  1. cascade cnn人脸校验模块原理是什么?

该网络用于窗口校正,使用三个偏移变量:Xn:水平平移量,Yn:垂直平移量,Sn:宽高比缩放。候选框口(x,y,w,h)中,(x,y)表示左上点坐标,(w,h)表示宽和高。

我们要将窗口的控制坐标调整为:

这项工作中,我们有$N=5×3×3=45$种模式。偏移向量三个参数包括以下值:

同时对偏移向量三个参数进行校正。

3、训练样本应该如何准备?

人脸样本:

非人脸样本:

  1. 级联的好处

级联的工作原理和好处:

  • 最初阶段的网络可以比较简单,判别阈值可以设得宽松一点,这样就可以在保持较高召回率的同时排除掉大量的非人脸窗口;
  • 最后阶段网络为了保证足够的性能,因此一般设计的比较复杂,但由于只需要处理前面剩下的窗口,因此可以保证足够的效率;
  • 级联的思想可以帮助我们去组合利用性能较差的分类器,同时又可以获得一定的效率保证。

8.4.7 基于多任务卷积神经网络的人脸检测(MTCNN)

1.MTCNN模型有三个子网络。分别是P-Net,R-Net,O-Net.我想问一下,1.模型中的三个input size是指的是同一张图resize到不同尺度下喂给不同模型,还是同一张图,依次经过三个模型,然后是不同的输入尺寸?(这部分能给我讲一下吗)2.每个模型它都有对应三个结果(face classification;bounding box;facial landmark)这三个在网络上是如何对应的呢?

为了检测不同大小的人脸,开始需要构建图像金字塔,先经过pNet模型,输出人脸类别和边界框(边界框的预测为了对特征图映射到原图的框平移和缩放得到更准确的框),将识别为人脸的框映射到原图框位置可以获取patch,之后每一个patch通过resize的方式输入到rNet,识别为人脸的框并且预测更准确的人脸框,最后rNet识别为人脸的的每一个patch通过resize的方式输入到oNet,跟rNet类似,关键点是为了在训练集有限情况下使模型更鲁棒。

还要注意一点构建图像金字塔的的缩放比例要保留,为了将边界框映射到最开始原图上的

还要注意一点:如何从featureMap映射回原图

8.4.8 Facebox

(1)Rapidly Digested Convolutional Layers(RDCL)

在网络前期,使用RDCL快速的缩小feature map的大小。 主要设计原则如下:

  • Conv1, Pool1, Conv2 和 Pool2 的stride分别是4, 2, 2 和 2。这样整个RDCL的stride就是32,可以很快把feature map的尺寸变小。
  • 卷积(或pooling)核太大速度就慢,太小覆盖信息又不足。文章权衡之后,将Conv1, Pool1, Conv2 和 Pool2 的核大小分别设为7x7,3x3,5x5,3x3
  • 使用CReLU来保证输出维度不变的情况下,减少卷积核数量。

(2)Multiple Scale Convolutional Layers(MSCL)

在网络后期,使用MSCL更好地检测不同尺度的人脸。 主要设计原则有:

  • 类似于SSD,在网络的不同层进行检测;
  • 采用Inception模块。由于Inception包含多个不同的卷积分支,因此可以进一步使得感受野多样化。

(3)Anchor densification strategy

为了anchor密度均衡,可以对密度不足的anchor以中心进行偏移加倍,如下图所示:

8.5 目标检测的技巧汇总

8.5.1 Data Augmentation(贡献者:北京理工大学—明奇)

介绍一篇发表在Big Data上的数据增强相关的文献综述。

  1. Introduction
  • 数据增强与过拟合
    验证是否过拟合的方法:画出loss曲线,如果训练集loss持续减小但是验证集loss增大,就说明是过拟合了。

  • 数据增强目的
    通过数据增强实现数据更复杂的表征,从而减小验证集和训练集以及最终测试集的差距,让网络更好地学习迁移数据集上的数据分布。这也说明网络不是真正地理解数据,而是记忆数据分布。

  • 数据增强的方法
    (1)数据变换增强
    包括几何变换、色彩空间变换,随机擦除,对抗训练,神经风格迁移等
    (2)重采样增强
    主要侧重于新的实例合成。如图像混合(mixup),特征空间的增强,GAN生成图片。一张图看明白:

  1. Image Data Augmentation techniques

2.1 Data Augmentations based on basic image manipulations

  • Geometric transformations
      如果数据集潜在的表征能够被观察和分离,那么简单的几何变换就能取得很好的效果。对于复杂的数据集如医学影像,数据小而且训练集和测试集的偏差大,几何变换等增强的合理运用就很关键。

    • Flipping
      作者提到了要衡量普遍性的观点。但是这种变换对于数字数据集不具有安全性。

    • Color space
      主要提及的识别RGB通道上的变换,将三通道图进行分离,以及直方图变换增强等。(颜色空间更多增强方式可以参考A Preliminary Study on Data Augmentation of Deep Learning for Image Classification)

    • Cropping
      通常在输入图片的尺寸不一时会进行按中心的裁剪操作。裁剪某种程度上和平移操作有相似性。根据裁剪幅度变化,该操作具有一定的不安全性。

    • Rotation
      大幅度的旋转对数字集会有不安全性的考虑。

    • Translation
      平移也需要合理设计。如车站人脸检测,只需要中心检测时,就可以加合适的平移增强。平移后空出部分填0或者255,或用高斯分布噪声。

    • Noise injection
      在像素上叠加高斯分布的随机噪声。

  • Color space transformations
      由于实际图像中一定存在光线偏差,所以光线的增强十分有必要(但是IJCV的光流文章指出,3D建模的灯光增强实在是很难学习到,所以对于光线增强的效果不如几何也可能因为光线的复杂度更高,数据样本远远不够)。色彩变换十分多样,如像素限制、像素矩阵变换、像素值颠倒等;灰度图和彩图相比,计算时间成本大大较少,但是据实验效果会下降一些,很明显因为特征的维度被降维了;还有尝试将RGB映射到其他的色彩空间进行学习,YUV,CMY.HSV等。
      除了计算大内存消耗和时间长等缺点,色彩变换也面临不安全性,比如识别人脸的关键信息是黄白黑,但是大量增强出红绿蓝,会丢信息。颜色变换的增强方法是从色彩空间角度拟合偏置,效果有限的可能性是多样的:1. 真实几何多样性比颜色更简单 2. 色彩的变化多样性更多,导致增强不够反而学不好,颜色空间的欠拟合 3. 变换不安全

  • Experiment

随机裁剪效果最好。

2.2 Geometric versus photometric transformations

  • Kernel filter
    滤波器核在图像处理用的比较广,这里提到用这种方法来增强。还提到了一种正则化增强方法PatchShuffle,在一个patch内随机交换像素值,使得对噪声的抵抗更强以及避免过拟合。
    文章指出关于应用滤波器增强的工作尚且不多,因为这种方法其实和CNN的机制是一样的,这么做也许还不如直接在原始CNN上加层加深网络。

  • Mixing images
    就是那篇被ICLR拒稿的采样方法直接均值相加混合。

  还有非线性的mixup裁剪如下:

  以及随机裁剪的图像混合:

  这些混合方式是十分反人类直觉的,因此可解释性不强。只能说是可能增强了对底层低级特征如线条边缘等的鲁棒性。其实有点没有抓住关键点。

  • Random erasing
    随机擦除就是类似cutout的思想,通过mask的遮挡使得网络能够提高遮挡情况的鲁棒性。需要手工设计的部分包括mask的大小以及生成方式。是一种比较有效的方法。这种方式也需要考量增强的安全性,比如MNIST数据集8cutout后可能出问题。

  • A note on combining augmentations
    组合的增强方式往往是连续变化的,导致数据集的容量会迅速扩大,这对于小数据集领域来说容易发生过拟合 ,所以需要设计合理的搜索算法设计恰当的训练数据集。

2.3 Data Augmentations based on Deep Learning

  • Feature space augmentation
    之前刚看的基于SMOTE类别不平衡的过采样法来进行特征空间的插值操作进行数据增强,就实验效果而言不算特别出众。

  • Adversarial training
    对抗样本训练可以提高鲁棒性,但是实际应用中其实提高不一定明显,因为自然对抗样本的数目没有那么多。而NIPS的对抗攻击大赛很多从神经网络的学习策略下手,进行梯度攻击,更加偏向于人为的攻击了,对于普适的检测性能提高意义反而不大,更强调安全需求高的场合。

  • GAN‑based Data Augmentation

  • Neural Style Transfer

不觉得这个效果会普遍很好,应该来说是针对特定域会有效(如白天黑夜),实际效果应该有限。

  • Meta learning Data Augmentations
    • Neural augmentation
    • Smart Augmentation
      两个东西差不多,就是上次看到SmartAugment方法。随机采样类内图片进行通道叠加然后输出融合图像,学通过梯度下降使得输出图像的类内差距减小(没考虑类间关系,可能也不便处理)。

  • AutoAugment
    谷歌最早做的自学习增强方法,走的NAS的思路RL+RNN搜索增强空间,还有后来最近发的检测增强也是大同小异,基本就是换汤不换药,问题在于搜索空间太大,复现搜索过于依赖硬件条件(普通实验室玩不起
  1. Design considerations for image Data Augmentation

3.1 Test-time augmentation
  许多都论文指出在检测阶段进行同等的数据增强能够获得较好的效果。归结可以认为是训练检测阶段的一致性。当然,这种手段时间成本太高,只在如医学影像等追求精度的关键领域可以使用。

3.2 Curriculum learning
  Bengio团队早年在ICML提出的观点,确实合理,一开始就进行大量的增强容易导致网络不收敛。
从一个数据集学习到的数据增强也可以迁移到其他数据集。

3.3 Resolution impact
高清(1920×1080×3)或4K(3840×2160×3)等高分辨率图像需要更多的处理和内存来训练深度CNN。然而下一代模型更倾向于使用这样更高分辨率的图像。因为模型中常用的下采样会造成图像中信息的丢失,使图像识别更困难。
研究人员发现,高分辨率图像和低分辨率图像一起训练的模型集合,比单独的任何一个模型都要好。
某个实验(这里就不注明引用了)在256×256图像和512×512图像上训练的模型分别获得7.96%和7.42%的top-5 error。汇总后,他们的top-5 error变低,为6.97%。
随着超分辨率网络的发展,将图像放大到更高的分辨率后训练模型,能够得到更好更健壮的图像分类器。

3.4 Final dataset size
  数据增强的形式可以分为在线和离线增强。前者是在加载数据时增强,可能造成额外的内存消耗(现在都是数据容量不变的随机增强)。
  此外作者提到了一个比较有意思的点:当前数据集尤其是进行增广后是十分庞大的,明显能够在一定程度上缩小数据集但是保持性能下降不多的子集效率会高得多。

3.5 Alleviating class imbalance with Data Augmentation
  这也是值得借鉴的一点。通过增强在一定程度上解决类别不平衡问题。但增强需要仔细设计,否则会面对已经学习较好的类别或者场景造成过拟合等问题。

8.5.2 OHEM

8.5.3 NMS:Soft NMS/ Polygon NMS/ Inclined NMS/ ConvNMS/ Yes-Net NMS/ Softer NMS

8.5.4 Multi Scale Training/Testing

8.5.5 建立小物体与context的关系

8.5.6 参考relation network

8.5.7 结合GAN

8.5.8 结合attention

8.5.9 训练tricks(贡献者:北京理工大学—明奇)

介绍一篇2019.2.4亚马逊挂在ArXiv的目标检测训练tricks的文章(之前亚马逊发了篇分类的tricks在CVPR上)

  1. Introduction

  上次亚马逊发了个分类的训练trick在CVPR上,这次是检测的,还没发表。就没什么多说的了,下面直接介绍。先看效果如下,其实摘要声称的5%是单阶段的yolov3的提升,说明:单阶段没有RoIPooling阶段很多性质确实不如两阶段,因此采用trick很有必要;相反,两阶段本身结构优于单阶段所以外加的trick提供的如不变性等网络自身能够学习和适应就不起作用了。

  1. Bag of Freebies

  提出了一种基于mixup的视觉联系图像混合方法,以及一些数据处理和训练策略。

2.1 Visually Coherent Image Mixup for Object Detection
  先介绍图像分类中的mixup方法,作用是提供了训练的正则化,应用到图像上如下图,将图像作简单的像素值输入mixup的凸函数中得到合成图;然后将one-hot编码类似处理得到新的label。

  技术细节:

  • 相比于分类的resize,为了保证检测图像不畸变影响效果,作者选择直接叠加,取最大的宽高,空白进行灰度填充,不进行缩放。
  • 选择ab较大(如1.5,1.5)的Beta分布作为系数来混合图像,作者说是相干性视觉图像的更强;loss是两张图像物体的loss之和,loss计算权重分别是beta分布的系数

2.2 Classification Head Label Smoothing
  标签平滑在检测的分类任务常有用到,最早是Inceptionv2中提出。
  如果标签中有的是错的,或者不准,会导致网络过分信任标签而一起错下去。为了提高网络泛化能力,避免这种错误,在one-hot的label进行计算loss时,真实类别位置乘以一个系数(1-e),e很小如0.05,以0.95的概率送进去;非标注的类别原来为0,现在改为e=0.05送进去计算loss。网络的优化方向不变,但是相比0-1label会更加平滑。
(标签平滑这个讲的不错:https://juejin.im/post/5a29fd4051882534af25dc92)

  这里进一步改进了一下label smooth的公式而已,在原来基础上除了个类别数。

2.3 Data Preprocessing
  就是数据增强,没什么其他的。至于分类也是几何变换和色彩变换。这么分区别其实是是否变换label。但是将真实世界就这么简单地分解过于粗糙了。好不容易谷歌的增强考虑到了如何学习一下检测任务的增强,但是也只是加了bbox_only的增强,就效果而言,一般;而且就实际来说,合理性和有效性有待商榷。
  作者认为,两阶段网络的RPN生成就是对输入的任意裁剪,所以这个增强就够了;这老哥膨胀了,two-stage就不用裁剪的增强,虽然两阶段能提供一些不变性,但是用了一般来说都是更好的。

2.4 Training Schedule Revamping
训练策略上:余弦学习率调整+warmup

2.5 Synchronized Batch Normalization
跨多卡同步正则化,土豪专区,穷人退避

2.6 Random shapes training for single-stage object detection networks
多尺度训练,每经过一定的iteration更换一种尺度。举例是yolov3的尺度范围。

8.6 目标检测的常用数据集

8.6.1 PASCAL VOC

​ VOC数据集是目标检测经常用的一个数据集,自2005年起每年举办一次比赛,最开始只有4类,到2007年扩充为20个类,共有两个常用的版本:2007和2012。学术界常用5k的train/val 2007和16k的train/val 2012作为训练集,test 2007作为测试集,用10k的train/val 2007+test 2007和16k的train/val 2012作为训练集,test2012作为测试集,分别汇报结果。

8.6.2 MS COCO

​ COCO数据集是微软团队发布的一个可以用来图像recognition+segmentation+captioning 数据集,该数据集收集了大量包含常见物体的日常场景图片,并提供像素级的实例标注以更精确地评估检测和分割算法的效果,致力于推动场景理解的研究进展。依托这一数据集,每年举办一次比赛,现已涵盖检测、分割、关键点识别、注释等机器视觉的中心任务,是继ImageNet Chanllenge以来最有影响力的学术竞赛之一。

相比ImageNet,COCO更加偏好目标与其场景共同出现的图片,即non-iconic images。这样的图片能够反映视觉上的语义,更符合图像理解的任务要求。而相对的iconic images则更适合浅语义的图像分类等任务。

​ COCO的检测任务共含有80个类,在2014年发布的数据规模分train/val/test分别为80k/40k/40k,学术界较为通用的划分是使用train和35k的val子集作为训练集(trainval35k),使用剩余的val作为测试集(minival),同时向官方的evaluation server提交结果(test-dev)。除此之外,COCO官方也保留一部分test数据作为比赛的评测集。

8.6.3 Google Open Image

​ Open Image是谷歌团队发布的数据集。最新发布的Open Images V4包含190万图像、600个种类,1540万个bounding-box标注,是当前最大的带物体位置标注信息的数据集。这些边界框大部分都是由专业注释人员手动绘制的,确保了它们的准确性和一致性。另外,这些图像是非常多样化的,并且通常包含有多个对象的复杂场景(平均每个图像 8 个)。

8.6.4 ImageNet

​ ImageNet是一个计算机视觉系统识别项目, 是目前世界上图像识别最大的数据库。ImageNet是美国斯坦福的计算机科学家,模拟人类的识别系统建立的。能够从图片识别物体。Imagenet数据集文档详细,有专门的团队维护,使用非常方便,在计算机视觉领域研究论文中应用非常广,几乎成为了目前深度学习图像领域算法性能检验的“标准”数据集。Imagenet数据集有1400多万幅图片,涵盖2万多个类别;其中有超过百万的图片有明确的类别标注和图像中物体位置的标注。

8.6.5 DOTA

​ DOTA是遥感航空图像检测的常用数据集,包含2806张航空图像,尺寸大约为4kx4k,包含15个类别共计188282个实例,其中14个主类,small vehicle 和 large vehicle都是vehicle的子类。其标注方式为四点确定的任意形状和方向的四边形。航空图像区别于传统数据集,有其自己的特点,如:尺度变化性更大;密集的小物体检测;检测目标的不确定性。数据划分为1/6验证集,1/3测试集,1/2训练集。目前发布了训练集和验证集,图像尺寸从800x800到4000x4000不等。

8.7 目标检测常用标注工具

8.7.1 LabelImg

​ LabelImg 是一款开源的图像标注工具,标签可用于分类和目标检测,它是用 Python 编写的,并使用Qt作为其图形界面,简单好用。注释以 PASCAL VOC 格式保存为 XML 文件,这是 ImageNet 使用的格式。 此外,它还支持 COCO 数据集格式。

8.7.2 labelme

​ labelme 是一款开源的图像/视频标注工具,标签可用于目标检测、分割和分类。灵感是来自于 MIT 开源的一款标注工具 LabelMe。labelme 具有的特点是:

  • 支持图像的标注的组件有:矩形框,多边形,圆,线,点(rectangle, polygons, circle, lines, points)
  • 支持视频标注
  • GUI 自定义
  • 支持导出 VOC 格式用于 semantic/instance segmentation
  • 支出导出 COCO 格式用于 instance segmentation

8.7.3 Labelbox

​ Labelbox 是一家为机器学习应用程序创建、管理和维护数据集的服务提供商,其中包含一款部分免费的数据标签工具,包含图像分类和分割,文本,音频和视频注释的接口,其中图像视频标注具有的功能如下:

  • 可用于标注的组件有:矩形框,多边形,线,点,画笔,超像素等(bounding box, polygons, lines, points,brush, subpixels)
  • 标签可用于分类,分割,目标检测等
  • 以 JSON / CSV / WKT / COCO / Pascal VOC 等格式导出数据
  • 支持 Tiled Imagery (Maps)
  • 支持视频标注 (快要更新)

8.7.4 RectLabel

​ RectLabel 是一款在线免费图像标注工具,标签可用于目标检测、分割和分类。具有的功能或特点:

  • 可用的组件:矩形框,多边形,三次贝塞尔曲线,直线和点,画笔,超像素
  • 可只标记整张图像而不绘制
  • 可使用画笔和超像素
  • 导出为YOLO,KITTI,COCO JSON和CSV格式
  • 以PASCAL VOC XML格式读写
  • 使用Core ML模型自动标记图像
  • 将视频转换为图像帧

8.7.5 CVAT

​ CVAT 是一款开源的基于网络的交互式视频/图像标注工具,是对加州视频标注工具(Video Annotation Tool) 项目的重新设计和实现。OpenCV团队正在使用该工具来标注不同属性的数百万个对象,许多 UI 和 UX 的决策都基于专业数据标注团队的反馈。具有的功能

  • 关键帧之间的边界框插值
  • 自动标注(使用TensorFlow OD API 和 Intel OpenVINO IR格式的深度学习模型)

8.7.6 VIA

​ VGG Image Annotator(VIA)是一款简单独立的手动注释软件,适用于图像,音频和视频。 VIA 在 Web 浏览器中运行,不需要任何安装或设置。 页面可在大多数现代Web浏览器中作为离线应用程序运行。

  • 支持标注的区域组件有:矩形,圆形,椭圆形,多边形,点和折线

8.7.6 其他标注工具

​ liblabel,一个用 MATLAB 写的轻量级 语义/示例(semantic/instance) 标注工具。
ImageTagger:一个开源的图像标注平台。
Anno-Mage:一个利用深度学习模型半自动图像标注工具,预训练模型是基于MS COCO数据集,用 RetinaNet 训练的。

</br>
​ 当然还有一些数据标注公司,可能包含更多标注功能,例如对三维目标检测的标注(3D Bounding box Labelling),激光雷达点云的标注(LIDAR 3D Point Cloud Labeling)等。

8.8 目标检测工具和框架(贡献者:北京理工大学—明奇)

各种不同的算法虽然部分官方会有公布代码,或者github上有人复现,但是囿于安装环境不一,实现的框架(pytorch、C++、Caffee、tensorflow、MXNet等)不同,每次更换算法都需要重新安装环境,并且代码之间的迁移性差,十分不方便。所以为了方便将不同的算法统一在一个代码库中,不同的大厂都提出了自己的解决方案。如facebook的Detectron、商汤科技的mmdetection、SimpleDet等。其中Detectron最早,所以用户量最大,其次是国内近段时间崛起的mmdetection,下面介绍该目标检测工具箱。

  1. Introduction
    MMdetection的特点:
  • 模块化设计:将不同网络的部分进行切割,模块之间具有很高的复用性和独立性(十分便利,可以任意组合)
  • 高效的内存使用
  • SOTA
  1. Support Frameworks
  • 单阶段检测器
    SSD、RetinaNet、FCOS、FSAF

  • 两阶段检测器
    Faster R-CNN、R-FCN、Mask R-CNN、Mask Scoring R-CNN、Grid R-CNN

  • 多阶段检测器
    Cascade R-CNN、Hybrid Task Cascade

  • 通用模块和方法
    soft-NMS、DCN、OHEN、Train from Scratch 、M2Det 、GN 、HRNet 、Libra R-CNN

  1. Architecture

模型表征:划分为以下几个模块:
Backbone(ResNet等)、Neck(FPN)、DenseHead(AnchorHead)、RoIExtractor、RoIHead(BBoxHead/MaskHead)
结构图如下:

  1. Notice
  • 1x代表12epoch的COCO训练,2x类似推导
  • 由于batch-size一般比较小(1/2这样的量级),所以大多数地方默认冻结BN层。可以使用GN代替。
  1. 参考链接
    mmdetection代码高度模块化,十分好用和便利,更详细的文档直接参见官方文档:
    https://github.com/open-mmlab/mmdetection

注释版的mmdetection代码(更新至v1.0.0):https://github.com/ming71/mmdetection-annotated

使用方法简介:
安装记录(可能过时,以官方文档为准):https://ming71.github.io/mmdetection-memo.html
使用方法(截止更新日期,如果过时以官方为准):https://ming71.github.io/mmdetection-instruction.html

TODO

  • [ ] 目标检测基础知识:mAP、IoU和NMS等
  • [ ] 目标检测评测指标
  • [ ] 目标检测常见标注工具
  • [ ] 完善目标检测的技巧汇总
  • [ ] 目标检测的现在难点和未来发展

参考文献

https://github.com/amusi/awesome-object-detection

https://github.com/hoya012/deep_learning_object_detection

https://handong1587.github.io/deep_learning/2015/10/09/object-detection.html

https://www.zhihu.com/question/272322209/answer/482922713

http://blog.leanote.com/post/afanti.deng@gmail.com/b5f4f526490b

https://blog.csdn.net/hw5226349/article/details/78987385

[1] Girshick R, Donahue J, Darrell T, et al. Rich feature hierarchies for accurate object detection and semantic segmentation[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2014: 580-587.

[2] Girshick R. Fast r-cnn[C]//Proceedings of the IEEE international conference on computer vision. 2015: 1440-1448.

[3] He K, Zhang X, Ren S, et al. Spatial pyramid pooling in deep convolutional networks for visual recognition[J]. IEEE transactions on pattern analysis and machine intelligence, 2015, 37(9): 1904-1916.

[4] Ren S, He K, Girshick R, et al. Faster r-cnn: Towards real-time object detection with region proposal networks[C]//Advances in neural information processing systems. 2015: 91-99.

[5] Lin T Y, Dollár P, Girshick R, et al. Feature pyramid networks for object detection[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2017: 2117-2125.

[6] He K, Gkioxari G, Dollár P, et al. Mask r-cnn[C]//Proceedings of the IEEE international conference on computer vision. 2017: 2961-2969.

[7] Liu W, Anguelov D, Erhan D, et al. Ssd: Single shot multibox detector[C]//European conference on computer vision. Springer, Cham, 2016: 21-37.

[8] Fu C Y, Liu W, Ranga A, et al. Dssd: Deconvolutional single shot detector[J]. arXiv preprint arXiv:1701.06659, 2017.

[9] Redmon J, Divvala S, Girshick R, et al. You only look once: Unified, real-time object detection[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2016: 779-788.

[10] Redmon J, Farhadi A. YOLO9000: better, faster, stronger[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2017: 7263-7271.

[11] Redmon J, Farhadi A. Yolov3: An incremental improvement[J]. arXiv preprint arXiv:1804.02767, 2018.

[12] Lin T Y, Goyal P, Girshick R, et al. Focal loss for dense object detection[C]//Proceedings of the IEEE international conference on computer vision. 2017: 2980-2988.

[13] Liu S, Huang D. Receptive field block net for accurate and fast object detection[C]//Proceedings of the European Conference on Computer Vision (ECCV). 2018: 385-400.

[14] Zhao Q, Sheng T, Wang Y, et al. M2Det: A Single-Shot Object Detector based on Multi-Level Feature Pyramid Network[J]. arXiv preprint arXiv:1811.04533, 2018.

[TOC]

第九章 图像分割

9.1 图像分割算法分类?

图像分割是预测图像中每一个像素所属的类别或者物体。基于深度学习的图像分割算法主要分为两类:

1.语义分割

为图像中的每个像素分配一个类别,如把画面中的所有物体都指出它们各自的类别。

2.实例分割

与语义分割不同,实例分割只对特定物体进行类别分配,这一点与目标检测有点相似,但目标检测输出的是边界框和类别,而实例分割输出的是掩膜(mask)和类别。

9.2 传统的基于CNN的分割方法缺点?

传统的基于CNN的分割方法:为了对一个像素分类,使用该像素周围的一个图像块作为CNN的输入,用于训练与预测,这种方法主要有几个缺点:
1)存储开销大,例如,对每个像素使用15 * 15的图像块,然后不断滑动窗口,将图像块输入到CNN中进行类别判断,因此,需要的存储空间随滑动窗口的次数和大小急剧上升;
2)效率低下,相邻像素块基本上是重复的,针对每个像素块逐个计算卷积,这种计算有很大程度上的重复;
3)像素块的大小限制了感受区域的大小,通常像素块的大小比整幅图像的大小小很多,只能提取一些局部特征,从而导致分类性能受到限制。
而全卷积网络(FCN)则是从抽象的特征中恢复出每个像素所属的类别。即从图像级别的分类进一步延伸到像素级别的分类。

9.3 FCN

9.3.1 FCN改变了什么?

​ 对于一般的分类CNN网络,如VGG和Resnet,都会在网络的最后加入一些全连接层,经过softmax后就可以获得类别概率信息。但是这个概率信息是1维的,即只能标识整个图片的类别,不能标识每个像素点的类别,所以这种全连接方法不适用于图像分割。
​ 而FCN提出可以把后面几个全连接都换成卷积,这样就可以获得一张2维的feature map,后接softmax层获得每个像素点的分类信息,从而解决了分割问题,如图4。

图 4

9.3.2 FCN网络结构?

​ FCN对图像进行像素级的分类,从而解决了语义级别的图像分割(semantic segmentation)问题。与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类(全联接层+softmax输出)不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸,从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。
​ 下图是语义分割所采用的全卷积网络(FCN)的结构示意图:

9.3.3 全卷积网络举例?

​ 通常CNN网络在卷积层之后会接上若干个全连接层, 将卷积层产生的特征图(feature map)映射成一个固定长度的特征向量。以AlexNet为代表的经典CNN结构适合于图像级的分类和回归任务,因为它们最后都得到整个输入图像的一个概率向量。

  
如上图所示:
  
(1)在CNN中, 猫的图片输入到AlexNet, 得到一个长为1000的输出向量, 表示输入图像属于每一类的概率, 其中在“tabby cat”这一类统计概率最高, 用来做分类任务。
  
(2)FCN与CNN的区别在于把CNN最后的全连接层转换成卷积层,输出的是一张已经带有标签的图片, 而这个图片就可以做语义分割。
  
(3)CNN的强大之处在于它的多层结构能自动学习特征,并且可以学习到多个层次的特征: 较浅的卷积层感知域较小,学习到一些局部区域的特征;较深的卷积层具有较大的感知域,能够学习到更加抽象一些的特征。高层的抽象特征对物体的大小、位置和方向等敏感性更低,从而有助于识别性能的提高, 所以我们常常可以将卷积层看作是特征提取器。

9.2.4 全连接层和卷积层如何相互转化?

  
两者相互转换的可能性:
  
全连接层和卷积层之间唯一的不同就是卷积层中的神经元只与输入数据中的一个局部区域连接,并且在卷积列中的神经元共享参数。然而在两类层中,神经元都是计算点积,所以它们的函数形式是一样的。因此,将此两者相互转化是可能的:
  
(1)对于任一个卷积层,都存在一个能实现和它一样的前向传播函数的全连接层。权重矩阵是一个巨大的矩阵,除了某些特定块,其余部分都是零。而在其中大部分块中,元素都是相等的。
  
(2)任何全连接层都可以被转化为卷积层。比如VGG16中第一个全连接层是25088 4096的数据尺寸,将它转化为512 7 7 4096的数据尺寸,即一个K=4096的全连接层,输入数据体的尺寸是7 7 512,这个全连接层可以被等效地看做一个F=7, P=0, S=1, K=4096 的卷积层。换句话说,就是将滤波器的尺寸设置为和输入数据体的尺寸一致7 7, 这样输出就变为1 1 4096, 本质上和全连接层的输出是一样的。
  
*输出激活数据体深度是由卷积核的数目决定的(K=4096)。

  
在两种变换中,将全连接层转化为卷积层在实际运用中更加有用。假设一个卷积神经网络的输入是227x227x3的图像,一系列的卷积层和下采样层将图像数据变为尺寸为7x7x512的激活数据体, AlexNet的处理方式为使用了两个尺寸为4096的全连接层,最后一个有1000个神经元的全连接层用于计算分类评分。我们可以将这3个全连接层中的任意一个转化为卷积层:
  
(1)第一个连接区域是[7x7x512]的全连接层,令其滤波器尺寸为F=7,K=4096,这样输出数据体就为[1x1x4096]。
  
(2)第二个全连接层,令其滤波器尺寸为F=1,K=4096,这样输出数据体为[1x1x4096]。
  
(3)最后一个全连接层也做类似的,令其F=1,K=1000,最终输出为[1x1x1000]。

9.2.5 为什么传统CNN的输入图片是固定大小?

  
对于CNN,一幅输入图片在经过卷积和pooling层时,这些层是不关心图片大小的。比如对于一个卷积层,outputsize = (inputsize - kernelsize) / stride + 1,它并不关心inputsize多大,对于一个inputsize大小的输入feature map,滑窗卷积,输出outputsize大小的feature map即可。pooling层同理。但是在进入全连接层时,feature map(假设大小为n×n)要拉成一条向量,而向量中每个元素(共n×n个)作为一个结点都要与下一个层的所有结点(假设4096个)全连接,这里的权值个数是4096×n×n,而我们知道神经网络结构一旦确定,它的权值个数都是固定的,所以这个n不能变化,n是conv5的outputsize,所以层层向回看,每个outputsize都要固定,那每个inputsize都要固定,因此输入图片大小要固定。

9.2.6 把全连接层的权重W重塑成卷积层的滤波器有什么好处?

  
这样的转化可以在单个向前传播的过程中, 使得卷积网络在一张更大的输入图片上滑动,从而得到多个输出(可以理解为一个label map)。
  
比如: 我们想让224×224尺寸的浮窗,以步长为32在384×384的图片上滑动,把每个经停的位置都带入卷积网络,最后得到6×6个位置的类别得分, 那么通过将全连接层转化为卷积层之后的运算过程为:
  
如果224×224的输入图片经过卷积层和下采样层之后得到了[7x7x512]的数组,那么,384×384的大图片直接经过同样的卷积层和下采样层之后会得到[12x12x512]的数组, 然后再经过上面由3个全连接层转化得到的3个卷积层,最终得到[6x6x1000]的输出((12 – 7)/1 + 1 = 6), 这个结果正是浮窗在原图经停的6×6个位置的得分。
  
一个确定的CNN网络结构之所以要固定输入图片大小,是因为全连接层权值数固定,而该权值数和feature map大小有关, 但是FCN在CNN的基础上把1000个结点的全连接层改为含有1000个1×1卷积核的卷积层,经过这一层,还是得到二维的feature map,同样我们也不关心这个feature map大小, 所以对于输入图片的size并没有限制。
  
如下图所示,FCN将传统CNN中的全连接层转化成卷积层,对应CNN网络FCN把最后三层全连接层转换成为三层卷积层:

一个分类网络

变为全卷积网络

End-to-end, pixels-to pixels网络

(1)全连接层转化为全卷积层 : 在传统的CNN结构中,前5层是卷积层,第6层和第7层分别是一个长度为4096的一维向量,第8层是长度为1000的一维向量,分别对应1000个不同类别的概率。FCN将这3层表示为卷积层,卷积核的大小 (通道数,宽,高) 分别为 (4096,1,1)、(4096,1,1)、(1000,1,1)。看上去数字上并没有什么差别,但是卷积跟全连接是不一样的概念和计算过程,使用的是之前CNN已经训练好的权值和偏置,但是不一样的在于权值和偏置是有自己的范围,属于自己的一个卷积核。
  
(2)CNN中输入的图像大小是统一固定成227x227大小的图像,第一层pooling后为55x55,第二层pooling后图像大小为27x27,第五层pooling后的图像大小为13x13, 而FCN输入的图像是H W大小,第一层pooling后变为原图大小的1/2,第二层变为原图大小的1/4,第五层变为原图大小的1/8,第八层变为原图大小的1/16。
  
(3)经过多次卷积和pooling以后,得到的图像越来越小,分辨率越来越低。其中图像到H/32
W/32的时候图片是最小的一层时,所产生图叫做heatmap热图,热图就是我们最重要的高维特征图,得到高维特征的heatmap之后就是最重要的一步也是最后的一步对原图像进行upsampling,把图像进行放大几次到原图像的大小。
  
相较于使用被转化前的原始卷积神经网络对所有36个位置进行迭代计算优化模型,然后再对36个位置做预测,使用转化后的卷积神经网络进行一次前向传播计算要高效得多,因为36次计算都在共享计算资源。这一技巧在实践中经常使用,通常将一张图像尺寸变得更大,然后使用变换后的卷积神经网络来对空间上很多不同位置进行评价得到分类评分,然后在求这些分值的平均值。

9.2.7 反卷积层理解

  
Upsampling的操作可以看成是反卷积(deconvolutional),卷积运算的参数和CNN的参数一样是在训练FCN模型的过程中通过bp算法学习得到。反卷积层也是卷积层,不关心input大小,滑窗卷积后输出output。deconv并不是真正的deconvolution(卷积的逆变换),最近比较公认的叫法应该是transposed convolution,deconv的前向传播就是conv的反向传播。
  
反卷积参数: 利用卷积过程filter的转置(实际上就是水平和竖直方向上翻转filter)作为计算卷积前的特征图。
  
反卷积的运算如下所示:
  
蓝色是反卷积层的input,绿色是反卷积层的outputFull padding, transposed Full padding, transposed。

上图中的反卷积,input是2×2, output是4×4。 Zero padding, non-unit strides, transposed。

上图中的反卷积,input feature map是3×3, 转化后是5×5, output是5×5

9.2.8 跳级(skip)结构

  
对CNN的结果做处理,得到了dense prediction,而作者在试验中发现,得到的分割结果比较粗糙,所以考虑加入更多前层的细节信息,也就是把倒数第几层的输出和最后的输出做一个fusion,实际上也就是加和:


  
实验表明,这样的分割结果更细致更准确。在逐层fusion的过程中,做到第三行再往下,结果又会变差,所以作者做到这里就停了。

9.2.9 模型训练

  
(1)用AlexNet,VGG16或者GoogleNet训练好的模型做初始化,在这个基础上做fine-tuning,全部都fine-tuning,只需在末尾加上upsampling,参数的学习还是利用CNN本身的反向传播原理。
  
(2)采用whole image做训练,不进行patchwise sampling。实验证明直接用全图已经很effective and efficient。
  
(3)对class score的卷积层做全零初始化。随机初始化在性能和收敛上没有优势。
举例:
  
FCN例子: 输入可为任意尺寸图像彩色图像;输出与输入尺寸相同,深度为:20类目标+背景=21,模型基于AlexNet。
  
蓝色:卷积层。
  
绿色:Max Pooling层。
  
黄色: 求和运算, 使用逐数据相加,把三个不同深度的预测结果进行融合:较浅的结果更为精细,较深的结果更为鲁棒。
  
灰色: 裁剪, 在融合之前,使用裁剪层统一两者大小, 最后裁剪成和输入相同尺寸输出。
  
对于不同尺寸的输入图像,各层数据的尺寸(height,width)相应变化,深度(channel)不变。


  
(1)全卷积层部分进行特征提取, 提取卷积层(3个蓝色层)的输出来作为预测21个类别的特征。

  
(2)图中虚线内是反卷积层的运算, 反卷积层(3个橙色层)可以把输入数据尺寸放大。和卷积层一样,升采样的具体参数经过训练确定。

    
1) 以经典的AlexNet分类网络为初始化。最后两级是全连接(红色),参数弃去不用。


    
2) 从特征小图()预测分割小图(),之后直接升采样为大图。

反卷积(橙色)的步长为32,这个网络称为FCN-32s

    
3) 升采样分为两次完成(橙色×2), 在第二次升采样前,把第4个pooling层(绿色)的预测结果(蓝色)融合进来。使用跳级结构提升精确性。

第二次反卷积步长为16,这个网络称为FCN-16s

    
4) 升采样分为三次完成(橙色×3), 进一步融合了第3个pooling层的预测结果。

第三次反卷积步长为8,记为FCN-8s

其他参数:
  
minibatch:20张图片。
  
learning rate:0.001。
  
初始化:分类网络之外的卷积层参数初始化为0。
  
反卷积参数初始化为bilinear插值。
  
最后一层反卷积固定位bilinear插值不做学习。

9.2.10 FCN缺点

  
(1)得到的结果还是不够精细。进行8倍上采样虽然比32倍的效果好了很多,但是上采样的结果还是比较模糊和平滑,对图像中的细节不敏感。
  
(2)对各个像素进行分类,没有充分考虑像素与像素之间的关系。忽略了在通常的基于像素分类的分割方法中使用的空间规整(spatial regularization)步骤,缺乏空间一致性。

9.3 U-Net

  
卷积网络被大规模应用在分类任务中,输出的结果是整个图像的类标签。然而,在许多视觉任务,尤其是生物医学图像处理领域,目标输出应该包括目标类别的位置,并且每个像素都应该有类标签。另外,在生物医学图像往往缺少训练图片。所以,Ciresan等人训练了一个卷积神经网络,用滑动窗口提供像素的周围区域(patch)作为输入来预测每个像素的类标签。这个网络有两个优点:
第一,输出结果可以定位出目标类别的位置;
第二,由于输入的训练数据是patches,这样就相当于进行了数据增广,解决了生物医学图像数量少的问题。
  
但是,这个方法也有两个很明显缺点。
  
第一,它很慢,因为这个网络必须训练每个patch,并且因为patch间的重叠有很多的冗余(冗余会造成什么影响呢?卷积核里面的W,就是提取特征的权重,两个块如果重叠的部分太多,这个权重会被同一些特征训练两次,造成资源的浪费,减慢训练时间和效率,虽然说会有一些冗余,训练集大了,准确率不就高了吗?可是你这个是相同的图片啊,重叠的东西都是相同的,举个例子,我用一张相同的图片训练20次,按照这个意思也是增大了训练集啊,可是会出现什么结果呢,很显然,会导致过拟合,也就是对你这个图片识别很准,别的图片就不一定了)。
  
第二,定位准确性和获取上下文信息不可兼得。大的patches需要更多的max-pooling层这样减小了定位准确性(为什么?因为你是对以这个像素为中心的点进行分类,如果patch太大,最后经过全连接层的前一层大小肯定是不变的,如果你patch大就需要更多的pooling达到这个大小,而pooling层越多,丢失信息的信息也越多;小的patches只能看到很小的局部信息,包含的背景信息不够。
  
这篇论文建立了一个更好全卷积方法。我们定义和扩展了这个方法它使用更少的训练图片但产生更精确的分割。

  
(1) 使用全卷积神经网络。(全卷积神经网络就是卷积取代了全连接层,全连接层必须固定图像大小而卷积不用,所以这个策略使得,你可以输入任意尺寸的图片,而且输出也是图片,所以这是一个端到端的网络。)
  
(2) 左边的网络是收缩路径:使用卷积和maxpooling。
  
(3) 右边的网络是扩张路径:使用上采样产生的特征图与左侧收缩路径对应层产生的特征图进行concatenate操作。(pooling层会丢失图像信息和降低图像分辨率且是不可逆的操作,对图像分割任务有一些影响,对图像分类任务的影响不大,为什么要做上采样?因为上采样可以补足一些图片的信息,但是信息补充的肯定不完全,所以还需要与左边的分辨率比较高的图片相连接起来(直接复制过来再裁剪到与上采样图片一样大小),这就相当于在高分辨率和更抽象特征当中做一个折衷,因为随着卷积次数增多,提取的特征也更加有效,更加抽象,上采样的图片是经历多次卷积后的图片,肯定是比较高效和抽象的图片,然后把它与左边不怎么抽象但更高分辨率的特征图片进行连接)。
  
(4) 最后再经过两次反卷积操作,生成特征图,再用两个1X1的卷积做分类得到最后的两张heatmap,例如第一张表示的是第一类的得分,第二张表示第二类的得分heatmap,然后作为softmax函数的输入,算出概率比较大的softmax类,选择它作为输入给交叉熵进行反向传播训练。

下面是U-Net模型的代码实现:(贡献者:黄钦建-华南理工大学)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def get_unet():
inputs = Input((img_rows, img_cols, 1))
conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
# pool1 = Dropout(0.25)(pool1)
# pool1 = BatchNormalization()(pool1)

conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)
conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
# pool2 = Dropout(0.5)(pool2)
# pool2 = BatchNormalization()(pool2)

conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)
conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
# pool3 = Dropout(0.5)(pool3)
# pool3 = BatchNormalization()(pool3)

conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)
conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)
# pool4 = Dropout(0.5)(pool4)
# pool4 = BatchNormalization()(pool4)

conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(pool4)
conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)

up6 = concatenate([Conv2DTranspose(256, (2, 2), strides=(
2, 2), padding='same')(conv5), conv4], axis=3)
# up6 = Dropout(0.5)(up6)
# up6 = BatchNormalization()(up6)
conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)

up7 = concatenate([Conv2DTranspose(128, (2, 2), strides=(
2, 2), padding='same')(conv6), conv3], axis=3)
# up7 = Dropout(0.5)(up7)
# up7 = BatchNormalization()(up7)
conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)

up8 = concatenate([Conv2DTranspose(64, (2, 2), strides=(
2, 2), padding='same')(conv7), conv2], axis=3)
# up8 = Dropout(0.5)(up8)
# up8 = BatchNormalization()(up8)
conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)

up9 = concatenate([Conv2DTranspose(32, (2, 2), strides=(
2, 2), padding='same')(conv8), conv1], axis=3)
# up9 = Dropout(0.5)(up9)
# up9 = BatchNormalization()(up9)
conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)

# conv9 = Dropout(0.5)(conv9)

conv10 = Conv2D(1, (1, 1), activation='sigmoid')(conv9)

model = Model(inputs=[inputs], outputs=[conv10])

model.compile(optimizer=Adam(lr=1e-5),
loss=dice_coef_loss, metrics=[dice_coef])

return model

9.4 SegNet

  
可训练的图像分割引擎,包含一个encoder网络,一个对应的decoder网络,衔接像素级分类层,解码网络与VGG16的13层卷积层相同。解码网络是将低分辨率的编码特征图映射到全分辨率的特征图。解码网络使用最大池化层的池化索引进行非线性上采样,上采样过程就不需要学习。上采样得到的稀疏图与可训练的滤波器卷积得到致密的特征图。
  
使用池化层索引进行上采样的优势:
  
1)提升边缘刻画度;
  
2)减少训练的参数;
  
3)这种上采样模式可以包含到任何编码-解码网络中。
  
SegNet网络的结构如下图所示:

  
SegNet网络结构如图1所示,Input为输入图片,Output为输出分割的图像,不同颜色代表不同的分类。语义分割的重要性就在于不仅告诉你图片中某个东西是什么,而且告知你他在图片的位置。我们可以看到是一个对称网络,由中间绿色pooling层与红色upsampling层作为分割,左边是卷积提取高维特征,并通过pooling使图片变小,SegNet作者称为Encoder,右边是反卷积(在这里反卷积与卷积没有区别)与upsampling,通过反卷积使得图像分类后特征得以重现,upsampling使图像变大,SegNet作者称为Decoder,最后通过Softmax,输出不同分类的最大值。这就是大致的SegNet过程,下面对这个过程里面使用到的方法进行介绍。
  
编码网络与滤波器族卷积得到特征图,进行BN,ReLU,最大池化。最大池化是为了获得空间小位移的平移不变。最大池化和下采样损失了边缘细节,因此,在编码过程中保存边缘信息很重要。考虑到内存原因,只保存最大池化索引,如最大特征值的位置。
  
SegNet解码技术如下图所示:

  
解码网络使用保存的最大池化索引上采样,得到稀疏的特征图,将特征图与可训练的解码滤波器族卷积得到致密的特征图。之后进行BN。高维的特征图输入soft-max层,对每个像素进行分类,得到每个像素属于K类的概率。 图3中右边是FCN的解码技术,FCN对编码的特征图进行降维,降维后输入到解码网络,解码网络中,上采样使用反卷积实现,上采样的特征图与降维的编码图进行element-wise add得到最终的解码特征图。FCN解码模型需要存储编码特征图,在嵌入式设备中内存紧张。
  
SegNet的Encoder过程中,卷积的作用是提取特征,SegNet使用的卷积为same卷积(详见卷积神经网络CNN(1)),即卷积后不改变图片大小;在Decoder过程中,同样使用same卷积,不过卷积的作用是为upsampling变大的图像丰富信息,使得在Pooling过程丢失的信息可以通过学习在Decoder得到。SegNet中的卷积与传统CNN的卷积并没有区别。

9.5 空洞卷积(Dilated Convolutions)

  
在图像分割领域,图像输入到CNN(典型的网络比如FCN[3])中,FCN先像传统的CNN那样对图像做卷积再pooling,降低图像尺寸的同时增大感受野,但是由于图像分割预测是pixel-wise的输出,所以要将pooling后较小的图像尺寸upsampling到原始的图像尺寸进行预测(upsampling一般采用deconv反卷积操作,deconv可参见知乎答案如何理解深度学习中的deconvolution networks?),之前的pooling操作使得每个pixel预测都能看到较大感受野信息。因此图像分割FCN中有两个关键,一个是pooling减小图像尺寸增大感受野,另一个是upsampling扩大图像尺寸。在先减小再增大尺寸的过程中,肯定有一些信息损失掉了,那么能不能设计一种新的操作,不通过pooling也能有较大的感受野看到更多的信息呢?答案就是dilated conv。
  
以前的CNN主要问题总结:
  
(1)Up-sampling / pooling layer
  
(2)内部数据结构丢失;空间层级化信息丢失。
  
(3)小物体信息无法重建 (假设有四个pooling layer 则 任何小于 2^4 = 16 pixel 的物体信息将理论上无法重建。)
  
举例如下:

Dilated Convolution with a 3 x 3 kernel and dilation rate 2

  
下面看一下dilated conv原始论文[4]中的示意图

  
(a) 图对应3x3的1-dilated conv,和普通的卷积操作一样,(b)图对应3x3的2-dilated conv,实际的卷积kernel size还是3x3,但是空洞为1,也就是对于一个7x7的图像patch,只有9个红色的点和3x3的kernel发生卷积操作,其余的点略过。也可以理解为kernel的size为7x7,但是只有图中的9个点的权重不为0,其余都为0。 可以看到虽然kernel size只有3x3,但是这个卷积的感受野已经增大到了7x7(如果考虑到这个2-dilated conv的前一层是一个1-dilated conv的话,那么每个红点就是1-dilated的卷积输出,所以感受野为3x3,所以1-dilated和2-dilated合起来就能达到7x7的conv),(c)图是4-dilated conv操作,同理跟在两个1-dilated和2-dilated conv的后面,能达到15x15的感受野。对比传统的conv操作,3层3x3的卷积加起来,stride为1的话,只能达到(kernel-1) * layer+1=7的感受野,也就是和层数layer成线性关系,而dilated conv的感受野是指数级的增长。
  
dilated的好处是不做pooling损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。在图像需要全局信息或者语音文本需要较长的sequence信息依赖的问题中,都能很好的应用dilated conv,比如图像分割、语音合成WaveNet、机器翻译ByteNet中。

9.6 RefineNet

  
网络结构:
  
RefineNet block的作用就是把不同resolution level的feature map进行融合。网络结构如下:


  
最左边一栏就是FCN的encoder部分(文中是用的ResNet),先把pretrained ResNet按feature map的分辨率分成四个ResNet blocks,然后向右把四个blocks分别作为4个path通过RefineNet block进行融合refine,最后得到一个refined feature map(接softmax再双线性插值输出)。
注意除了RefineNet-4,所有的RefineNet block都是二输入的,用于融合不同level做refine,而单输入的RefineNet-4可以看作是先对ResNet的一个task adaptation。

  
RefineNet Block
  
接下来仔细看一下RefineNet block,可以看到主要组成部分是Residual convolution unit, Multi-resolution fusion, Chained residual pooling, Output convolutions. 切记这个block作用是融合多个level的feature map输出单个level的feature map,但具体的实现应该是和输入个数、shape无关的。

  
Residual convolution unit就是普通的去除了BN的residual unit;

  
Multi-resolution fusion是先对多输入的feature map都用一个卷积层进行adaptation(都化到最小的feature map的shape),再上采样再做element-wise的相加。注意如果是像RefineNet-4那样的单输入block这一部分就直接pass了;

  
Chained residual pooling中的ReLU对接下来池化的有效性很重要,还可以使模型对学习率的变化没这么敏感。这个链式结构能从很大范围区域上获取背景context。另外,这个结构中大量使用了identity mapping这样的连接,无论长距离或者短距离的,这样的结构允许梯度从一个block直接向其他任一block传播。

  
Output convolutions就是输出前再加一个RCU。

9.7 PSPNet

  
场景解析对于无限制的开放词汇和不同场景来说是具有挑战性的.本文使用文中的pyramid pooling module实现基于不同区域的上下文集成,提出了PSPNet,实现利用上下文信息的能力进行场景解析。
  
作者认为,FCN存在的主要问题是没有采取合适的策略来用全局的信息,本文的做法就是借鉴SPPNet来设计了PSPNet解决这个问题。
  
很多State-of-the-art的场景解析框架都是基于FCN的.基于CNN的方法能够增强动态物体的理解,但是在无限制词汇和不同场景中仍然面临挑战.举个例子,如下图.


  
FCN认为右侧框中是汽车,但是实际上是船,如果参考上下文的先验知识,就会发现左边是一个船屋,进而推断是框中是船.FCN存在的主要问题就是不能利用好全局的场景线索。

  
对于尤其复杂的场景理解,之前都是采用空间金字塔池化来做的,和之前方法不同(为什么不同,需要参考一下经典的金字塔算法),本文提出了pyramid scene parsing network(PSPNet)。
  
本文的主要贡献如下:
  
(1) 提出了PSPNet在基于FCN的框架中集成困难的上下文特征
  
(2) 通过基于深度监督误差开发了针对ResNet的高效优化策略
  
(3) 构建了一个用于state-of-the-art的场景解析和语义分割的实践系统(具体是什么?)
  
通过观察FCN的结果,发现了如下问题:
  
(1) 关系不匹配(Mismatched Relationship)
  
(2) 易混淆的类别(Confusion Categories)
  
(3) 不显眼的类别(Inconspicuous Classes)
  
总结以上结果发现,以上问题部分或者全部与上下文关系和全局信息有关系,因此本文提出了PSPNet.框架如下:


  
并且加入额外的深度监督 Loss

9.8 DeepLab系列

9.8.1 DeepLabv1

  
DeepLab 是结合了深度卷积神经网络(DCNNs)和概率图模型(DenseCRFs)的方法。
  
在实验中发现 DCNNs 做语义分割时精准度不够的问题,根本原因是 DCNNs 的高级特征的平移不变性,即高层次特征映射,根源于重复的池化和下采样。
  
针对信号下采样或池化降低分辨率,DeepLab 是采用的 atrous(带孔)算法扩展感受野,获取更多的上下文信息。
  
分类器获取以对象中心的决策是需要空间变换的不变性,这天然地限制了 DCNN 的定位精度,DeepLab 采用完全连接的条件随机场(CRF)提高模型捕获细节的能力。
  
除空洞卷积和 CRFs 之外,论文使用的 tricks 还有 Multi-Scale features。其实就是 U-Net 和 FPN 的思想,在输入图像和前四个最大池化层的输出上附加了两层的 MLP,第一层是 128 个 3×3 卷积,第二层是 128 个 1×1 卷积。最终输出的特征与主干网的最后一层特征图融合,特征图增加 5×128=640 个通道。
  
实验表示多尺度有助于提升预测结果,但是效果不如 CRF 明显。
  
论文模型基于 VGG16,在 Titan GPU 上运行速度达到了 8FPS,全连接 CRF 平均推断需要 0.5s ,在 PASCAL VOC-2012 达到 71.6% IOU accuracy。

9.8.2 DeepLabv2

  
DeepLabv2 是相对于 DeepLabv1 基础上的优化。DeepLabv1 在三个方向努力解决,但是问题依然存在:特征分辨率的降低、物体存在多尺度,DCNN 的平移不变性。
  
因 DCNN 连续池化和下采样造成分辨率降低,DeepLabv2 在最后几个最大池化层中去除下采样,取而代之的是使用空洞卷积,以更高的采样密度计算特征映射。
  
物体存在多尺度的问题,DeepLabv1 中是用多个 MLP 结合多尺度特征解决,虽然可以提供系统的性能,但是增加特征计算量和存储空间。
  
论文受到 Spatial Pyramid Pooling (SPP) 的启发,提出了一个类似的结构,在给定的输入上以不同采样率的空洞卷积并行采样,相当于以多个比例捕捉图像的上下文,称为 ASPP (atrous spatial pyramid pooling) 模块。
  
DCNN 的分类不变形影响空间精度。DeepLabv2 是采样全连接的 CRF 在增强模型捕捉细节的能力。
  
论文模型基于 ResNet,在 NVidia Titan X GPU 上运行速度达到了 8FPS,全连接 CRF 平均推断需要 0.5s ,在耗时方面和 DeepLabv1 无差异,但在 PASCAL VOC-2012 达到 79.7 mIOU。

9.8.3 DeepLabv3

  
好的论文不止说明怎么做,还告诉为什么。DeepLab 延续到 DeepLabv3 系列,依然是在空洞卷积做文章,但是探讨不同结构的方向。
  
DeepLabv3 论文比较了多种捕获多尺度信息的方式:

  
1.Image Pyramid:将输入图片放缩成不同比例,分别应用在 DCNN 上,将预测结果融合得到最终输出。
  
2.Encoder-Decoder:利用 Encoder 阶段的多尺度特征,运用到 Decoder 阶段上恢复空间分辨率,代表工作有 FCN、SegNet、PSPNet 等工。
  
3.Deeper w. Atrous Convolution:在原始模型的顶端增加额外的模块,例如 DenseCRF,捕捉像素间长距离信息。
  
4.Spatial Pyramid Pooling:空间金字塔池化具有不同采样率和多种视野的卷积核,能够以多尺度捕捉对象。
  
DeepLabv1-v2 都是使用带孔卷积提取密集特征来进行语义分割。但是为了解决分割对象的多尺度问题,DeepLabv3 设计采用多比例的带孔卷积级联或并行来捕获多尺度背景。
  
此外,DeepLabv3 将修改之前提出的带孔空间金字塔池化模块,该模块用于探索多尺度卷积特征,将全局背景基于图像层次进行编码获得特征,取得 state-of-art 性能,在 PASCAL VOC-2012 达到 86.9 mIOU。

9.8.4 DeepLabv3+

  
语义分割关注的问题:
  
1、 实例对象多尺度问题。
  
2、 因为深度网络存在stride=2的层,会导致feature分辨率下降,从而导致预测精度降低,而造成的边界信息丢失问题。
  
deeplab V3新设计的aspp结构解决了问题1,deeplab v3+主要目的在于解决问题2。
  
问题2 可以使用空洞卷积替代更多的pooling层来获取分辨率更高的feature。但是feature分辨率更高会极大增加运算量。以deeplab v3使用的resnet101为例,stride=16将造成后面9层feature变大,后面9层的计算量变为原来的2*2=4倍大。stride=8则更为恐怖,后面78层的计算量都会变大很多。
  
解决方案:1、编解码器结构;2 Modified Aligned Xception

  
在deeplabv3基础上加入解码器。A是aspp结构,其中8x的上采样可以看做是一个解码器。B是编解码结构,它集合了高层和底层的特征。C就是本文采取的结构。
  
方法:
  
(1)Encoder-Decoder with Atrous Convolution

  
编码器采用deeplabv3。
  
解码器部分:先从低层级选一个feature,将低层级的feature用1 1的卷积进行通道压缩(原本为256通道,或者512通道),目的在于减少低层级的比重。作者认为编码器得到的feature具有更丰富的信息,所以编码器的feature应该有更高的比重。 这样做有利于训练。
  
再将编码器的输出上采样,使其分辨率与低层级feature一致。举个例子,如果采用resnet conv2 输出的feature,则这里要
4上采样。将两种feature连接后,再进行一次3 * 3的卷积(细化作用),然后再次上采样就得到了像素级的预测。后面的实验结果表明这种结构在 stride=16 时既有很高的精度速度又很快。stride=8相对来说只获得了一点点精度的提升,但增加了很多的计算量。
  
(2)Modified Aligned Xception
  
Xception主要采用了deepwish seperable convolution来替换原来的卷积层。简单的说就是这种结构能在更少参数更少计算量的情况下学到同样的信息。这边则是考虑将原来的resnet-101骨架网换成xception。

  
红色部分为修改
  
更多层:重复8次改为16次(基于MSRA目标检测的工作)。
  
将原来简单的pool层改成了stride为2的deepwish seperable convolution。
  
额外的RELU层和归一化操作添加在每个 3 × 3 depthwise convolution之后(原来只在1 * 1卷积之后)

9.9 Mask-R-CNN

9.9.1 Mask-RCNN 的网络结构示意图

  
其中黑色部分为原来的Faster-RCNN,红色部分为在Faster网络上的修改:
  
1)将ROI Pooling层替换成了ROIAlign;
  
2)添加并列的FCN层(Mask层);
  
先来概述一下Mask-RCNN的几个特点(来自于PaperMask R-CNN的Abstract):
  
1)在边框识别的基础上添加分支网络,用于语义Mask识别;
  
2)训练简单,相对于Faster仅增加一个小的Overhead,可以跑到5FPS;
  
3)可以方便的扩展到其他任务,比如人的姿态估计等;
  
4)不借助Trick,在每个任务上,效果优于目前所有的 single-model entries;包括 COCO 2016 的Winners。

9.9.2 RCNN行人检测框架

  
来看下后面两种RCNN方法与Mask结合的示意图:


  
图中灰色部分是原来的RCNN结合ResNet or FPN的网络,下面黑色部分为新添加的并联Mask层,这个图本身与上面的图也没有什么区别,旨在说明作者所提出的Mask RCNN方法的泛化适应能力:可以和多种RCNN框架结合,表现都不错。

9.9.3 Mask-RCNN 技术要点

  
1.技术要点1 - 强化的基础网络
  
通过ResNeXt-101+FPN用作特征提取网络,达到state-of-the-art的效果。
  
2.技术要点2 - ROIAlign
  
采用ROIAlign替代RoiPooling(改进池化操作)。引入了一个插值过程,先通过双线性插值到1414,再pooling到77,很大程度上解决了仅通过Pooling直接采样带来的Misalignment对齐问题。
  
PS: 虽然 Misalignment 在分类问题上影响并不大,但在 Pixel 级别的 Mask 上会存在较大误差。
  
后面我们把结果对比贴出来(Table2 c & d),能够看到 ROIAlign 带来较大的改进,可以看到,Stride 越大改进越明显。
  
3.技术要点3 - Loss Function
  
每个ROIAlign对应K m^2维度的输出。K对应类别个数,即输出K个mask,m对应池化分辨率(7 7)。Loss函数定义:

  
$Lmask(Cls_k) = Sigmoid (Cls_k)$,平均二值交叉熵 (average binary cross-entropy)Loss,通过逐像素的 Sigmoid 计算得到。
  
Why K个mask?通过对每个 Class 对应一个Mask可以有效避免类间竞争(其他Class不贡献Loss)。


  
通过结果对比来看(Table2 b),也就是作者所说的 Decouple 解耦,要比多分类的Softmax效果好很多。
  
另外,作者给出了很多实验分割效果,就不都列了,只贴一张和FCIS的对比图(FCIS出现了Overlap的问题)

9.10 CNN在基于弱监督学习的图像分割中的应用

  
答案来源:CNN在基于弱监督学习的图像分割中的应用

  
最近基于深度学习的图像分割技术一般依赖于卷积神经网络CNN的训练,训练过程中需要非常大量的标记图像,即一般要求训练图像中都要有精确的分割结果。
  
对于图像分割而言,要得到大量的完整标记过的图像非常困难,比如在ImageNet数据集上,有1400万张图有类别标记,有50万张图给出了bounding box,但是只有4460张图像有像素级别的分割结果。对训练图像中的每个像素做标记非常耗时,特别是对医学图像而言,完成对一个三维的CT或者MRI图像中各组织的标记过程需要数小时。
  
如果学习算法能通过对一些初略标记过的数据集的学习就能完成好的分割结果,那么对训练数据的标记过程就很简单,这可以大大降低花在训练数据标记上的时间。这些初略标记可以是:
  
1、只给出一张图像里面包含哪些物体,
  
2、给出某个物体的边界框,
  
3、对图像中的物体区域做部分像素的标记,例如画一些线条、涂鸦等(scribbles)。

9.10.1 Scribble标记

  
论文地址:ScribbleSup: Scribble-Supervised Convolutional Networks for Semantic Segmentation (CVPR 2016)
  
香港中文大学的Di Lin提出了一个基于Scribble标记的弱监督学习方法。Scribble是一个很方便使用的标记方法,因此被用得比较广泛。如下图,只需要画五条线就能完成对一副图像的标记工作。


  
ScribbleSup分为两步,第一步将像素的类别信息从scribbles传播到其他未标记的像素,自动完成所有的训练图像的标记工作; 第二步使用这些标记图像训练CNN。在第一步中,该方法先生成super-pxels, 然后基于graph cut的方法对所有的super-pixel进行标记。

  
Graph Cut的能量函数为:

  
在这个graph中,每个super-pixel是graph中的一个节点,相接壤的super-pixel之间有一条连接的边。这个能量函数中的一元项包括两种情况,一个是来自于scribble的,一个是来自CNN对该super-pixel预测的概率。整个最优化过程实际上是求graph cut能量函数和CNN参数联合最优值的过程:

  
上式的最优化是通过交替求 $Y$ 和 $\theta$ 的最优值来实现的。文章中发现通过三次迭代就能得到比较好的结果。

9.10.2 图像级别标记

  
论文地址:Constrained Convolutional Neural Networks for Weakly Supervised Segmentation (ICCV 2015)
  
UC Berkeley的Deepak Pathak使用了一个具有图像级别标记的训练数据来做弱监督学习。训练数据中只给出图像中包含某种物体,但是没有其位置信息和所包含的像素信息。该文章的方法将image tags转化为对CNN输出的label分布的限制条件,因此称为 Constrained convolutional neural network (CCNN).


  

该方法把训练过程看作是有线性限制条件的最优化过程:

  

其中的线性限制条件来自于训练数据上的标记,例如一幅图像中前景类别像素个数期望值的上界或者下界(物体大小)、某个类别的像素个数在某图像中为0,或者至少为1等。该目标函数可以转化为为一个loss function,然后通过SGD进行训练。


  
实验中发现单纯使用Image tags作为限制条件得到的分割结果还比较差,在PASCAL VOC 2012 test数据集上得到的mIoU为35.6%,加上物体大小的限制条件后能达到45.1%,如果再使用bounding box做限制,可以达到54%。FCN-8s可以达到62.2%,可见弱监督学习要取得好的结果还是比较难。

9.10.3 DeepLab+bounding box+image-level labels**

  
论文地址:Weakly-and Semi-Supervised Learning of a DCNN for Semantic Image Segmentation
  
Google的George Papandreou 和UCLA的Liang-Chieh Chen等在DeepLab的基础上进一步研究了使用bounding box和image-level labels作为标记的训练数据。使用了期望值最大化算法(EM)来估计未标记的像素的类别和CNN的参数。


  
对于image-level标记的数据,我们可以观测到图像的像素值和图像级别的标记 ,但是不知道每个像素的标号,因此把$y$当做隐变量。使用如下的概率图模式:

  
这篇论文是通过EM算法来学习模型的参数$\theta$,具体推导过程可参考原论文。


  
对于给出bounding box标记的训练图像,该方法先使用CRF对该训练图像做自动分割,然后在分割的基础上做全监督学习。通过实验发现,单纯使用图像级别的标记得到的分割效果较差,但是使用bounding box的训练数据可以得到较好的结果,在VOC2012 test数据集上得到mIoU 62.2%。另外如果使用少量的全标记图像和大量的弱标记图像进行结合,可以得到与全监督学习(70.3%)接近的分割结果(69.0%)。

9.10.4 统一的框架

  
论文地址:Learning to Segment Under Various Forms of Weak Supervision (CVPR 2015)

  
Wisconsin-Madison大学的Jia Xu提出了一个统一的框架来处理各种不同类型的弱标记:图像级别的标记、bounding box和部分像素标记如scribbles。该方法把所有的训练图像分成共计$n$个super-pixel,对每个super-pixel提取一个$d$维特征向量。因为不知道每个super-pixel所属的类别,相当于无监督学习,因此该方法对所有的super-pixel做聚类,使用的是最大间隔聚类方法(max-margin clustering, MMC),该过程的最优化目标函数是:

  
在这个目标函数的基础上,根据不同的弱标记方式,可以给出不同的限制条件,因此该方法就是在相应的限制条件下求最大间隔聚类。

  
该方法在Siftflow数据集上得到了比较好的结果,比state-of-the-art的结果提高了10%以上。

  
小结:在弱标记的数据集上训练图像分割算法可以减少对大量全标记数据的依赖,在大多数应用中会更加贴合实际情况。弱标记可以是图像级别的标记、边框和部分像素的标记等。训练的方法一般看做是限制条件下的最优化方法。另外EM算法可以用于CNN参数和像素类别的联合求优。

9.10.5 弱监督分割最新进展(贡献者:明奇-北京理工大学)

  • bbox监督
  1. Learning to Segment via Cut-and-Paste(ECCV 2018)

    利用GAN对抗学习的思想,在cut-paste思想指导下利用bbox弱监督进行实例分割。

    采用对抗学习的思想,网络主体分为两大部分:mask生成器和合成图像判别器。具体过程为:(1)在图像上截取gt,经过特征提取后预测一个bbox内gt的mask;(2)在原图上随机cut一个背景图像,将bbox内按照生成的mask提取出物体分割结果,然后paste到原图裁剪的背景上去;(3)合成的图像经过判别器进行真假判断。
    通过生成器生成更好mask来使得判别器更难判别,在对抗学习中提升两者的性能,逐渐获得更好的结果 .

  2. Simple Does It: Weakly Supervised Instance and Semantic Segmentation(CVPR2017)
    本文做的是bbox弱监督语义/实例分割任务,能达到全监督分割效果(DeepLabv1)的95%。主要工作为:讨论了使用弱监督语义标签进行迭代训练的方法,以及其限制和不足之处;证明了通过类似GrabCut的算法能通过bbox生成分割训练标签方法的可行性,可以避免像上面的迭代方法重新调整网络训练策略;在VOC数据集上逼近监督学习的分割任务效果。
    作者的启发是:将bbox level的mask送入网络训练后得到分割mask的比输入的bbox mask要好(这是很好的insight)。因此启发的操作是:将bbox level标注作为初始mask输入优化,每次得到的标注作为gt进行下一轮的迭代,从而不断获得更好的效果。效果图如下:

    在此基础上,再加上优化的GrabCut+算法,以及部分区域的筛选,以及BSDS500的边界预测信息整合到一起,能够达到很好的弱监督迭代分割效果。

  • 分类监督
  1. Weakly Supervised Learning of Instance Segmentation with Inter-pixel Relations(CVPR2019)
    使用分类标注作为弱监督信息,在CAM提取到特征的基础上,进一步设计IRNet学习额外的特征约束,从而到达更好的弱监督实例分割效果。为了解决CAM应用到实例分割的上述局限,设计IRNet。其组成为两部分:(1)不分类别的实例响应图 (2)pairwise semantic affinitie。其中通过不分类别的实例响应图和CAM结合,约束后得到instance-wise CAMS;另一个分支预先预测物体的边界然后得到pairwise semantic affinitie(关于这个的论文参考Related Work的对应部分,有相应的方法,暂时不深究)进行融合和处理得到最终的分割。整体流程如下:

  2. Weakly Supervised Instance Segmentation using Class Peak Response(CVPR2018)
    本文使用图像级的类别标注监督信息,通过探索类别响应峰值使分类网络能够很好地提取实例分割mask。本工作是使用图像级标注进行弱监督实例分割的首个工作。
    在分类监督信息之下,CNN网络会产生一个类别响应图,每个位置是类别置信度分数。其局部极大值往往具有实例很强视觉语义线索。首先将类别峰值响应图的信息进行整合,然后反向传播将其映射到物体实例信息量较大的区域如边界。上述从类别极值响应图产生的映射图称为Peak Response Maps (PRMs),该图提供了实例物体的详细表征,可以很好地用作分割监督信息。
    具体流程如图:

    首先将图片经过正常的分类网络训练,其中在类别预测响应图上提取出局部响应极值点,进行增强卷积后预测出PRM。然后结合多种信息进行推断生成mask。

  3. Weakly Supervised Semantic Segmentation Using Superpixel Pooling Network(AAAI 2017)
    本文介绍通过类别标注的标签实现弱监督语义分割的方法。该方法在语义分割mask生成和使用生成mask学习分割生成网络之间反复交替。要实现这种交替迭代学习,关键点就是如何利用类别标注得到较准确的初始分割。为了解决这一问题,提出了Superpixel Pooling Network (SPN),将输入图像的超像素分割结果作为低阶结构的表征,辅助语义分割的推断。

    首先是SPN生成初始mask,然后用另一个网络DecoupledNet来学习每个像素的mask标注。其中,该分割网络将语义分割任务解耦为分类和分割两个子任务,并且能够从类别标注中学习形状先验知识用于辅助分割。

9.11 DenseNet(贡献者:黄钦建-华南理工大学)

  
这篇论文是CVPR2017年的最佳论文。

  
卷积神经网络结构的设计主要朝着两个方向发展,一个是更宽的网络(代表:GoogleNet、VGG),一个是更深的网络(代表:ResNet)。但是随着层数的加深会出现一个问题——梯度消失,这将会导致网络停止训练。到目前为止解决这个问题的思路基本都是在前后层之间加一个identity connections(short path)。

  
由上图中可知Resnet是做值的相加(也就是add操作),通道数是不变的。而DenseNet是做通道的合并(也就是Concatenation操作),就像Inception那样。从这两个公式就可以看出这两个网络的本质不同。此外DensetNet的前面一层输出也是后面所有层的输入,这也不同于ResNet残差网络。

  
DenseNet的Block结构如上图所示。

  
1*1卷积核的目的:减少输入的特征图数量,这样既能降维减少计算量,又能融合各个通道的特征。我们将使用BottleNeck Layers的DenseNet表示为DenseNet-B。(在论文的实验里,将1×1×n小卷积里的n设置为4k,k为每个H产生的特征图数量)

  
上图是DenseNet网络的整体网络结构示意图。其中1*1卷积核的目的是进一步压缩参数,并且在Transition Layer层有个参数Reduction(范围是0到1),表示将这些输出缩小到原来的多少倍,默认是0.5,这样传给下一个Dense Block的时候channel数量就会减少一半。当Reduction的值小于1的时候,我们就把带有这种层的网络称为DenseNet-C。

  
DenseNet网络的优点包括:

  • 减轻了梯度消失
  • 加强了feature的传递
  • 更有效地利用了feature
  • 一定程度上较少了参数数量
  • 一定程度上减轻了过拟合

9.12 图像分割的常用数据集

9.12.1 PASCAL VOC

VOC 数据集分为20类,包括背景为21类,分别如下:

  • Person: person
  • Animal: bird, cat, cow, dog, horse, sheep
  • Vehicle: aeroplane, bicycle, boat, bus, car, motorbike, train
  • Indoor: bottle, chair, dining table, potted plant, sofa, tv/monitor

VOC 数据集中用于分割比赛的图片实例如下,包含原图以及图像分类分割和图像物体分割两种图(PNG格式)。图像分类分割是在20种物体中,ground-turth图片上每个物体的轮廓填充都有一个特定的颜色,一共20种颜色。

9.12.2 MS COCO

MS COCO 是最大图像分割数据集,提供的类别有 80 类,有超过 33 万张图片,其中 20 万张有标注,整个数据集中个体的数目超过 150 万个。MS COCO是目前难度最大,挑战最高的图像分割数据集。

9.12.3 Cityscapes

Cityscapes 是驾驶领域进行效果和性能测试的图像分割数据集,它包含了5000张精细标注的图像和20000张粗略标注的图像,这些图像包含50个城市的不同场景、不同背景、不同街景,以及30类涵盖地面、建筑、交通标志、自然、天空、人和车辆等的物体标注。Cityscapes评测集有两项任务:像素级(Pixel-level)图像场景分割(以下简称语义分割)与实例级(Instance-level)图像场景分割(以下简称实例分割)。

9.13 全景分割(贡献者:北京理工大学—明奇)

全景分割的开山之作:何恺明的Panoptic Segmentation

  1. Introduction

  语义分割通过带孔全卷积网络,根据不同的stuff进行划分;实例分割则是在目标检测的基础上基于检测框进行物体的分割。缺少一种框架可以将两者进行融合实现既能分割背景又能分割实例,而这在自动驾驶和AR技术中大有作为。由此提出的全景分割任务能将两者进行结合。

  全景分割的思路很直观:为图像的每个像素分配语义label和类内实例id,前者用于区分语义信息,后者用于分割实例(因此stuff不具有实例id)。提出全景分割时,只是启发式地将语意分割和实例分割两种任务的输出进行后处理的融合(如NMS),并以此建立PS任务的baseline。为了评价全景分割的质量,提出panoptic quality (PQ) 标准,将背景和物体的评价纳入一个完整的框架下。示意图如下:

  1. Panoptic Segmentation
  • Task format
    全景分割的标注方法:
    像素级的标注,标出类别label和类内实例id。如果某像素的这两个信息都能匹配,则可以将该像素匹配到某个类别和实例中去;类外的像素可以分配空标签,即并不是所有的像素都要有语义类别。

  • Stuff and thing labels
    对于stuff和thing(背景填充和物体实例)的标签,交集是空集,并集是所有可能的label空间。这两者是互相独立不相关的(很好理解,像素属于那个类和它属于哪个物体不具有相关性)。

  • Relationship
    都是像素级的label,需要为每个像素分配对应的标签。但是实例分割基于region的,允许重叠的segmentation,而全景分割和语义分割一样是像素级的label,不允许重叠标签的出现。

  • Confidence scores
    这一点上更像语义分割而不是实例分割,对于PS不需要置信分数评价分割质量。提到这个,作者认为语义分割和全景分割可以直接利用人工标注的label进行对比从而评价当前mask的质量;而实例分割在选择mask时评价的是分类置信度,这个并没有人工标注进行参考,因此难以把握。

  1. Panoptic Segmentation Metric
      用于衡量全景分割效果的指标应具有:完备性;可解释性;简洁性。由是提出了PQ指标,可分为两步:分割匹配、在匹配上进行计算PQ。

3.1 Segment Matching
  定义match:预测的segmentation和gt的iou大于0.5,说明两者can match。再结合全景分割的不可重叠性,不难得到:最多只有一个预测的segmentation可以match gt。

3.2 PQ Computation
  PQ的计算类似mAP,也是类内求取,然后求类间的平均值,以便不敏感类别不平衡。对于每一类,可以根据gt与预测的segmentation分为三类(下图描述):

TP: 预测为正,实际为正,描述match较好的
FP: 预测为正,实际为负,描述match错的
FN: 预测为负,实际为正,描述没match出来的gt
  通过上述三类可以计算得到PQ值公式:

式中出去FP与FN后,剩下的式子描述的是match的segmentation的平均IoU,加上FP与FN是为了惩罚match失败的分割实例。
有意思的是,对上述式子进行简单的恒等变化:

第一项评价的是match分割的质量,第二项类似于F1得分。因此可以PQ分解为:

  • Void labels
    gt中可能出现两种像素标注为空的情况:超出类别的像素和模糊不清的像素(难以分类)。在评估结果时,这些空的标签不予以评估。具体而言:
    (1)在matching部分,预测出为void的像素会被移出prediction并不参与IoU计算;
    (2)matching后,unmatched prediction按照一般情况会计算FP FN,但是对于空标签情况,如果该prediction含有的void像素块超过一定匹配阈值就会被移除,并不算作FP计算得分。

  • Group labels
    有时区分相同语义类别的实例个体标注比较困难,因此有提出组标签的标注方法。但对于PQ计算而言:
    (1)matching部分不使用组标签,而是严格区分实例
    (2)matching后,对于包含一部分相同类别像素点的unmatched predicted segments,这一部分将被去除并不视作false positives

3.3 Comparison to Existing Metrics

  • Semantic segmentation metrics
    衡量语义分割的标准有像素级精度,平均精度,IoU。但是其只专注于像素级的划分,不能反映物体实例级别的分割性能。

  • Instance segmentation metrics
    度量为AP,主要是引入了置信度分数confidence score对检测目标进行打分。(两者不是完全的隔绝,实例分割也有用IoU监督的,而confidence score是否能够反映mask的真实质量也有存疑过,这个标准也不是固定的)

  • Panoptic quality
    PQ的度量可以分解成SQ和RQ,SQ反映了语义分割的像素级IoU性能,RQ专注于检测识别的效果,因此将两者统一到一个框架下。

分割效果:






TODO

  • [ ] 图像分割数据集标注工具
  • [ ] 图像分割评价标准
  • [x] 全景分割
  • [ ] UNet++

[TOC]

第一章 数学基础

深度学习通常又需要哪些数学基础?深度学习里的数学到底难在哪里?通常初学者都会有这些问题,在网络推荐及书本推荐里,经常看到会列出一系列数学科目,比如微积分、线性代数、概率论、复变函数、数值计算、优化理论、信息论等等。这些数学知识有相关性,但实际上按照这样的知识范围来学习,学习成本会很久,而且会很枯燥,本章我们通过选举一些数学基础里容易混淆的一些概念做以介绍,帮助大家更好的理清这些易混淆概念之间的关系。

1.1 向量和矩阵

1.1.1 标量、向量、矩阵、张量之间的联系

标量(scalar)
一个标量表示一个单独的数,它不同于线性代数中研究的其他大部分对象(通常是多个数的数组)。我们用斜体表示标量。标量通常被赋予小写的变量名称。

向量(vector)
​一个向量表示一组有序排列的数。通过次序中的索引,我们可以确定每个单独的数。通常我们赋予向量粗体的小写变量名称,比如xx。向量中的元素可以通过带脚标的斜体表示。向量$X$的第一个元素是$X_1$,第二个元素是$X_2$,以此类推。我们也会注明存储在向量中的元素的类型(实数、虚数等)。

矩阵(matrix)
​矩阵是具有相同特征和纬度的对象的集合,表现为一张二维数据表。其意义是一个对象表示为矩阵中的一行,一个特征表示为矩阵中的一列,每个特征都有数值型的取值。通常会赋予矩阵粗体的大写变量名称,比如$A$。

张量(tensor)
​在某些情况下,我们会讨论坐标超过两维的数组。一般地,一个数组中的元素分布在若干维坐标的规则网格中,我们将其称之为张量。使用 $A$ 来表示张量“A”。张量$A$中坐标为$(i,j,k)$的元素记作$A_{(i,j,k)}$。

四者之间关系

标量是0阶张量,向量是一阶张量。举例:
​标量就是知道棍子的长度,但是你不会知道棍子指向哪儿。
​向量就是不但知道棍子的长度,还知道棍子指向前面还是后面。
​张量就是不但知道棍子的长度,也知道棍子指向前面还是后面,还能知道这棍子又向上/下和左/右偏转了多少。

1.1.2 张量与矩阵的区别

  • 从代数角度讲, 矩阵它是向量的推广。向量可以看成一维的“表格”(即分量按照顺序排成一排), 矩阵是二维的“表格”(分量按照纵横位置排列), 那么$n$阶张量就是所谓的$n$维的“表格”。 张量的严格定义是利用线性映射来描述。
  • 从几何角度讲, 矩阵是一个真正的几何量,也就是说,它是一个不随参照系的坐标变换而变化的东西。向量也具有这种特性。
  • 张量可以用3×3矩阵形式来表达。
  • 表示标量的数和表示向量的三维数组也可分别看作1×1,1×3的矩阵。

1.1.3 矩阵和向量相乘结果

若使用爱因斯坦求和约定(Einstein summation convention),矩阵$A$, $B$相乘得到矩阵$C$可以用下式表示:

其中,$a{ik}$, $b{kj}$, $c_{ij}$分别表示矩阵$A, B, C$的元素,$k$出现两次,是一个哑变量(Dummy Variables)表示对该参数进行遍历求和。
而矩阵和向量相乘可以看成是矩阵相乘的一个特殊情况,例如:矩阵$B$是一个$n \times 1$的矩阵。

1.1.4 向量和矩阵的范数归纳

向量的范数(norm)
​ 定义一个向量为:$\vec{a}=[-5, 6, 8, -10]$。任意一组向量设为$\vec{x}=(x_1,x_2,…,x_N)$。其不同范数求解如下:

  • 向量的1范数:向量的各个元素的绝对值之和,上述向量$\vec{a}$的1范数结果就是:29。
  • 向量的2范数:向量的每个元素的平方和再开平方根,上述$\vec{a}$的2范数结果就是:15。
  • 向量的负无穷范数:向量的所有元素的绝对值中最小的:上述向量$\vec{a}$的负无穷范数结果就是:5。
  • 向量的正无穷范数:向量的所有元素的绝对值中最大的:上述向量$\vec{a}$的正无穷范数结果就是:10。
  • 向量的p范数:

矩阵的范数

定义一个矩阵$A=[-1, 2, -3; 4, -6, 6]$。 任意矩阵定义为:$A{m\times n}$,其元素为 $a{ij}$。

矩阵的范数定义为

当向量取不同范数时, 相应得到了不同的矩阵范数。

  • 矩阵的1范数(列范数):矩阵的每一列上的元

素绝对值先求和,再从中取个最大的,(列和最大),上述矩阵$A$的1范数先得到$[5,8,9]$,再取最大的最终结果就是:9。

  • 矩阵的2范数:矩阵$A^TA$的最大特征值开平方根,上述矩阵$A$的2范数得到的最终结果是:10.0623。

其中, $\lambda_{max}(A^T A)$ 为 $A^T A​$ 的特征值绝对值的最大值。

  • 矩阵的无穷范数(行范数):矩阵的每一行上的元素绝对值先求和,再从中取个最大的,(行和最大),上述矩阵$A$的行范数先得到$[6;16]$,再取最大的最终结果就是:16。

  • 矩阵的核范数:矩阵的奇异值(将矩阵svd分解)之和,这个范数可以用来低秩表示(因为最小化核范数,相当于最小化矩阵的秩——低秩),上述矩阵A最终结果就是:10.9287。

  • 矩阵的L0范数:矩阵的非0元素的个数,通常用它来表示稀疏,L0范数越小0元素越多,也就越稀疏,上述矩阵$A$最终结果就是:6。

  • 矩阵的L1范数:矩阵中的每个元素绝对值之和,它是L0范数的最优凸近似,因此它也可以表示稀疏,上述矩阵$A$最终结果就是:22。
  • 矩阵的F范数:矩阵的各个元素平方之和再开平方根,它通常也叫做矩阵的L2范数,它的优点在于它是一个凸函数,可以求导求解,易于计算,上述矩阵A最终结果就是:10.0995。
  • 矩阵的L21范数:矩阵先以每一列为单位,求每一列的F范数(也可认为是向量的2范数),然后再将得到的结果求L1范数(也可认为是向量的1范数),很容易看出它是介于L1和L2之间的一种范数,上述矩阵$A$最终结果就是:17.1559。
  • 矩阵的 p范数

1.1.5 如何判断一个矩阵为正定

判定一个矩阵是否为正定,通常有以下几个方面:

  • 顺序主子式全大于0;
  • 存在可逆矩阵$C$使$C^TC$等于该矩阵;
  • 正惯性指数等于$n$;
  • 合同于单位矩阵$E$(即:规范形为$E$)
  • 标准形中主对角元素全为正;
  • 特征值全为正;
  • 是某基的度量矩阵。

1.2 导数和偏导数

1.2.1 导数偏导计算

导数定义:

导数(derivative)代表了在自变量变化趋于无穷小的时候,函数值的变化与自变量的变化的比值。几何意义是这个点的切线。物理意义是该时刻的(瞬时)变化率。

注意:在一元函数中,只有一个自变量变动,也就是说只存在一个方向的变化率,这也就是为什么一元函数没有偏导数的原因。在物理学中有平均速度和瞬时速度之说。平均速度有

其中$v$表示平均速度,$s$表示路程,$t$表示时间。这个公式可以改写为

其中$\Delta s$表示两点之间的距离,而$\Delta t$表示走过这段距离需要花费的时间。当$\Delta t$趋向于0($\Delta t \to 0$)时,也就是时间变得很短时,平均速度也就变成了在$t_0$时刻的瞬时速度,表示成如下形式:

实际上,上式表示的是路程$s$关于时间$t$的函数在$t=t_0$处的导数。一般的,这样定义导数:如果平均变化率的极限存在,即有

则称此极限为函数 $y=f(x)$ 在点 $x0$ 处的导数。记作 $f’(x_0)$ 或 $y’\vert{x=x0}$ 或 $\frac{dy}{dx}\vert{x=x0}$ 或 $\frac{df(x)}{dx}\vert{x=x_0}$。

通俗地说,导数就是曲线在某一点切线的斜率。

偏导数:

既然谈到偏导数(partial derivative),那就至少涉及到两个自变量。以两个自变量为例,$z=f(x,y)​$,从导数到偏导数,也就是从曲线来到了曲面。曲线上的一点,其切线只有一条。但是曲面上的一点,切线有无数条。而偏导数就是指多元函数沿着坐标轴的变化率。

注意:直观地说,偏导数也就是函数在某一点上沿坐标轴正方向的的变化率。

设函数$z=f(x,y)​$在点$(x_0,y_0)​$的领域内有定义,当$y=y_0​$时,$z​$可以看作关于$x​$的一元函数$f(x,y_0)​$,若该一元函数在$x=x_0​$处可导,即有

函数的极限$A$存在。那么称$A$为函数$z=f(x,y)$在点$(x0,y_0)$处关于自变量$x$的偏导数,记作$f_x(x_0,y_0)$或$\frac{\partial z}{\partial x}\vert{y=y0}^{x=x_0}$或$\frac{\partial f}{\partial x}\vert{y=y0}^{x=x_0}$或$z_x\vert{y=y_0}^{x=x_0}$。

偏导数在求解时可以将另外一个变量看做常数,利用普通的求导方式求解,比如$z=3x^2+xy$关于$x$的偏导数就为$z_x=6x+y$,这个时候$y$相当于$x$的系数。

某点$(x_0,y_0)$处的偏导数的几何意义为曲面$z=f(x,y)$与面$x=x_0$或面$y=y_0$交线在$y=y_0$或$x=x_0$处切线的斜率。

1.2.2 导数和偏导数有什么区别?

导数和偏导没有本质区别,如果极限存在,都是当自变量的变化量趋于0时,函数值的变化量与自变量变化量比值的极限。

  • 一元函数,一个$y$对应一个$x$,导数只有一个。
  • 二元函数,一个$z$对应一个$x$和一个$y$,有两个导数:一个是$z$对$x$的导数,一个是$z$对$y$的导数,称之为偏导。
  • 求偏导时要注意,对一个变量求导,则视另一个变量为常数,只对改变量求导,从而将偏导的求解转化成了一元函数的求导。

1.3 特征值和特征向量

1.3.1 特征值分解与特征向量

  • 特征值分解可以得到特征值(eigenvalues)与特征向量(eigenvectors);

  • 特征值表示的是这个特征到底有多重要,而特征向量表示这个特征是什么。

    如果说一个向量$\vec{v}$是方阵$A$的特征向量,将一定可以表示成下面的形式:

$\lambda$为特征向量$\vec{v}$对应的特征值。特征值分解是将一个矩阵分解为如下形式:

其中,$Q$是这个矩阵$A$的特征向量组成的矩阵,$\sum$是一个对角矩阵,每一个对角线元素就是一个特征值,里面的特征值是由大到小排列的,这些特征值所对应的特征向量就是描述这个矩阵变化方向(从主要的变化到次要的变化排列)。也就是说矩阵$A$的信息可以由其特征值和特征向量表示。

1.3.2 奇异值与特征值有什么关系

那么奇异值和特征值是怎么对应起来的呢?我们将一个矩阵$A$的转置乘以$A$,并对$A^TA​$求特征值,则有下面的形式:

这里$V​$就是上面的右奇异向量,另外还有:

这里的$\sigma​$就是奇异值,$u​$就是上面说的左奇异向量。【证明那个哥们也没给】
​奇异值$\sigma​$跟特征值类似,在矩阵$\sum​$中也是从大到小排列,而且$\sigma​$的减少特别的快,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上了。也就是说,我们也可以用前$r​$($r​$远小于$m、n​$)个的奇异值来近似描述矩阵,即部分奇异值分解:

右边的三个矩阵相乘的结果将会是一个接近于$A$的矩阵,在这儿,$r$越接近于$n$,则相乘的结果越接近于$A$。

1.4 概率分布与随机变量

1.4.1 机器学习为什么要使用概率

事件的概率是衡量该事件发生的可能性的量度。虽然在一次随机试验中某个事件的发生是带有偶然性的,但那些可在相同条件下大量重复的随机试验却往往呈现出明显的数量规律。
​机器学习除了处理不确定量,也需处理随机量。不确定性和随机性可能来自多个方面,使用概率论来量化不确定性。
​概率论在机器学习中扮演着一个核心角色,因为机器学习算法的设计通常依赖于对数据的概率假设。

​ 例如在机器学习(Andrew Ng)的课中,会有一个朴素贝叶斯假设就是条件独立的一个例子。该学习算法对内容做出假设,用来分辨电子邮件是否为垃圾邮件。假设无论邮件是否为垃圾邮件,单词x出现在邮件中的概率条件独立于单词y。很明显这个假设不是不失一般性的,因为某些单词几乎总是同时出现。然而,最终结果是,这个简单的假设对结果的影响并不大,且无论如何都可以让我们快速判别垃圾邮件。

1.4.2 变量与随机变量有什么区别

随机变量(random variable)

表示随机现象(在一定条件下,并不总是出现相同结果的现象称为随机现象)中各种结果的实值函数(一切可能的样本点)。例如某一时间内公共汽车站等车乘客人数,电话交换台在一定时间内收到的呼叫次数等,都是随机变量的实例。
​随机变量与模糊变量的不确定性的本质差别在于,后者的测定结果仍具有不确定性,即模糊性。

变量与随机变量的区别:
​当变量的取值的概率不是1时,变量就变成了随机变量;当随机变量取值的概率为1时,随机变量就变成了变量。

比如:
​ 当变量$x$值为100的概率为1的话,那么$x=100$就是确定了的,不会再有变化,除非有进一步运算.
​ 当变量$x$的值为100的概率不为1,比如为50的概率是0.5,为100的概率是0.5,那么这个变量就是会随不同条件而变化的,是随机变量,取到50或者100的概率都是0.5,即50%。

1.4.3 随机变量与概率分布的联系

一个随机变量仅仅表示一个可能取得的状态,还必须给定与之相伴的概率分布来制定每个状态的可能性。用来描述随机变量或一簇随机变量的每一个可能的状态的可能性大小的方法,就是 概率分布(probability distribution).

随机变量可以分为离散型随机变量和连续型随机变量。

相应的描述其概率分布的函数是

概率质量函数(Probability Mass Function, PMF):描述离散型随机变量的概率分布,通常用大写字母 $P$表示。

概率密度函数(Probability Density Function, PDF):描述连续型随机变量的概率分布,通常用小写字母$p$表示。

1.4.4 离散型随机变量和概率质量函数

PMF 将随机变量能够取得的每个状态映射到随机变量取得该状态的概率。

  • 一般而言,$P(x)​$ 表示时$X=x​$的概率.
  • 有时候为了防止混淆,要明确写出随机变量的名称$P(​$x$=x)​$
  • 有时候需要先定义一个随机变量,然后制定它遵循的概率分布x服从$P(​$x​$)​$

PMF 可以同时作用于多个随机变量,即联合概率分布(joint probability distribution) $P(X=x,Y=y)$*表示 $X=x$和$Y=y$同时发生的概率,也可以简写成 $P(x,y)$.

如果一个函数$P​$是随机变量 $X​$ 的 PMF, 那么它必须满足如下三个条件

  • $P​$的定义域必须是的所有可能状态的集合
  • $∀x∈​$x, $0 \leq P(x) \leq 1 ​$.
  • $∑_{x∈X} P(x)=1$. 我们把这一条性质称之为 归一化的(normalized)

1.4.5 连续型随机变量和概率密度函数

如果一个函数$p​$是x的PDF,那么它必须满足如下几个条件

  • $p$的定义域必须是 xx 的所有可能状态的集合。
  • $∀x∈X,p(x)≥0$. 注意,我们并不要求$ p(x)≤1$,因为此处 $p(x)$不是表示的对应此状态具体的概率,而是概率的一个相对大小(密度)。具体的概率,需要积分去求。
  • $∫p(x)dx=1$, 积分下来,总和还是1,概率之和还是1.

注:PDF$p(x)$并没有直接对特定的状态给出概率,给出的是密度,相对的,它给出了落在面积为 $δx$的无线小的区域内的概率为$ p(x)δx$. 由此,我们无法求得具体某个状态的概率,我们可以求得的是 某个状态 $x$ 落在 某个区间$[a,b]$内的概率为$ \int_{a}^{b}p(x)dx$.

1.4.6 举例理解条件概率

条件概率公式如下:

说明:在同一个样本空间$\Omega$中的事件或者子集$A$与$B$,如果随机从$\Omega$中选出的一个元素属于$B$,那么下一个随机选择的元素属于$A$ 的概率就定义为在$B$的前提下$A$的条件概率。条件概率文氏图示意如图1.1所示。
条件概率

图1.1 条件概率文氏图示意

根据文氏图,可以很清楚地看到在事件B发生的情况下,事件A发生的概率就是$P(A\bigcap B)$除以$P(B)$。
​举例:一对夫妻有两个小孩,已知其中一个是女孩,则另一个是女孩子的概率是多少?(面试、笔试都碰到过)
穷举法:已知其中一个是女孩,那么样本空间为男女,女女,女男,则另外一个仍然是女生的概率就是1/3。
条件概率法:$P(女|女)=P(女女)/P(女)$,夫妻有两个小孩,那么它的样本空间为女女,男女,女男,男男,则$P(女女)$为1/4,$P(女)= 1-P(男男)=3/4$,所以最后$1/3$。
这里大家可能会误解,男女和女男是同一种情况,但实际上类似姐弟和兄妹是不同情况。

1.4.7 联合概率与边缘概率联系区别

区别:
​联合概率:联合概率指类似于$P(X=a,Y=b)$这样,包含多个条件,且所有条件同时成立的概率。联合概率是指在多元的概率分布中多个随机变量分别满足各自条件的概率。
​边缘概率:边缘概率是某个事件发生的概率,而与其它事件无关。边缘概率指类似于$P(X=a)$,$P(Y=b)$这样,仅与单个随机变量有关的概率。

联系:
​联合分布可求边缘分布,但若只知道边缘分布,无法求得联合分布。

1.4.8 条件概率的链式法则

由条件概率的定义,可直接得出下面的乘法公式:
​乘法公式 设$A, B$是两个事件,并且$P(A) > 0$, 则有

推广

一般地,用归纳法可证:若$P(A_1A_2…A_n)>0$,则有

任何多维随机变量联合概率分布,都可以分解成只有一个变量的条件概率相乘形式。

1.4.9 独立性和条件独立性

独立性
​两个随机变量$x$和$y$,概率分布表示成两个因子乘积形式,一个因子只包含$x$,另一个因子只包含$y$,两个随机变量相互独立(independent)。
​条件有时为不独立的事件之间带来独立,有时也会把本来独立的事件,因为此条件的存在,而失去独立性。
​举例:$P(XY)=P(X)P(Y)$, 事件$X$和事件$Y$独立。此时给定$Z$,

事件独立时,联合概率等于概率的乘积。这是一个非常好的数学性质,然而不幸的是,无条件的独立是十分稀少的,因为大部分情况下,事件之间都是互相影响的。

条件独立性
​给定$Z$的情况下,$X$和$Y$条件独立,当且仅当

$X$和$Y$的关系依赖于$Z$,而不是直接产生。

举例定义如下事件:
$X$:明天下雨;
$Y$:今天的地面是湿的;
$Z$:今天是否下雨;
$Z$事件的成立,对$X$和$Y$均有影响,然而,在$Z$事件成立的前提下,今天的地面情况对明天是否下雨没有影响。

1.5 常见概率分布

1.5.1 Bernoulli分布

Bernoulli分布是单个二值随机变量分布, 单参数$\phi​$∈[0,1]控制,$\phi​$给出随机变量等于1的概率. 主要性质有:

其期望和方差为:

Multinoulli分布也叫范畴分布, 是单个k值随机分布,经常用来表示对象分类的分布. 其中$k$是有限值.Multinoulli分布由向量$\vec{p}\in[0,1]^{k-1}$参数化,每个分量$p_i$表示第$i$个状态的概率, 且$p_k=1-1^Tp​$.

适用范围: 伯努利分布适合对离散型随机变量建模.

1.5.2 高斯分布

高斯也叫正态分布(Normal Distribution), 概率度函数如下:

其中, $\mu​$和$\sigma​$分别是均值和方差, 中心峰值x坐标由$\mu​$给出, 峰的宽度受$\sigma​$控制, 最大点在$x=\mu​$处取得, 拐点为$x=\mu\pm\sigma​$

正态分布中,±1$\sigma$、±2$\sigma$、±3$\sigma$下的概率分别是68.3%、95.5%、99.73%,这3个数最好记住。

此外, 令$\mu=0,\sigma=1​$高斯分布即简化为标准正态分布:

对概率密度函数高效求值:

其中,$\beta=\frac{1}{\sigma^2}$通过参数$\beta∈(0,\infty)​$来控制分布精度。

1.5.3 何时采用正态分布

问: 何时采用正态分布?
答: 缺乏实数上分布的先验知识, 不知选择何种形式时, 默认选择正态分布总是不会错的, 理由如下:

  1. 中心极限定理告诉我们, 很多独立随机变量均近似服从正态分布, 现实中很多复杂系统都可以被建模成正态分布的噪声, 即使该系统可以被结构化分解.
  2. 正态分布是具有相同方差的所有概率分布中, 不确定性最大的分布, 换句话说, 正态分布是对模型加入先验知识最少的分布.

正态分布的推广:
正态分布可以推广到$R^n$空间, 此时称为多位正态分布, 其参数是一个正定对称矩阵$\Sigma​$:

对多为正态分布概率密度高效求值:

此处,$\vec\beta$是一个精度矩阵。

1.5.4 指数分布

深度学习中, 指数分布用来描述在$x=0​$点处取得边界点的分布, 指数分布定义如下:

指数分布用指示函数$I_{x\geq 0}​$来使$x​$取负值时的概率为零。

1.5.5 Laplace 分布

一个联系紧密的概率分布是 Laplace 分布(Laplace distribution),它允许我们在任意一点 $\mu$处设置概率质量的峰值

1.5.6 Dirac分布和经验分布

Dirac分布可保证概率分布中所有质量都集中在一个点上. Diract分布的狄拉克$\delta​$函数(也称为单位脉冲函数)定义如下:

Dirac 分布经常作为 经验分布(empirical distribution)的一个组成部分出现

, 其中, m个点$x^{1},…,x^{m}$是给定的数据集, 经验分布将概率密度$\frac{1}{m}​$赋给了这些点.

当我们在训练集上训练模型时, 可以认为从这个训练集上得到的经验分布指明了采样来源.

适用范围: 狄拉克δ函数适合对连续型随机变量的经验分布.

>

1.6 期望、方差、协方差、相关系数

1.6.1 期望

在概率论和统计学中,数学期望(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和。它反映随机变量平均取值的大小。

  • 线性运算: $E(ax+by+c) = aE(x)+bE(y)+c$
  • 推广形式: $E(\sum{k=1}^{n}{a_ix_i+c}) = \sum{k=1}^{n}{a_iE(x_i)+c}$
  • 函数期望:设$f(x)$为$x$的函数,则$f(x)$的期望为
    • 离散函数: $E(f(x))=\sum_{k=1}^{n}{f(x_k)P(x_k)}$
    • 连续函数: $E(f(x))=\int_{-\infty}^{+\infty}{f(x)p(x)dx}$

注意:

  • 函数的期望大于等于期望的函数(Jensen不等式),即$E(f(x))\geqslant f(E(x))$
  • 一般情况下,乘积的期望不等于期望的乘积。
  • 如果$X$和$Y$相互独立,则$E(xy)=E(x)E(y)​$。

1.6.2 方差

概率论中方差用来度量随机变量和其数学期望(即均值)之间的偏离程度。方差是一种特殊的期望。定义为:

方差性质:

1)$Var(x) = E(x^2) -E(x)^2$
2)常数的方差为0;
3)方差不满足线性性质;
4)如果$X$和$Y$相互独立, $Var(ax+by)=a^2Var(x)+b^2Var(y)$

1.6.3 协方差

协方差是衡量两个变量线性相关性强度及变量尺度。 两个随机变量的协方差定义为:

方差是一种特殊的协方差。当$X=Y$时,$Cov(x,y)=Var(x)=Var(y)$。

协方差性质:

1)独立变量的协方差为0。
2)协方差计算公式:

>

3)特殊情况:

1.6.4 相关系数

相关系数是研究变量之间线性相关程度的量。两个随机变量的相关系数定义为:

相关系数的性质:
1)有界性。相关系数的取值范围是 [-1,1],可以看成无量纲的协方差。
2)值越接近1,说明两个变量正相关性(线性)越强。越接近-1,说明负相关性越强,当为0时,表示两个变量没有相关性。

参考文献

[1]Ian,Goodfellow,Yoshua,Bengio,Aaron…深度学习[M],人民邮电出版,2017

[2]周志华.机器学习[M].清华大学出版社,2016.

[3]同济大学数学系.高等数学(第七版)[M],高等教育出版社,2014.

[4]盛骤,试式千,潘承毅等编. 概率论与数理统计(第4版)[M],高等教育出版社,2008

快手实习项目整理

论文阅读

首先,是图像修复领域的调研和复现,主要是《Image Inpainting with Learnable Bidirectional Attention Maps》、《EdgeConnect: Structure Guided Image Inpainting using Edge Prediction》以及《Free-Form Image Inpainting with Gated Convolution》。
《Free-Form Image Inpainting with Gated Convolution》

图像修复

1、使用低阶图像特征的块(patch)匹配:生成看似合理的平稳纹理,但在处理复杂的场景,例如人脸和物体的时候,常出现严重的错误。
2、使用卷积神经网络推理生成模型: 从大规模数据集中学习到的语义,以端到端的方式合成非平稳图像中的内容。但是普通卷积的深度生成模型,在图像填充上存在严重的问题,因为普通卷积识所有输入的像素和特征,均为有效像素。对于图像填充来说,每一层的输入时由确实外的有效像素/特征和缺失区域(掩码区域)的无效像素组成。普通卷积使用相同的卷积核,适用于所有有效、无效和混合(例如那些空洞边界)的像素/特征,在自由形状上的掩码做测试时,导致视觉上的伪影(如颜色差异,模糊和孔周围明显的边缘响应)。

部分卷积

为了解决这一局限性,部分卷积(PartialConv),其中卷积被遮掩(masked)和归一化,仅以有效像素为条件。基于规则的掩码更新策略,用于更新下一层的有效位置。部分卷积将所有位置视为无效或有效,并用0或1掩码乘以所有层的输入,该掩码可以看做是一个单一的不可学习的特征门(gate)通道。
然而,这种假设是有几个局限性:
(1)考虑跨网络不同层的输入空间位置,他们可能包括:a)输入图像中有有效像素;b)输入图像中有掩蔽mask像素;c)感受野的神经元没有覆盖到输入图像的有效像素;d)感受野的神经元覆盖了不同数量的输入图像的有效像素,这些有效地图像像素也可能有不同的相对位置;e)深层合成的像素;f)启发式的将所有的位置归类为无效或有效,会忽略以上这些重要信息。
(2)如果我们扩展到用户知道的图像修复,用户在掩码内提供的稀疏草图(sparse sketch),这些像素位置应该被视为有效地还是无效的?如何正确地更新下一层的掩码?
(3)对于部分卷积,无效的像素将逐层逐渐消失,基于规则的掩码将在深层全部消失。然而,为了合成孔内的像素,这些深层可能还需要知道当前位置是在孔内还是孔外?全1掩码的部分卷积不能提供这样的信息。

门控卷积

因此提出了门控卷积的概念,门控卷积掩码更新过程,输入特征首先用于计算门控值$g=\theta(w_gx)$,$\theta$是激活函数,$w_g$是可学习参数。最终的输出是学习到的特征和门控值$y=\fi(wx)\bigdot g$的乘积。
由于普通卷积是将每一个像素都当成有效值去计算的,这个特性适用于分类和检测任务,但是不适用于inpainting任务,因为inpainting任务中hole里面的像素是无效值,因此对空洞hole里面的内容和外面的内容要加以区分,部分卷积虽然将里面和外面的内容加以区分,但是它将含有1个有效值像素的区域与含有9个有效值像素的区域同等对待,这明显不合理,gated conv则是使用卷积核sigmoid函数使得网络去学习这种区分。

光谱归一化马尔科夫判别器(SNPatchGAN)

之前的修复网络,为了修复带有矩形确实部分的图片,提出 local GAN 来提升实验结果;然而,我们要研究的是对任意形状缺失的形状,借鉴 global and GANs、MarkovianGANs、perpetual loss、spectral-normalized GANs,作者提出一个有效地GAN loss,即为 SN-PatchGAN。
SN-PatchGAN的组成,是由卷积网络构成,输入为image、mask、guidance channel,输出是一个形状为h×w×c的3维特征,h、w、c分别代表高、宽和通道数。SN-PatchGAN由6个卷积层(卷积核大小为2,步幅为2)堆叠来获得Markovian Patches特征的统计信息。然后直接将SN-PatchGAN应用到特征图的每一个特征元素,以输入图像的不同位置和不同语义(在不同的通道中表示)的形式表示GAN的$h\times w\times c$个。
值得注意的是,在训练的环境中,输出图中每个神经元的感受野可以覆盖整个输入图像,因此不需要全局判别器。
作者也采用了最近提出的Spectral normalization来进一步稳定GANs的训练。我们采用SN-GANs中描述的默认Spectral normalization的fast approximation算法。
为了判别输入的真假,作者也采用了hings loss来作为目标函数,未采用Perceptual loss的原因是相似的patch-level information已经被编码在SN-PatchGAN中。

网络结构

作者定制了一个带有Gated convolution layer和SN-PatchGan loss的generative inpainting network。网络结构由粗修复和细修复两个网络构成,采用了encoder-decoder network(PartialConv采用的是类似U-net的结构)。网络为全卷积神经网络,支持不同分辨率图片的输入。训练是一个端到端的过程。

“蝴蝶消失”特效算法

快手的“蝴蝶消失”特效算法,主要是在用户上传的图片中,在蝴蝶飞舞的特效下,图片中的人像逐渐消失,还原完整的背景图像信息。算法的实现,是通过人像分割算法,检测图片中人体的位置并去除人体图像信息,然后采用图像修复算法还原人像区域可能存在的背景内容,实现蝴蝶飞舞下人像消失的特效。在这项工作中,我主要负责的是图像修复算法的研究以及后期的模型压缩等工作。
对于图像修复算法,我们使用卷积神经网络推理生成模型,从大规模数据集中学习到的语义,以端到端的方式合成非平稳图像中的内容。但是普通卷积的深度生成模型,在图像填充上存在严重的问题,因为普通卷积识所有输入的像素和特征,均为有效像素。但是对于图像填充来说,每一层的输入是由图像的有效像素和缺失区域的无效像素组成。普通卷积使用相同的卷积核,在人像这种自由形状上进行修复时,会导致视觉上的伪影(如颜色差异,模糊和孔周围明显的边缘响应)。
因此,我们采用门控卷积用于不规则的图像修复,它会为每个通道和每个空间位置(例如内部和外部掩码,RGB通道和用户知道通道)学习动态特征门控机制,使得最终的输出是学习到的特征与门控值g的乘积,门控卷积可以学会在单独的通道中突出掩码区域的信息,提高了不规则掩码输入的图像修复质量。我们通过堆叠门控卷积形成编码器和解码器网络,并将上下文注意模块集成到网络中,来更好的捕获远距离的依赖关系。
网络结构
由于网络采用的是生成对抗网络,处理像素级的l1重建损失函数和GAN loss(生成器和判别器都使用hinge loss)外,我们还尝试添加其他的损失函数优化图像修复效果。 我们发现不同的损失函数对图像的修复结果有很大的影响,添加log-loss以及ls-loss生成的纹理信息相对来说比较差,但可以避免斑块状伪影的问题,而relgan-loss生成的纹理信息比较好,但会出现斑块状的纹理。添加感知损失perceptual loss,通过VGG16计算全图区域的影响能有效平滑修复区域的斑块信息,减少伪影现象,而添加风格损失style loss计算图像的风格变化,并没有带来明显的效果提升,因此模型最终选择添加感知损失来优化模型修复效果。(感知损失将真实图片卷积得到的feature与生产图片卷积得到的feature进行对比,是高层的内容和全局信息接近,也就是感知的含义)。
由于图像修复是基于人像分割算法得到的人像区域上进行修复的,在真实场景中,可能由于人像手持物体或者头发等导致人像分割的区域不准确,有残留的边缘区域会导致修复的结果出现斑块状的伪影现象。针对这种现象,我们在模型训练的时候添加了攻击噪声,使得模型更加的稳定和鲁棒。考虑到人像分割的不准确性多是发生于边缘区域,因此我们训练的时候对人像的mask轮廓上随机添加块状的缺口,模拟分割不准确问题。在验证集的添加30%的边界攻击数据集上进行验证,模型修复的SSIM相较于原始模型降低0.04,但相较于原始模型在攻击数据集的表降低0.1现,添加边界噪声的模型具有更加鲁棒的结果,模型最终的修复指标SSIM为0.737。

图像修复的评价指标

计算图像修复的质量,最直接的思路即比较修复后的图片与真实图像之间的可视误差,通过visibility of errors评价图像的质量。

PSNR

PSNR(Peak Signal to nise Ratio),峰值信噪比,即峰值信号的能量与噪声的平均能量之比,通常表示时取log变成db计算,由于MSE为真实图片与含噪图像之差的能量均值,而两者的差即为噪声,因此PSNR即峰值信号能量与MSE之比。
优点:算法简单,计算的速度快。
缺点:基于对应像素点间的误差,呈现的差异值与人的主观感受不成比例,不符合人类视觉系统(HVS)的评价结果。

SSIM

SSIM(Structural Similarity),结构相似性,也就是一种全参考的图像质量评价指标,它分别从亮度、对比度、结构三方面度量图像相似性。SSIM取值范围[0, 1],值越大,表示图像失真越小,SSIM在图像去噪、图像相似度评价上是由于PSNR的。

我们每次计算都是从图片上取一个NxN的窗口,然后不断滑动窗口进行计算,最后取平均值作为全局的SSIM。
优点:改进了PSNR的缺点,比较符合人体视觉系统的评估。
缺点:结构相似性指标对于图像出现位移、缩放、旋转等非结构性的失真无法有效的运作。

模型压缩算法

分组卷积

分组卷积(Group convolution):将多个卷积核拆分为分组,每个分组单独执行一系列运算之后,最终在全连接层再拼接在一起。分组卷积的重点不在于卷积,而在于分组:在执行卷积之后,将输出的feature map 执行分组。然后在每个组的数据会在各个GPU 上单独训练。
分组卷积在网络的全连接层才进行融合,这使得每个GPU 中只能看到部分通道的数据,这降低了模型的泛化能力。但是分组卷积降低了模型的参数数量以及计算量。
假设输入feature map具有$C_I$的输入通道,宽/高分别为$W_I, H_I$,假设卷积核的宽/高分别为$W_K, H_K$,有$C_O$个卷积核,则卷积的参数量为:$W_K\times H_K\times C_I\times C_O$,计算量为:$W_K\times H_K\times C_I\times W_O\times H_O\times C_O$。假设采用分组卷积,将输入通道分成G组,则分组后:参数量为$W_K\times H_K\times \frac{C_I}{G}\times \frac{C_O}{G}$,分组卷积的参数量、计算量均为标准卷积计算的$\frac{1}{G}$。

可分离卷积DepthWise

标准的卷积会考虑所有的输入通道,而DepthWise 卷积会针对每一个输入通道进行卷积操作,然后接一个1x1 的跨通道卷积操作。
DepthWise 卷积与分组卷积的区别在于:
1)分组卷积是一种通道分组的方式,它改变的是对输入的feature map 处理的方式。Depthwise 卷积是一种卷积的方式,它改变的是卷积的形式。
2)Depthwise 分组卷积结合了两者:首先沿着通道进行分组,然后每个分组执行DepthWise 卷积。
假设使用标准卷积,输入通道的数量为$C_I$,输出通道的数量为$C_O$,卷积核的尺寸为$W_K\times H_K$。则需要的参数数量为$C_I\times W_K\times H_K\times C_O$。使用Depthwise卷积时,图像的每个通道先通过一个$W_K\times H_K$的depthwise卷积层,再经过一个1x1、输出为$C_O$的卷积层。参数量为:

其参数数量是标准卷积的$\frac{1}{C_O}+\frac{1}{W_KH_K}$。

知识蒸馏

知识蒸馏的本质是让大的teacher model来协助线上的student model进行训练。因为模型训练时,我们通常采用复杂模型或Ensemble方式来获取最好的结果,从而导致参数冗余验证,在前向推理的时候,需要对模型进行复杂的计算。而知识蒸馏是把复杂模型或多个模型Ensemble(Teacher)学到的知识迁移到另一个轻量级模型上(Student)叫知识蒸馏,使得模型变轻量的同时(方便部署),尽量不损失性能。
知识蒸馏主要分成三个大类:
(1)输出迁移(output transfer),将网络的输出(soft-target)作为知识;
(2)特征迁移(feature transfer),将网络学习的特征作为知识;
(3)关系迁移(relation transfer),将网络或样本的关系作为知识。
在输出迁移中,我们对一些术语进行定义:

  • Teacher:原始较大的模型或模型Ensemble,用于获取知识;
  • Student:新的较小模型,接收teacher的知识,训练后用于前向预测;
  • Hard target:样本原本的标签,Onehot
  • Soft target:Teacher输出的预测结果(一般是softmax之后的概率)

这里的软目标的优势在于:
(1)弥补了简单分类中监督信号不足(信息熵比较少)的问题,增加了信息量;
(2)提供了训练数据中类别的关系(数据增强);
(3)可能增强了模型泛化的能力。
而特征迁移Feature Transfer——将网络学习的特征作为知识,对卷积网络隐藏层输出的特征图——feature map(特征 & 知识)进行迁移(Attention transfer),让学生网络的feature map与教师网络的feature map尽可能相似。
关系迁移Relation Transfer——将网络或者样本的关系作为知识,让学生网络学习教师网络层与层之间的关系(特征关系)。

模型压缩过程

在原始的图像修复模型中,输入的图像大小为256x256,卷积的第一层通道数为48,模型的参数量接近25G,模型修复指标SSIM为0.7273。首先,们将输出图像的大小resize到128x128大小,模型的参数量降低为6G,但是模型的修复指标SSIM降低为0.6918,然后我们采用mobile_v2中的可分离卷积的思想,替换模型中的卷积方式,模型的参数量减少为1G,此时模型的SSIM指标为0.6486;接着我们进一步将卷积层的通道数减少为24,模型的参数量为300M,修复指标为0.6276。我们采用压缩的方式,很好的降低了模型的参数量,但由于模型压缩过程导致有用的参数的丢失,使得模型修复指标出现严重的下降,图像修复结果也出现严重的斑块状的伪影。为此,我们采用知识蒸馏的思想,将未压缩的模型作为教师网络,利用教师网络中生成的粗糙和中间特征图和输出的精细修复图,对学生网络的粗糙特征图和输出进行是修复图进行监督,在损失函数中计算二者的重建损失l1-loss,使得学生网络在训练过程中保留更多有用的信息。采用知识蒸馏的做法后,在参数量为1G的压缩模型中,SSIM指标提升为0.6661,在300M的蒸馏版本中模型的SSIM指标提升为0.6500,相较于未蒸馏前的效果有了明显的改进,而且修复的图片的斑块状伪影减少,修复区域更加的平滑。但在一些颜色变化复杂的区域,修复效果和原始相比还是会呈现明显的亮斑,因此我们添加感知损失计算teacher模型输出图像和学生网络输出图像的差值来平滑图像学生网络图像修复的结果。

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment