我的模型有两个输入,我想分别计算两个输入的损失,因为输入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_true
和y_pred
。
所以我无法在模型中添加x = my_categorical_crossentropy_layer()[y_true, y_pred]
。
在keras模型中,有没有办法像这样进行变量计算?
此外,Keras在训练过程中能否获得上一个时期的训练损失或val损失? 我想将前一个时期的训练损失作为我在最后一次损失中的体重。
答案 0 :(得分:1)
这是我的建议...
这是您想使用一次拟合进行的双二进制分类问题。首先要注意的是,您需要注意维数:您的输入是4d,而目标是2d单热编码,因此您的网络需要一些降低维数的东西,例如,扁平化或全局池化。之后,您可以开始创建具有两个输入和两个输出的单个模型,并使用两个损失。在您的情况下,损失加权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)