简体   繁体   English

如何批量训练具有多个输入的 model?

[英]How to train a model with multiple inputs in a batch?

I have a model like我有一个 model 之类的

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])
....

It has 2 inputs, a preprocessed image, and some extra info.它有 2 个输入、一个预处理图像和一些额外信息。

My problem is to train more than one instance at a time.我的问题是一次训练多个实例。 I have this train function:我有这列火车 function:

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

In the line logits = my_model(observations) if I give just 1 sample it works, but if I send a list it gives the error " Layer model expects 2 input(s), but it received 34 input tensors ".logits = my_model(observations)行中,如果我只给出 1 个样本,它可以工作,但如果我发送一个列表,它会给出错误“ model 层需要 2 个输入,但它收到 34 个输入张量”。

I suspect I'm not passing the arguments correctly (it used to work when I had 1 input model).我怀疑我没有正确通过 arguments(它曾经在我有 1 个输入模型时工作)。

How should I pass a batch of observations to this model?我应该如何将一批观察结果传递给这个 model?

To clarify:澄清:

  • observations is a list of numpy arrays. observations是 numpy arrays 的列表。
  • my_model(observations) throws an error " Layer model expects... " my_model(observations)抛出错误“层 model 预期...
  • my_model([observations[0][0], observations[0][1]]) works my_model([observations[0][0], observations[0][1]])有效
  • my_model([[observations[0][0], observations[0][1]],[observations[1][0], observations[1][1]]]) throws an error Layer model expects 2 input(s), but it received 4 input tensors . 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

I can just train using a call to my_model([observations[i][0], observations[i][1]]) , in a loop (where i is my n-th observation in this batch. But I suppose that there will be performance issues if I do this compared to just send all the training batch in a call.我可以在循环中使用对my_model([observations[i][0], observations[i][1]])的调用进行训练(其中i是我在这批中的第 n 个观察结果。但我想有如果我这样做与仅在呼叫中发送所有训练批次相比,将是性能问题。

EDIT编辑

To be more clear.要更清楚。 I can:我可以:

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])

This works perfectly.这完美地工作。

But if I have more than one observation in a batch, I don't know how to pass the parameters:但是如果我在一批中有多个观察,我不知道如何传递参数:

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]])

Throws:抛出:

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

If I understand the main problem that you've faced is to pass the input data correctly for the multiple inputs model.如果我了解您面临的主要问题是为多个输入 model 正确传递输入数据。 As you mentioned, observations is a list of numpy arrays, and you passed the data to a multi-input model as follows my_model(observations) - which seems problematic.正如您所提到的, observationsnumpy arrays 的列表,并且您将数据传递给多输入 model 如下my_model(observations) - 这似乎有问题。 What you probably need to do is to unpack the observations and pass the data as a list , eg my_model([input1, input2]) .您可能需要做的是解压缩observations并将数据作为list传递,例如my_model([input1, input2]) Here is a possible solution.这是一个可能的解决方案。

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}

Base Model底座 Model

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"])

Train火车

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM