Image segmentation suite PaddleSeg comprehensive analysis (6) Loss function code analysis

The PaddleSeg suite supports a variety of loss functions. Cross Entroy Loss (Cross Entroy Loss) is a very commonly used loss function, which is basically used in image classification. Generally, in image classification, the number of final output nodes of the neural network is consistent with the number of categories, and the shape is [batch_size, num_classes], and the sample label is directly represented by the serial number of the category, and the shape is [batch_size, 1]. The function to calculate cross entropy in paddle is softmax_with_cross_entropy. Generally, the two commonly used parameters are logits and label, which can be calculated directly using logits and the label representing the category number. for example

import paddle.fluid as fluid
#这里会自动组装成batch,实际data的shape为[batch_size, 128],label的shape为[batch_size, 1]
#softmax_with_cross_entropy接收的两个参数的维度一致,只是在最后一个维度上形状不同,label在最后
#一个维度上的长度为1,代表的就是类别的编号,一般从0开始计数。
data = fluid.layers.data(name='data', shape=[128], dtype='float32')
label = fluid.layers.data(name='label', shape=[1], dtype='int64')
fc = fluid.layers.fc(input=data, size=100)
out = fluid.layers.softmax_with_cross_entropy(logits=fc, label=label)

Here softmax_with_cross_entropy first performs softmax calculation on logits, the formula is as follows:

s o f t m a x [ i , j ] = exp ⁡ ( x [ i , j ] ) ∑ j ( e x p ( x [ i , j ] ) softmax[i, j] = \frac{\exp(x[i, j])}{\sum_j(exp(x[i, j])} softmax[i,j]=j(exp(x[i,j])exp(x[i,j])

Then calculate the cross entropy, the calculation formula is as follows:

o u t p u t [ i 1 , i 2 , . . . , i k ] = − l o g ( i n p u t [ i 1 , i 2 , . . . , i k , j ] ) , l a b e l [ i 1 , i 2 , . . . , i k ] = j , j ! = i g n o r e _ i n d e x output[i_1, i_2, ..., i_k]=-log(input[i_1, i_2, ..., i_k, j]), label[i_1, i_2, ..., i_k] = j, j != ignore\_index output[i1,i2,...,ik]=log(input[i1,i2,...,ik,j]),label[i1,i2,...,ik]=j,j!=i g n o r e _ i n d e x
The formula for calculating the cross entropy is explained briefly, which is to convert the label to one hot form, the logit value corresponding to 1 in the label vector to calculate the -log value, if the logit value The closer to 1, the smaller the loss value. As shown below:

The cross entropy function in PaddleSeg is defined in the paddleseg/models/losses/cross_entroy_loss.py function. Let's analyze the code below.

class CrossEntropyLoss(nn.Layer):

    def __init__(self, ignore_index=255):
        super(CrossEntropyLoss, self).__init__()
        #保存需要忽略的类别序号
        self.ignore_index = ignore_index
        self.EPS = 1e-5

    def forward(self, logit, label):
        #比较label和logit的维度是否一致,一般传入label维度可能会比logit少1,
        #soft_with_cross_entropy的参数要求维度数量一致,所以这里把label扩展一个维度
        if len(label.shape) != len(logit.shape):
            label = paddle.unsqueeze(label, 1)
        #对logit和label进行转置,将通道转置到最后一个维度,原来的形状为[batch_size, channel, height, width]
        #转置后形状为[batch_size, height, width, channel]
        #这时logit的channel的维度长度与类别数目一致,label的channel维度为长度为1,保存的是类别序号。
        logit = paddle.transpose(logit, [0, 2, 3, 1])
        label = paddle.transpose(label, [0, 2, 3, 1])
        #计算交叉熵
        loss = F.softmax_with_cross_entropy(
            logit, label, ignore_index=self.ignore_index, axis=-1)
        #统计有效的像素的数量,这里执行后类型为boolean
        mask = label != self.ignore_index
        #boolean无法与float32运算,所以这里需要进行类型转换。
        mask = paddle.cast(mask, 'float32')
        #统计需要计算loss的像素的数量,如果有的label是需要忽略的,那么在mask对应的位置则为0。
        loss = loss * mask
        #计算整幅图像的损失值。如果图像中有忽略的部分,用损失值除以有效部分的占比,可以估算出整幅图像的损失值,
        #这样保证了有忽略部分的图像和没有忽略的图像损失计算的都是整幅图像的损失值。
        avg_loss = paddle.mean(loss) / (paddle.mean(mask) + self.EPS)

        label.stop_gradient = True
        mask.stop_gradient = True
        return avg_loss

The above is the interpretation of the loss function part.

PaddleSeg warehouse address: https://github.com/PaddlePaddle/PaddleSeg

Guess you like

Origin blog.csdn.net/txyugood/article/details/111125112