- 为什么要提出MDNet?
- 现有的一些目标跟踪算法是通过在大规模分类数据集ImageNet上进行预训练,但是跟踪任务和分类任务是不同的视觉任务,它们的模型之间存在“鸿沟”。
- 为了充分的发挥CNN在视觉跟踪方面强大的表现力,需要在大规模专门用于视觉跟踪的数据集上做训练,要求该数据集中包含目标和背景的各种变化,但是在具有完全不同特征的视频序列上学习统一的特征表示具有很大的挑战性(比如说同一类型的对象可能在一个视频序列中为目标而在另一个视频序列中却是背景)。
由1,2可知基于标准分类任务的普通学习方法是不合适的,另一种为了得到更好的跟踪特征表示而获得视频序列独立信息的方法应该被采纳,所以提出了MDNet。
- 摘要
- 预训练时,MDNet由conv1-fc5构成的共享层和多分支fc6构成的特定域层构成,其中共享层来学习跟踪任务的共享属性,特定域层的每一个分支是一个二分类器,用来识别对应域中的目标和背景(这里的域指的是不同的视频序列),在训练时,每次选取一个域独立的进行训练,只有训练相对应的域其FC6层才会进行更新,而共享层每次训练都会进行更新,通过这种训练策略,共享层学习到了通用的视觉跟踪的特征表示(共享属性,域独立信息),FC6层学习到的是域特定信息。
- 在线跟踪时,是通过预训练的共享层和一个新的二分类器(这是由于FC6层的每个分支学习到的都是每个域的一个二分类器,故而没有共享的意义)来在构建一个新的网络进行跟踪。
- 网络结构分析
self.K = K # 分支数目
# 共享层
self.layers = nn.Sequential(OrderedDict([
('conv1', nn.Sequential(nn.Conv2d(3, 96, kernel_size=7, stride=2),
nn.ReLU(),
LRN(),
nn.MaxPool2d(kernel_size=3, stride=2))),
('conv2', nn.Sequential(nn.Conv2d(96, 256, kernel_size=5, stride=2),
nn.ReLU(),
LRN(),
nn.MaxPool2d(kernel_size=3, stride=2))),
('conv3', nn.Sequential(nn.Conv2d(256, 512, kernel_size=3, stride=1),
nn.ReLU())),
('fc4', nn.Sequential(nn.Dropout(0.5),
nn.Linear(512 * 3 * 3, 512),
nn.ReLU())),
('fc5', nn.Sequential(nn.Dropout(0.5),
nn.Linear(512, 512),
nn.ReLU()))]))
# 分支层
self.branches = nn.ModuleList([nn.Sequential(nn.Dropout(0.5),
nn.Linear(512, 2)) for _ in range(K)])
以conv1为例,输入是107*107*3,kernel_size=7,stride=2,所以输出是 , n(input)=107, f(filter)=7, p(padding)=0, s(stride)=2.
- MDNet在视觉跟踪方面更有效的原因
- 网络较浅:视觉跟踪的任务是为了区分目标和背景两类,比一般的视觉识别问题具有更小的复杂度(ImageNet的分类任务需要区分1000类)
- 定位精确:深层的CNN不利于精确地目标定位,因为网络越深,空间信息往往会被稀释
- 目标较小:视觉跟踪中的目标往往较小,这就使得网络的输入图像尺寸变小,继而降低了网络的深度
- 速度较快:目标跟踪任务中较小的网络效果往往更好,训练和测试是在线进行的。
- 多域训练如何学习到不同视频序列中的共享属性(通用的特征表示)[理论]?
所有域中的目标表示存在一些常见描述属性,例如对照明变化的鲁棒性,运动模糊,尺度变化等。为了提取满足这些公共属性的有用特征,通过结合多域学习框架将域独立信息与域特定信息分开。
使用SGD(随机梯度下降)方法进CNN的训练,每次迭代对所有的域独立的进行处理,具体的训练方法如下:
- 假设视频序列个数为K个
- 打乱K个视频序列顺序以及每个视频序列中的图片顺序(SGD)
- 以下是迭代的过程:
1.第一次迭代,用来自第一个视频序列的mini-batch进行网络更新(按顺序取8帧即可,因为此时第一个视频序列已经被打乱了顺序; 且此时的第一个视频序列不一定是原来的第一个视频序列,因为K个视频序列的顺序也已被打乱)
2.第二次迭代,用来自第二个视频序列的mini-batch进行网络更新
......
第N次迭代,用来自第(N mod K)个视频序列的mini-batch进行网络更新(此时,整个数据集已经循环了N//K次)
迭代直到网络收敛或迭代次数达到设定值,通过这种学习方式,将域独立信息(共享层学习)和域特定信息(对应的FC6分支层学习)分离开
- 多域训练如何学习到不同视频序列中的共享属性(通用的特征表示)[代码实现]?
假设用k个视频进行训练,共进行N次循环,每个mini-batch是由某个视频序列中随机采集8帧图片,在这8帧图片中随机采集32个正样本区域和96个负样本区域(总计128个)
在每次循环中会依次进行k次迭代,从k个视频序列中取出一个mini-batch进行训练,每个视频序列对应自己的FC6层,通过这样的训练共享层可以学习到各个视频序列中的域独立信息,对应的FC6层可以学习到对应视频序列的域特定信息,重复进行N次循环
- 多域训练的数据准备
以第一个视频序列为例,由于采用SGD方法训练,所以首先打乱该视屏序列(原先的视频序列是按照帧顺序排列的),然后每次迭代到第一个视频序列时,依次取8帧,然后在这8帧中,每一帧取4个正样本(IOU>=0.7)和12个负样本(IOU<=0.5)的bounding box,然后从原图中按照bounding box 区域截取图片再统一为107*107作为网络的输入(总共32个正样本,96个负样本组成一个mini-batch)
- 多域训练过程
迭代50轮,每次迭代的过程如下:
- SGD打乱视频序列顺序,然后遍历所有的视频序列,对于每个视频序列的处理,过程如下:
- 从该视频序列中随机抽取8帧,然后从每一帧抽取4个正样本(IOU>=0.7)和12个负样本(IOU<=0.5)的bounding box,再从原图中截取出对应的图片,resize为107*107作为网络的输入
- 分别计算出正样本和负样本的得分(FC6层的输出值,还没有经过softmax)
- 将正样本的输出结果和负样本的输出结果放到损失函数中进行计算(log_softmax,正样本计算输出为目标的得分,负样本计算输出为背景的得分,然后求和)
- 反向传播,更新参数,计算精度
一次迭代过后计算平均精度,若比上一个模型效果好便保存下来
- 在线跟踪
在进行测试序列的在线跟踪时,使用一个新的单分支的FC6层来代替原来网络的多分支FC6层,然后在线微调FC4-FC6
长期更新
每隔10帧更新一次,详细内容见下文"在线跟踪的过程"
短期更新
每当跟踪出错时更新一次,详细内容见下文"在线跟踪的过程"
困难负样本挖掘
从生成的1024个负样本中选取96个对训练最有价值的负样本,详细内容见下文"在线跟踪的过程"
bounding box regression
目的是微调候选窗口,使得跟踪效果更好
候选框生成
在每一帧上根据前一帧预测的目标位置生成一个符合高斯分布的256个候选框(符合一定的overlap ratio,translation and scale dimension要求,生成的候选框表示为(min_x, min_y, w, h)),然后从原图中截取候选框区域,再将大小统一为107*107作为网络的输入进行计算。
训练数据
离线多域训练的数据:从每一帧上收集50个正样本(IOU>=0.7)和200个负样本(IOU<=0.5)【此处的IOU是和ground truth比较】
在线学习的数据:从每一帧上收集50个正样本(IOU>=0.7)和200个负样本(IOU<=0.3)【此处的IOU是和上一帧预测的bounding box 比较】,注意第一帧需要生成500个正样本(IOU>=0.7)和5000个负样本(IOU<=0.5)【此处的IOU是和ground truth比较】,用于训练bounding box regression.
网络学习
对于具有K个视频序列的多域学习,对网络进行100K次迭代训练,卷积层的学习率为0.0001,全连接层的学习率为0.001。
对于测试序列的初始化框架,对全连接层进行30次迭代训练,FC4-5的学习率为0.0001,FC6的学习率为0.001。
对于在线更新,为了快速适应对初始化框架的全连接层进行10次迭代训练,FC4-5的学习率为0.0001*3,FC6的学习率为0.001*3。
动量梯度下降系数为0.9,权重衰减的系数为0.0005。
每个mini-batch包含M+(= 32)个正样本和从M-(= 1024)个负样本中选出的M h -(= 96)个困难负样本。
- 在线跟踪的过程
- 加载第一帧图片,初始化target bounding box 为第一帧图片的ground truth,生成1000张符合要求的候选区域(IOU>=0.6),将这1000张候选区域输入到网络,得到conv3的特征,然后利用这些特征结合ground truth进行bounding box regression训练
- 针对第一帧生成500个正样本(IOU>0.7)和5000个负样本(IOU<0.5)区域,并提取正负样本conv3的特征(为什么要提取conv3的特征呢?这是由于在线更新时只是微调全连接层的参数用来适应不同的视频序列,卷积层是不发生改变的,这样做的好处是可以提高计算效率并且通过保留域独立信息来避免过拟合情况的发生)
- 对网络进行30次的迭代训练,每次迭代随机抽取32个正样本的conv3特征和1024个负样本的conv3特征,构成一个mini-batch,然后将这1024个负样本放入测试模型中,做1024/256次循环,计算得分(输入是FC4,输出是FC6,计算结果为(256,2),分别表示背景的得分和目标的得分,只保留计算结果是目标的得分),然后从这1024个负样本中挑选出96个计算目标得分最大的作为困难负样本。接着导入训练模型,分别计算正样本(32个)的得分和困难负样本(96个)的得分,前向传播计算损失(FC4层到FC6层),然后进行优化器优化以及更新参数等(这一部分与多域训练相同)
接下来是每一帧的跟踪过程,每一帧跟踪过程如下:
- 根据上一帧的target bounding box 生成256个候选区域
- 前向传播计算这256个候选区域的得分(conv1-FC6),挑选出计算目标得分最高的5个,对这5个候选区域取平均生成当前帧的target bounding box,并且计算这5个区域得分的平均值,与一个阈值(作者代码中提供的是0)比较,判断是否跟踪成功。若成功,则进行bounding box 微调;若跟踪不成功,首先扩大搜索区域(下一帧生成候选区域时用到),然后复制前一帧的结果为当前帧的结果。
- 跟踪成功时收集数据:根据当前帧预测的target bounding box 生成50个正样本区域(IOU>=0.7),生成200个负样本区域(IOU<=0.3),然后分别对这些样本区域进行前向传播,最后保存的是这些区域的conv3特征 【其中帧数超过100个则抛弃最早的那些帧的正样本区域,帧数个数若超过20个则抛弃最早的那些帧的负样本区域】
- 跟踪失败时进行网络的短期更新,选择最近的20帧的正样本和负样本(这些正样本和负样本都是以conv3特征进行保存),然后进行迭代训练15轮,迭代过程和步骤3相同
- 每10帧进行一次长期更新,选择最近100帧的正样本区域和最近20帧的负样本区域进行网络更新,然后迭代15轮,迭代过程和步骤3相同
只有详细的阅读代码才能更好的理解论文,以下是我对作者提供的代码加了些许注释(修改了代码中的部分内容使其兼容python3,故需要python3版本才能执行),希望能方便读者的阅读。
代码链接:https://download.youkuaiyun.com/download/qq_35323001/10791225