【问题标题】:Tensorflow Model fit format data correctly -- TypeError: Cannot convert a symbolic Keras input/output to a numpy arrayTensorflow 模型正确拟合格式数据——TypeError:无法将符号 Keras 输入/输出转换为 numpy 数组
【发布时间】:2021-11-01 03:28:48
【问题描述】:

对于 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))

In the original github code 使用 Keras 中已弃用的方法 fit_generator 将生成器用作 fit() 的输入,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))

正在崩溃,与上述相同的错误。

【问题讨论】:

  • 你可以试试这个:from tensorflow.python.framework.ops import disable_eager_execution \n disable_eager_execution() 并检查错误代码
  • 没有错误,只是一个警告WARNING:tensorflow:When passing input data as arrays, do not specify steps_per_epoch/steps argument. Please use batch_size instead. 和更早(训练前)另一个警告,warnings.warn( UserWarning: The lr argument is deprecated, use learning_rate instead.
  • @AlexandreMahdhaoui 有什么建议吗?

标签: python tensorflow machine-learning dataset training-data


【解决方案1】:

问题:

TypeError:无法将符号 Keras 输入/输出转换为 numpy 大批。
此错误可能表明您正在尝试通过 NumPy 调用的符号值,不支持。或者你 可能正在尝试将 Keras 符号输入/输出传递给 TF API 不注册调度,阻止 Keras 自动地 将 API 调用转换为功能模型中的 lambda 层。

调查

由于这个 TypeError 的性质,我建议你在禁用 Eager Execution 时检查错误代码:

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.

了解问题

我将首先解释这个建议的原因。使用功能 API 创建的模型的行为在启用急切执行的情况下似乎相当不可预测。 但我们会理解它发生的原因以及如何解决它。

在这里您会发现来自 KerasTensor 类的 TypeError:https://github.com/keras-team/keras/blob/4a978914d2298db2c79baa4012af5ceff4a4e203/keras/engine/keras_tensor.py#L244

为什么禁用急切执行似乎可以解决问题:

让我们先来看看https://www.tensorflow.org/guide/eager的这段话

启用急切执行会改变 TensorFlow 操作的行为方式——现在它们会立即评估并将其值返回给 Python。 tf.Tensor 对象引用具体值而不是 计算图中节点的符号句柄。由于没有 在会话中稍后构建和运行的计算图,很容易 使用 print() 或调试器检查结果。评估、印刷、 并且检查张量值不会破坏计算流程 渐变。

急切执行与 NumPy 配合得很好。 NumPy 操作接受 tf.Tensor 参数。 TensorFlow tf.math 操作转换 Python 对象和 NumPy 数组到 tf.Tensor 对象。 tf.Tensor.numpy 方法将对象的值作为 NumPy ndarray 返回。

但是 Eager Execution 应该可以很好地与 Numpy 一起工作,为什么在使用 numpy 数组时似乎会发生错误?

Tensorflow 的急切执行不会引发此错误。这个错误是由 Keras 引发的,更具体地说是由 KerasTensor 引发的。

在您的模型的功能 API 构建期间,KerasTensors 被创建来表示“符号输入”和输出 每个 Keras 层。 您的输入是一个 np.ndarray。 Keras 将您的数组放入 tf.keras.Input` 层,生成 KerasTensor。 抛出错误是因为您的模型将尝试将此符号输入/输出转换为 np.ndarray。

但是为什么会有这种行为呢?

在急切执行期间记住tf.Tensor objects reference concrete values instead of symbolic handles to nodes in a computational graph. 因此,急切的执行将尝试从您的 KerasTensor 获取一个具体值,这将引发此错误TypeError: Cannot convert a symbolic Keras input/output to a numpy array.

禁用急切执行后,您将永远不会尝试从 KerasTensor 获取具体值,并且永远不会抛出此错误。

如果您想更好地了解函数模型内部发生的情况,请阅读 KerasTensor 课程中的这 2 条引文:

KerasTensor 传递给tf.keras.Layer __call__ 让 层知道您正在构建功能模型。层 __call__ 将推断输出签名并返回KerasTensors,tf.TypeSpecs 对应于该符号输出 层调用。这些输出KerasTensors 将包含所有 Keras 需要的附加到它们的内部 KerasHistory 元数据 构建功能模型。目前,层推断输出 签名:
* 创建一个划痕FuncGraph
* 在草稿图中制作与输入类型规范匹配的占位符
* 在这些占位符上调用 layer.call
* 在清除暂存图之前提取输出的签名

如果您将 KerasTensor 传递给支持调度的 TF API, Keras 会自动将该 API 调用转换为 lambda 层 函数模型,并返回代表
的 KerasTensors 符号输出。

建议的解决方案:

禁用急切执行并不是一个令人满意的解决方案。

我建议您尝试将training_data 转换为具有tf.data.Dataset 类的数据集,或者在model.fit 之前转换为具有tf.Tensor 类的张量。

此外,如果问题仍未解决,如果您能够提供一些代码来重现错误,这将有所帮助。

【讨论】:

  • 非常感谢,实际上training_data = pad_sequences(sequences, maxlen = MAX_SEQUENCE_LENGTH) 似乎返回了一个Numpy 数组,该类型被认为是模型fit() 支持的类型。
  • 我添加了一个链接到我开始的原始代码和一些 cmets
  • 输入的格式似乎不是根本原因,见stackoverflow.com/questions/69071167/…
  • 我接受你的回答,请看stackoverflow.com/questions/69071167/…
猜你喜欢
  • 1970-01-01
  • 2021-03-29
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2021-07-13
  • 2021-06-26
  • 2021-11-11
相关资源
最近更新 更多