我想使用FCN(一种U-Net)来进行语义分割。
我使用基于Tensorflow后端的Python和Keras进行了此操作。现在,我取得了良好的结果,我正在尝试改善它们,我认为做到这一点的一种方法是改善损失计算。
我知道在我的输出中,几个类是不平衡的,使用默认的categorical_crossentropy
函数可能是个问题。
我的模型输入和输出均为float32格式,输入为channel_first,输出为channel_last(在模型末尾完成排列)
在二进制情况下,当我只想细分一个类时,我以这种方式更改了损失函数,因此它可以根据输出内容逐个添加权重:
def weighted_loss(y_true, y_pred):
def weighted_binary_cross_entropy(y_true, y_pred):
w = tf.reduce_sum(y_true)/tf_cast(tf_size(y_true), tf_float32)
real_th = 0.5-th
tf_th = tf.fill(tf.shape(y_pred), real_th)
tf_zeros = tf.fill(tf.shape(y_pred), 0.)
return (1.0 - w) * y_true * - tf.log(tf.maximum(tf.zeros, tf.sigmoid(y_pred) + tf_th)) +
(1- y_true) * w * -tf.log(1 - tf.maximum(tf_zeros, tf.sigmoid(y_pred) + tf_th))
return weighted_binary_coss_entropy
请注意,th是激活阈值,默认情况下为1 / nClasses,我已对其进行了更改,以查看哪个值能给我带来最佳效果 你怎么看待这件事? 对其进行更改,以便能够计算加权分类交叉熵(在多类情况下)
答案 0 :(得分:0)
您的实现将适用于二进制类,对于多类,它将只是
-y_true * tf.log(tf.sigmoid(y_pred))
并使用内置的张量流方法来计算类别熵,因为它避免了y_pred <0
的溢出您可以查看此答案Unbalanced data and weighted cross entropy,它说明了加权分类交叉熵的实现。
categorical_crossentropy的唯一变化是
def weighted_loss(y_true, y_pred):
def weighted_categorical_cross_entropy(y_true, y_pred):
w = tf.reduce_sum(y_true)/tf_cast(tf_size(y_true), tf_float32)
loss = w * tf.nn.softmax_cross_entropy_with_logits(onehot_labels, logits)
return loss
return weighted_categorical_cross_entropy
提取单个班级的预测
def loss(y_true, y_pred):
s = tf.shape(y_true)
# if number of output classes is at last
number_classses = s[-1]
# this will give you one hot code for your prediction
clf_pred = tf.one_hot(tf.argmax(y_pred, axis=-1), depth=number_classses, axis=-1)
# extract the values of y_pred where y_pred is max among the classes
prediction = tf.where(tf.equal(clf_pred, 1), y_pred, tf.zeros_like(y_pred))
# if one hotcode == 1 then class1_prediction == y_pred else class1_prediction ==0
class1_prediction = prediction[:, :, :, 0:1]
# you can compute your loss here on individual class and return the loss ,just for simplicity i am returning the class1_prediction
return class1_prediction
模型输出
y_pred = [[[[0.5, 0.3, 0.7],
[0.6, 0.3, 0.2]]
,
[[0.7, 0.9, 0.6],
[0.3 ,0.9, 0.3]]]]
相应的地面真相
y_true = [[[[0, 1, 0],
[1 ,0, 0]]
,
[[1,0 , 0],
[0,1, 0]]]]
第1类的预测
prediction = loss(y_true, y_pred)
# prediction = [[[[0. ],[0.6]],[0. ],[0. ]]]]