我最近尝试通过提供附加到最后一个编码块的附加分支来修改一维数据的 U-NET 模型,其目的是将数据分类到皮层的十八个区域。 (基于本文的灵感:https://arxiv.org/pdf/1806.01313)
负责语义分割的部分将数据(一维形式的皮层特征)划分为六层。
示例输入形状为 (15000, 256, 1),其中 15000 是一维皮质轮廓(或向量)的数量,256 是单个轮廓的深度,1 是皮质特征或通道(例如强度或估计大小)细胞)。对于分割,目标是 one-hot (15000, 256, 6),其中 6 是层数,对于区域分类,目标是 (15000, 18)。
然而,令我困惑的是:
我尝试了这两种方法,并观察到,当我加入损失函数时,获得的分类精度和损失比使用单独的损失函数时要低得多。这让我想到了下一个问题:
Separate loss functions:
883/883 ━━━━━━━━━━━━━━━━━━━━ 63s 71ms/step - classification_accuracy: 0.8877 - classification_loss: 0.2729 - loss: 0.5143 - segmentation_accuracy: 0.8440 - segmentation_loss: 0.2413
Jointed loss functions:
883/883 ━━━━━━━━━━━━━━━━━━━━ 56s 63ms/step - classification_accuracy: 0.0556 - classification_loss: 2.0994e-07 - loss: 0.3952 - segmentation_accuracy: 0.6453 - segmentation_loss: 0.3952
我用来连接分类和分割损失的函数是:
def joint_loss(y_true, y_pred):
# Unpack the true values
y_true_segmentation = y_true[0]
y_true_classification = y_true[1]
y_pred_segmentation = y_pred[0]
y_pred_classification = y_pred[1]
# segmentation loss
segmentation_loss = tf.keras.losses.categorical_crossentropy(
y_true_segmentation,
y_pred_segmentation)
# classification loss
classification_loss = tf.keras.losses.categorical_crossentropy(
y_true_classification,
y_pred_classification)
segmentation_loss = tf.reduce_mean(segmentation_loss)
classification_loss = tf.reduce_mean(classification_loss)
alpha = 1.0 # weight for segmentation
beta = 1.0 # weight for classification
total_loss = alpha * segmentation_loss + beta * classification_loss
return total_loss
然后我编译模型:
loss = {"segmentation": "categorical_crossentropy",
"classification": "categorical_crossentropy"}
metrics = {"segmentation": "accuracy",
"classification": "accuracy"}
model.compile(optimizer=Adam(learning_rate),
loss=joint_loss,
metrics=metrics)
其中
loss
表示单独使用 categorical_crossentropy
进行分类和分割。
是否有可能是模型修改(额外的输出分支)导致的问题?
我知道这可能很多,并且有相关主题,但它们都没有给我我的疑问和问题的答案。
张量流中不存在“单独的损失函数”之类的东西。当你要求它最小化一个多维对象(例如 2 个数字)时,它只是将它们相加。因此,“联合或单独”之间没有真正的选择。张量流令人困惑的是,它隐式地添加这些数字,而不告诉你。
这里真正的选择是什么?
单个损失函数,可能具有权重 alpha(因此 alpha*l1 + (1-alpha)*l2)。优点是:相对简单,仅添加一个超参数,并且一般来说 - 这是所有方法中最常见的方法请注意,您根本不需要“beta”,只需使用 alpha 和 1-alpha。
单独的优化程序(不仅仅是损失!)。这可以采取多种形式,您可以有 2 个独立的 adam,在每次迭代中您可以将其称为 opne。这提供了更大的灵活性,允许对每个损失进行单独的统计,等等,但是......这很难做到。最终你会得到一个巨大的设计空间,多个超参数可供选择。因此,除非您是一位经验丰富的研究人员,并且确切地知道自己在做什么,否则您不太可能真正从中受益。这还包括诸如零空间投影等或使用一种损失作为预训练,然后训练主要损失的单独训练过程。
当您提到“问题”时,您可能意味着主要损失开始表现不佳。一般来说,添加辅助损失并不能保证对您有帮助。通常,人们只是调整权重。因此,如果你有 alpha*main loss + (1-alpha)*new loss,只需从 alpha=1 开始,事情的表现应该与没有新损失时完全相同。如果他们不这样做——你就有一个错误。一旦经过测试,慢慢减少 alpha,检查 0.999、0.99、0.9 等。绘制行为并决定什么对您有效。
如果您想了解更多有关辅助损失的各种挑战,请查看https://arxiv.org/pdf/1812.02224,其中有一些玩具问题,展示了为什么它有时会有所帮助,有时会起到相反的作用。