从名字上来看语义分割应当属于图像分割的范畴,但是实际上它是一个精确到像素的分类任务。
在英文文献中称其为dense prediction, 他的任务生成一张分割图,其能够将原图中的物体按照语义类别进行分割,
这个任务的实质是对每个像素所属类别进行标注,因此在训练的时候需要为每一张图像匹配相应的label。
--------------------------------------------------------------------------------
在看语义分割相关论文(是在U-Net 当中)的时候,我发现了这样的一句话:
The energy function is computed by a pixel-wise soft-max
over the final feature map combined with the cross entropy loss function.
这其中涉及到了一个energy function , 我百度了一下发现能量函数(energy function)一开始在热力学中被定义,用于描述系统的能量值,当能量值达到最小时系统达到稳定状态。
RBM(玻尔兹曼机)首次在神经网络(Neural Network)中用到 了这个概念,类比的来看,这个energy function函数的作用和loss函数的作用应当是差不多的,都是通过最小化该函数来训练网络。
并且在U-Net的论文当中说他们所使用的energy function 包含两部分,一部分是softmax, 另一部分是 cross entropy loss function 也就是常说的交叉熵。
并且这两部分都是pixel-wise的, 也就是说计算时最基本的单位是像素点。
其实在语义分割任务中最常见的 损失函数 就是 交叉熵。
(当然,如何定义模型的损失函数也是网络训练中的重要内容,但在这里我们不做详细的讨论。 有兴趣的朋友可以看一下这篇博客 https://blog.csdn.net/wangdongwei0/article/details/84576044)
-----------------------------------------------------------------------------------
网络在训练的时候需要最小化我们定义的损失函数, 交叉熵在单分类问题上基本是标配的损失函数,在这里我们先来看一下它的相关定义以及在普通单分类网络中的使用。(ps: 单分类任务,即每一张图像样本只能有一个类别,比如只能是狗或只能是猫。)
下面的公式代表一张样本的交叉熵的计算方法,其中n代表着类别数。
举例说明,比如有如下样本:(样例来源:https://blog.csdn.net/tsyccnh/article/details/79163834)
下表是其对应的 标签 和 预测值,(softmax 的使用可以将网络的输出转化为Pred的值,而不是在loss function当中使用。)
我们根据这张表格可以计算出其交叉熵为:
loss = −(0×log(0.3)+1×log(0.6)+0×log(0.1)
= −log(0.6)
那么其对应的一个batch 的 交叉熵就是
其中m为当前batch的样本数,也就是batch_size的大小。
-------------------------------------------------------------------------------------------------------
OK ,现在对于语义分割的实际任务 与 交叉熵的计算方式都有了一定的了解,下面我们就来看一下在
语义分割任务中是如何应用交叉熵的。
(例子来源: https://www.zybuluo.com/Team/note/1205894#%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0)
任务描述:
简单来说,我们的目标是输入一个RGB彩色图片(height, width, 3)或者是一张灰度图(height, width, 1),然后输出一个包含各个像素类别标签的分割图 (height, width, 1) 。
如下图,(为了清晰起见,这里只给出一个低分辨率的预测图。)
与我们处理标准分类值的方式类似,我们的预测目标可以采用one-hot编码,即为每一个可能的类创建一个输出通道,
最终通过取每个像素点在各个 channel 的 argmax 可以得到最终的预测分割图 。 (如下图)
(上面青蛙的 label值 就是一个one-hot 编码, 关于one-hot编码不太理解大家可以自行百度。)
神经网络的输出是每一个像素属于哪种类别的概率大小, 同上面青蛙的例子是相同的,因为使用的都是 softmax 。
对于一个随机的像素经由网络训练所得出的结果可能会是如下的形式,(简写,部分属性未给出)
person | plants | building | |
label | 0 | 0 | 1 |
pred | 0.1 | 0.1 | 0.8 |
是不是很熟悉,这和上面青蛙的例子是一样的,后面的计算过程也就不再给出。
要注意的是这里的 交叉熵 要计算的是一张图像上所有的像素点,所以在语义分割的任务中一定要注意你所给定的
batch_size 的大小,否则内存汇爆掉