[英]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.正如您所提到的, observations
是numpy
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.