Tensorflow 自定义训练步骤失败,"Unexpected result of train_function"



我已经子类化了tensorflow.keras.models.Model类,并按照这里描述的过程编写了一个自定义train_step。该模型接受两个2d数组作为输入(它是一个多输入模型),并产生一个浮点值作为输出。

我使用以下方法将TFRecord数据集传递给模型,其中parse_element_func返回一个包含4项的元组:(2d数组,2d数组,float, float)。第一项和第二项是输入数据,第三项是目标值,最后一项是在自定义损失函数中使用的数字,该函数随训练示例而变化。在训练期间,这些项目中的每一个都被扩展了一个维度,因为它们是批处理的。

train_dataset = tf.data.TFRecordDataset(records_train).map(parse_element_func).batch(batch_size).prefetch(tf.data.AUTOTUNE)

类是这样的:

import tensorflow.keras.backend as K
from tensorflow.keras.metrics import Mean
from tensorflow.keras.models import Model
loss_tracker = Mean(name="loss")
custom_metric_tracker = Mean(name="custom_metric")
magic_number = 4

class CustomModel(Model):

def __init__(self, *args, clip_global_norm: float = 1.0, **kwargs):
super(CustomModel, self).__init__(*args, **kwargs)
self.clip_global_norm = clip_global_norm
def train_step(self, data):
# unpack data
x_input_1, x_input_2, y_true, loss_modifier = data
with tf.GradientTape() as tape:
# predict
y_pred = self((x_input_1, x_input_2), training=True)

# calculate loss
weights = K.pow(K.square(loss_modifier + magic_number), -1)
squared_error = K.square(y_pred - y_true)
loss = K.mean(weights * squared_error, axis=0)

# calculate custom metric
num = K.sum(K.square(y_pred - y_true), axis=0)
denom = K.sum(y_true - K.mean(y_true), axis=0)
custom_metric_value = 1 - num / (denom + 0.000001)  # to prevent being 0            
trainable_vars = self.trainable_variables
gradients = tape.gradient(loss, trainable_vars)
gradients, _ = tf.clip_by_global_norm(gradients, clip_norm=self.clip_global_norm)
self.optimizer.apply_gradients(zip(gradients, trainable_vars))
loss_tracker.update_state(loss)
custom_metric_tracker.update_state(custom_metric_value)
return {"loss": loss_tracker.result(), "custom_metric": custom_metric_tracker.result()}

模型构建和编译很好,我已经检查了所有的形状都是正确的使用plot_model。当我测试加载数据时,所有东西的形状和值都是正确的。无论如何,我得到相同的ValueError:

ValueError: Unexpected result of `train_function` (Empty logs).

这是我得到的唯一消息。它并没有告诉我什么是错的,除了它与训练函数有关,它发生在model.fit期间。当我调用它时,它在脚本中看起来像这样:

train_dataset = tf.data.TFRecordDataset(records_train).map(parse_element_func).batch(batch_size).prefetch(tf.data.AUTOTUNE)
val_dataset = tf.data.TFRecordDataset(records_val).map(parse_element_func).batch(batch_size).prefetch(tf.data.AUTOTUNE)
model = build_model_func(**model_build_params)
model.compile(optimizer="adam")
history = model.fit(
train_dataset,
batch_size=batch_size,
epochs=epochs,
validation_data=val_dataset,
)

我是否急切地运行它并没有什么区别。我想也许我的数据集传递4个值的元组可能是问题,但就我所能通过文档它应该是好的,甚至我修改TFRecord数据集元素解析器只提供输入和输出,没有其他值(所以2值而不是4),我仍然得到同样的错误。

我花了几个小时在这上面,只是不知道为什么我得到这个错误,这个函数或我的过程有什么问题。有谁能帮我解决这个问题吗?

在innat的建议下创建可复制的代码时,我终于弄明白了。错误信息让我相信它与自定义训练函数有关,但它实际上与TFRecordDataset有关。

结果是,在脚本中的某个时刻,records_train(最初有一个tfrecord文件名列表)变成了一个空列表。所以基本上没有数据传递给model.fit

作为参考,这是产生错误的代码行:

history = model.fit(
train_dataset,
batch_size=batch_size,
epochs=epochs,
validation_data=val_dataset,
)

但是错误的实际来源,不在堆栈跟踪中,也没有提到过,是这一行,其中records_train = []:

train_dataset = tf.data.TFRecordDataset(records_train).map(parse_element_func).batch(batch_size).prefetch(tf.data.AUTOTUNE)

下面是错误信息:

ValueError: Unexpected result of `train_function` (Empty logs).

一个非常无用的错误信息,但也许这篇文章将来会对某人有所帮助。

相关内容

最新更新