原文地址: https://blog.csdn.net/nus_cs/article/details/78964207
weiliu89在caffe里面加了这么一堆东西,来做他的ssd,我觉得作者实在是有点overdesign了,把代码搞的可读性很差。而且很关键的一点是,这哥们不喜欢在代码里加任何空行,所有代码都密密麻麻挤在一起。你的屏幕面积就那么宝贵么?
费了好几天劲,终于大概看完了他的代码,大概有这么些东西:
数据集准备
caffe/data/coco
caffe/tools/convert_annoset.cpp
caffe proto
LabelMapItem, LabelMap,
NormalizedBBox, Annotation, AnnotationGroup, AnnotatedDatum
ExpansionParameter,
SaltPepperParameter, NoiseParameter, DistortionParameter,
Sampler, SampleConstraint, BatchSampler, EmitConstraint
ResizeParameter,
AnnotatedDataParameter
PriorBoxParameter
MultiBoxLossParameter
NonMaximumSuppressionParameter, SaveOutputParameter, DetectionOutputParameter
新增的h/cpp/cu代码
layers/annotated_data_layer.hpp/cpp
layers/detection_evaluate_layer.hpp/cpp
layers/detection_output_layer.hpp/cpp/cu
layers/multibox_loss_layer.hpp/cpp
layers/prior_box_layer.hpp/cpp
layers/smooth_L1_loss_layer.hpp/cpp/cu
util/bbox_util.hpp/cpp/cu
util/im_transforms.hpp/cpp
util/samper.hpp/cpp
data_transformer.hpp/cpp
然后其实他的算法过程就是这么些东西:
Annotated data layer和data transformer
Annotated data layer产生图像以及图像中标记的目标框。图像以及目标框经过data
transformer进行一系列变换,依次为:
(1) Image distortion;
(2) Image expansion;
(3) Sampling a random crop window;
(4) Data transform: Adding noise, resizing,
步骤(1)中,使用了caffe proto中的DistortionParameter.
步骤(2)中,使用了caffe proto中的ExpansionParameter。
步骤(3)中,使用了caffe proto中的Sampler, SampleConstraint, BatchSampler。
步骤(4)中,使用了caffe proto中的ResizeParameter和NoiseParameter,先resize 然后加
noise,并且将去掉中心点落到图像外的目标框。
AnnotatedDataLayer输出的目标表示为N81*1的tensor,有N个目标,8个值分别为:
(0) - 来自batch中的第i张图片;
(1) - 目标类别;
(2) - 目标序号;
(3-7) - xmin, ymin, xmax, ymax坐标,均为相对图像宽高归一化到[0, 1]之间的值;
(8) - 是否difficult。
Prior box layer产生prior box
Prior box layer根据图像大小和feature map大小,以及预设的参数,生成prior box。
PriorBoxParameter中,指定了min_size,max_size,和aspect_ratio。另外还有参数flip
和clip,如果flip为true,则将有一组额外的aspect ratio。如果clip为true,则将超出图
像边缘的prior box固定到图像内。作者给的训练网络中flip为true,clip为false。
每个min_size和aspect_ratio的组合生成一个prior box,每个max_size 再生成一个额外的
prior box。在作者的训练网络中,每个prior box用xmin,ymin,xmax,ymax表示,均为相
对于图像宽高的归一化值。此外每个prior box还有4个variance值,用于计算损失时对坐标
进行归一化。作者在训练网络中将这4个variance分别设置为0.1, 0.1, 0.2, 0.2。
Multi box loss layer计算multi box loss
在计算multi box loss时,依次进行如下操作:
(1) GetGroundTruth,从blob复原回NormalizedBBox。
(2) GetPriorBoxes,获取feature map上每个点对应的prior box。
(3) GetLocPredictions,获取feature map上每个点的预测的目标框。注意对不同类别共用
一个目标框。
(4) FindMatches,将prior box与groundtruth box进行匹配,找到prior box中哪些应作为
正样本。这里如下参数发挥作用:
- use_prior_for_matching:在作者的代码中为true,即匹配prior box与gnd box。
- overlap_threshold:控制了判定样本为正样本的覆盖率阈值。
- match_type:在作者的代码中设置为PER_PREDICTION,即对每个 gnd box,选择最佳
匹配的prior box作为positive box,以及对每个prior box,如果与其覆盖率最高的
gnd box的覆盖率超过overlap_threshold,也将其作为positive box。
(5) MinHardExamples,选择hard negative window。这里如下参数发挥作用:
- do_neg_mining
- mining_type
- use_prior_for_nms
- nms_param
- neg_pos_ratio:
- neg_overlap:如果prior box与gnd box的覆盖率超过此值,则不作为negative。
- sample_size
在进行hard neg mining时,按如下步骤进行计算:
- 计算每个prior box的confidence loss。
- 如果mining_type为HARD_EXAMPLE,计算location loss,并将location loss和conf
loss加起来作为损失。注意prior box和gnd box为(xmin, ymin, xmax, ymax)格式,
但location pred为(ncx, ncy, nw, nh)格式,其中ncx,ncy为中心点偏移,用prior
box宽高和variance[0]和 variance[1]归一化。nw和nh为宽度和高度偏移,用prior
box宽高和variance[2]和variance[3]归一化。需要依次调用EncodeLocPrediction和
ComputeLocLoss计算位置损失。
- 如果has_nms_param为true,则对negative window进行nms后再选取。
如果use_prior_for_nms,则使用prior box进行nms,否则使用pred box进行nms。在
进行nms之前需要先调用DecodeBBoxes将pred bbox转化为(xmin, ymin, xmax, ymax)
格式,然后再调用ApplyNMS。
- 如果mining_type为MAX_NEGATIVE,则根据neg_pos_ratio以及positive数目确定选取
的negative数目,否则根据sample_size确定要选取的negative数目。
上面这几步完了之后,就是调用具体的loss layer计算损失值了。在backward时,也只需要
将loss layer传回来的diff拷贝到对应窗口的feature map的diff中即可。
作者:nus_cs
来源:CSDN
原文:https://blog.csdn.net/nus_cs/article/details/78964207?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!