Tensorflow TF.Keras中的单损耗多输出模型

Tensorflow TF.Keras中的单损耗多输出模型,tensorflow,python,machine-learning,keras,deep-learning,Tensorflow,Python,Machine Learning,Keras,Deep Learning,我使用的数据集是y是一个6张量的字典,我都在一个损失函数中使用了它,如下所示: def CustomLoss(): def自定义损耗(y_真,y_pred): a=tf.keras.loss.binary_交叉熵(y_真['a_0'],y_pred[0])*y_真['a_1'] b=tf.square(y_真['b_0']-y_pred[1])*y_真['b_1'] c=tf.abs(y_真['c_0']-y_pred[2])*y_真['c_1'] 返回a+b+c 退还海关损失 我有一个模型,

我使用的数据集是
y
是一个6张量的字典,我都在一个损失函数中使用了它,如下所示:

def CustomLoss():
def自定义损耗(y_真,y_pred):
a=tf.keras.loss.binary_交叉熵(y_真['a_0'],y_pred[0])*y_真['a_1']
b=tf.square(y_真['b_0']-y_pred[1])*y_真['b_1']
c=tf.abs(y_真['c_0']-y_pred[2])*y_真['c_1']
返回a+b+c
退还海关损失
我有一个模型,有3个不同形状的输出。当我编译模型并调用
fit
方法时,我得到
Value Error

model.compile(optimizer=optimizer,loss=CustomLoss())
model.fit(数据集,历代=10)
其中,
output\u 0、'output\u 1'、'output\u 2'
是输出层的名称

我认为通过数据集中的键命名输出层应该可以解决这个问题,但问题是数据集中有6张量,只有3输出。我知道我可以用一个数据集地面真值张量为每个输出分配一个损失函数,但我需要将至少两个张量作为GT传递

到目前为止,我已经使用了一个定制的训练循环,但我更愿意使用
fit
方法。我使用的是2.3.1

编辑:

示例模型:

inputs=x=tf.keras.layers.Input((256,256,3))
x=tf.keras.applications.ResNet50(include_top=False,weights=None)(x)
x1=tf.keras.layers.flatte()(x)
x1=tf.keras.layers.density(2,name='output_1')(x1)
x2=tf.keras.layers.Conv2D(256,1,name='output_2')(x)
x3=tf.keras.layers.flatte()(x)
x3=tf.keras.layers.density(64,name='output_3')(x3)
模型=tf.keras.model(输入=输入,输出=[x1,x2,x3])
自定义训练循环:

avg_loss=tf.keras.metrics.Mean('loss',dtype=tf.float32)
对于范围内的历元(1,历元+1):
对于enumerate(train_数据集)中的批处理(图像、标签):
使用tf.GradientTape()作为磁带:
输出=模型(图像,训练=假)
reg_损失=tf.减少总和(模型损失)
pred_损耗=损耗(标签、输出)
总损耗=tf.减少总损耗(预损耗)+注册损耗
梯度=磁带.梯度(总损耗,模型.可训练变量)
优化器。应用_梯度(zip(梯度、模型、可训练的_变量))
平均损耗。更新状态(总损耗)
打印(f'Epoch{Epoch}/{Epoch}-Loss:{avg_Loss.result().numpy()}'))
平均损失重置状态()
最小可复制代码:

将tensorflow导入为tf
def CustomLoss():
def自定义损耗(y_真,y_pred):
a=tf.keras.loss.binary_交叉熵(y_真['a_0'],y_pred[0])*y_真['a_1']
b=tf.square(y_真['b_0']-y_pred[1])*y_真['b_1']
b=tf.减少_和(b,轴=(1,2,3))
c=tf.abs(y_真['c_0']-y_pred[2])*y_真['c_1']
c=tf.减少_和(c,轴=1)
返回a+b+c
退还海关损失
dataset=tf.data.dataset.from_张量((
tf.random.uniform((256,256,3)),
{'a_0':[0,1.],'a_1':[1.],'b_0':tf.random.uniform((8,8256)),'b_1':[1.],'c_0':tf.random.uniform((64,),'c_1':[1.]}
))
dataset=dataset.batch(1)
输入=x=tf.keras.layers.Input((256,256,3))
x=tf.keras.applications.ResNet50(include_top=False,weights=None)(x)
x1=tf.keras.layers.flatte()(x)
x1=tf.keras.layers.density(2,name='output_1')(x1)
x2=tf.keras.layers.Conv2D(256,1,name='output_2')(x)
x3=tf.keras.layers.flatte()(x)
x3=tf.keras.layers.density(64,name='output_3')(x3)
模型=tf.keras.model(输入=输入,输出=[x1,x2,x3])
优化器=tf.keras.optimizers.Adam(1e-3)
compile(优化器=优化器,loss=CustomLoss())
model.fit(数据集,epochs=1)

以下是一种针对您的案例的方法。我们仍将使用自定义训练循环,但也将利用方便的
.fit
方法,通过自定义此方法。请查看该文档以了解更多详细信息:


下面是一个简单的演示,扩展可复制的代码

import tensorflow as tf

# data set 
dataset = tf.data.Dataset.from_tensors((
    tf.random.uniform((256, 256, 3)),
    {'a_0': [0., 1.], 'a_1': [1.], 'b_0': tf.random.uniform((8, 8, 256)),
     'b_1': [1.], 'c_0': tf.random.uniform((64,)), 'c_1': [1.]}
))
dataset = dataset.batch(1)

# custom loss 
def loss(y_true, y_pred):
        a = tf.keras.losses.binary_crossentropy(y_true['a_0'], y_pred[0]) * y_true['a_1']
        b = tf.square(y_true['b_0'] - y_pred[1]) * y_true['b_1']
        b = tf.reduce_sum(b, axis=(1, 2, 3))
        c = tf.abs(y_true['c_0'] - y_pred[2]) * y_true['c_1']
        c = tf.reduce_sum(c, axis=1)
        return a + b + c
定制型号

# model 
inputs = x = tf.keras.layers.Input((256, 256, 3))
x = tf.keras.applications.ResNet50(include_top=False, weights=None)(x)
x1 = tf.keras.layers.Flatten()(x)
x1 = tf.keras.layers.Dense(2, name='output_1')(x1)
x2 = tf.keras.layers.Conv2D(256, 1, name='output_2')(x)
x3 = tf.keras.layers.Flatten()(x)
x3 = tf.keras.layers.Dense(64, name='output_3')(x3)

# simply pass input and outps to the custom model
custom_model = custom_fit(inputs=[inputs], 
                          outputs=[x1, x2, x3])
这基本上覆盖了将在每批数据上重复运行的
train\u步骤

avg_loss = tf.keras.metrics.Mean('loss', dtype=tf.float32)

class custom_fit(tf.keras.Model):
    def train_step(self, data):
        images, labels = data
        with tf.GradientTape() as tape:
            outputs = self(images, training=True) # forward pass 
            reg_loss = tf.reduce_sum(self.losses)
            pred_loss = loss(labels, outputs)
            total_loss = tf.reduce_sum(pred_loss) + reg_loss
        gradients = tape.gradient(total_loss, self.trainable_variables)
        self.optimizer.apply_gradients(zip(gradients, self.trainable_variables))
        avg_loss.update_state(total_loss)
        return {"loss": avg_loss.result()}
    
    @property
    def metrics(self):
        # We list our `Metric` objects here so that `reset_states()` can be
        # called automatically at the start of each epoch
        # or at the start of `evaluate()`.
        # If you don't implement this property, you have to call
        # `reset_states()` yourself at the time of your choosing.
        return [avg_loss]
构建模型

# model 
inputs = x = tf.keras.layers.Input((256, 256, 3))
x = tf.keras.applications.ResNet50(include_top=False, weights=None)(x)
x1 = tf.keras.layers.Flatten()(x)
x1 = tf.keras.layers.Dense(2, name='output_1')(x1)
x2 = tf.keras.layers.Conv2D(256, 1, name='output_2')(x)
x3 = tf.keras.layers.Flatten()(x)
x3 = tf.keras.layers.Dense(64, name='output_3')(x3)

# simply pass input and outps to the custom model
custom_model = custom_fit(inputs=[inputs], 
                          outputs=[x1, x2, x3])
编译并调整

custom_model.compile(optimizer='adam')
custom_model.fit(dataset, epochs=5, verbose=2)

Epoch 1/5
1/1 - 6s - loss: 73784.0078
Epoch 2/5
1/1 - 1s - loss: 64882.8984
Epoch 3/5
1/1 - 1s - loss: 54760.2500
Epoch 4/5
1/1 - 1s - loss: 47696.7031
Epoch 5/5
1/1 - 1s - loss: 40574.6328

你的模型定义是什么?你能添加吗?当然,我添加了简化模型使用自定义循环的当前方法是什么?它是否按预期工作?你能提供一些可复制的代码吗?我为我的定制培训添加了代码和最小可复制代码。关于我的定制培训,是的,它按照预期工作,我能够在单个数据集样本上进行过度拟合。