Python 如何在keras模型中计算不同输入的不同损耗

Python 如何在keras模型中计算不同输入的不同损耗,python,tensorflow,keras,deep-learning,neural-network,Python,Tensorflow,Keras,Deep Learning,Neural Network,我的模型有两个输入,我想分别计算两个输入的损耗,因为输入2的损耗必须乘以一个权重。然后将这两个损失相加,作为模型的最终损失。结构是这样的: 这是我的模型: def final_loss(y_true, y_pred): loss = x_loss_value.output + y_model.output*weight return loss def mymodel(input_shape): #pooling=max or avg img_input1 = Inp

我的模型有两个输入,我想分别计算两个输入的损耗,因为输入2的损耗必须乘以一个权重。然后将这两个损失相加,作为模型的最终损失。结构是这样的:

这是我的模型:

def final_loss(y_true, y_pred):
    loss = x_loss_value.output + y_model.output*weight
    return loss

def mymodel(input_shape): #pooling=max or avg

    img_input1 = Input(shape=(input_shape[0], input_shape[1], input_shape[2], ))
    image_input2 = Input(shape=(input_shape[0], input_shape[1], input_shape[2], )) 

    #for input1 
    x = Conv2D(32, (3, 3), strides=(2, 2))(img_input1)
    x_dense = Dense(2, activation='softmax', name='predictions')(x)
    x_loss_value = my_categorical_crossentropy_layer(x)[input1_y_true, input1_y_pred]
    x_model = Model(inputs=img_input1, outputs=x_loss_value)

    #for input2 
    y = Conv2D(32, (3, 3), strides=(2, 2))(image_input2)
    y_dense = Dense(2, activation='softmax', name='predictions')(y)
    y_loss_value = my_categorical_crossentropy_layer(y)[input2_y_true, input2_y_pred]
    y_model = Model(inputs=img_input2, outputs=y_loss_value)

    concat = concatenate([x_model.output, y_model.output])
    final_dense = Dense(2, activation='softmax')(concat)

    # Create model.
    model = Model(inputs=[img_input1,image_input2], output = final_dense)
    return model

    model.compile(optimizer = optimizers.adam(lr=1e-7), loss = final_loss, metrics = ['accuracy'])
我发现的大多数相关解决方案只是定制最终损耗,并在
Model.complie(loss=customize\u loss)
中更改损耗

但是,我需要对不同的输入应用不同的损耗。我正在尝试使用这样一个自定义层,并获取我的损失值,以进行最终损失计算:

class my_categorical_crossentropy_layer1(Layer):

    def __init__(self, **kwargs):
        self.is_placeholder = True
        super(my_categorical_crossentropy_layer1, self).__init__(**kwargs)

    def my_categorical_crossentropy_loss(self, y_true, y_pred):
        y_pred = K.constant(y_pred) if not K.is_tensor(y_pred) else y_pred
        y_true = K.cast(y_true, y_pred.dtype)
        return K.categorical_crossentropy(y_true, y_pred, from_logits=from_logits)

    def call(self, y_true, y_pred):
        loss = self.my_categorical_crossentropy_loss(y_true, y_pred)
        self.add_loss(loss, inputs=(y_true, y_pred))
        return loss
但是,在keras模型中,我不知道如何为我的损失层获取当前历元/批次的
y_true
y_pred
。 因此,我无法将
x=my\u categorical\u crossentropy\u layer()[y\u true,y\u pred]
添加到我的模型中

在keras模型中,有没有办法进行这样的变量计算

此外,在训练过程中,Keras能否获得上一个历元的训练损失或val损失? 我想把前一个时期的训练减量作为最后减量的体重。

这是我的建议

这是一个双二进制分类问题,您希望使用单一拟合来执行。首先要注意的是,你需要注意维度:你的输入是4d,而你的目标是热编码的2d,因此你的网络需要一些降低维度的东西,例如扁平化或全局池化。在此之后,可以开始拟合,创建具有两个输入和两个输出的单个模型,并使用两个损耗。在您的案例中,损失是加权的
分类交叉熵
。默认情况下,keras允许使用
loss\u weights
参数设置损耗权重。要复制公式
loss1*1+loss2*W
,请将权重设置为
[1,W]
。您还可以使用loss_weights参数为输出指定不同的损耗,方法是
loss=[loss1,loss2,…]
loss_weights

下面是一个工作示例

input_shape = (28,28,3)
n_sample = 10

# create dummy data
X1 = np.random.uniform(0,1, (n_sample,)+input_shape) # 4d
X2 = np.random.uniform(0,1, (n_sample,)+input_shape) # 4d
y1 = tf.keras.utils.to_categorical(np.random.randint(0,2, n_sample)) # 2d
y2 = tf.keras.utils.to_categorical(np.random.randint(0,2, n_sample)) # 2d

def mymodel(input_shape, weight):

    img_input1 = Input(shape=(input_shape[0], input_shape[1], input_shape[2], ))
    img_input2 = Input(shape=(input_shape[0], input_shape[1], input_shape[2], )) 

    # for input1 
    x = Conv2D(32, (3, 3), strides=(2, 2))(img_input1)
    x = GlobalMaxPool2D()(x) # pass from 4d to 2d
    x = Dense(2, activation='softmax', name='predictions1')(x)

    # for input2 
    y = Conv2D(32, (3, 3), strides=(2, 2))(img_input2)
    y = GlobalMaxPool2D()(y) # pass from 4d to 2d
    y = Dense(2, activation='softmax', name='predictions2')(y)

    # Create model
    model = Model([img_input1,img_input2], [x,y])
    model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'],
                  loss_weights=[1,weight])
    
    return model

weight = 0.3
model = mymodel(input_shape, weight)
model.summary()

model.fit([X1,X2], [y1,y2], epochs=2)