代码之家  ›  专栏  ›  技术社区  ›  Vadim Smolyakov

TensorFlow对象检测API中用于平衡数据的类权重

  •  2
  • Vadim Smolyakov  · 技术社区  · 7 年前

    我正在微调 SSD 物体探测器 TensorFlow object detection API 在…上 Open Images Dataset . 我的培训数据包含不平衡的课程,例如。

    1. 顶部(5K图像)
    2. 连衣裙(50K图片)

    我想将类权重添加到分类损失中以提高性能。我该怎么做?配置文件的以下部分似乎相关:

    loss {
      classification_loss {
        weighted_sigmoid {
        }
      }
      localization_loss {
        weighted_smooth_l1 {
        }
      }
     ...
      classification_weight: 1.0
      localization_weight: 1.0
    }
    

    2 回复  |  直到 7 年前
        1
  •  11
  •   simo23    7 年前

    API希望每个对象(bbox)直接在 注释文件 . 由于这一要求,使用等级权重的解决方案似乎是:

    1) 如果有自定义数据集,则可以修改每个对象(bbox)的注释,以将权重字段包含为“对象/权重”。

    只有tf_记录 文件以包括BBox的重量。

    3) 修改API的代码(在我看来相当棘手)

    我决定选择#2,所以我把代码放在这里来生成 加重 风俗 数据集包含两个类(“top”、“dress”),权重为(1.0,0.1),文件夹为 xml 注释如下:

    import os
    import io
    import glob
    import hashlib
    import pandas as pd
    import xml.etree.ElementTree as ET
    import tensorflow as tf
    import random
    from PIL import Image
    from object_detection.utils import dataset_util
    
    # Define the class names and their weight
    class_names = ['top', 'dress', ...]
    class_weights = [1.0, 0.1, ...]
    
    def create_example(xml_file):
    
            tree = ET.parse(xml_file)
            root = tree.getroot()
            image_name = root.find('filename').text
            image_path = root.find('path').text
            file_name = image_name.encode('utf8')
            size=root.find('size')
            width = int(size[0].text)
            height = int(size[1].text)
            xmin = []
            ymin = []
            xmax = []
            ymax = []
            classes = []
            classes_text = []
            truncated = []
            poses = []
            difficult_obj = []
            weights = [] # Important line
    
            for member in root.findall('object'):
    
               xmin.append(float(member[4][0].text) / width)
               ymin.append(float(member[4][1].text) / height)
               xmax.append(float(member[4][2].text) / width)
               ymax.append(float(member[4][3].text) / height)
               difficult_obj.append(0)
    
               class_name = member[0].text
               class_id = class_names.index(class_name)
               weights.append(class_weights[class_id])
    
               if class_name == 'top':
                   classes_text.append('top'.encode('utf8'))
                   classes.append(1)
               elif class_name == 'dress':
                   classes_text.append('dress'.encode('utf8'))
                   classes.append(2)
               else:
                   print('E: class not recognized!')
    
               truncated.append(0)
               poses.append('Unspecified'.encode('utf8'))
    
            full_path = image_path 
            with tf.gfile.GFile(full_path, 'rb') as fid:
                encoded_jpg = fid.read()
            encoded_jpg_io = io.BytesIO(encoded_jpg)
            image = Image.open(encoded_jpg_io)
            if image.format != 'JPEG':
               raise ValueError('Image format not JPEG')
            key = hashlib.sha256(encoded_jpg).hexdigest()
    
            #create TFRecord Example
            example = tf.train.Example(features=tf.train.Features(feature={
                'image/height': dataset_util.int64_feature(height),
                'image/width': dataset_util.int64_feature(width),
                'image/filename': dataset_util.bytes_feature(file_name),
                'image/source_id': dataset_util.bytes_feature(file_name),
                'image/key/sha256': dataset_util.bytes_feature(key.encode('utf8')),
                'image/encoded': dataset_util.bytes_feature(encoded_jpg),
                'image/format': dataset_util.bytes_feature('jpeg'.encode('utf8')),
                'image/object/bbox/xmin': dataset_util.float_list_feature(xmin),
                'image/object/bbox/xmax': dataset_util.float_list_feature(xmax),
                'image/object/bbox/ymin': dataset_util.float_list_feature(ymin),
                'image/object/bbox/ymax': dataset_util.float_list_feature(ymax),
                'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
                'image/object/class/label': dataset_util.int64_list_feature(classes),
                'image/object/difficult': dataset_util.int64_list_feature(difficult_obj),
                'image/object/truncated': dataset_util.int64_list_feature(truncated),
                'image/object/view': dataset_util.bytes_list_feature(poses),
                'image/object/weight': dataset_util.float_list_feature(weights) # Important line
            })) 
            return example  
    
    def main(_):
    
        weighted_tf_records_output = 'name_of_records_file.record' # output file
        annotations_path = '/path/to/annotations/folder/*.xml' # input annotations
    
        writer_train = tf.python_io.TFRecordWriter(weighted_tf_records_output)
        filename_list=tf.train.match_filenames_once(annotations_path)
        init = (tf.global_variables_initializer(), tf.local_variables_initializer())
        sess=tf.Session()
        sess.run(init)
        list = sess.run(filename_list)
        random.shuffle(list)  
    
        for xml_file in list:
          print('-> Processing {}'.format(xml_file))
          example = create_example(xml_file)
          writer_train.write(example.SerializeToString())
    
        writer_train.close()
        print('-> Successfully converted dataset to TFRecord.')
    
    
    if __name__ == '__main__':
        tf.app.run()
    

    如果您有其他类型的注释,代码将非常类似,但不幸的是,这一种将无法工作。

        2
  •  2
  •   Vadim Smolyakov    7 年前

    https://github.com/tensorflow/models/blob/master/research/object_detection/core/losses.py

    特别是,实施了以下损失类别:

    1. 加权乙状结肠分类损失
    2. 乙状结肠局部分类损失
    3. 加权最大分类损失
    4. 加权SoftMaxClassificationAgainstLogitsLoss
    5. 自举SigmoidClassificationLoss

    本地化损失:

    1. 加权二次定位损失

    重量参数用于平衡锚(先前的箱子)并具有一定的尺寸 [batch_size, num_anchors] 除了硬负开采。或者 focal loss 轻视分类良好的示例,并将重点放在硬示例上。

    推荐文章