Tensorflow v1.10 + манипулирование записями в данных tf для создания их меток - PullRequest
0 голосов
/ 23 апреля 2019

Этот вопрос является продолжением двух предыдущих вопросов:

Для контекста эти два предыдущих вопроса охватывают обработку pre шаг, т.е. преобразование ваших данных в соответствие с примером Tensorflow (Sequence) (tf.train.Example / tf.train.SequenceExample), чтобы вы могли использовать формат записи Tensorflow.Кроме того, они относятся к этапу «восстановления», т. Е. Учитывая, что ваши данные теперь являются Tensorflow Record, как их преобразовать в tf.data.Dataset.Есть также два связанных колба (1, 2).

Этот вопрос относится к шагам 3/4 или предварительной обработке (см. Схему ниже).для справки).Знание предыдущих шагов может быть уместным.

data pipeline
(1) raw data
    |
    |
    | (pre-pre-preprocessing: raw data to cleaned data)
    |
    v
(2) cleaned data
    |
    |
    | (pre-preprocessing: cleaned data into (Sequence)Example / Record)
    |
    v
(3) tf.Record (<-- tf docs tend to believe that your data starts here)
    |
    |
    | (recovery: tf.data.TFRecordDataset(filenames).map(lambda r: parse(r)))
    |
    v
(4) tf.data.Dataset
    |
    |
    | (preprocessing: dataset.map() etc into final (features, labels) form
    |
    v
(5) data iterator
    |
    |
    |
    |
    |
    v
(6) train

Итак, теперь мы разбросали наши данные по нескольким файлам записей:

n_shards = 10
tf_record_files = ['shard_{}.record'.format(i) for i in range(n_shards)]

и создали набор данных тензорного потока:

ds = tf.data.TFRecordDataset(tf_record_files)

первое, что нужно сделать, - это проанализировать наш (Sequence) пример Protos («записи»)

context_features = {
    # whatever you data is
}
sequence_features = None # or whatever your sequence features are

def parse_fn(record, ctx_fts, seq_fts=None):
    p = tf.parse_single_example if seq_fts is None else tf.parse_single_sequence_example
    return p(record, context_features=ctx_fts, sequence_features=seq_fts)

ds = ds.map(lambda r: parse_fn(r, context_features, sequence_features))

или при использовании сторонней библиотеки, такой как fio :

from fio import FIO 
schema = {
    # data structure
}
fio = FIO(schema)
ds = ds.map(lambda r: fio.from_record(r))

предположим, что для одного примера у нас есть что-то вроде:

# example
{
    'a': 10,
    'b': 20,
    'c': 'e1'
}

, тогда (при условии ds.batch(1)) наш пример на данный момент:

{
    'a': <tf.Tensor 'ParseSingleExample/ParseSingleExample:0' shape=() dtype=int64>,
    'b': <tf.Tensor 'ParseSingleExample/ParseSingleExample:1' shape=() dtype=int64>,
    'c': <tf.Tensor 'ParseSingleExample/ParseSingleExample:2' shape=() dtype=string>

}

и работает sess.eval:

{
    'a': array([10]),
    'b': array([20],
    'c': array([b'e1']
}

Это примечательно как 1. данные являются типами TF и ​​должны обрабатываться как таковые; 2. строки двоично кодируются (даже после eval).

У меня есть функция python, которая упаковывает системную команду, которая преобразует строку tsv

# e.g. something like this
labels = convert_tsv_to_labels(tsv_string)

, где tsv_string будет выглядеть примерно так:

"""
10\t20\e1\n    # <--- example 1
20\t15\e2\n
"""

какэта функция 1. Python (хотя она вызывает os.subprocess) 2. Нетривиально, было бы неплохо использовать это вшаг предварительной обработки.Кроме того, этикетки могут меняться в зависимости от эпохи.Таким образом, мой вопрос заключается в том, как сделать это в точке конвейера преобразования данных.Предварительный расчет и хранение всех меток является чрезмерным.

Тем не менее, в этот момент атрибуты разбиваются на массивы TF.Итак, как бы я поступил об этом?

Например,

def transform_fn(record):
    tsv_str = record_to_tsv
    record['label'] = convert_tsv_to_labels(tsv_str)
    return record

ds.map(lambda r: transform_fn(r))

Примечание: эта функция может обрабатывать несколько строк одновременно

...