总结:根据documentation ,Keras model.fit()
应该接受 tf.dataset 作为输入(我使用的是 TF 版本 1.12.0)。如果我手动执行训练步骤,我可以训练我的模型,但在同一模型上使用 model.fit()
时,我会收到无法解决的错误。
这是我所做的一个草图:我的数据集太大,无法放入内存,由许多文件组成,每个文件具有不同的行数(100 个特征,标签)。我想使用 tf.data
构建我的数据管道:
def data_loader(filename):
'''load a single data file with many rows'''
features, labels = load_hdf5(filename)
...
return features, labels
def make_dataset(filenames, batch_size):
'''read files one by one, pick individual rows, batch them and repeat'''
dataset = tf.data.Dataset.from_tensor_slices(filenames)
dataset = dataset.map( # Problem here! See edit for solution
lambda filename: tuple(tf.py_func(data_loader, [filename], [float32, tf.float32])))
dataset = dataset.flat_map(
lambda features, labels: tf.data.Dataset.from_tensor_slices((features, labels)))
dataset = dataset.batch(batch_size)
dataset = dataset.repeat()
dataset = dataset.prefetch(1000)
return dataset
_BATCH_SIZE = 128
training_set = make_dataset(training_files, batch_size=_BATCH_SIZE)
我想尝试一个非常基本的逻辑回归模型:
inputs = tf.keras.layers.Input(shape=(100,))
outputs = tf.keras.layers.Dense(1, activation='softmax')(inputs)
model = tf.keras.Model(inputs, outputs)
如果我手动训练一切正常,例如:
labels = tf.placeholder(tf.float32)
loss = tf.reduce_mean(tf.keras.backend.categorical_crossentropy(labels, outputs))
train_step = tf.train.GradientDescentOptimizer(.05).minimize(loss)
iterator = training_set.make_one_shot_iterator()
next_element = iterator.get_next()
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init_op)
for i in range(training_size // _BATCH_SIZE):
x, y = sess.run(next_element)
train_step.run(feed_dict={inputs: x, labels: y})
但是,如果我尝试像这样使用 model.fit
:
model.compile('adam', 'categorical_crossentropy', metrics=['acc'])
model.fit(training_set.make_one_shot_iterator(),
steps_per_epoch=training_size // _BATCH_SIZE,
epochs=1,
verbose=1)
我在 keras 的 _standardize_user_data
函数内收到一条错误消息 ValueError: Cannot take the length of Shape withknownrank.
。
我已经尝试了很多方法,但无法解决问题。有什么想法吗?
编辑:根据@kvish的回答,解决方案是将映射从 lambda 更改为指定正确张量维度的函数,例如:
def data_loader(filename):
def loader_impl(filename):
features, labels, _ = load_hdf5(filename)
...
return features, labels
features, labels = tf.py_func(loader_impl, [filename], [tf.float32, tf.float32])
features.set_shape((None, 100))
labels.set_shape((None, 1))
return features, labels
现在,所需要做的就是从 map
调用此函数:
dataset = dataset.map(data_loader)
最佳答案
tf.py_func 可能会产生 Keras 无法推断的未知形状。我们可以使用 set_shape(your_shape) 方法设置它返回的张量的形状,这将有助于 Keras 推断结果的形状。
关于python - Keras model.fit() 与 tf.dataset 失败,而使用 tf.train 工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54055707/