Вопрос TFRecord - лучший способ сериализации / загрузки моего набора данных - PullRequest
0 голосов
/ 27 апреля 2020

Здравствуйте, заранее спасибо за чтение этого вопроса и любую помощь, которую вы можете предложить.


Сводка вопроса

Я sh заберу свой набор данных и сериализую (& осколок), используя TFRecords в TF 2.x. Документация и учебные пособия охватывают базовые c случаи TFRecord сериализации, но не хватает документации и / или учебных пособий, охватывающих более сложные варианты использования.

В моем нынешнем виде у меня есть метод сериализации и десериализации, который работает, но я хочу посмотреть, есть ли лучший способ.

Проект, над которым я работаю, должен следовать передовым методам, и поэтому я хочу убедиться, что использую все возможности, чтобы делать все правильно.

Я ищу объективный метод наилучшей практики для сериализации и десериализации набора сложных-i sh, как в примере, который я опубликовал ниже.


Мой набор данных

  • У меня есть набор данных, состоящий из 5000+ изображений.
    • Каждое изображение имеет уникальные метаданные (потенциально переменная ширина, высота)
    • Каждое изображение содержит людей ( субъектов ) и других объекты .
      • Люди считаются субъектами , а также объектами
      • Объектами считаются только объект
    • Каждое изображение имеет аннотации, которые относятся к конкретному c объектам, с которыми он / она взаимодействует. Эта информация о субъект-объектных отношениях имеет следующий вид:
      • Метка субъекта
        • Целое число, соответствующее метке person
      • Метка (и) объекта
        • Целое число (я), соответствующее соответствующей метке (ам)
      • Метка (и) предиката (глагола)
        • Целое число (я), соответствующее соответствующей взаимосвязи, которая описывает взаимосвязь между каждой парой субъект-объект
      • Тема Bbox
        • Список Ints [xmin, xmax, ymin, ymax]
      • Объект (ы) Bbox
        • Список значений [xmin, xmax, ymin, ymax]
Пример:

На этом рисунке показан удар бейсболиста (subject) (predicate) бейсбол (object). Есть два отношения субъект-объект-предикат для описания. Отношения между бейсболистом и битой и отношения между бейсболистом и бейсболом. Мы не будем углубляться в сложности маркировки, но предположим, что существует структура маркировки субъект-предикат-объект, где это имеет смысл.

Baseball Player Hitting Baseball


Моя попытка при сериализации

I l oop над каждым изображением и выполнение следующих действий:

  1. Инициализация словаря для хранения сериализованной информации и присвоение некоторых основных c мета для изображения. self.get_img_from_img_idx() вернет изображение в виде байтовой строки, т.е. return open(img_path, 'rb').read(). img_meta["width"] и img_meta["height"] возвращают целые числа.
serialized_info = {
            "image/encoded":self.get_img_from_img_idx(idx, as_string=True),
            "image/width":img_meta["width"],
            "image/height":img_meta["height"],
            "image/subject/label":[],
            "image/subject/bbox/xmin":[],
            "image/subject/bbox/xmax":[],
            "image/subject/bbox/ymin":[],
            "image/subject/bbox/ymax":[],
            "image/object/label":[],
            "image/object/bbox/xmin":[],
            "image/object/bbox/xmax":[],
            "image/object/bbox/ymin":[],
            "image/object/bbox/ymax":[],
            "image/predicate/label":[],
        }
Заполняйте оставшиеся списки по одному для каждой пары субъект-объект-предикат. то есть для спаривания baseball-player-baseball-bat-holding вы можете добавить следующее ...
serialized_info = {
            "image/encoded": ...,
            "image/width": ...,
            "image/height": ...,
            "image/subject/label":[..., 1],       # Let's say 1 is the label for person
            "image/subject/bbox/xmin":[..., 10],  # These are obviously bogus numbers
            "image/subject/bbox/xmax":[..., 100], # They are just here for visualizing
            "image/subject/bbox/ymin":[...,10],
            "image/subject/bbox/ymax":[...,100],
            "image/object/label":[..., 8],        # Let's say 8 is the label for baseball-bat
            "image/object/bbox/xmin":[..., 50],   # These are obviously bogus numbers
            "image/object/bbox/xmax":[..., 200],  # They are just here for visualizing
            "image/object/bbox/ymin":[..., 80],
            "image/object/bbox/ymax":[..., 100],
            "image/predicate/label":[..., 100],   # Let's say 100 represents the relationship 'holding'
        }

Теперь у нас есть законченный словарь, который содержит всю необходимую информацию, относящуюся к одному изображению (Example). Здесь я начинаю сомневаться ... Теперь мы конвертируем значения нашего словаря в **tf.train.Feature** с, выполнив следующие действия.

  • Для изображения

    • tf.train.Feature(bytes_list=tf.train.BytesList(value=[img]))
  • Для мета-изображения

    • tf.train.Feature(int64_list=tf.train.Int64List(value=[img_meta_value]))
  • Для списки меток и значений bbox

    • tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_vals))
    • Обратите внимание, что здесь мы не переносим значение в список

Это где я продолжаю быть неуверенным. Теперь мы преобразуем наш словарь tf.train.Feature** с в один объект **tf.train.Features, после чего мы преобразуем этот объект в tf.train.Example. Для этого я использую следующую команду (предположим, serialized_info - словарь **tf.train.Feature** с)

tf_ex = tf.train.Example(features=tf.train.Features(feature=serialized_info))
Затем я использую tf.io.TFRecordWriter и команду tf_ex.SerializeToString() для создания моего заштрихованного набора данных (я относительно уверен, что это все правильно).

Моя попытка при десериализации

  1. При загрузке теперь очищенного набора данных. Я определяю шаблон и определяю словарь описания возможностей. Я очень не уверен в этом.
feature_description = {
    "image/encoded":tf.io.FixedLenFeature([], tf.string),
    "image/width":tf.io.FixedLenFeature([], tf.int64, default_value=0),
    "image/height":tf.io.FixedLenFeature([], tf.int64, default_value=0),
    "image/subject/label":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/subject/bbox/xmin":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/subject/bbox/xmax":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/subject/bbox/ymin":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/subject/bbox/ymax":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/object/label":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/object/bbox/xmin":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/object/bbox/xmax":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/object/bbox/ymin":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/object/bbox/ymax":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    "image/predicate/label":tf.io.FixedLenSequenceFeature([], tf.int64, default_value=0, allow_missing=True),
    }
Теперь, когда у меня загружен набор данных и сделано описание функции. Я использую следующие функции для разбора tfrecord.
def _parse_function(example_proto):
    # Parse the input `tf.Example` proto using the dictionary above.
    return tf.io.parse_single_example(example_proto, feature_description)

def parse_tfrecord(example_proto):

    # Decode features using _parse_function containing proto format
    features = _parse_function(example_proto)
    img = tf.image.decode_image(features['image/encoded'],
                                  channels=3,
                                  dtype=tf.uint8)

    img_w = features["image/width"]
    img_h = features["image/height"]

    iterables = [features["image/subject/label"], 
                 features["image/object/label"],
                 features["image/predicate/label"],
                 features["image/object/bbox/xmin"],
                 features["image/object/bbox/xmax"],
                 features["image/object/bbox/ymin"],
                 features["image/object/bbox/ymax"],
                 features["image/subject/bbox/xmin"],
                 features["image/subject/bbox/xmax"],
                 features["image/subject/bbox/ymin"],
                 features["image/subject/bbox/ymax"],]

    for iterable in zip(*iterables):
        subj_label, obj_label, pred_label = iterable[:3]
        obj_bbox = iterable[3:7]
        obj_xmin, obj_xmax, obj_ymin, obj_ymax = obj_bbox

        subj_bbox = iterable[7:]
        subj_xmin, subj_xmax, subj_ymin, subj_ymax = subj_bbox

    # I would then continue to do stuff with the extracted 
    # features (that are now tensors containing the relevant data)
    # ...

Заключительные замечания

Я понимаю, что это невероятно подробный вопрос. Я заранее прошу прощения за то, как подробно я получил. Это сложная тема c, и я хотел изложить все как можно более четко. Кроме того, я подробно изучил учебные пособия по Tensorflow, а также несколько средних статей ... Я включу ссылки ниже.

Еще раз спасибо!


Ссылки

...