【问题标题】:How to calculate different loss for different input in keras model如何计算keras模型中不同输入的不同损失
【发布时间】:2020-08-07 08:17:33
【问题描述】:

我的模型有两个输入,我想分别计算两个输入的损失,因为输入 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_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_truey_pred。 所以我不能将x = my_categorical_crossentropy_layer()[y_true, y_pred] 添加到我的模型中。

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

进一步,Keras 能否在训练过程中得到上一个 epoch 的训练损失或 val 损失? 我想将上一个 epoch 的训练损失作为我在最终损失中的权重。

【问题讨论】:

    标签: python tensorflow keras deep-learning neural-network


    【解决方案1】:

    这是我的提议……

    您的这是一个双二元分类问题,您希望使用单一拟合来执行。首先要注意的是您需要注意维度:您的输入是 4d,而您的目标是 2d one-hot 编码,因此您的网络需要一些东西来降低维度,例如扁平化或全局池化。在此之后,您可以开始拟合创建具有两个输入和两个输出的单个模型并使用两个损失。在您的情况下,损失加权categorical_crossentropy。 keras 默认启用以使用loss_weights 参数设置损失权重。重现公式loss1*1+loss2*W 将权重设置为[1, W]。您可以使用 loss_weights 参数,也可以通过这种方式为您的输出指定不同的损失 losses=[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)
    

    【讨论】:

      猜你喜欢
      • 2019-02-09
      • 2018-07-21
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-10
      • 2019-07-25
      • 2020-10-07
      相关资源
      最近更新 更多