Как сопоставить функцию с предварительно обработанным (‘BatchDataset’) тензором в Tensorflow

#python-3.x #tensorflow #machine-learning #keras

#python-3.x #tensorflow #машинное обучение #keras

Вопрос:

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

  def make_dataset(data=train_df[0]):
    ds = tf.keras.preprocessing.timeseries_dataset_from_array(
        data=data,
        targets=None,
        sequence_length=total_window_size,
        sequence_stride=1,
        shuffle=True,
        batch_size=32
    )

    return ds

  

Пример возвращаемой формы:

 for example in tensor.take(1):
  print(f'shape: {example.shape}')

shape: (32, 48, 18)
  

Что мне нужно сделать сейчас, так это разделить измерение времени на мои пары ввода-вывода, и у меня есть функция для этого, однако, когда я пытаюсь сопоставить эту функцию с моим ‘ds’ в вышеупомянутой функции, я получаю следующую ошибку:

 'BatchDataset' object is not subscriptable
  

Я надеюсь, что кто-нибудь может помочь мне понять, где я ошибаюсь? Я довольно новичок в tensorflow… Мой код приведен ниже, в этом примере ‘входной фрагмент’ и ‘label_slice’ равны 0 и 24 соответственно. Итак, моя цель — разделить мои пакеты на пары ввода-вывода длиной 24 каждая.

 def split_window(features):
  inputs = features[:, input_slice, :]
  labels = features[:, labels_slice, :]

  inputs.set_shape([None, input_width, None])
  labels.set_shape([None, label_width, None])

  return inputs, labels
  
  def make_dataset(data=train_df[0]):
    data = np.array(data, dtype=np.float32)
    ds = tf.keras.preprocessing.timeseries_dataset_from_array(
        data=data,
        targets=None,
        sequence_length=total_window_size,
        sequence_stride=1,
        shuffle=True,
        batch_size=32
    )

    ds = ds.map(split_window(ds))

    return ds
  
 tensor = make_dataset()
tensor

'BatchDataset' object is not subscriptable
  

Ответ №1:

Ваш фрагмент кода похож на руководство по временным рядам в Tensorflow. Основываясь на этом, я изменил основной класс WindowGenerator() (исключил части наборов данных train / val / test и выбор выходных меток) на более простой класс, подходящий для вашего вопроса.

 
    class WindowGenerator():

      def __init__(self, input_width, label_width, shift):

       self.input_width = input_width
       self.label_width = label_width
       self.shift = shift

       self.total_window_size = input_width   shift
       self.input_slice = slice(0, input_width)
       self.input_indices = np.arange(self.total_window_size[self.input_slice]
       self.label_start = self.total_window_size - self.label_width
       self.labels_slice = slice(self.label_start, None)
       self.label_indices = np.arange(self.total_window_size [self.labels_slice]

      def split_window(self, features):
       inputs = features[:, self.input_slice, :]
       labels = features[:, self.labels_slice, :]
       inputs.set_shape([None, self.input_width, None])
       labels.set_shape([None, self.label_width, None])

    return inputs, labels

      def make_dataset(self, data):
       data = np.array(data, dtype=np.float32)
       ds = tf.keras.utils.timeseries_dataset_from_array(
         data=data,
         targets=None,
         sequence_length=self.total_window_size,
         sequence_stride=1,
         shuffle=True,
         batch_size=batch_size,)
       ds = ds.map(self.split_window)
    
       return ds  


input_width=24
label_width=24
total_windth = input_width   label_width
batch_size = 32

window = WindowGenerator(input_width=input_width, label_width=label_width, shift=1)
dataset = window.make_dataset(train_df[0])

  

Однако я бы рекомендовал использовать Dataset.window() . Это проще и интуитивно понятнее.

 dataset = tf.data.Dataset.from_tensor_slices(train_df[0])
dataset = dataset.window(total_windth, shift=1, drop_remainder=True)
dataset = dataset.flat_map(lambda window: window.batch(batch_size))
dataset = dataset.map(lambda window: (window[:-label_width], window[-input_width:]))