Keras fit_generator () - Как работает пакет для временных рядов? - PullRequest
11 голосов
/ 21 мая 2019

Контекст:

В настоящее время я работаю над прогнозированием временных рядов, используя Keras с бэкэндом Tensorflow, и поэтому изучил предоставленный учебник здесь .

После этого урока я пришел к тому, что описан генератор для метода fit_generator().Вывод, который генерирует этот генератор, выглядит следующим образом (левый образец, правая цель):

[[[10. 15.]
  [20. 25.]]] => [[30. 35.]]     -> Batch no. 1: 2 Samples | 1 Target
  ---------------------------------------------
[[[20. 25.]
  [30. 35.]]] => [[40. 45.]]     -> Batch no. 2: 2 Samples | 1 Target
  ---------------------------------------------
[[[30. 35.]
  [40. 45.]]] => [[50. 55.]]     -> Batch no. 3: 2 Samples | 1 Target
  ---------------------------------------------
[[[40. 45.]
  [50. 55.]]] => [[60. 65.]]     -> Batch no. 4: 2 Samples | 1 Target
  ---------------------------------------------
[[[50. 55.]
  [60. 65.]]] => [[70. 75.]]     -> Batch no. 5: 2 Samples | 1 Target
  ---------------------------------------------
[[[60. 65.]
  [70. 75.]]] => [[80. 85.]]     -> Batch no. 6: 2 Samples | 1 Target
  ---------------------------------------------
[[[70. 75.]
  [80. 85.]]] => [[90. 95.]]     -> Batch no. 7: 2 Samples | 1 Target
  ---------------------------------------------
[[[80. 85.]
  [90. 95.]]] => [[100. 105.]]   -> Batch no. 8: 2 Samples | 1 Target

В учебном пособии использовался TimeSeriesGenerator, но для моего вопроса второстепенно, если пользовательский генератор или этот классиспользуемый.Что касается данных, у нас есть 8 steps_per_epoch и образец формы (8, 1, 2, 2).Генератор подается в рекуррентную нейронную сеть, реализованную LSTM.

Мои вопросы

fit_generator() допускает только одну цель на пакет, как выводитсяTimeSeriesGenerator.Когда я впервые прочитал о параметрах пакетов для fit (), я подумал, что у меня может быть несколько выборок и соответствующее количество целей (которые обрабатываются партиями, то есть строка за строкой).Но это не допускается fit_generator() и, следовательно, очевидно ложно.Это будет выглядеть, например, следующим образом:

[[[10. 15. 20. 25.]]] => [[30. 35.]]     
[[[20. 25. 30. 35.]]] => [[40. 45.]]    
    |-> Batch no. 1: 2 Samples | 2 Targets
  ---------------------------------------------
[[[30. 35. 40. 45.]]] => [[50. 55.]]    
[[[40. 45. 50. 55.]]] => [[60. 65.]]    
    |-> Batch no. 2: 2 Samples | 2 Targets
  ---------------------------------------------
...

Во-вторых, я думал, что, например, [10, 15] и [20, 25] использовались в качестве входных данных для RNN последовательно для цели [30,35], что означает, что это аналог ввода [10, 15, 20, 25].Поскольку выходные данные из RNN отличаются при использовании второго подхода (я проверял его), это также должно быть неправильным выводом.

Следовательно, мои вопросы:

  1. Почему толькоразрешена одна цель на партию (я знаю, что есть обходные пути, но должна быть причина)?
  2. Как я могу понять расчет одной партии?То есть, как обрабатывается некоторый ввод, такой как [[[40, 45], [50, 55]]] => [[60, 65]], и почему он не аналогичен [[[40, 45, 50, 55]]] => [[60, 65]]



Редактировать в соответствии с сегодняшним ответом
Поскольку в моем определении выборок и целей есть некоторое недопонимание, я понимаю, что, как я понимаю, Керас пытается сказать мне, говоря:

ValueError: Входные массивы должны иметь одинаковые значения.количество выборок в качестве целевых массивов.Найдено 1 входной выборки и 2 целевых выборки.

Эта ошибка возникает, когда я создаю, например, пакет, который выглядит следующим образом:

#This is just a single batch - Multiple batches would be fed to fit_generator()
(array([[[0, 1, 2, 3, 4],
        [5, 6, 7, 8, 9]]]), 
                           array([[ 5,  6,  7,  8,  9],
                           [10, 11, 12, 13, 14]]))

Это должен быть один пакетсодержащий две временные последовательности длиной 5 (5 последовательных точек данных / временных шагов), целью которых также являются две соответствующие последовательности.[ 5, 6, 7, 8, 9] является целью [0, 1, 2, 3, 4], а [10, 11, 12, 13, 14] является соответствующей целью [5, 6, 7, 8, 9].
Примерная форма в этом случае будет shape(number_of_batches, number_of_elements_per_batch, sequence_size), а целевая форма shape(number_of_elements_per_batch, sequence_size).
Керас.видит 2 целевых образца (в ValueError), потому что у меня есть два, которые предоставляют 3D-образцы в качестве входных данных и 2D-цели в качестве выходных данных (может быть, я просто не понимаю, как предоставить 3D-цели ..).

Так или иначе, согласно ответу / комментариям @todays, это интерпретируется Keras как два временных шага и пять функций.Что касается моего первого вопроса (где я все еще вижу последовательность в качестве цели для моей последовательности, как в этом примере редактирования), я ищу информацию о том, как / если я могу достичь этого и как будет выглядеть такая партия (как я пытался визуализировать ввопрос).

1 Ответ

1 голос
/ 02 июня 2019

Короткие ответы:

Почему разрешена только одна цель на партию (я знаю, что есть некоторые обходные пути, но должна быть причина)?

Это совсем не так. Нет ограничений на количество целевых образцов в партии. Единственное требование - чтобы вы имели одинаковое количество входных и выходных выборок в каждой партии. Прочитайте длинный ответ для уточнения.

Как я могу понять расчет одной партии? То есть, как обрабатывается какой-то ввод, такой как [[[40, 45], [50, 55]]] => [[60, 65]], и почему он не аналогичен [[[40, 45, 50, 55]]] => [[60, 65]]?

Первый - это многовариантный временной ряд (т. Е. Каждый временной шаг имеет более одного признака), а второй - однофакторный временный ряд (т. Е. Каждый временной шаг имеет одну особенность). Так что они не эквивалентны. Прочитайте длинный ответ для уточнения.

Длинный ответ:

Я дам ответ, который я упомянул в разделе комментариев, и постараюсь уточнить его, используя примеры:

Я думаю, что вы смешиваете образцы, временные шаги, функции и цели. Позвольте мне описать, как я это понимаю: в первом примере, который вы предоставили, кажется, что каждая входная выборка состоит из 2 временных шагов, например [10, 15] и [20, 25], где каждый временной шаг состоит из двух функций, например 10 и 15 или 20 и 25. Кроме того, соответствующая цель состоит из одного временного шага, например, [30, 35], который также имеет две функции. Другими словами, каждая входная выборка в пакете должна иметь соответствующую цель. Однако форма каждого входного сэмпла и соответствующей ему цели может не совпадать.

Например, рассмотрим модель, в которой и ее вход, и выход являются временными рядами. Если мы обозначим форму каждой входной выборки как (input_num_timesteps, input_num_features), а форму каждого целевого (т.е. выходного) массива как (output_num_timesteps, output_num_features), мы получим следующие случаи:

1) Количество входных и выходных временных интервалов одинаково (т. Е. input_num_timesteps == output_num_timesteps). В качестве примера, следующая модель может достичь этого:

from keras import layers
from keras import models

inp = layers.Input(shape=(input_num_timesteps, input_num_features))

# a stack of RNN layers on top of each other (this is optional)
x = layers.LSTM(..., return_sequences=True)(inp)
# ...
x = layers.LSTM(..., return_sequences=True)(x)

# a final RNN layer that has `output_num_features` unit
out = layers.LSTM(output_num_features, return_sequneces=True)(x)

model = models.Model(inp, out)

2) Количество входных и выходных временных шагов различно (т.е. input_num_timesteps ~= output_num_timesteps). Обычно это достигается путем сначала кодирования входных временных рядов в вектор с использованием стека из одного или нескольких слоев LSTM, а затем повторение этого вектора output_num_timesteps раз для получения временных рядов желаемой длины. Для повторной операции мы можем легко использовать слой RepeatVector в Керасе. Опять же, в качестве примера, следующая модель может достичь этого:

from keras import layers
from keras import models

inp = layers.Input(shape=(input_num_timesteps, input_num_features))

# a stack of RNN layers on top of each other (this is optional)
x = layers.LSTM(..., return_sequences=True)(inp)
# ...
x = layers.LSTM(...)(x)  # The last layer ONLY returns the last output of RNN (i.e. return_sequences=False)

# repeat `x` as needed (i.e. as the number of timesteps in output timseries)
x = layers.RepeatVector(output_num_timesteps)(x)

# a stack of RNN layers on top of each other (this is optional)
x = layers.LSTM(..., return_sequences=True)(x)
# ...
out = layers.LSTM(output_num_features, return_sequneces=True)(x)

model = models.Model(inp, out)

В особом случае, если количество выходных временных шагов равно 1 (например, сеть пытается предсказать следующий временной шаг с учетом последних t временных шагов), нам может не понадобиться повторение, и вместо этого мы можем просто использовать Слой Dense (в этом случае выходная форма модели будет (None, output_num_features), а не (None, 1, output_num_features)):

inp = layers.Input(shape=(input_num_timesteps, input_num_features))

# a stack of RNN layers on top of each other (this is optional)
x = layers.LSTM(..., return_sequences=True)(inp)
# ...
x = layers.LSTM(...)(x)  # The last layer ONLY returns the last output of RNN (i.e. return_sequences=False)

out = layers.Dense(output_num_features, activation=...)(x)

model = models.Model(inp, out)

Обратите внимание, что представленные выше архитектуры приведены только для иллюстрации, и вам может понадобиться настроить или адаптировать их, например, добавив больше слоев, таких как Dense layer, в зависимости от вашего варианта использования и проблемы, которую вы пытаетесь решить.


Обновление: Проблема в том, что вы не уделяете достаточного внимания при чтении моих комментариев и ответов, а также об ошибке, выдвинутой Keras. Ошибка ясно гласит, что:

... Найдено 1 входных и 2 целевых образца.

Итак, после прочтения этого внимательно, на вашем месте я бы сказал себе: «Хорошо, Керас считает, что у входной партии есть 1 входная выборка, но я думаю, что я предоставляю две выборки !! Так как я очень хороший Человек (!), я думаю, что очень вероятно, что я буду неправ, чем Керас, так что давайте выясним, что я делаю неправильно! ». Простая и быстрая проверка - просто проверить форму входного массива:

>>> np.array([[[0, 1, 2, 3, 4],
               [5, 6, 7, 8, 9]]]).shape
(1,2,5)

"О, это говорит (1,2,5)! Так что это означает один сэмпл, который имеет два временных шагов и каждый временной шаг имеет пять функций !!! Так что я ошибался, полагая, что этомассив состоит из двух выборок длиной 5, где каждый временной шаг имеет длину 1 !! Так что мне теперь делать ??? "Ну, вы можете это исправить, шаг за шагом:

# step 1: I want a numpy array
s1 = np.array([])

# step 2: I want it to have two samples
s2 = np.array([
               [],
               []
              ])

# step 3: I want each sample to have 5 timesteps of length 1 in them
s3 = np.array([
               [
                [0], [1], [2], [3], [4]
               ],
               [
                [5], [6], [7], [8], [9]
               ]
              ])

>>> s3.shape
(2, 5, 1)

Вуаля!Мы сделали это!Это был входной массив;Теперь проверьте целевой массив, он должен иметь две целевые выборки длиной 5 с каждой особенностью, т.е. иметь форму (2, 5, 1):

>>> np.array([[ 5,  6,  7,  8,  9],
              [10, 11, 12, 13, 14]]).shape
(2,5)

Почти!Последнее измерение (т. Е. 1) отсутствует ( ПРИМЕЧАНИЕ: в зависимости от архитектуры вашей модели вам может понадобиться или не потребоваться эта последняя ось).Таким образом, мы можем использовать пошаговый подход, описанный выше, чтобы найти свою ошибку, или же мы можем быть немного умнее и просто добавить ось в конец:

>>> t = np.array([[ 5,  6,  7,  8,  9],
                  [10, 11, 12, 13, 14]])
>>> t = np.expand_dims(t, axis=-1)
>>> t.shape
(2, 5, 1)

Извините, я не могу объяснитьэто лучше чем это!Но в любом случае, когда вы видите, что что-то (то есть форма входных / целевых массивов) повторяется снова и снова в моих комментариях и моем ответе, предположите, что это должно быть что-то важное и должно быть проверено.

...