Keras 中(有些)重叠子模型的多个损失函数
Multiple loss functions on (somewhat) overlapping sub-models in Keras
我在 Keras 中有一个模型,我想在其中使用两个损失函数。该模型由一个自动编码器和一个分类器组成。我想要一个损失函数来确保自动编码器安装得相当好(例如,它可以是 mse)和另一个评估分类器的损失函数(例如,categorical_crossentropy)。我想拟合我的模型并使用一个损失函数,它是两个损失函数的线性组合。
# loss functions
def ae_mse_loss(x_true, x_pred):
ae_loss = K.mean(K.square(x_true - x_pred), axis=1)
return ae_loss
def clf_loss(y_true, y_pred):
return K.sum(K.categorical_crossentropy(y_true, y_pred), axis=-1)
def combined_loss(y_true, y_pred):
???
return ae_loss + w1*clf_loss
其中 w1 是定义最终组合损失中“clf_loss 的重要性”的权重。
# autoencoder
ae_in_layer = Input(shape=in_dim, name='ae_in_layer')
ae_interm_layer1 = Dense(interm_dim, activation='relu', name='ae_interm_layer1')(ae_in_layer)
ae_mid_layer = Dense(latent_dim, activation='relu', name='ae_mid_layer')(ae_interm_layer1)
ae_interm_layer2 = Dense(interm_dim, activation='relu', name='ae_interm_layer2')(ae_mid_layer)
ae_out_layer = Dense(in_dim, activation='linear', name='ae_out_layer')(ae_interm_layer2)
ae_model=Model(ae_input_layer, ae_out_layer)
ae_model.compile(optimizer='adam', loss = ae_mse_loss)
# classifier
clf_in_layer = Dense(interm_dim, activation='sigmoid', name='clf_in_layer')(ae_out_layer)
clf_out_layer = Dense(3, activation='softmax', name='clf_out_layer')(clf_in_layer)
clf_model = Model(clf_in_layer, clf_out_layer)
clf_model.compile(optimizer='adam', loss = combined_loss, metrics = [ae_mse_loss, clf_loss])
我不确定的是如何区分两个损失函数中的 y_true 和 y_pred(因为它们指的是模型中不同阶段的真实数据和预测数据)。我的想法是这样的(我不确定如何实现它,因为显然我只需要传递一组参数 y_true & y_pred):
def combined_loss(y_true, y_pred):
ae_loss = ae_mse_loss(x_true_ae, x_pred_ae)
clf_loss = clf_loss(y_true_clf, y_pred_clf)
return ae_loss + w1*clf_loss
我可以将这个问题定义为两个单独的模型并分别训练每个模型,但如果可能的话我真的更愿意一次完成所有这些(因为它会同时优化两个问题)。我意识到,这个模型没有多大意义,但它演示了我试图以简单的方式解决的(更复杂的)问题。
如有任何建议,我们将不胜感激。
您所需要的一切都可以在原生 keras 中轻松获得
你可以使用loss_weights
参数
自动组合多个损失
在下面的示例中,我尝试重现您的示例,其中我结合了回归任务的 mse
损失和分类任务的 categorical_crossentropy
损失
in_dim = 10
interm_dim = 64
latent_dim = 32
n_class = 3
n_sample = 100
X = np.random.uniform(0,1, (n_sample,in_dim))
y = tf.keras.utils.to_categorical(np.random.randint(0,n_class, n_sample))
# autoencoder
ae_in_layer = Input(shape=in_dim, name='ae_in_layer')
ae_interm_layer1 = Dense(interm_dim, activation='relu', name='ae_interm_layer1')(ae_in_layer)
ae_mid_layer = Dense(latent_dim, activation='relu', name='ae_mid_layer')(ae_interm_layer1)
ae_interm_layer2 = Dense(interm_dim, activation='relu', name='ae_interm_layer2')(ae_mid_layer)
ae_out_layer = Dense(in_dim, activation='linear', name='ae_out_layer')(ae_interm_layer2)
# classifier
clf_in_layer = Dense(interm_dim, activation='sigmoid', name='clf_in_layer')(ae_out_layer)
clf_out_layer = Dense(n_class, activation='softmax', name='clf_out_layer')(clf_in_layer)
model = Model(ae_in_layer, [ae_out_layer,clf_out_layer])
model.compile(optimizer='adam',
loss = {'ae_out_layer':'mse', 'clf_out_layer':'categorical_crossentropy'},
loss_weights = {'ae_out_layer':1., 'clf_out_layer':0.5})
model.fit(X, [X,y], epochs=10)
在此特定情况下,loss
是 1*ae_out_layer_loss + 0.5*clf_out_layer_loss
的结果
我在 Keras 中有一个模型,我想在其中使用两个损失函数。该模型由一个自动编码器和一个分类器组成。我想要一个损失函数来确保自动编码器安装得相当好(例如,它可以是 mse)和另一个评估分类器的损失函数(例如,categorical_crossentropy)。我想拟合我的模型并使用一个损失函数,它是两个损失函数的线性组合。
# loss functions
def ae_mse_loss(x_true, x_pred):
ae_loss = K.mean(K.square(x_true - x_pred), axis=1)
return ae_loss
def clf_loss(y_true, y_pred):
return K.sum(K.categorical_crossentropy(y_true, y_pred), axis=-1)
def combined_loss(y_true, y_pred):
???
return ae_loss + w1*clf_loss
其中 w1 是定义最终组合损失中“clf_loss 的重要性”的权重。
# autoencoder
ae_in_layer = Input(shape=in_dim, name='ae_in_layer')
ae_interm_layer1 = Dense(interm_dim, activation='relu', name='ae_interm_layer1')(ae_in_layer)
ae_mid_layer = Dense(latent_dim, activation='relu', name='ae_mid_layer')(ae_interm_layer1)
ae_interm_layer2 = Dense(interm_dim, activation='relu', name='ae_interm_layer2')(ae_mid_layer)
ae_out_layer = Dense(in_dim, activation='linear', name='ae_out_layer')(ae_interm_layer2)
ae_model=Model(ae_input_layer, ae_out_layer)
ae_model.compile(optimizer='adam', loss = ae_mse_loss)
# classifier
clf_in_layer = Dense(interm_dim, activation='sigmoid', name='clf_in_layer')(ae_out_layer)
clf_out_layer = Dense(3, activation='softmax', name='clf_out_layer')(clf_in_layer)
clf_model = Model(clf_in_layer, clf_out_layer)
clf_model.compile(optimizer='adam', loss = combined_loss, metrics = [ae_mse_loss, clf_loss])
我不确定的是如何区分两个损失函数中的 y_true 和 y_pred(因为它们指的是模型中不同阶段的真实数据和预测数据)。我的想法是这样的(我不确定如何实现它,因为显然我只需要传递一组参数 y_true & y_pred):
def combined_loss(y_true, y_pred):
ae_loss = ae_mse_loss(x_true_ae, x_pred_ae)
clf_loss = clf_loss(y_true_clf, y_pred_clf)
return ae_loss + w1*clf_loss
我可以将这个问题定义为两个单独的模型并分别训练每个模型,但如果可能的话我真的更愿意一次完成所有这些(因为它会同时优化两个问题)。我意识到,这个模型没有多大意义,但它演示了我试图以简单的方式解决的(更复杂的)问题。
如有任何建议,我们将不胜感激。
您所需要的一切都可以在原生 keras 中轻松获得
你可以使用loss_weights
参数
在下面的示例中,我尝试重现您的示例,其中我结合了回归任务的 mse
损失和分类任务的 categorical_crossentropy
损失
in_dim = 10
interm_dim = 64
latent_dim = 32
n_class = 3
n_sample = 100
X = np.random.uniform(0,1, (n_sample,in_dim))
y = tf.keras.utils.to_categorical(np.random.randint(0,n_class, n_sample))
# autoencoder
ae_in_layer = Input(shape=in_dim, name='ae_in_layer')
ae_interm_layer1 = Dense(interm_dim, activation='relu', name='ae_interm_layer1')(ae_in_layer)
ae_mid_layer = Dense(latent_dim, activation='relu', name='ae_mid_layer')(ae_interm_layer1)
ae_interm_layer2 = Dense(interm_dim, activation='relu', name='ae_interm_layer2')(ae_mid_layer)
ae_out_layer = Dense(in_dim, activation='linear', name='ae_out_layer')(ae_interm_layer2)
# classifier
clf_in_layer = Dense(interm_dim, activation='sigmoid', name='clf_in_layer')(ae_out_layer)
clf_out_layer = Dense(n_class, activation='softmax', name='clf_out_layer')(clf_in_layer)
model = Model(ae_in_layer, [ae_out_layer,clf_out_layer])
model.compile(optimizer='adam',
loss = {'ae_out_layer':'mse', 'clf_out_layer':'categorical_crossentropy'},
loss_weights = {'ae_out_layer':1., 'clf_out_layer':0.5})
model.fit(X, [X,y], epochs=10)
在此特定情况下,loss
是 1*ae_out_layer_loss + 0.5*clf_out_layer_loss