Dataset.from_generator无法复制numpy数组的功能作为一维Convnet的输入

时间:2019-10-05 08:48:47

标签: python tensorflow keras tensorflow-datasets

我正在将许多长度为100和3的特征的时间序列输入到1D Convnet中。我有太多这些无法使用numpy数组,因此我需要使用Dataset.from_generator()。

问题是,当我在数据集上训练模型时,会出现错误:

expected conv1d_input to have 3 dimensions, but got array with shape (100, 3)

下面的代码演示了该问题。生成器将每个元素生成为预期的(100,3)数组。为什么模型无法将生成器的输出识别为有效的?

非常感谢您的帮助。朱利安

import numpy as np
import tensorflow as tf
def create_timeseries_element():
    # returns a random time series of 100 intervals, each with 3 features,
    # and a random one-hot array of 5 entries
    data = np.random.rand(100,3)
    label = np.eye(5, dtype='int')[np.random.choice(5)]
    return data, label

def data_generator():
    d, l = create_timeseries_element()
    yield (d, l)

model = tf.keras.models.Sequential([
    tf.keras.layers.Conv1D(128, 9, activation='relu', input_shape=(100, 3)),
    tf.keras.layers.Conv1D(128, 9, activation='relu'),
    tf.keras.layers.MaxPooling1D(2),
    tf.keras.layers.Conv1D(256, 5, activation='relu'),
    tf.keras.layers.Conv1D(256, 5, activation='relu'),
    tf.keras.layers.GlobalAveragePooling1D(),
    tf.keras.layers.Dropout(0.5),
    tf.keras.layers.Dense(5, activation='softmax')])
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

x_train = []
y_train = []
for _ in range(1000):
    d, l = create_timeseries_element()
    x_train.append(d)
    y_train.append(l)
x_train = np.array(x_train)
y_train = np.array(y_train)

# train model with numpy arrays - this works
model.fit(x=x_train, y=y_train)

ds = tf.data.Dataset.from_generator(data_generator, output_types=(tf.float32, tf.int32),
                                      output_shapes=(tf.TensorShape([100, 3]), tf.TensorShape([5])))
# train model with dataset - this fails
model.fit(ds)

1 个答案:

答案 0 :(得分:0)

模型需要一批样品/列表。您可以通过在创建数据集时简单地设置批处理属性来做到这一点,如下所示:

ds = tf.data.Dataset.from_generator(data_generator, output_types=(tf.float32, tf.int32),
                                      output_shapes=(tf.TensorShape([100, 3]), tf.TensorShape([5])))
ds = ds.batch(16)

在准备样品时,您也可以使用另一种方法。这样,您需要扩展样本维,以便样本作为批处理(您也可以传递样本列表),并且必须在数据集的output_shapes和{{1 }}功能

create_timeseries_element

上述更改将为数据集的每个时期仅提供一个批次(第一个解决方案的样本)。您可以在定义数据集时将参数传递给def create_timeseries_element(): # returns a random time series of 100 intervals, each with 3 features, # and a random one-hot array of 5 entries # Expand dimensions to create a batch of single sample data = np.expand_dims(np.random.rand(100, 3), axis=0) label = np.expand_dims(np.eye(5, dtype='int')[np.random.choice(5)], axis=0) return data, label ds = tf.data.Dataset.from_generator(data_generator, output_types=(tf.float32, tf.int32), output_shapes=(tf.TensorShape([None, 100, 3]), tf.TensorShape([None, 5]))) 函数,以生成所需数量的批次(第一个解决方案的样本)(例如25个),

data_generator