如何使用具有多个输入张量的 tensorflow 生成器 (tf.keras.utils.Sequence)?

How do I use a tensorflow generator (tf.keras.utils.Sequence) with more than one input tensor?

提问人:chockeyblocky 提问时间:10/31/2023 最后编辑:chockeyblocky 更新时间:11/1/2023 访问量:42

问:

我正在尝试使用 tensorflow 训练深度网络,其第一层/模块是图转换器。问题是,这个图转换器将几个张量作为其输入,每个张量都有不同的形状。我正在训练的数据集也非常大,其原始文件中的数据在加载后需要进行一些预处理,以使其转换为正确的形状/格式,以用于图形转换器的输入。这意味着我正在尝试使用自定义生成器类(继承自 tf.keras.utils.Sequence)为我进行此预处理。但是,当我尝试在 getitem 中返回批处理时,存在一个明显的问题,因为它需要形状(batch_size、*input_dims)的张量或 numpy 数组,这与我的问题不兼容。

我尝试过使用输入张量元组的 numpy 数组进行批处理,并且尝试使用张量元组列表,但似乎没有任何效果,因为它期望这种形状并尝试转换为张量,但没有成功。有没有人对我可以尝试什么有任何建议?我对传入生成器来训练模型时进行的幕后处理没有深入的了解,因此任何见解都会有所帮助。例如,如果有人知道对“批处理”的约束(getitem 的返回值),或者任何绕过它似乎需要是 numpy 数组或张量这一事实的方法。

编辑:

我试图实现的代码示例,以及相关的错误:


import tensorflow as tf
import keras
import numpy as np


class DataGenerator(tf.keras.utils.Sequence):
    'Generates data for Keras'

    def __init__(self, list_IDs, labels, batch_size=32, dim=(32, 32, 32), n_channels=1,
                 n_classes=10, shuffle=True):
        'Initialization'
        self.dim = dim
        self.batch_size = batch_size
        self.labels = labels
        self.list_IDs = list_IDs
        self.n_channels = n_channels
        self.n_classes = n_classes
        self.shuffle = shuffle
        self.on_epoch_end()

    def __len__(self):
        'Denotes the number of batches per epoch'
        return int(np.floor(len(self.list_IDs) / self.batch_size))

    def __getitem__(self, index):
        'Generate one batch of data'
        # Generate indexes of the batch
        indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]

        # Find list of IDs
        list_IDs_temp = [self.list_IDs[k] for k in indexes]

        # Generate data
        X = [[tf.constant([1, 2]), tf.constant([3])]] * self.batch_size
        y = [tf.constant([1])] * self.batch_size

        return X, y

    def on_epoch_end(self):
        'Updates indexes after each epoch'
        self.indexes = np.arange(len(self.list_IDs))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)


class Net(tf.keras.Model):

    def __init__(self):
        super().__init__()
        self.dense1 = tf.keras.layers.Dense(5, activation=tf.nn.relu)
        self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)

    def call(self, inputs):
        # actual desired behaviour calls layer(inputs[0], inputs[1]) but this is a representative example
        x = self.dense1(inputs[0])
        x += self.dense2(inputs[1])
        return x


model = Net()

train_gen = DataGenerator([], [])

model.compile(loss=tf.keras.losses.mean_squared_error)
model.fit(x=train_gen, epochs=1, verbose=1, batch_size=4)

收到错误:

Traceback (most recent call last):
  File "generator_test.py", line 69, in <module>
    model.fit(x=train_gen, epochs=1, verbose=1, batch_size=4)
  File "\venv\Lib\site-packages\keras\src\utils\traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "generator_test.py", line 59, in call
    x = self.dense1(inputs[0])
        ^^^^^^^^^^^^^^^^^^^^^^
ValueError: Exception encountered when calling layer 'net' (type Net).

Layer "dense" expects 1 input(s), but it received 2 input tensors. Inputs received: [<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2])>, <tf.Tensor: shape=(1,), dtype=int32, numpy=array([3])>]

Call arguments received by layer 'net' (type Net):
  • inputs=(('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'), ('tf.Tensor(shape=(2,), dtype=int32)', 'tf.Tensor(shape=(1,), dtype=int32)'))

Process finished with exit code 1
Python TensorFlow 机器学习 深度学习 生成器

评论

1赞 Community 10/31/2023
请提供足够的代码,以便其他人可以更好地理解或重现问题。

答: 暂无答案