Использование функции window () в наборе данных TensorFlow для доступа к нескольким строкам - PullRequest
0 голосов
/ 02 июля 2019

У меня проблема с преобразованием набора данных, считанного из файлов .csv, с помощью tf.data.experimental.CsvDataset в "временные ряды".

То, что я пытаюсь сделать, это получить доступ к нескольким строкам набора данных одновременно, чтобы добавить объекты предыдущих 2 строк в текущую строку и сохранить метку текущей строки. Я хотел бы сделать это для каждого ряда (кроме первых двух). Я думал, что применение функции window() - правильный подход, но теперь я не уверен.

Исходный набор данных, состоящий примерно из 300 столбцов, создается путем чтения набора файлов .csv, например:

ds = tf.data.experimental.CsvDataset(
            filenames,
            [tf.float32] * len(columns_indices_to_parse),
            header=True,
            select_cols=columns_indices_to_parse
        )

Для воспроизводимости я использую комбинацию Dataset.from_tensor_slices () и Dataset.zip ():

import tensorflow as tf

tf.enable_eager_execution()

with tf.Graph().as_default(), tf.Session() as sess:
    # Simulate what's being returned from CsvDataset():
    feature_1_ds = tf.data.Dataset.from_tensor_slices([1., 3., 5., 7., 9.])
    feature_2_ds = tf.data.Dataset.from_tensor_slices([2., 4., 6., 8., 10.])
    label_1_ds = tf.data.Dataset.from_tensor_slices([1.0, 1.0, 0.0, 1.0, 0.0])

    ds = tf.data.Dataset.zip((feature_1_ds, feature_2_ds, label_1_ds))

    # Do transformations to obtain "timeseries" data.
    def _parse_function_features(*row):
        features = tf.stack(row[:2], axis=-1)
        return features

    def _parse_function_labels(*row):
        labels = tf.stack(row[2:], axis=-1)
        return labels

    def _reshape(x):
        # Flatten rows into one.
        return tf.reshape(x, shape=[-1])

    ds_features = ds.map(_parse_function_features).window(3).flat_map(lambda x: x.batch(3)).map(_reshape)
    ds_labels = ds.map(_parse_function_labels).skip(2)
    ds = tf.data.Dataset.zip((ds_features, ds_labels))

    iter = ds.make_one_shot_iterator().get_next()
    # Show dataset contents
    print('Result:')
    while True:
        try:
            print(sess.run(iter))
        except tf.errors.OutOfRangeError:
            break

Я все еще думаю о преобразовании window (), я видел эту проблему с GitHub, но она не решает мою проблему.

Теперь я получаю:

(array([1., 2., 3., 4., 5., 6.], dtype=float32), array([0.], dtype=float32))
(array([ 7.,  8.,  9., 10.], dtype=float32), array([1.], dtype=float32))

Проблема в том, что он ведет себя как пакет - обрабатывает строки в три раза. Чего я хотел бы добиться, так это:

(array([1., 2., 3., 4., 5., 6.], dtype=float32), array([0.], dtype=float32)) # with label of the third row
(array([3., 4., 5., 6., 7., 8.], dtype=float32), array([1.], dtype=float32)) # with label of the fourth row
(array([5., 6., 7., 8., 9., 10.], dtype=float32), array([0.], dtype=float32)) # with label of the fifth row

Я немного застрял, я не уверен, что использование функции window () для доступа к нескольким строкам набора данных - даже правильный подход. Ранее я задавал очень похожий вопрос, но я удалил его, так как думаю, что включил слишком много деталей, здесь я постарался сделать его как можно более скудным. Любая помощь будет оценена, спасибо!

1 Ответ

0 голосов
/ 03 июля 2019

Хорошо, после решения проблемы со многих сторон, я наконец-то смог достичь требуемого результата. У меня есть два решения: одно, которое обрабатывает объекты и метки как отдельные наборы данных, и второе, которое применяет преобразования к набору данных за один раз. Оба могут быть полезны в зависимости от варианта использования.

  1. Функции процесса и метки в виде отдельных наборов данных:
import tensorflow as tf

tf.enable_eager_execution()

with tf.Graph().as_default(), tf.Session() as sess:
    # Simulate what's being returned from CsvDataset():
    feature_1_ds = tf.data.Dataset.from_tensor_slices([1., 3., 5., 7., 9.])
    feature_2_ds = tf.data.Dataset.from_tensor_slices([2., 4., 6., 8., 10.])
    label_1_ds = tf.data.Dataset.from_tensor_slices([1.0, 1.0, 0.0, 1.0, 0.0])

    ds = tf.data.Dataset.zip((feature_1_ds, feature_2_ds, label_1_ds))

    # Do transformations to obtain "timeseries" data.
    def _parse_function_features(*row):
        features = tf.stack(row[:2], axis=-1)
        return features

    def _parse_function_labels(*row):
        labels = tf.stack(row[2:], axis=-1)
        return labels

    def _reshape(x):
        # Flatten rows into one.
        return tf.reshape(x, shape=[-1])

    ds_features = ds.map(_parse_function_features).window(3, shift=1).flat_map(lambda x: x.batch(3)).map(_reshape)
    ds_labels = ds.map(_parse_function_labels).window(3, shift=1).flat_map(lambda x: x.skip(2))
    ds = tf.data.Dataset.zip((ds_features, ds_labels))

    iter = ds.make_one_shot_iterator().get_next()
    # Show dataset contents
    print('Result:')
    while True:
        try:
            print(sess.run(iter))
        except tf.errors.OutOfRangeError:
            break
  1. Преобразование набора данных за один раз:
import tensorflow as tf

tf.enable_eager_execution()

with tf.Graph().as_default(), tf.Session() as sess:
    # Simulate what's being returned from CsvDataset():
    feature_1_ds = tf.data.Dataset.from_tensor_slices([1., 3., 5., 7., 9.])
    feature_2_ds = tf.data.Dataset.from_tensor_slices([2., 4., 6., 8., 10.])
    label_1_ds = tf.data.Dataset.from_tensor_slices([1.0, 1.0, 0.0, 1.0, 0.0])

    ds = tf.data.Dataset.zip((feature_1_ds, feature_2_ds, label_1_ds))

    # Do transformations to obtain "timeseries" data.
    def _parse_function(*row):
        features = tf.stack(row[:2], axis=-1)
        labels = tf.stack(row[2:], axis=-1)
        return features, labels


    def _reshape(features, labels):
        # Flatten features into one row.
        return tf.reshape(features, shape=[-1]), labels


    ds = ds.map(_parse_function)
    ds = ds.window(3, shift=1)
    ds = ds.flat_map(lambda x, y: tf.data.Dataset.zip((x.batch(3), y.skip(2))))
    ds = ds.map(_reshape)

    iter = ds.make_one_shot_iterator().get_next()
    # Show dataset contents
    print('Result:')
    while True:
        try:
            print(sess.run(iter))
        except tf.errors.OutOfRangeError:
            break

Для обоих из них вывод:

Result:
(array([1., 2., 3., 4., 5., 6.], dtype=float32), array([0.], dtype=float32))
(array([3., 4., 5., 6., 7., 8.], dtype=float32), array([1.], dtype=float32))
(array([ 5.,  6.,  7.,  8.,  9., 10.], dtype=float32), array([0.], dtype=float32))
...