python-3.x - 使用多输入输出 Tensorflow 模型子类验证/测试更差的指标
问题描述
我已经被这个错误困扰了一段时间了。我有一个中等大小的 Tensorflow 模型,有 4 个输入和 2 个输出。我的意图是对其进行细微的结构更改并比较指标。为了保存旧的模型定义并尽可能多地重用代码,我选择采用模型子类化路径,直接扩展模型类。这样我就可以继承和重用图层。我通过模型传递数据,该模型tf.data.Dataset
是用于输入输出的字典元组,例如{'input_1': <INPUT_1_TENSOR>, 'input_2', ...}, {'output_1': <OUTPUT_1_TENSOR>, 'output_2'}
.
但是,当我执行模型子类化方法时,会弹出一个非常奇怪的错误(错误?)。简而言之,即使看起来训练正在发挥作用(我可以看到训练指标上升),验证指标在每个 epoch 之后都会变得越来越差。当我删除 Model 子类并直接定义 Model 时,不会发生这种情况。我认为两者之间的一切都是平等的(优化器、损失、指标、没有回调)。我的模型类如下所示。
class MyModel(Model):
def __init__(self, **kwargs):
super(MyModel, self).__init__(**kwargs)
# Input layers
self.input_1 = Input(shape=(6), dtype=tf.uint32, name='input_1')
self.input_2 = Input(shape=(6), dtype=tf.uint32, name='input_2')
self.input_3 = Input(shape=(1,), dtype=tf.uint32, name='input_3')
self.input_4 = Input(shape=(1,), dtype=tf.uint32, name='input_4')
# Define rest of layers (no custom layers here)
# ....
# ....
# ....
def call(self, inputs, training=True, mask=None):
# WE ASSUME THAT THE INPUTS ARE PASSED IN AS DICTIONARIES WITH THE KEYS:
# [input_1, input_2, input_3, input_4]
input_1, input_2, input_3, input_4 = inputs['input_1'], inputs['input_2'], \
inputs['input_3'], inputs['input_4']
# Pass through all the layers define in __init__() and grab the two outputs.
# ....
# ....
# ....
return {'output_1': output_1, 'output_2': output_2}
def build(self, input_shapes=None):
"""
I had to define this because it wouldn't let me do .summary() before .fit().
"""
input_list = {'input_1': self.input_1,
'input_2': self.input_2,
'input_3': self.input_3,
'input_4': self.input_4}
return Model(inputs=input_list, outputs=self.call(input_list))
然后真正适合,我做
model = MyModel(...)
model.build().summary()
optimizer = Adam(learning_rate=0.01)
model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy', loss_weights=[1., 1.],
metrics=['accuracy'])
model.fit(train_dataset,
epochs=3,
verbose=1,
validation_data=vali_dataset)
正如我之前所说,如果我将这些东西call()
移出课堂并以这种方式创建模型对象,那么训练就会正常进行,并且验证指标会按预期发生变化。
我还可以删除 Model 子类并定义一个常规类calL()
,用它替换build_model()
返回 Model 对象而不是输出字典。这也运行良好。它可以称为解决方案,但认为它不应该是必要的,并且违背了能够扩展 Model 类的目的。唯一的问题是模型子类。
除了这个Stack Overflow 问题之外,我也找不到任何关于使用具有多个输入和输出的模型子类化的综合文档。
所以总结一下:
- 模型子类化导致每个时期的验证指标更差(包括验证损失)
- 将模型独立放在类之外以及删除模型类继承不会导致训练问题
- 在优化器、损失等方面,一切都保持不变。
- 4 个命名输入,2 个命名输出,数据作为字典通过
tf.data.Dataset
. - Python 3.7、张量流 2.4.0
关于错误可能在哪里或从哪里开始的任何想法?
谢谢!
解决方案
推荐阅读
- python - 如何按日期对帖子进行排序(FLASK、PYTHON、SQLALCHEMY)
- algorithm - 程序员使用什么排序算法?
- java - SpringBootRequestHandler 的 NoClassDefFoundError
- c++ - 添加新的基本 Q_OBJECT 导致 MOC 中的 QT 构建错误。CMAKE & QT6
- django - Django不使用ajax保存表单中的图像
- firebase - firebase_messaging 与项目的依赖一致性
- http - 当我喜欢聊天消息时,如何从 Instagram 上的浏览器获取传出的 POST HTTP 请求?
- python - 基本 Celery 任务未运行(错误/MainProcess] 收到“app.celery_tasks.test_task”类型的未注册任务)
- asp.net-mvc - 在 API 控制器中使用 urlencoded 正文
- c - 如何通过c中的套接字读取文件并写入另一个文件