对于NLP任务,我的输入数据集被转换为如下所示:整数列表。要素和标签是同一个数据集。
>>>training_data = [[ 0 4 79 3179 11 44 8 1 11245 173 152 10
1 1138 1079]
[ 0 0 4 79 3179 11 44 8 11566 173 152 8
1 1138 1079]
[ 0 0 0 0 0 0 0 9 15 333 44 3
61 63 533]
[ 0 0 0 0 0 0 3 19 253 28 44 3
61 63 533]
[ 0 0 0 0 0 0 0 0 0 0 0 2
3 49 4395]
[ 0 0 0 0 0 0 0 0 0 0 0 0
75 65 4395]
[ 3 1 7128 3388 289 10 446 200 675 8 3320 14
32 82 234]
[ 7 74 268 577 23 49 31 5 1032 98 10 4270
5026 12 6570]
[ 0 0 0 0 0 0 0 2 3 39 7 27
155 29 4534]
[ 0 0 0 0 0 2 3 19 39 7 27 155
29 34 4534]]
验证数据集是主数据集的摘录,格式相同。
然后我调用fit()
方法——我的模型是vae
n_steps = (800000 / 2) / batch_size
for counter in range(nb_epoch):
print('-------epoch: ',counter,'--------')
vae.fit(x=np.array(training_data),y=np.array(training_data), steps_per_epoch=n_steps,
epochs=1, callbacks=[checkpointer], validation_data=(data_1_val, data_1_val))
它给出了这个错误
TypeError: Cannot convert a symbolic Keras input/output to a numpy array.
This error may indicate that you're trying to pass a symbolic value to a NumPy call,
which is not supported. Or, you may be trying to pass Keras symbolic inputs/outputs to
a TF API that does not register dispatching, preventing Keras from automatically
converting the API call to a lambda layer in the Functional Model.
我试过
vae.fit(x=training_data,y=training_data, steps_per_epoch=n_steps,
epochs=1, callbacks=[checkpointer], validation_data=(data_1_val, data_1_val))
以及相同的错误。
欢迎使用列表、np.arrays或生成器来提供任何关于如何格式化训练数据的好的解决方案或提示。
编辑:一些代码
training_data = pad_sequences(sequences, maxlen = MAX_SEQUENCE_LENGTH)
len_val = int(np.floor ( len(texts) * 0.2 )) # num samples for validation
data_1_val = data_1[-len_val:] #select len_val sentences as validation data
建立和训练模型
x = Input(batch_shape=(None, max_len))
x_embed = Embedding(NB_WORDS, emb_dim, weights=[glove_embedding_matrix],
input_length=max_len, trainable=False)(x)
[…]
loss_layer = CustomVariationalLayer()([x, x_decoded_mean])
vae = Model(x, [loss_layer])
opt = Adam(lr=0.01) #SGD(lr=1e-2, decay=1e-6, momentum=0.9, nesterov=True)
vae.compile(optimizer='adam', loss=[zero_loss])
nb_epoch = 100
n_steps = (800000 / 2) / batch_size
for counter in range(nb_epoch):
print('-------epoch: ',counter,'--------')
vae.fit(training_data,training_data, steps_per_epoch=n_steps,
epochs=1, callbacks=[checkpointer], validation_data=(data_1_val, data_1_val))
在最初的github代码中,生成器被用作fit()
的输入,在Keras中使用了一种不推荐使用的方法fit_generator
for counter in range(nb_epoch):
print('-------epoch: ',counter,'--------')
vae.fit_generator(sent_generator(TRAIN_DATA_FILE, batch_size/2),
steps_per_epoch=n_steps, epochs=1, callbacks=[checkpointer],
validation_data=(data_1_val, data_1_val))
由于fit()也支持生成器参数,我第一次尝试
for counter in range(nb_epoch):
print('-------epoch: ',counter,'--------')
vae.fit(sent_generator(TRAIN_DATA_FILE, batch_size/2),
steps_per_epoch=n_steps, epochs=1, callbacks=[checkpointer],
validation_data=(data_1_val, data_1_val))
它正在崩溃,具有与上面相同的错误。
问题:
类型错误:无法将符号Keras输入/输出转换为numpy数组
此错误可能表示您正试图通过NumPy调用的符号值,这是不受支持的。或者,你可能试图将Keras符号输入/输出传递给TF API不注册调度,阻止Keras自动地将API调用转换为函数模型中的lambda层。
调查
由于此TypeError的性质,我建议您在禁用急切执行时检查错误代码:
from tensorflow.python.framework.ops import disable_eager_execution
disable_eager_execution()
您没有错误,但出现以下警告:WARNING:tensorflow:When passing input data as arrays, do not specify steps_per_epoch/steps argument. Please use batch_size instead.
了解问题
我将首先解释这个建议的原因。使用Functional API创建的模型的行为,如果启用了热切的执行,可能看起来相当不可预测。但我们会理解为什么会发生这种情况以及如何修复它
在这里,您可以找到来自KerasSensor类的TypeError:https://github.com/keras-team/keras/blob/4a978914d2298db2c79baa4012af5ceff4a4e203/keras/engine/keras_tensor.py#L244
为什么禁用急切执行似乎可以解决问题:
让我们首先阅读以下引文https://www.tensorflow.org/guide/eager
启用热切执行会改变TensorFlow操作的行为方式——现在它们会立即求值并将值返回给蟒蛇tf.Tensor对象引用具体值,而不是计算图中节点的符号句柄。既然没有一个计算图,可以在会话后期构建和运行,这很容易使用print()或调试器检查结果。评估、打印、,检查张量值不会破坏计算流程梯度。
热切的执行与NumPy配合得很好。NumPy操作接受tf.Tensor参数。TensorFlow tf.math操作转换Python对象和NumPy数组到tf.Tensor对象。tf.Tensor.numpy方法以NumPy ndarray形式返回对象的值。
但是热切的执行应该能很好地与Numpy配合使用,为什么在使用Numpy数组时会出现错误?
Tensorflow的急切执行并没有引发此错误。这个错误是由Keras抛出的,更具体地说是由KerasSensor抛出的。
在模型的Functional API构造期间,创建KerasTensor
s以表示;符号输入";和输出每个Keras层。你的输入是一个np.ndarray。Keras获取你的数组,并将其放入一个tf.Keras.input`层,生成一个KerasSensor。由于您的模型将尝试将此符号输入/输出转换为np.ndarray.,因此引发错误
但为什么会有这种行为呢?
在急切执行tf.Tensor objects reference concrete values instead of symbolic handles to nodes in a computational graph.
时记住因此,急切的执行将尝试从KerasSensor中获得一个具体的值,该值将抛出此错误TypeError: Cannot convert a symbolic Keras input/output to a numpy array.
禁用急切执行时,您永远不会尝试从KerasSensor中获取具体值,并且永远不会抛出此错误。
如果你想更好地了解你的功能模型内部发生了什么,请阅读KerasSensor类的这2句话:
将
KerasTensor
传递给tf.keras.Layer
__call__
使层知道您正在构建一个功能模型。图层__call__
将推断输出签名并返回KerasTensor
s,其中tf.TypeSpec
s对应于该签名的符号输出层调用。这些输出KerasTensor
将具有Keras需要附加的内部KerasHistory元数据构建一个功能模型。当前,层推断输出签名者:
*创建一个暂存FuncGraph
**在暂存图中制作与输入类型规范匹配的占位符
*在这些占位符上调用layer.call
**在清除暂存图之前提取输出的签名
如果将
KerasTensor
传递给支持调度的TFneneneba API,Keras将自动将API调用转换为函数模型,并返回表示
符号输出的KerasSensor。
建议的解决方案:
禁用急切执行不是一个令人满意的解决方案。
我建议您尝试使用tf.data.Dataset
类将training_data
转换为数据集,或者在model.fit
之前使用tf.Tensor
类将其转换为张量。
此外,如果问题仍未解决,如果您能够提供一些代码来重现错误,这将有所帮助。