Tensorflow / Keras: несоответствие формы вывода в данных обучения и прогнозируемых данных - PullRequest
1 голос
/ 26 мая 2020

У меня есть модель LSTM, определенная в tenorflow / keras, как показано ниже. Я включаю только важные детали, относящиеся к вопросу.

t_steps = 60
n_features = 3

def LSTMModel():
  input = Input(shape=(t_steps, n_features))
  l1 = BatchNormalization()(input)
  l2 = LSTM(160,return_sequences=True)(l1)
  l3 = LSTM(80,return_sequences=True)(l2)
  l4 = LSTM(10,return_sequences=True)(l3)
  l5 = Dense(1, activation = 'relu')(l4)
  model = Model(inputs = input, outputs = l5)
  model.compile(loss="mean_squared_error", optimizer='adam')
  return model

# shape of X_train_seq is (275268, 60, 3)
# shape of Y_train_seq is (275268,)

model = LSTMModel()
model.fit(X_train_seq, Y_train_seq, epochs=n_epochs,
  batch_size=batch_size,verbose=1,initial_epoch=init_epoch)

Затем, когда я предсказываю, используя эту модель на X_test_seq формы (30355, 60, 3), я получаю Y_test_seq_pred формы (30355, 60, 1), в то время как я ожидаю предсказания формы (30355 ,). Это произошло потому, что моя строка l4 в приведенном выше коде должна была быть

l4 = LSTM(10,return_sequences=False)(l3)

. Мой вопрос: с исходным кодом, почему Tensorflow / Keras не выдал ошибку или не выдал какое-либо предупреждение во время обучения в виде формы из Y_train_seq, который передается в метод fit (), равен (275268,), и во время обучения он должен был внутренне предсказывать Y формы (batch_size, 60, 1) для каждой партии во время оптимизации и сравнивать ее с фрагментом формы (batch_size,) из Y_train_seq. Почему это несоответствие размеров в Y позволяет коду продолжать работу только для меня, чтобы узнать об этом в конце обучения? Я уверен, что за этим должна быть какая-то причина, и я хочу знать, что происходит. Спасибо !!

1 Ответ

0 голосов
/ 27 мая 2020

Это происходит из-за того, что вызывается Numpy широковещательной рассылкой, которая описывает, как Numpy обрабатывает массивы с разными формами.

Давайте сначала определим два тензора A и B тензоры со следующими формами,

dim(A) = (32, 60, 1)
dim(B) = (32,)

Например, если вы попытаетесь выполнить некоторые операции, такие как вычитание , сложение или любая поэлементная операция между A и B , в этом случае так, как Tensorflow представляет B

dim(B) = (do_not_care, do_not_care, 32)

Таким образом, при итерации скалярное значение x вычитается из массива из 32 элементов (значений), поэтому на выходе получается матрица столбцов содержит 32 различных значения.

dim(output) = (32, 60, 32), что допустимо, но неожиданное поведение.

Такая операция может быть реализована рекурсивно , мы выполняем итерацию по тензору с более высоким размером, начиная с 1-го копейки nsion ( axis ) к известной размерности второго тензора, то мы можем применить требуемую операцию к результирующему тензору chunked , если их формы совпадают, другими словами, широковещательный успешно .


Реализация широковещательной передачи для вычитания может быть выполнена следующим образом.

def supstract(a, b): # a and b are numpy.array()

  # check if shape valid
  if a.squeeze().ndim == b.squeeze().ndim:
    if b.squeeze().shape[-1] == b.squeeze().shape[-1]:
      print(a - b, '\n')
      return
    else:
      raise ValueError(f'could not Broadcasting, {a.shape} != {b.shape}')

  elif a.ndim > b.ndim:
    for sub_a in a:
      supstract(sub_a, b) # recursive call
  else:
    for sub_b in b:
      supstract(a, sub_b) # recursive call

Я использовал следующий пример для проверки реализации, поэтому Возможно, я пропустил некоторые условия (обработка разных случаев).

a = np.random.randint(1, 4, (2, 2, 6, 1))
b = np.random.randint(1, 4, (4, )) 

В вашем случае Tensorflow требуется Y для вычисления функции потерь, вы используете MSE , которое является просто скалярным значением, вычисленным с использованием Keras бэкэнда следующим образом.

from tensorflow.keras import backend as K

def mean_squared_error(y_true, y_pred):
  return K.mean((y_pred - y_true) ** 2) # broadcasting (y_pred - y_true)

Обновление

|1 2 3| + |7 8 9|
|4 5 6|

|1 2 3| + 7 = |8  9  10|
|4 5 6|       |11 12 13|

На основе Tensorflow документация для описания трансляции . Numpy (широковещательная передача) обрабатывает любую из вышеперечисленных операций, но математически вы не можете применить ни одну из них. Если вы хотите получать предупреждения для любой операции вещания, вы можете ожидать получения тонн предупреждений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...