Генератор Keras с API Tensorflow Dataset - IndexError: выскочить из пустого списка

Мне нужно разработать модель RNN, и я хотел бы использовать генератор данных для заполнения циклов обучения / оценки.

Для начала, у меня есть эта функция справки, чтобы использовать при получении данных из CSV-файла.

RECORD_DEFAULTS_TRAIN = [[0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]]

def decode_csv(line):
   parsed_line = tf.decode_csv(line, RECORD_DEFAULTS_TRAIN)
   label =  parsed_line[-1]      # label is the last element of the list
   del parsed_line[-1]           # delete the last element from the list
   del parsed_line[0]            # even delete the first element bcz it is assumed NOT to be a feature
   features = tf.stack(parsed_line)  # Stack features so that you can later vectorize forward prop., etc.
   return features, label 

А вот моя функция генератора данных:

def data_generator(file_path_list, batch_size):

  filenames = tf.placeholder(tf.string, shape=[None])
  dataset = tf.data.Dataset.from_tensor_slices(filenames)
  dataset = dataset.flat_map(lambda filename: tf.data.TextLineDataset(filename).skip(1).map(decode_csv))
  dataset = dataset.shuffle(buffer_size=1000)
  dataset = dataset.batch(batch_size)
  iterator = dataset.make_initializable_iterator()
  next_element = iterator.get_next()

  with tf.Session() as sess:
      while True:
          sess.run(iterator.initializer, feed_dict={filenames: file_path_list})
          while True:            
              try:
                batch_data, batch_labels = sess.run(next_element)
                # Dimension of the data needs to be: (batch_size, length_of_each_sequence, nr_inputs_in_each_timestep)
                # Since the last batch in a epoch can have a different size,
                # "batch_data.shape[0]" is used instead of batch_size
                batch_data = np.reshape(batch_data, (batch_data.shape[0], SEQUENCE_LEN, 1))
              except tf.errors.OutOfRangeError:
                break
              yield (batch_data, batch_labels)

Вот как я строю и тренирую свою модель:

lstm_model = Sequential()
lstm_model.add(LSTM(5, input_shape=(SEQUENCE_LEN, 1), return_sequences=True))
lstm_model.add(LSTM(5, input_shape=(SEQUENCE_LEN, 1), return_sequences=False))
lstm_model.add(Dense(1))

opt = tf.keras.optimizers.Adam(lr=0.001, decay=0.0009)

lstm_model.compile(loss='mean_absolute_error', optimizer=opt, metrics=['accuracy'])

lstm_model.fit_generator(data_generator(TRAIN_FILE_PATHS, TRAIN_BATCH_SIZE), #generator, 
                         steps_per_epoch=(NR_TRAIN_EXAMPLES // TRAIN_BATCH_SIZE),
                         epochs=NR_EPOCHS, 
                         verbose=1,
                         validation_data=data_generator(DEV_FILE_PATHS, TRAIN_BATCH_SIZE),
                         validation_steps=(NR_DEV_EXAMPLES // DEV_BATCH_SIZE))

А вот как я оцениваю модель на тестовом наборе:

lstm_model.evaluate_generator(data_generator(TEST_FILE_PATHS, TEST_BATCH_SIZE), 
                             steps=(NR_TEST_EXAMPLES // TEST_BATCH_SIZE), 
                             verbose=1)

После обучения и оценки я вижу следующую ошибку в журналах:

IndexError: pop from empty list

Вот последняя часть логов после окончания обучения:

Epoch 200/200
2/2 [==============================] - 0s 28ms/step - loss: 0.0091 - acc: 0.0120 - val_loss: 0.0128 - val_acc: 0.0000e+00
Exception ignored in: <generator object data_generator at 0x7fa97d9e34c0>
Traceback (most recent call last):
  File "<ipython-input-7-2ef5e6514df7>", line 33, in data_generator
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1530, in __exit__
    self._default_graph_context_manager.__exit__(exec_type, exec_value, exec_tb)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 5025, in get_controller
    context.context().context_switches.pop()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/context.py", line 136, in pop
    self.stack.pop()
IndexError: pop from empty list
Exception ignored in: <generator object data_generator at 0x7fa97d9e3678>
Traceback (most recent call last):
  File "<ipython-input-7-2ef5e6514df7>", line 33, in data_generator
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1530, in __exit__
    self._default_graph_context_manager.__exit__(exec_type, exec_value, exec_tb)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 5025, in get_controller
    context.context().context_switches.pop()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/context.py", line 136, in pop
    self.stack.pop()
IndexError: pop from empty list

<tensorflow.python.keras.callbacks.History at 0x7fa97d8b4828>

И вот что я вижу после бега evaluate_generator():

2/2 [==============================] - 0s 28ms/step

Exception ignored in: <generator object data_generator at 0x7fa97d732af0>
Traceback (most recent call last):
  File "<ipython-input-7-2ef5e6514df7>", line 33, in data_generator
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1530, in __exit__
    self._default_graph_context_manager.__exit__(exec_type, exec_value, exec_tb)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ops.py", line 5025, in get_controller
    context.context().context_switches.pop()
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/context.py", line 136, in pop
    self.stack.pop()
IndexError: pop from empty list

[0.008863004390150309, 0.0]

Что меня смущает, так это то, почему я вижу сообщение об ошибке IndexError: pop from empty list в каждом случае выше? Это нормально? Или я что-то не так делаю?

1 ответ

Решение

Решаемые. Я хочу объяснить проблему, а не удалять свое сообщение, чтобы оно могло помочь и другим людям.

Я приведу только пример для evaluate_generator(...) функция. Вот как я вызывал функцию..

lstm_model.evaluate_generator(data_generator(TEST_FILE_PATHS, TEST_BATCH_SIZE), 
                             steps=(NR_TEST_EXAMPLES // TEST_BATCH_SIZE), 
                             verbose=1)

И я изменил это следующим образом:

test_data_generator = data_generator(TEST_FILE_PATHS, TEST_BATCH_SIZE)
lstm_model.evaluate_generator(test_data_generator, 
                              steps=(NR_TEST_EXAMPLES // TEST_BATCH_SIZE), 
                              verbose=1)

И проблема решена. Я видел оба способа использования в разных местах, даже если каждая информация, найденная в сети, не обязательно соответствует действительности. Мне также не ясно, почему это решается при изменении кода выше. Если кто-нибудь знает, я был бы рад услышать объяснение.

Другие вопросы по тегам