Skip to content

Verify the correctness of detection_output API in SSD.  #8687

Closed
@qingqing01

Description

@qingqing01
  • Target: this verification is to make the detection consistent with Caffe.

  • Method: similar to Verify the correctness of SSD loss. #8626 (comment)

  • The main code of fluid is as follows, which will check the output label, scores, boxes and output LoD.

    import paddle.v2 as paddle
    import paddle.fluid as fluid
    import numpy as np
    
    def load(file_name, shape):
        with open(file_name, 'rb') as f:
            return np.fromfile(f, dtype=np.float32).reshape(shape)
    
    def load_data(loc_shape, conf_shape, prior_shape, out_shape):
        loc = load('detection_data/detect_loc_data', loc_shape)
        conf = load('detection_data/detect_conf_data', conf_shape)
        prior = load('detection_data/detect_prior_data', prior_shape)
        pb = prior[0, :]
        pbv = prior[1, :]
    
        decode_box = load('detection_data/detect_decode_bboxes_data', loc_shape)
        out = load('detection_data/detection_output_data', out_shape)
    
        return loc, conf, pb, pbv, decode_box, out
    
    def detection_output_check():
        p_num = 8732
        num_class = 21
    
        conf = fluid.layers.data(name='conf', shape=[p_num, num_class], dtype='float32')
        loc = fluid.layers.data(name='loc', shape=[p_num, 4], dtype='float32')
        prior = fluid.layers.data(name='prior', shape=[p_num, 4], dtype='float32', append_batch_size=False)
        prior_var = fluid.layers.data(name='prior_var', shape=[p_num, 4], dtype='float32', append_batch_size=False)
    
        out = fluid.layers.detection_output(loc, conf, prior, prior_var, nms_threshold=0.45)
        out.persistable = True
    
        place = fluid.CPUPlace()
        exe = fluid.Executor(place)
    
        loc_shape = [-1, p_num, 4]
        conf_shape = [-1, p_num, num_class]
        proir_shape = [2, p_num, 4]
        out_shape = [-1, 7]
    
        loc_t, conf_t, pb_t, pbv_t, decode_box, expect_out = load_data(loc_shape, conf_shape, proir_shape, out_shape)
    
        feeding = {'loc': loc_t, 'conf': conf_t, 'prior': pb_t, 'prior_var': pbv_t}
        #print fluid.default_main_program()
        out_v, = exe.run(fluid.default_main_program(), feed=feeding, fetch_list=[out], return_numpy=False)
    
        out_arr = np.array(out_v)
        out_var = fluid.global_scope().find_var('detection_output_0.tmp_0').get_tensor()
        fluid_lod = out_var.lod()
    
        fluid_label = out_arr[:, 0]
        fluid_score = out_arr[:, 1]
        fluid_box = out_arr[:, 2:6]
    
        caffe_iterm = expect_out[:, 0].astype(int).tolist()
        caffe_label = expect_out[:, 1]
        caffe_score = expect_out[:, 2]
        caffe_box = expect_out[:, 3:7]
    
        batch_size = max(caffe_iterm) + 1 # iterm index is from 0
        lod = [0 for i in range(batch_size + 1)]
        for i in range(batch_size):
            lod[i + 1] = lod[i] + caffe_iterm.count(i)
    
        score_diff = caffe_score - fluid_score
        box_diff = caffe_box - fluid_box
    
        caffe_lod = np.array(lod).astype(int)
        fluid_lod = np.array(fluid_lod).astype(int)
    
        assert caffe_label.any() == fluid_label.any()
        assert caffe_lod.any() == fluid_lod[0].any()
        print 'the shape of fluid output', out_arr.shape
        print 'the shape of caffe output', expect_out.shape
        print 'score diff', score_diff[score_diff > 0.]
        print 'box diff', box_diff[box_diff > 0.]
    
    if __name__ == '__main__':
        detection_output_check()
  • Results:

    • batch_size=2
    • one mini-batch testing data
    • same inputs, the outputs of above code are:
    the shape of fluid output (400, 6)
    the shape of caffe output (400, 7)
    score diff []
    box diff [  2.98023224e-08   7.45058060e-09   5.96046448e-08   7.45058060e-09
    7.45058060e-09   7.45058060e-09   7.45058060e-09   7.45058060e-09
    3.72529030e-09   2.98023224e-08   3.72529030e-09   2.98023224e-08
    7.45058060e-09   2.98023224e-08   7.45058060e-09   7.45058060e-09
    7.45058060e-09   3.72529030e-09   5.96046448e-08   7.45058060e-09
    1.49011612e-08   5.96046448e-08   3.72529030e-09   2.98023224e-08
    2.98023224e-08   5.96046448e-08   7.45058060e-09   2.98023224e-08
    7.45058060e-09   1.49011612e-08   3.72529030e-09   1.49011612e-08
    2.98023224e-08   2.98023224e-08   5.96046448e-08   2.98023224e-08
    2.98023224e-08   2.98023224e-08   2.98023224e-08   2.98023224e-08
    2.98023224e-08   5.96046448e-08   2.98023224e-08   2.98023224e-08
    3.72529030e-09   2.98023224e-08   1.49011612e-08   5.96046448e-08
    7.45058060e-09   2.98023224e-08   7.45058060e-09   3.72529030e-09
    3.72529030e-09   7.45058060e-09   5.96046448e-08   1.49011612e-08
    5.96046448e-08   1.49011612e-08   1.49011612e-08   1.49011612e-08
    3.72529030e-09   7.45058060e-09]
    

    From this results, we can see that there is no diff for output label index and score and LoD. Some boxes have diff, but the absolute error is about 0.000006 % ~ 0.000007 %, this is very small.

  • Conlusion

    There is no problem of detection_output API, which is consistent with Caffe.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions