Запись ZipDataSet в TFRecord - PullRequest
       26

Запись ZipDataSet в TFRecord

2 голосов
/ 19 марта 2019

Я пытаюсь записать сжатый набор данных в файлы TFRecord после этого учебное пособие , но моя ситуация отличается тем, что каждый элемент каждого набора данных в ZipDataSet представляет собой тензор, а не скаляр.

В руководстве рассматривается это обстоятельство с примечанием

Примечание. Для простоты в этом примере используются только скалярные входные данные. Самым простым способом обработки нескалярных функций является использование tf.serialize_tensor для преобразования тензоров в двоичные строки. Строки являются скалярами в тензорном потоке. Используйте tf.parse_tensor для преобразования двоичной строки обратно в тензор.

Но я получаю ошибки, которые указывают на то, что функция _bytes_feature получает тензоры, а не байты.

import tensorflow as tf
import numpy as np

sess = tf.Session()
def _bytes_feature(value):
    """Returns a bytes_list from a string / byte."""
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))


def serialize_with_labels(a, b, c, d):
    """
    Creates a tf.Example message ready to be written to a file.
    """

    # Create a dictionary mapping the feature name to the tf.Example-compatible
    # data type.

    feature = {'a': _bytes_feature(a),
               'b': _bytes_feature(b),
               'c': _bytes_feature(c),
               'd': _bytes_feature(d),
                }

    # Create a Features message using tf.train.Example.

    example_proto = tf.train.Example(features=tf.train
                                                .Features(feature=feature))
    return example_proto.SerializeToString()


def tf_serialize_w_labels(a, b, c, d):
    """Map serialize_with_labels to tf.data.Dataset."""
    tf_string = tf.py_func(serialize_with_labels,
                           (a, b, c, d),
                           tf.string)
    return tf.reshape(tf_string, ())

# a is a [n,m,p] tensor
# b is a [n,m,p] tensor
# c is a [n,m,p] tensor
# d is a [n,1,1] tensor

zipped = tf.data.Dataset().from_tensor_slices((a,b,c,d))
# I have confirmed that each item of serial_tensors is a tuple
# of four bytestrings.
serial_tensors = zipped.map(tf.serialize_tensor)

# Each item of serialized_features_dataset is a single bytestring
serialized_features_dataset = serial_tensors.map(tf_serialize_w_labels)
writer = tf.contrib.data.TFRecordWriter('test_output')
writeop = writer.write(serialized_features_dataset)
sess.run(writeop)

Базовый формат кода, который я пытаюсь запустить. Он пишет, но когда я читаю в TFRecord,

def _parse_function(example_proto):
    # Parse the input tf.Example proto using the dictionary below.

    feature_description = {
    'a': tf.FixedLenFeature([], tf.string, default_value=''),
    'b': tf.FixedLenFeature([], tf.string, default_value=''),
    'c': tf.FixedLenFeature([], tf.string, default_value=''),
    'd': tf.FixedLenFeature([], tf.string, default_value='')
    }
    return tf.parse_single_example(example_proto, feature_description)

filenames = ['zipped_TFR']
raw_dataset = tf.data.TFRecordDataset(filenames)
parsed = raw_dataset.map(_parse_function)
parsed_it = parsed.make_one_shot_iterator()

# prints the first element of a
print(sess.run(tf.parse_tensor(parsed_it.get_next()['a'], out_type=tf.int32)))
#prints the first element of b
print(sess.run(tf.parse_tensor(parsed_it.get_next()['b'], out_type=tf.int32)))
#prints the first element of c
print(sess.run(tf.parse_tensor(parsed_it.get_next()['c'], out_type=tf.int32)))
#prints nothing
print(sess.run(tf.parse_tensor(parsed_it.get_next()['d'], out_type=tf.int32)))

Дело не в том, что итератор исчерпан, так как, например, я попытался напечатать d перед печатью a, b или c, ничего не получил, а затем успешно напечатал a в том же сеансе.

Я использую tenorflow-gpu версии 1.10, и на данный момент я застрял с ней, поэтому я использую

writer = tf.contrib.data.TFRecordWriter('test_output')

вместо

writer = tf.data.experimental.TFRecordWriter('test_output')

РЕДАКТИРОВАТЬ: Вот что сработало.

Сначала я сплющил a, b, c и d, чтобы придать им форму [n, -1]. Затем я изменил serialize_w_labels на приведенный ниже код (оставив только tf_serialize_w_examples).

def serialize_w_labels(a, b, c, d, n, m, p):
    # The object we return
    ex = tf.train.SequenceExample()
    # A non-sequential feature of our example
    ex.context.feature["d"].int64_list.value.append(d)
    ex.context.feature["n"].int64_list.value.append(n)
    ex.context.feature["m"].int64_list.value.append(m)
    ex.context.feature["p"].int64_list.value.append(p)
    # Feature lists for the two sequential features of our example
    fl_a = ex.feature_lists.feature_list["a"]
    fl_b = ex.feature_lists.feature_list["b"]
    fl_c = ex.feature_lists.feature_list["c"]
    for _a, _b, _c in zip(a, b, c):
        fl_a.feature.add().int64_list.value.append(_a)
        fl_b.feature.add().int64_list.value.append(_b)
        fl_c.feature.add().float_list.value.append(_c)
    return ex.SerializeToString()

Следующее правильно анализирует элементы результирующего набора данных:

context_features = {
    "d": tf.FixedLenFeature([], dtype=tf.int64),
    "m": tf.FixedLenFeature([], dtype=tf.int64),
    "n": tf.FixedLenFeature([], dtype=tf.int64),
    "p": tf.FixedLenFeature([], dtype=tf.int64)
 }
sequence_features = {
    "a": tf.FixedLenSequenceFeature([], dtype=tf.int64),
    "b": tf.FixedLenSequenceFeature([], dtype=tf.int64),
    "c": tf.FixedLenSequenceFeature([], dtype=tf.float32)
}

context_parsed, sequence_parsed = tf.parse_single_sequence_example(
    serialized=ex,
    context_features=context_features,
    sequence_features=sequence_features
)

Ваши dtypes могут отличаться, очевидно. Затем контекстные объекты можно использовать для изменения формы сплющенных a, b и c.

Ответы [ 2 ]

1 голос
/ 19 марта 2019

Я думаю, вам стоит взглянуть на tf.io.FixedLenSequenceFeature, что позволит вам записать последовательность объектов в виде объекта в файл TFRecord.Например, он использовался в наборе данных YouTube8M для хранения функции, которая для каждого видео представляла собой набор кадров и для каждого из ваших кадров Tensor.

Документы: https://www.tensorflow.org/api_docs/python/tf/io/FixedLenSequenceFeature

Пример, как это читать: https://github.com/google/youtube-8m/blob/2c94ed449737c886175a5fff1bfba7eadc4de5ac/readers.py

0 голосов
/ 23 марта 2019

Если вы хотите использовать tf.serialize_tensor для своих записей, вам нужно будет создать сеанс и оценить тензор.

_bytes_feature(sess.run(tf.serialize_tensor(features[key])))
...