【问题标题】:How to train a model with multiple inputs in a batch?如何批量训练具有多个输入的模型?
【发布时间】:2021-04-22 10:48:02
【问题描述】:

我有一个类似的模型

inputA = tf.keras.layers.Input(shape=(40,40))
inputB = tf.keras.layers.Input(shape=6)

a = tf.keras.layers.Conv2D(...)(inputA)
...
b = tf.keras.layers.Dense(...)(inputB)
combined = tf.keras.layers.concatenate([a, b])
....

它有 2 个输入、一个预处理图像和一些额外信息。

我的问题是一次训练多个实例。我有这个火车功能:

def train_step(observations, actions, rewards):
    with tf.GradientTape() as tape:
        logits = my_model(observations)
        loss = self.compute_loss(logits, actions, rewards)
    ....

logits = my_model(observations) 行中,如果我只给出 1 个样本,它可以工作,但如果我发送一个列表,它会给出错误“层模型需要 2 个输入,但它接收到 34 个输入张量”。

我怀疑我没有正确传递参数(它曾经在我有 1 个输入模型时工作)。

我应该如何将一批观察结果传递给这个模型?

澄清一下:

  • observations 是一个 numpy 数组列表。
  • my_model(observations) 抛出错误“层模型需要...
  • my_model([observations[0][0], observations[0][1]]) 工作
  • my_model([[observations[0][0], observations[0][1]],[observations[1][0], observations[1][1]]]) 抛出错误 Layer model expects 2 input(s), but it received 4 input tensors

我可以在循环中使用对my_model([observations[i][0], observations[i][1]]) 的调用进行训练(其中i 是我在这批中的第n 个观察结果。但我认为与仅发送相比,如果我这样做会出现性能问题调用中的所有训练批次。

编辑

为了更清楚。我可以:

input_a = np.random.randint(0, 255, size=(1, 40, 40, 3)).astype("int8")
input_b = np.random.randint(0, 1, size=(1, 6)).astype("int8")
logits = my_model([input_a, input_b])

这很好用。

但是如果我在一批中有多个观察,我不知道如何传递参数:

input_a0 = np.random.randint(0, 255, size=(1, 40, 40, 3)).astype("int8")
input_b0 = np.random.randint(0, 1, size=(1, 6)).astype("int8")
input_a1 = np.random.randint(0, 255, size=(1, 40, 40, 3)).astype("int8")
input_b1 = np.random.randint(0, 1, size=(1, 6)).astype("int8")
logits = my_model([[input_a0, input_a0], [input_a1, input_a1]])

投掷:

ValueError: Layer model expects 2 input(s), but it received 4 input tensors. Inputs received: ...

【问题讨论】:

    标签: python tensorflow machine-learning keras deep-learning


    【解决方案1】:

    如果我理解您面临的主要问题是为多输入模型正确传递输入数据。正如您所提到的,observationsnumpy 数组的列表,并且您将数据传递给多输入模型,如下所示my_model(observations) - 这似乎有问题。您可能需要做的是解压缩observations 并将数据作为list 传递,例如my_model([input1, input2])。这是一个可能的解决方案。

    CustomFit

    from tensorflow import keras
    import tensorflow as tf 
    
    class CustomModel(keras.Model):
        def train_step(self, data):
            # Unpack the data. Its structure depends on your model and
            # on what you pass to `fit()`.
            (x, z), y = data
    
            with tf.GradientTape() as tape:
                y_pred = self([x, z], training=True)  # Forward pass
                # Compute the loss value
                # (the loss function is configured in `compile()`)
                loss = self.compiled_loss(y, y_pred, regularization_losses=self.losses)
    
            # Compute gradients
            trainable_vars = self.trainable_variables
            gradients = tape.gradient(loss, trainable_vars)
            # Update weights
            self.optimizer.apply_gradients(zip(gradients, trainable_vars))
            # Update metrics (includes the metric that tracks the loss)
            self.compiled_metrics.update_state(y, y_pred)
            # Return a dict mapping metric names to current value
            return {m.name: m.result() for m in self.metrics}
    

    基础模型

    import numpy as np
    
    # Construct and compile an instance of CustomModel
    inputA = keras.Input(shape=(28, 28))
    inputB = keras.Input(shape=(32))
    
    a = tf.keras.layers.Flatten()(inputA)
    b = tf.keras.layers.Dense(16)(inputB)
    combined  = tf.keras.layers.concatenate([a, b])
    outputs = keras.layers.Dense(1)(combined)
    
    # without custom fit 
    # model = tf.keras.Model([inputA, inputB], outputs)
    
    model = CustomModel([inputA, inputB], outputs)
    model.compile(optimizer="adam", loss="mse", metrics=["mae"])
    

    训练

    x = np.random.randint(0, 256, size=(50, 28, 28)).astype("float32")
    z = np.random.random((50, 32))
    y = np.random.random((50, 1))
    print(x.shape, z.shape, y.shape)
    
    model.fit([x, z], y, epochs=3, verbose=2)
    
    (50, 28, 28) (50, 32) (50, 1)
    Epoch 1/3
    7ms/step - loss: 19227.8789 - mae: 112.9769
    Epoch 2/3
    8ms/step - loss: 16268.3952 - mae: 98.0642
    Epoch 3/3
    10ms/step - loss: 14247.0742 - mae: 95.9225
    

    【讨论】:

    • 感谢您的回答。问题不是解包,而是一次发送多个参数(一批)。请在问题中查看我的编辑。
    • 你过得怎么样*_b0/b1?也是您正在寻找train_on_batch 功能的东西吗?
    • train_on_batch 级别更高,我正在实现自定义训练功能
    • 感谢@M.Innat 问题已解决:这是一种数据打包问题,您的回复让我意识到了这一点。问题是我的单个项目的形状是 (1, x, y, 3),而它必须是 (x, y, 3),然后当聚合所有批次时它变成 (batch_size, x, y 3)。
    • 我明白了,很高兴知道。别忘了给hat>^-^
    猜你喜欢
    • 2021-08-13
    • 1970-01-01
    • 2021-11-27
    • 2019-04-02
    • 2018-09-25
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 2021-07-03
    相关资源
    最近更新 更多