使用隐藏层输出作为 objective 一部分的 Keras 自定义损失函数
Keras custom loss function that uses hidden layer outputs as part of the objective
我正在尝试在 Keras 中实现一个自动编码器,它不仅可以最小化重建误差,而且其构造的特征还应该最大化我定义的度量。我真的不知道该怎么做。
这是我目前所拥有的片段:
corrupt_data = self._corrupt(self.data, 0.1)
# define encoder-decoder network structure
# create input layer
input_layer = Input(shape=(corrupt_data.shape[1], ))
encoded = Dense(self.encoding_dim, activation = "relu")(input_layer)
decoded = Dense(self.data.shape[1], activation="sigmoid")(encoded)
# create autoencoder
dae = Model(input_layer, decoded)
# define custom multitask loss with wlm measure
def multitask_loss(y_true, y_pred):
# extract learned features from hidden layer
learned_fea = Model(input_layer, encoded).predict(self.data)
# additional measure I want to optimize from an external function
wlm_measure = wlm.measure(learned_fea, self.labels)
cross_entropy = losses.binary_crossentropy(y_true, y_pred)
return wlm_measure + cross_entropy
# create optimizer
dae.compile(optimizer=self.optimizer, loss=multitask_loss)
dae.fit(corrupt_data, self.data,
epochs=self.epochs, batch_size=20, shuffle=True,
callbacks=[tensorboard])
# separately create an encoder model
encoder = Model(input_layer, encoded)
目前这不能正常工作...当我查看训练历史时,模型似乎忽略了额外的度量并且仅基于交叉熵损失进行训练。此外,如果我将损失函数更改为仅考虑 wlm 度量,我会得到错误 "numpy.float64" object has no attribute "get_shape" (我不知道是否将我的 wlm 函数的 return 类型更改为张量会有所帮助)。
我认为有几个地方可能出错了。我不知道我是否在我的自定义损失函数中正确提取了隐藏层的输出。我也不知道我的 wlm.measure 函数是否输出正确——它应该输出 numpy.float32 还是 float32 类型的一维张量。
基本上传统的损失函数只关心输出层的预测标签和真实标签。就我而言,我还需要考虑隐藏层的输出(激活),这在 Keras 中实现起来并不那么简单。
感谢您的帮助!
您不想在自定义损失函数中定义 learned_fea
Model
。相反,您可以预先定义一个具有两个输出的单一模型:解码器的输出(重建)和编码器的输出(特征表示):
multi_output_model = Model(inputs=input_layer, outputs=[decoded, encoded])
现在您可以编写仅适用于编码器输出的自定义损失函数:
def custom_loss(y_true, y_pred):
return wlm.measure(y_pred, y_true)
编译模型时,您传递一个损失函数列表(如果您命名张量,则传递一个字典):
model.compile(loss=['binary_crossentropy', custom_loss], optimizer=...)
并通过传递输出列表来拟合模型:
model.fit(X=X, y=[data_to_be_reconstructed,labels_for_wlm_measure])
我正在尝试在 Keras 中实现一个自动编码器,它不仅可以最小化重建误差,而且其构造的特征还应该最大化我定义的度量。我真的不知道该怎么做。
这是我目前所拥有的片段:
corrupt_data = self._corrupt(self.data, 0.1)
# define encoder-decoder network structure
# create input layer
input_layer = Input(shape=(corrupt_data.shape[1], ))
encoded = Dense(self.encoding_dim, activation = "relu")(input_layer)
decoded = Dense(self.data.shape[1], activation="sigmoid")(encoded)
# create autoencoder
dae = Model(input_layer, decoded)
# define custom multitask loss with wlm measure
def multitask_loss(y_true, y_pred):
# extract learned features from hidden layer
learned_fea = Model(input_layer, encoded).predict(self.data)
# additional measure I want to optimize from an external function
wlm_measure = wlm.measure(learned_fea, self.labels)
cross_entropy = losses.binary_crossentropy(y_true, y_pred)
return wlm_measure + cross_entropy
# create optimizer
dae.compile(optimizer=self.optimizer, loss=multitask_loss)
dae.fit(corrupt_data, self.data,
epochs=self.epochs, batch_size=20, shuffle=True,
callbacks=[tensorboard])
# separately create an encoder model
encoder = Model(input_layer, encoded)
目前这不能正常工作...当我查看训练历史时,模型似乎忽略了额外的度量并且仅基于交叉熵损失进行训练。此外,如果我将损失函数更改为仅考虑 wlm 度量,我会得到错误 "numpy.float64" object has no attribute "get_shape" (我不知道是否将我的 wlm 函数的 return 类型更改为张量会有所帮助)。
我认为有几个地方可能出错了。我不知道我是否在我的自定义损失函数中正确提取了隐藏层的输出。我也不知道我的 wlm.measure 函数是否输出正确——它应该输出 numpy.float32 还是 float32 类型的一维张量。
基本上传统的损失函数只关心输出层的预测标签和真实标签。就我而言,我还需要考虑隐藏层的输出(激活),这在 Keras 中实现起来并不那么简单。
感谢您的帮助!
您不想在自定义损失函数中定义 learned_fea
Model
。相反,您可以预先定义一个具有两个输出的单一模型:解码器的输出(重建)和编码器的输出(特征表示):
multi_output_model = Model(inputs=input_layer, outputs=[decoded, encoded])
现在您可以编写仅适用于编码器输出的自定义损失函数:
def custom_loss(y_true, y_pred):
return wlm.measure(y_pred, y_true)
编译模型时,您传递一个损失函数列表(如果您命名张量,则传递一个字典):
model.compile(loss=['binary_crossentropy', custom_loss], optimizer=...)
并通过传递输出列表来拟合模型:
model.fit(X=X, y=[data_to_be_reconstructed,labels_for_wlm_measure])