Как вычислить потерю цепных моделей с помощью Keras?

#python #tensorflow #keras

#python #тензорный поток #keras

Вопрос:

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

Вот мои две простые модели:

 model1 = tf.keras.models.Sequential([
    tf.keras.layers.Dense(10, activation="relu", input_shape=(10,)),
])

model2 = tf.keras.models.Sequential([
    tf.keras.layers.Dense(10, activation="softmax", input_shape=(10,)),
])
  

И я выполняю прямой проход через две модели, вычисляю потери второй модели и применяю градиенты:

 optimizer = tf.keras.optimizers.SGD()
loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)

x = tf.random.normal((1, 10)) # Input of the 1st model
y = tf.random.normal((1, 10)) # Expected output of the 2nd model

with tf.GradientTape() as tape:
    pred1 = model1(x, training=True)
    pred2 = model2(pred1, training=True)
    loss_value2 = loss(y, pred2) # Compute the loss for the second model prediction

grads = tape.gradient(loss_value2, model2.trainable_variables)
optimizer.apply_gradients(zip(grads, model2.trainable_variables))
  

Но как мне получить ожидаемый результат первой модели по второй модели, чтобы вычислить потери и применить к ним градиенты?

Редактировать:

Конечная цель тестирования — иметь две модели 1, которые отправляют свои выходные данные в одну третью модель. И каждая модель 1 обучена на двух графических процессорах:

 with tf.device('/gpu:0'):
    pred1_1 = model1_1(x, training=True)

with tf.device('/gpu:1'):
    pred1_2 = model1_2(x, training=True)

pred1 = tf.keras.layers.concatenate([pred1_1, pred1_2])

with tf.device('/gpu:0'):
    pred2 = model2(pred1, training=True)
  

Ответ №1:

@Begoodpy, я предлагаю вам объединить 2 модели в одну и обучить ее, как вы обычно делаете.

 supermodel = keras.Sequential(
    [
      model1(),
      model2(),
    ]
  

Если вам нужно больше контроля над моделями, попробуйте это:

 all_vars = model1.trainable_variables   model2.trainable_variables

grads = tape.gradient(loss_value2, all_vars)
optimizer.apply_gradients(zip(grads, all_vars))
  

Комментарии:

1. Спасибо, но я намерен отправлять каждую модель на один графический процессор, поэтому я не могу использовать их в одной модели

2. С 2 графическими процессорами почему бы не объединить мой ответ с другим от Александра Каталано? TF выполнит разделение между графическими процессорами за вас.

3. Потому что это обходные пути и не решает мою проблему. У меня есть ограничения, такие как размер моделей, которые не могут поместиться в один графический процессор, и ни объединение моделей, ни распределенная стратегия не помогут.

4. вы можете объединить 2 списка переменных и передать их функциям backprop. Я добавил пример выше.

5. Это выглядит потрясающе! Разве это не то же самое, что дважды вызывать tape.gradient(loss_value2, model1.trainable_variables) и tape.gradient(loss_value2, model2.trainable_variables) ?