精华内容
下载资源
问答
  • 从loss处理图像分割中类别极度均衡的状况---keras

    万次阅读 多人点赞 2019-02-10 23:21:35
    最近在做小目标图像分割任务(医疗方向),往往一幅图像中只有一个或者两个目标,而且目标的像素比例比较小,选择合适的loss function往往可以解决这个问题。以下是我的实验比较。 场景: 1.U-Net网络 2. keras...

    前言

    最近在做小目标图像分割任务(医疗方向),往往一幅图像中只有一个或者两个目标,而且目标的像素比例比较小,使网络训练较为困难,一般可能有三种的解决方式:

    1. 选择合适的loss function,对网络进行合理的优化,关注较小的目标。
    2. 改变网络结构,使用attention机制(类别判断作为辅助)。
    3. 与2的根本原理一致,类属attention,即:先检测目标区域,裁剪之后进行分割训练。

    通过使用设计合理的loss function,相比于另两种方式更加简单易行,能够保留图像所有信息的情况下进行网络优化,达到对小目标精确分割的目的。

    场景

    1. 使用U-Net作为基准网络。
    2. 实现使用keras
    3. 小目标图像分割场景,如下图举例。
      AI Challenger眼底水肿病变区域自动分割,背景占据了很大的一部分
      在这里插入图片描述
      segthor医疗影像器官分割
      在这里插入图片描述

    loss function

    一、Log loss

    对于二分类而言,对数损失函数如下公式所示: − 1 N ∑ i = 1 N ( y i log ⁡ p i + ( 1 − y i ) log ⁡ ( 1 − p i ) ) -\frac{1}{N}\sum_{i=1}^{N}(y_i\log p_i + (1-y_i)\log (1-p_i)) N1i=1N(yilogpi+(1yi)log(1pi))
    其中, y i y_i yi为输入实例 x i x_i xi真实类别, p i p_i pi为预测输入实例 x i x_i xi 属于类别 1 的概率. 对所有样本的对数损失表示对每个样本的对数损失的平均值, 对于完美的分类器, 对数损失为 0。
    此loss function每一次梯度的回传对每一个类别具有相同的关注度!所以极易受到类别不平衡的影响,在图像分割领域尤其如此。
    例如目标在整幅图像当中占比也就仅仅千分之一,那么在一副图像中,正样本(像素点)与父样本的比例约为1~1000,如果训练图像中还包含大量的背景图,即图像当中不包含任何的疾病像素,那么不平衡的比例将扩大到>10000,那么训练的后果将会是,网络倾向于什么也不预测!生成的mask几乎没有病灶像素区域!
    此处的案例可以参考airbus-ship-detection

    二、WCE Loss

    带权重的交叉熵loss — Weighted cross-entropy (WCE)[6]
    R为标准的分割图,其中 r n r_n rn为label 分割图中的某一个像素的GT。P为预测的概率图, p n p_n pn为像素的预测概率值,背景像素图的概率值就为1-P。
    只有两个类别的带权重的交叉熵为:
    W C E = − 1 N ∑ n = 1 N ( w r n l o g ( p n ) + ( 1 − r n ) l o g ( 1 − p n ) ) WCE = - \frac{1}{N}\sum_{n=1}^{N}(wr_nlog(p_n) + (1 - r_n)log(1 - p_n)) WCE=N1n=1N(wrnlog(pn)+(1rn)log(1pn))
    w w w为权重, w = N − ∑ n p n ∑ n p n w=\frac{N-\sum_np_n}{\sum_np_n} w=npnNnpn

    缺点是需要人为的调整困难样本的权重,增加调参难度。

    三、Focal loss

    能否使网络主动学习困难样本呢?
    focal loss的提出是在目标检测领域,为了解决正负样本比例严重失衡的问题。是由log loss改进而来的,为了于log loss进行对比,公式如下:
    − 1 N ∑ i = 1 N ( α y i ( 1 − p i ) γ log ⁡ p i + ( 1 − α ) ( 1 − y i ) p i γ log ⁡ ( 1 − p i ) ) -\frac{1}{N}\sum_{i=1}^{N}(\alpha y_i(1-p_i)^{\gamma}\log p_i + (1-\alpha )(1-y_i)p_i^{\gamma}\log (1-p_i)) N1i=1N(αyi(1pi)γlogpi+(1α)(1yi)piγlog(1pi))
    说白了就多了一个 ( 1 − p i ) γ (1-p_i)^{\gamma} (1pi)γ,loss随样本概率的大小如下图所示:
    在这里插入图片描述
    其基本思想就是,对于类别极度不均衡的情况下,网络如果在log loss下会倾向于只预测负样本,并且负样本的预测概率 p i p_i pi也会非常的高,回传的梯度也很大。但是如果添加 ( 1 − p i ) γ (1-p_i)^{\gamma} (1pi)γ则会使预测概率大的样本得到的loss变小,而预测概率小的样本,loss变得大,从而加强对正样本的关注度。
    可以改善目标不均衡的现象,对此情况比 binary_crossentropy 要好很多。
    目前在图像分割上只是适应于二分类。
    代码:https://github.com/mkocabas/focal-loss-keras

    from keras import backend as K
    '''
    Compatible with tensorflow backend
    '''
    def focal_loss(gamma=2., alpha=.25):
    	def focal_loss_fixed(y_true, y_pred):
    		pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
            pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))
            return -K.sum(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1))-K.sum((1-alpha) * K.pow( pt_0, gamma) * K.log(1. - pt_0))
    	return focal_loss_fixed
    

    使用方法:

    model_prn.compile(optimizer=optimizer, loss=[focal_loss(alpha=.25, gamma=2)])
    

    目前实验得到结论:

    1. 经过测试,发现使用focal loss很容易就会过拟合??且效果一般。。。I don’t know why?
    2. 此方法代码有待改进,因为此处使用的网络为U-net,输入和输出都是一张图!直接使用会导致loss的值非常的大!
    3. 需要添加额外的两个全局参数alpha和gamma,对于调参不方便。

    以上的方法Log loss,WBE Loss,Focal loss都是从本源上即从像素上来对网络进行优化。针对的都是像素的分类正确与否。有时并不能在评测指标上DICE上得到较好的结果。

    ---- 更新2020-4-1
    将K.sum改为K.mean, 与其他的keras中自定义的损失函数保持一致:

    -K.mean(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1)) - K.mean((1 - alpha) * K.pow(pt_0, gamma) * K.log(1. - pt_0))
    

    效果还未尝试,如果有同学尝试了可以留言交流~

    四、Dice loss

    dice loss 的提出是在V-net中,其中的一段原因描述是在感兴趣的解剖结构仅占据扫描的非常小的区域,从而使学习过程陷入损失函数的局部最小值。所以要加大前景区域的权重。

    Dice 可以理解为是两个轮廓区域的相似程度,用A、B表示两个轮廓区域所包含的点集,定义为:
    D S C ( A , B ) = 2 ∣ A ⋂ B ∣ ∣ A ∣ + ∣ B ∣ DSC(A,B) = 2\frac{|A\bigcap B |}{|A| + |B|} DSC(A,B)=2A+BAB
    其次Dice也可以表示为:
    D S C = 2 T P 2 T P + F N + F P DSC = \frac{2TP}{2TP+FN+FP} DSC=2TP+FN+FP2TP
    其中TP,FP,FN分别是真阳性、假阳性、假阴性的个数。
    二分类dice loss:
    D L 2 = 1 − ∑ n = 1 N p n r n + ϵ ∑ n = 1 N p n + r n + ϵ − ∑ n = 1 N ( 1 − p n ) ( 1 − r n ) + ϵ ∑ n = 1 N 2 − p n − r n + ϵ DL_2 = 1 - \frac{\sum_{n=1}^{N}p_nr_n + \epsilon}{\sum_{n=1}^{N}p_n + r_n + \epsilon} -\frac{\sum_{n=1}^{N}(1 - p_n)(1 - r_n) + \epsilon}{\sum_{n=1}^{N}2 - p_n - r_n + \epsilon} DL2=1n=1Npn+rn+ϵn=1Npnrn+ϵn=1N2pnrn+ϵn=1N(1pn)(1rn)+ϵ

    代码:

    def dice_coef(y_true, y_pred, smooth=1):
        intersection = K.sum(y_true * y_pred, axis=[1,2,3])
        union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3])
        return K.mean( (2. * intersection + smooth) / (union + smooth), axis=0)
    def dice_coef_loss(y_true, y_pred):
    	1 - dice_coef(y_true, y_pred, smooth=1)
    

    结论:

    1. 有时使用dice loss会使训练曲线有时不可信,而且dice loss好的模型并不一定在其他的评价标准上效果更好,例如mean surface distance 或者是Hausdorff surface distance
      不可信的原因是梯度,对于softmax或者是log loss其梯度简化而言为 p − t p-t pt t t t为目标值, p p p为预测值。而dice loss为 2 t 2 ( p + t ) 2 \frac{2t^2}{(p+t)^2} (p+t)22t2,如果 p p p t t t过小则会导致梯度变化剧烈,导致训练困难。
    2. 属于直接在评价标准上进行优化。
    3. 不均衡的场景下的确好使。
      论文中在前列腺MRI容积图中的分割表现:
      在这里插入图片描述

    五、IOU loss

    可类比DICE LOSS,也是直接针对评价标准进行优化[11]。
    在图像分割领域评价标准IOU实际上 I O U = T P T P + F P + F N IOU = \frac{TP}{TP + FP + FN} IOU=TP+FP+FNTP,而TP,FP,FN分别是真阳性、假阳性、假阴性的个数。
    而作为loss function,定义 I O U = I ( X ) U ( X ) IOU = \frac{I(X)}{U(X)} IOU=U(X)I(X),其中, I ( X ) = X ∗ Y I(X) = X*Y I(X)=XY
    U ( X ) = X + Y − X ∗ Y U(X) = X + Y - X*Y U(X)=X+YXY,X为预测值而Y为真实标签。

    ## intersection over union
    def IoU(y_true, y_pred, eps=1e-6):
        if np.max(y_true) == 0.0:
            return IoU(1-y_true, 1-y_pred) ## empty image; calc IoU of zeros
        intersection = K.sum(y_true * y_pred, axis=[1,2,3])
        union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3]) - intersection
        return -K.mean( (intersection + eps) / (union + eps), axis=0)
    

    [11]在PASCAL VOC 2010上的实验效果如下,基础框架还是FCN
    在这里插入图片描述
    IOU loss的缺点呢同DICE loss是相类似的,训练曲线可能并不可信,训练的过程也可能并不稳定,有时不如使用softmax loss等的曲线有直观性,通常而言softmax loss得到的loss下降曲线较为平滑。

    六、Tversky loss

    提到Tversky loss不得不提Tversky 系数,Tversky系数是Dice系数和 Jaccard 系数的一种广义系数,公式如下:
    T ( A , B ) = ∣ A ⋂ B ∣ ∣ A ⋂ B ∣ + α ∣ A − B ∣ + β ∣ B − A ∣ T(A,B) = \frac{|A \bigcap B|}{|A \bigcap B| + \alpha |A - B| + \beta |B - A|} T(A,B)=AB+αAB+βBAAB
    再抄一遍Dice系数公式:
    D S C ( A , B ) = 2 ∣ A ⋂ B ∣ ∣ A ∣ + ∣ B ∣ DSC(A,B) = 2\frac{|A\bigcap B |}{|A| + |B|} DSC(A,B)=2A+BAB,此时A为预测,而B为真实标签。
    观察可得当设置 α = β = 0.5 \alpha = \beta = 0.5 α=β=0.5,此时Tversky系数就是Dice系数。而当设置 α = β = 1 \alpha = \beta = 1 α=β=1时,此时Tversky系数就是Jaccard系数。
    对于Tversky loss也是相似的形式就不重新编写了,但是在 T ( A , B ) T(A,B) T(A,B)中, ∣ A − B ∣ |A - B| AB则意味着是FP(假阳性),而 ∣ B − A ∣ |B - A| BA则意味着是FN(假阴性); α 和 β \alpha和 \beta αβ分别控制假阴性和假阳性。通过调整 α \alpha α β \beta β我们可以控制假阳性和假阴性之间的权衡。
    不同的 α \alpha α β \beta β下各个指标的结果:
    在这里插入图片描述
    在极小的病灶下的分割效果图如下:
    在这里插入图片描述
    在较大病灶下的分割结果:
    在这里插入图片描述
    考虑到处理数据类别极度不均衡情况下的指标FP和FN,在牺牲一定精度的情况下,从而提高像素分类的召回率

    代码参考keras

    def tversky(y_true, y_pred):
        y_true_pos = K.flatten(y_true)
        y_pred_pos = K.flatten(y_pred)
        true_pos = K.sum(y_true_pos * y_pred_pos)
        false_neg = K.sum(y_true_pos * (1-y_pred_pos))
        false_pos = K.sum((1-y_true_pos)*y_pred_pos)
        alpha = 0.7
        return (true_pos + smooth)/(true_pos + alpha*false_neg + (1-alpha)*false_pos + smooth)
    def tversky_loss(y_true, y_pred):
        return 1 - tversky(y_true,y_pred)
    def focal_tversky(y_true,y_pred):
        pt_1 = tversky(y_true, y_pred)
        gamma = 0.75
        return K.pow((1-pt_1), gamma)
    

    七、敏感性–特异性 loss

    首先敏感性就是召回率,检测出确实有病的能力
    S e n s i t i v i t y = T P T P + F N Sensitivity = \frac{TP}{TP+FN} Sensitivity=TP+FNTP
    特异性,检测出确实没病的能力
    S p e c i f i c i t y = T N T N + F P Specificity = \frac{TN}{TN+FP} Specificity=TN+FPTN
    Sensitivity - Specificity (SS)[8]提出是在:
    S S = λ ∑ n = 1 N ( r n − p n ) 2 r n ∑ n = 1 N r n + ϵ   + ( 1 − λ ) ∑ n = 1 N ( r n − p n ) 2 ( 1 − r n ) ∑ n = 1 N ( 1 − r n ) + ϵ SS = \lambda\frac{\sum_{n=1}^{N}(r_n - p_n)^2r_n}{\sum_{n=1}^{N}r_n + \epsilon} + (1 - \lambda)\frac{\sum_{n=1}^{N}(r_n - p_n)^2(1 - r_n)}{\sum_{n=1}^{N}(1 - r_n) + \epsilon} SS=λn=1Nrn+ϵn=1N(rnpn)2rn +(1λ)n=1N(1rn)+ϵn=1N(rnpn)2(1rn)

    其中左边为病灶像素的错误率即, 1 − S e n s i t i v i t y 1- Sensitivity 1Sensitivity,而不是正确率,所以设置λ 为0.05。其中 ( r n − p n ) 2 (r_n - p_n)^2 (rnpn)2是为了得到平滑的梯度。

    八、Generalized Dice loss

    区域大小和Dice分数之间的相关性:
    在使用DICE loss时,对小目标是十分不利的,因为在只有前景和背景的情况下,小目标一旦有部分像素预测错误,那么就会导致Dice大幅度的变动,从而导致梯度变化剧烈,训练不稳定。
    首先Generalized Dice loss的提出是源于Generalized Dice index[12]。当病灶分割有多个区域时,一般针对每一类都会有一个DICE,而Generalized Dice index将多个类别的dice进行整合,使用一个指标对分割结果进行量化。

    GDL(the generalized Dice loss)公式如下(标签数量为2):
    G D L = 1 − 2 ∑ l = 1 2 w l ∑ n r l n p l n ∑ l = 1 2 w l ∑ n r l n + p l n GDL = 1 - 2\frac{\sum_{l=1}^{2}w_l\sum_nr_{ln}p_{ln}}{\sum_{l=1}^{2}w_l\sum_nr_{ln} + p_{ln}} GDL=12l=12wlnrln+plnl=12wlnrlnpln
    其中 r l n r_{ln} rln为类别l在第n个像素的标准值(GT),而 p l n p_{ln} pln为相应的预测概率值。此处最关键的是 w l w_l wl,为每个类别的权重。其中 w l = 1 ( ∑ n = 1 N r l n ) 2 w_l = \frac{1}{(\sum_{n=1}^{N}r_{ln})^2} wl=(n=1Nrln)21,这样,GDL就能平衡病灶区域和Dice系数之间的平衡。
    论文中的一个效果:
    在这里插入图片描述
    但是在AnatomyNet中提到GDL面对极度不均衡的情况下,训练的稳定性仍然不能保证。
    参考代码

    def generalized_dice_coeff(y_true, y_pred):
        Ncl = y_pred.shape[-1]
        w = K.zeros(shape=(Ncl,))
        w = K.sum(y_true, axis=(0,1,2))
        w = 1/(w**2+0.000001)
        # Compute gen dice coef:
        numerator = y_true*y_pred
        numerator = w*K.sum(numerator,(0,1,2,3))
        numerator = K.sum(numerator)
        denominator = y_true+y_pred
        denominator = w*K.sum(denominator,(0,1,2,3))
        denominator = K.sum(denominator)
        gen_dice_coef = 2*numerator/denominator
        return gen_dice_coef
    def generalized_dice_loss(y_true, y_pred):
        return 1 - generalized_dice_coeff(y_true, y_pred)
    

    以上本质上都是根据评测标准设计的loss function,有时候普遍会受到目标太小的影响,导致训练的不稳定;对比可知,直接使用log loss等的loss曲线一般都是相比较光滑的。

    九、BCE + Dice loss

    BCE : Binary Cross Entropy
    说白了,添加二分类交叉熵损失函数。在数据较为平衡的情况下有改善作用,但是在数据极度不均衡的情况下,交叉熵损失会在几个训练之后远小于Dice 损失,效果会损失。
    代码:

    import keras.backend as K
    from keras.losses import binary_crossentropy
    def dice_coef(y_true, y_pred, smooth=1):
        intersection = K.sum(y_true * y_pred, axis=[1,2,3]) ##y_true与y_pred都是矩阵!(Unet)
        union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3])
        return K.mean( (2. * intersection + smooth) / (union + smooth), axis=0)
    def dice_p_bce(in_gt, in_pred):
        return 1e-3*binary_crossentropy(in_gt, in_pred) - dice_coef(in_gt, in_pred)
    

    -------更新2018-11-8

    keras.losses.binary_crossentropy
    

    只沿最后一个轴进行计算[3]。因此,binary_crossentropy(y_true,y_pred)+ dice_loss(y_true,y_pred)仍将是(batch_size,height,width)张量。
    改进:

    K.mean(binary_crossentropy(y_true,y_pred))+ dice_loss(y_true,y_pred)
    

    正确性有待验证。

    思考:Dice + Focal loss ???
    ------------------更新2018-11-18

    十、Dice + Focal loss

    最近腾讯医疗AI新突破:提出器官神经网络,全自动辅助头颈放疗规划 | 论文[2] 中提出了Dice + Focal loss来处理小器官的分割问题。在前面的讨论也提到过,直接使用Dice会使训练的稳定性降低[1],而此处再添加上Focal loss这个神器。
    首先根据论文的公式:
    T P p ( c ) = ∑ n = 1 N p n ( c ) g n ( c ) TP_p(c) = \sum_{n=1}^{N}p_n(c)g_n(c) TPp(c)=n=1Npn(c)gn(c)
    F N p ( c ) = ∑ n = 1 N ( 1 − p n ( c ) ) g n ( c ) FN_p(c) = \sum_{n=1}^{N}(1-p_n(c))g_n(c) FNp(c)=n=1N(1pn(c))gn(c)
    F P n ( c ) = ∑ n = 1 N p n ( c ) ( 1 − g n ( c ) ) FP_n(c) = \sum_{n=1}^{N}p_n(c)(1-g_n(c)) FPn(c)=n=1Npn(c)(1gn(c))
    L D i c e = ∑ c = 0 C T P n ( c ) T P p ( c ) + α F N p ( c ) + β F P p ( c ) − L_{Dice} = \sum_{c=0}^{C} \frac{TP_n(c)}{TP_p(c) + \alpha FN_p(c) + \beta FP_p(c)} - LDice=c=0CTPp(c)+αFNp(c)+βFPp(c)TPn(c)
    其中 T P p ( c ) , F N p ( c ) , F P p ( c ) TP_p(c) ,FN_p(c) ,FP_p(c) TPp(c)FNp(c)FPp(c),分别对于类别c的真阳性,假阴性,假阳性。此处的 α = β = 0.5 \alpha = \beta = 0.5 α=β=0.5,此时Tversky系数就是Dice系数,为Dice loss。
    最终的loss为:
    L = L D i c e + λ L F o c a l = C − ∑ c = 0 C T P n ( c ) T P p ( c ) + α F N p ( c ) + β F P p ( c ) − λ 1 N ∑ c = 0 C ∑ n = 1 N g n ( c ) ( 1 − p n ( c ) ) 2 l o g ( p n ( c ) ) L = L_{Dice} + \lambda L_{Focal} = C - \sum_{c=0}^{C} \frac{TP_n(c)}{TP_p(c) + \alpha FN_p(c) + \beta FP_p(c)} - \lambda \frac{1}{N} \sum_{c=0}^{C} \sum_{n=1}^{N}g_n(c)(1-p_n(c))^2log(p_n(c)) L=LDice+λLFocal=Cc=0CTPp(c)+αFNp(c)+βFPp(c)TPn(c)λN1c=0Cn=1Ngn(c)(1pn(c))2log(pn(c))
    论文中头颈部癌症放疗靶区自动勾画效果展示:
    在这里插入图片描述
    项目地址

    Focal loss理论上应该还是会得到很大的值?

    十一、Exponential Logarithmic loss

    加权的DICE LOSS进行对比,此方法觉得而且这种情况跟不同标签之间的相对尺寸无关,但是可以通过标签频率来进行平衡[9]。
    结合了focal loss以及Dice loss。此loss的公式如下:
    L E X P = w d i c e ∗ L D i c e + w C r o s s ∗ L C r o s s L_{EXP} = w_{dice}*L_{Dice} + w_{Cross}*L_{Cross} LEXP=wdiceLDice+wCrossLCross L D i c e L_{Dice} LDice为 指数log Dice损失, L C r o s s L_{Cross} LCross为指数交叉熵损失。
    L D i c e = E [ ( − l n ( D i c e i ) ) γ D i c e ] L_{Dice} = E[(-ln({Dice}_i))^{\gamma_{Dice}}] LDice=E[(ln(Dicei))γDice]
    i i i为label。
    复习一下交叉熵损失:
    L C E = − l o g ( p l ( x ) ) L_{CE} = -log(p_l(x)) LCE=log(pl(x))
    新的指数交叉熵损失:
    L C r o s s = w l ( − l n ( p l ( x ) ) ) γ C r o s s L_{Cross} = w_l(-ln(p_l(x)))^{\gamma_{Cross}} LCross=wl(ln(pl(x)))γCross
    其中, w l = ( ∑ k f k f l ) 0.5 w_l = (\frac{\sum_kf_k}{f_l})^{0.5} wl=(flkfk)0.5 f k f_k fk为标签k的出现频率, w l w_l wl这个参数可以减小出现频率较高的类别权重。由公式可知, w l w_l wl f l f_l fl的增大而变小,即减小权重,反之如果 f l f_l fl太大,那么权重会变小
    γ D i c e \gamma_{Dice} γDice γ C r o s s \gamma_{Cross} γCross,提升非线性的作用。
    如下图显示的是不同的指数log非线性表现:
    在这里插入图片描述
    新增添了4个参数权重分别是 w D i c e w_{Dice} wDice w C r o s s w_{Cross} wCross γ D i c e \gamma_{Dice} γDice γ C r o s s \gamma_{Cross} γCross,给调参带来不小的麻烦。

    以上都是针对多种loss的简单结合或者是加权结合,可能也有些小的改进,但如何平衡两个或者多个loss也是偏经验的调参问题。


    如果有好的方式方法可以在此讨论:小目标的图像语义分割,有什么解决类别不平衡的方法吗?[5]
    所有代码将整理到GitHub。


    参考

    [1] C. H. Sudre, W. Li, T. Vercauteren, S. Ourselin, and M. J. Cardoso, “Generalised dice overlap as a deep learning loss function for highly unbalanced segmentations,” in Deep Learning in Medical Image Analysis and Multimodal Learning for Clinical Decision Support, 2017.
    [2] AnatomyNet: Deep Learning for Fast and Fully Automated Whole-volume Segmentation of Head and Neck Anatomy: https://arxiv.org/pdf/1808.05238.pdf
    [3] https://www.kaggle.com/c/airbus-ship-detection/discussion/70549
    [4] https://www.kaggle.com/kmader/baseline-u-net-model-part-1
    [5] 小目标的图像语义分割,有什么解决类别不平衡的方法吗?:https://www.zhihu.com/question/297255242/answer/505965855
    [6] Generalised Dice overlap as a deep learning loss function for highly unbalanced segmentations-2017
    [7] Ronneberger, O., Fischer, P., Brox, T.: U-net: Convolutional networks for biomedical image segmentation. In: MICCAI. pp. 234–241. Springer (2015)
    [8] Brosch, T., Yoo, Y., Tang, L.Y., Li, D.K., Traboulsee, A., Tam, R.: Deep convolutional encoder networks for multiple sclerosis lesion segmentation. In: MICCAI 2015. pp. 3–11. Springer (2015)
    [9]3D Segmentation with Exponential LogarithmicLoss for Highly Unbalanced Object Sizes-MICCAI2018【论文理解】
    [10]Dice-coefficient loss function vs cross-entropy
    [11]Md Atiqur Rahman and Yang Wang, Optimizing Intersection-Over-Union in Deep Neural Networks for Image Segmentation
    [12]Crum, W., Camara, O., Hill, D.: Generalized Overlap Measures for Evaluation and Validation in Medical Image Analysis. IEEE TMI 25(11), 1451–1461 (nov 2006)

    展开全文
  • 一:表名定义规范: (1)数据库表的命名以是名词的复数形式且都为小写,如cities, categories, friends等等  这一条不是硬规定,可以看个人习惯,统一就好。 (2)如果表名由几个单词组成,则单词间用...
     一:表名定义规范:
    (1)数据库表的命名以是名词的复数形式且都为小写,如cities, categories, friends等等 

    这一条不是硬性规定,可以看个人习惯,统一就好。


    (2)如果表名由几个单词组成,则单词间用下划线("_")分割,如subscribed_pois,poi_categories等 


    (3)表名尽量用全名 


    (4)表名限制在30个字符内。当表的全名超过30字符时,可用缩写来减少表名的长度,如description --> desc;information --> info;address --> addr等 
     
    (5)同类数据库对象要有统一的前缀名
      一个比较复杂的系统,数据库表往往很多,要快速定位自己需要的表,不太容易。因此,可以在同一个模块     中的表,加上一个统一的前缀。
      比如权限管理相关的表可以统一加一个前缀p_。用户表p_user;角色表p_role;组织表p_orgnization;
      权限表p_power;
      中间表加前缀rel_
     
     
     
     
     二:字段名定义规范

    (1)数据库字段全部采用小写英文单词


    (2)字段长度不宜过长,尽量简洁明了
     字段名限制在30个字符内。当字段名超过30字符时,可用缩写来减少字段名的长度,

     如description --> desc;information --> info;address --> addr等 


    (3)如果表或者是字段的名称仅有一个单词,那么建议不使用缩写,而是用完整的单词。


    (4)如果表或者字段由多个单词构成,单词之间用”_”隔开。

        实体属性的首字母小写,如果有多个单词,其他单词的首字母大写。
        比如:
             /**
    * 创建时间
    */
    @Column(name = "creation_time")
    private long creationTime;

    (5)常用的字段例如name,不宜直接用name,最好定义为xx_name.

      防止关联查询的时候,两个表的字段名称一样,不方便处理。可能还需要起别名as


    (6)字段名称尽量避免中文拼音


    (7)字段尽量避免关键字


    (8)表中应该避免可为空的列。
    虽然表中允许空列,但是,空字段是一种比较特殊的数据类型。
    数据库在处理的时候,需要进行特殊的处理。如此的话,就会增加数据库处理记录的复杂性。
    当表中有比较多的空字段时,在同等条件下,数据库处理的性能会降低许多。
    解决方法:一是通过设置默认值的形式,来避免空字段的产生。


    (8)不能为空的字段最好加上默认值
    所有字段在设计时,除以下数据类型timestamp、datetime外,必须有默认值。
    字符型的默认值为一个空字符值串’’;
    数值型的默认值为数值0;
    布尔型的默认值为数值0;系统中所有逻辑型中数值0表示为“假”;数值1表示为“真”。
    datetime、smalldatetime类型的字段没有默认值,必须为NULL。







    展开全文
  • 线性可分 线性不可

    千次阅读 2017-12-05 15:21:11
    转自http://blog.csdn.net/u013300875/article/details/44081067很多机器学习分类算法,比如支持向量机(SVM),的介绍都说了假设数据要是线性分。...理论上一定能在更高的维度把数据线性可分。何为线性

    转自http://blog.csdn.net/u013300875/article/details/44081067

    很多机器学习分类算法,比如支持向量机(SVM),的介绍都说了假设数据要是线性可分。如果数据不是线性可分的,我们就必须要采用一些特殊的方法,比如SVM的核技巧把数据转换到更高的维度上,在那个高维空间数据更可能是线性可分的(Cover定理)。

    理论上一定能在更高的维度把数据线性可分。

    何为线性可分和线性不可分

    线性可分就是说可以用一个线性函数把两类样本分开,比如二维空间中的直线、三维空间中的平面以及高维空间中的线型函数。
    所谓可分指可以没有误差地分开;线性不可分指有部分样本用线性分类面划分时会产生分类误差的情况。
    在这种情况下,SVM就通过一个非线性映射函数把样本映射到一个线性可分高维空间,在此高维空间建立线性分类面,而此高维空间的现行分类面对应的就是输入空间中的非线性分类面。

    判断是否线性可分

    不同样本集用凸包包起来,判断不同凸包的边是否有交叉。

    展开全文
  • 介绍SLIC超像素分割算法,给出其与openCV的接口,代码用VS2012和openCV2.4.9测试运行。

    超像素概念是2003年Xiaofeng Ren[1]提出和发展起来的图像分割技术,是指具有相似纹理、颜色、亮度等特征的相邻像素构成的有一定视觉意义的不规则像素块。它利用像素之间特征的相似性将像素分组,用少量的超像素代替大量的像素来表达图片特征,很大程度上降低了图像后处理的复杂度,所以通常作为分割算法的预处理步骤。已经广泛用于图像分割、姿势估计、目标跟踪、目标识别等计算机视觉应用[2],而目前,OpenCV于超像素生成,没有发现网上有相关代码,但其实在opencv_contrib目录下面的未稳定功能模块SLICSEEDSLSC算法相关实现,如果想要使用这个目录的功能,需要自己重新进行OpenCV的编译[8],有关编译和配置方法可参考[8 ,9]。一些常用的超像素分割算法和性能对比如下表[3]:


    本文介绍SLIC(simple lineariterativeclustering)超像素分割算法,即简单的线性迭代聚类,该算法是目前执行速度最快的超像素分割方法[3],2015年实现并行执行速度达250FPS [4,5]。SLIC算法是2010年Achanta[6]提出的一种思想简单、实现方便的算法,将彩色图像转化为CIELAB颜色空间和XY坐标下的5维特征向量,然后对5维特征向量构造距离度量标准,对图像像素进行局部聚类的过程[2],算法基本思路与Kmeans聚类算法类似。算法具体实现过程如下[6,2]:


    1.  初始化种子点(聚类中心):按照设定的超像素个数,在图像内均匀的分配种子点。假设图片总共有 N 个像素点,预分割为 K 个相同尺寸的超像素,那么每个超像素的大小为N/ K ,则相邻种子点的距离(步长)近似为S=sqrt(N/K)。

    2.  在种子点的n*n邻域内重新选择种子点(一般取n=3)。具体方法为:计算该邻域内所有像素点的梯度值,将种子点移到该邻域内梯度最小的地方。这样做的目的是为了避免种子点落在梯度较大的轮廓边界上,以免影响后续聚类效果。

    3.  在每个种子点周围的邻域内为每个像素点分配类标签(即属于哪个聚类中心)。和标准的k-means在整张图中搜索不同,SLIC的搜索范围限制为2S*2S,可以加速算法收敛,如下图。在此注意一点:期望的超像素尺寸为S*S,但是搜索的范围是2S*2S。

    4.  距离度量。包括颜色距离和空间距离。对于每个搜索到的像素点,分别计算它和该种子点的距离。距离计算方法如下:

    其中,dc代表颜色距离,ds代表空间距离,Ns是类内最大空间距离,定义为Ns=S=sqrt(N/K),适用于每个聚类。最大的颜色距离Nc既随图片不同而不同,也随聚类不同而不同,所以我们取一个固定常数m(取值范围[1,40],一般取10)代替。最终的距离度量D'如下:


    由于每个像素点都会被多个种子点搜索到,所以每个像素点都会有一个与周围种子点的距离,取最小值对应的种子点作为该像素点的聚类中心。

    5.  迭代优化。理论上上述步骤不断迭代直到误差收敛(可以理解为每个像素点聚类中心不再发生变化为止),实践发现10次迭代对绝大部分图片都可以得到较理想效果,所以一般迭代次数取10。

    6.  增强连通性。经过上述迭代优化可能出现以下瑕疵:出现多连通情况、超像素尺寸过小,单个超像素被切割成多个不连续超像素等,这些情况可以通过增强连通性解决。主要思路是:新建一张标记表,表内元素均为-1,按照“Z”型走向(从左到右,从上到下顺序)将不连续的超像素、尺寸过小超像素重新分配给邻近的超像素,遍历过的像素点分配给相应的标签,直到所有点遍历完毕为止。

    SLIC算法的代码(C++和matlab版)可到该算法发明人Achanta的页面[7]下载,我们下载该代码的C++windows版本,并编写一个简单图像格式转换函数,将SLIC超像素算法与openCV一起实现了一个简单的应用实例,因为SLIC算法输入必须是RGB彩色图像,因此我们考虑了灰度图像和彩色图像两种不同情况下的数据转换,当输入为灰度图时,将该灰度图像复制三次到其他色彩通道,主程序如下(代码运行还需要从Achanta网站[7]下载的SLIC.cpp和SLIC.h文件,有关我们测试程序的所有代码(包括了SLIC.cpp和SLIC.h文件)下载网站:http://download.csdn.net/detail/zhouxianen1987/9778247):

    #if 1
    #include <iostream>  
    #include <time.h>
    #include "opencv2/opencv.hpp" 
    #include "SLIC.h"
    using namespace std;
    using namespace cv;
    int imgOpenCV2SLIC(Mat img, int &height, int &width, int &dim, unsigned int * &image);
    int imgSLIC2openCV(unsigned int *image, int height, int width, int dim, Mat &imgSLIC);
    int main()
    {
    
    	Mat imgRGB;
    	time_t tStart,tEnd,exeT;
    
    	imgRGB= imread("0_0_77rgb.jpg");
    	if (imgRGB.empty() == true){
    		cout<<"can not open rgb image!"<<endl;
    	}
    
    	unsigned int *image; 
    
    	int height; 
    	int width; 
    	int dim;
    	long imgSize;
    	
    	int numlabels(0);
    	SLIC slic;
    	int m_spcount= 100 ;
    	int m_compactness=10;
    	imgOpenCV2SLIC(imgRGB,  height,  width,  dim, image);//OpenCV 图像数据转换成SLIC图像数据
    	imgSize = height* width;
    	int* labels = new int[imgSize];
    
    	tStart=clock();
    	//SLIC超像素分割,代码下载网站:http://ivrl.epfl.ch/research/superpixels#SLICO
    	slic.DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels(image, width, height, labels, numlabels, m_spcount, m_compactness);
    	slic.DrawContoursAroundSegments(image, labels, width, height, 0);
    
    	tEnd=clock();
    	exeT=tEnd-tStart;
    
    	Mat imgSLIC;
    
    	imgSLIC2openCV(image, height,width,dim,imgSLIC);//SLIC结果:SLIC图像数据转换成OpenCV 图像数据
    
    
    	//结果显示
    	cout<<"SLIC执行时间exeT:"<<exeT<<"毫秒"<<endl;
    	imshow("imgRGB",imgRGB);
    	imshow("imgSLIC1",imgSLIC);
    	waitKey();
    	return 0;
    
    }
    
    
    //OpenCV Mat图像数据转换为SLIC图像数据
    //输入:Mat img, int &height, int &width, int &dim,
    //输出:unsigned int * &image,同时返回转换是否成功的标志:成功为0,识别为1
    int imgOpenCV2SLIC(Mat img, int &height, int &width, int &dim, unsigned int * &image)
    {
    	int error=0;
    	if( img.empty() ) //请一定检查是否成功读图 
    	{ 
    		error =1;
    	} 
    
    	dim=img.channels();//图像通道数目
    	height=img.rows;
    	width=img.cols;
    
    	int imgSize=width*height;
    
    	unsigned char *pImage  = new unsigned char [imgSize*4];
    	if(dim==1){
    		for(int j = 0; j < height; j++){
    			uchar * ptr = img.ptr<uchar>(j);
    			for(int i = 0; i < width; i++) {
    				pImage[j * width*4 + 4*i+3] = 0;
    				pImage[j * width*4 + 4*i+2] = ptr[0];
    				pImage[j * width*4 + 4*i+1] = ptr[0];
    				pImage[j * width*4 + 4*i] = ptr[0];		
    				ptr ++;
    			}
    		}
    	}
    	else{
    		if(dim==3){
    			for(int j = 0; j < height; j++){
    				Vec3b * ptr = img.ptr<Vec3b>(j);
    				for(int i = 0; i < width; i++) {
    					pImage[j * width*4 + 4*i+3] = 0;
    					pImage[j * width*4 + 4*i+2] = ptr[0][2];//R
    					pImage[j * width*4 + 4*i+1] = ptr[0][1];//G
    					pImage[j * width*4 + 4*i]   = ptr[0][0];//B		
    					ptr ++;
    				}
    			}
    		}
    		else  error=1;
    
    	}
    
    	image = new unsigned int[imgSize];
    	memcpy( image, (unsigned int*)pImage, imgSize*sizeof(unsigned int) );
    	delete pImage;
    
    	return error;
    
    }
    
    
    //SLIC图像数据转换为OpenCV Mat图像数据
    //输入:unsigned int *image, int height, int width, int dim
    //输出:Mat &imgSLIC ,同时返回转换是否成功的标志:成功为0,识别为1
    int imgSLIC2openCV(unsigned int *image, int height, int width, int dim, Mat &imgSLIC)
    {
    	int error=0;//转换是否成功的标志:成功为0,识别为1
    
    	if(dim==1){
    		imgSLIC.create(height, width, CV_8UC1);
    		//遍历所有像素,并设置像素值 
    		for( int j = 0; j< height; ++j) 
    		{ 
    			//获取第 i行首像素指针 
    			uchar * p = imgSLIC.ptr<uchar>(j); 
    			//对第 i行的每个像素(byte)操作 
    			for( int i = 0; i < width; ++i ) 
    				p[i] =(unsigned char)(image[j*width+i]& 0xFF)  ; 
    		} 
    	}
    	else{
    		if(dim==3){
    			imgSLIC.create(height, width, CV_8UC3);
    			//遍历所有像素,并设置像素值 
    			for( int j = 0; j < height; ++j) 
    			{ 
    				//获取第 i行首像素指针 
    				Vec3b * p = imgSLIC.ptr<Vec3b>(j); 
    				for( int i = 0; i < width; ++i ) 
    				{ 
    					p[i][0] = (unsigned char)(image[j*width+i]          & 0xFF ); //Blue 
    					p[i][1] = (unsigned char)((image[j*width+i] >>  8 ) & 0xFF ); //Green 
    					p[i][2] = (unsigned char)((image[j*width+i] >>  16) & 0xFF ) ; //Red 
    				} 
    			}
    		}
    		else  error= 1 ;
    
    	}
    
    	return error;
    }
    
    #endif

    执行效果如下:




    参考资料:

    [1]Ren X,Malik J.  Learning a classification model forsegmentation[C]/ /Proceedings of the IEEE International Conference on Computer  Vision.   Washington  DC, USA:   IEEE,2003:   10-17.[DOI:  10. 1109 /ICCV. 2003. 1238308]

    [2] http://blog.csdn.net/electech6/article/details/45509779

    [3]Achanta,Radhakrishna, et al. "SLICsuperpixels compared to state-of-the-artsuperpixel methods." PatternAnalysis and Machine Intelligence, IEEETransactions on 34.11 (2012): 2274-2282.

    [4] http://www.robots.ox.ac.uk/~victor/gslicr/

    [5] gSLICr: SLIC superpixels at over 250Hz

    [6] Achanta,Radhakrishna, et al. Slicsuperpixels. No. EPFL REPORT 149300. 2010.

    [7] http://ivrl.epfl.ch/research/superpixels#SLICO

    [8] http://blog.csdn.net/zhangyonggang886/article/details/52854219?locationNum=5&fps=1

    [9] http://blog.csdn.net/jarvischu/article/details/8468894


    展开全文
  • 阈值分割

    千次阅读 2015-09-01 12:05:05
    通过迭代法来求出分割的最佳阈值,具有一定的自适应,这种方法适用于物体的和背景有较大的区分,即其直方图有相当清楚的波谷;具体算法步骤如下: 1.为全局阈值选择一个初始估计值T。 2.用T分割图像。产生两组...
  • 图像分割综述

    万次阅读 多人点赞 2019-07-09 22:03:48
    所谓图像分割是指根据灰度、彩色、空间纹理、几何形状等特征把图像划分成若干个互不相交的区域,使得这些特征在同一区域内表现出一致或相似,而在不同区域间表现出明显的不同。简单的说就是在一副图像中,把目标...
  • 显著物体检测与分割

    千次阅读 2016-09-25 16:11:23
    显著物体检测与分割 活动时间:2014年9月4日星期4,北京时间20:00开始。 主持人:山世光 主讲人:卢湖川,李寅,程明明,等 专题题目:显著物体检测与分割 1. 相关文献阅读 Salient Object ...
  • 点云分割 博文末尾支持二维码赞赏哦_ 点云分割是根据空间,几何和纹理等特征对点云进行划分, 使得同一划分内的点云拥有相似的特征,点云的有效分割往往是许多应用的前提, 例如逆向工作,CAD领域对零件的不同...
  • 图像分割—灰度阈值分割

    万次阅读 多人点赞 2019-08-14 11:39:55
    阈值分割概念图像阈值分割具有直观和易于实现的特点,在图像分割应用中占有重要地位。许多情况下,图像$f(x,y)$由暗对象和亮对象这两类具有不同灰度级的区域组成,如报纸和书本。这种图像的亮暗部分可以在直方图中...
  • 图像分割

    千次阅读 2018-07-03 22:04:58
    一、背景知识图像分割的主要算法:1.基于阈值的分割方法2.基于边缘的分割方法3.基于区域的分割方法4.基于聚类分析的图像分割方法5.基于小波变换的分割方法6.基于数学形态学的分割方法7.基于人工神经网络的分割方法二...
  • OpenCV阈值分割

    千次阅读 2018-11-16 11:26:56
    什么是阈值? 最简单的图像分割的方法。 应用举例:从一副图像中利用阈值分割出我们需要的物体部分(当然这里的物体可以是一部分或者整体)。这样的图像分割方法是基于图像中物体与...即:物体在不同的图像中有...
  • 机器学习(概述一)——定义

    千次阅读 2019-05-28 16:18:17
    聚类算法,是最大似然估计上的一个提升,功能是将n个对象根据属性特征分为k个分割(k),属于无监督学习 PageRank Google搜索重要算法之一,其实和机器学习关系不是很大 AdaBoost 迭代算法;利用多个...
  • 图像预处理——图像分割

    万次阅读 2017-06-01 17:03:03
    §1 数字图像分割 处理根据不同特征, 分为两类:基于边界分割和基于区域分割,主要方法有: 灰度阀值分割 边界分割法 基于纹理的分割 区域生长法 §2 基于边界分割 §2.1 边缘检测 基于边界...
  • java中,在使用sonarqube的时候,string类型的代码允许直接使用未经定义的常量,什么是未经定义的产量呢?下面举个例子: //这个会报未经定义的常量 String value = "常量"; 一开始想到的解决方案...
  • 语义分割分割常用网络

    千次阅读 2020-04-26 16:25:30
    语义分割 图像的语义分割是将输入图像中的每个像素分配一个语义类别,以...解码器的任务是将编码器学习到的判别特征(较低分辨率)从语义上投影到像素空间(较高分辨率),以获得密集分类。 不同于分类任务中网络...
  • 图像分割—基于区域的图像分割

    万次阅读 多人点赞 2019-08-17 10:40:40
    基于区域的分割是以直接寻找区域为基础的分割技术,实际上类似基于边界的图像分割技术一样利用了对象与背景灰度分布的相似。大体上基于区域的图像分割方法可以分为两大类:区域生长法区域分裂与合并1 区域生长法...
  • 常见图像和视频分割方法概述 图像与视频分割是指按照一定的原则将图像或视频序列分为若干个特定的、具有独特性质的部分或子集,并提取出感兴趣的目标,便于更高层次的分析和理解,因此图像与视频分割是目标特征...
  • 阈值分割与区域分割

    万次阅读 2017-01-02 13:22:51
    阈值分割我们曾在3.5节学习过灰度阈值变换的相关知识, 利用灰度阈值变换分割图像就称为阈值分割, 它是一种基本的图像分割方法。 阙值分割的基本思想是确定一个阈值, 然后把每个像素点的灰度值和阈值相比较,根据...
  • 在训练数据线性不可分时,如何定义此情形下支持向量机的最优化问题。如何设置 CvSVMParams 中的参数来解决此类问题。 动机 为什么需要将支持向量机优化问题扩展到线性不可分的情形? 在多数计算机视觉...
  • 图像分割技术介绍

    万次阅读 2018-11-13 10:39:48
    其它机器学习、深度学习算法的全面系统讲解可以阅读《机器学习-原理、算法与应用》,清华大学出版社,...图像分割是指将图像分成若干具有相似性质的区域的过程,从数学角度来看,图像分割是将图像划分成互不相交的区...
  • 英伟达近日发布了 NVIDIA DIGIT 5。DIGIT 5 有许多新功能,本文将...2.DIGITS 模型库(model store),一个公开的在线知识库,下载网络描述和预先训练的模型。这篇文章将探索图像分割的对象。将使用 DIGIT 5 来教一个
  • 数据库并发访问、事务与锁的关系 一、事务 I : 事务的定义: ...1 )原子 (Atomic) :指整个数据库事务是不可分割的工作单位。 2 )一致 (Consistency) :指数据库事务不能破坏关系数据
  • 语义分割综述

    万次阅读 多人点赞 2018-09-11 14:55:15
    太优秀了,收藏用!... 综述论文翻译:A Review on Deep Learning Techniques Applied to Semantic Segmentation ...近期主要在学习语义分割相关方法,计划将arXiv上的这篇综述好好翻译下,目前已完成了...
  • 图像分割与视频分割方法

    千次阅读 2019-05-12 12:15:54
    图像分割传统的图像分割方法1、基于阈值的图像分割单阈值分割局部阈值分割阈值的选取2、基于区域的图像分割区域生长区域分裂合并四叉树分解法3、基于边缘检测的图像分割结合特定工具的图像分割算法1、基于小波分析和...
  • 血管分割算法总结

    万次阅读 多人点赞 2018-03-03 16:43:29
    之前有5篇涉及眼底血管分割的博文,包括基于Hessian矩阵的Frangi算法,基于PCA的算法,匹配滤波算法,自适应对比度增强算法,当然还有其他的方法,目前来看,并没有一种完美的算法,即适应于所有不同成像方式,不同...
  • 原子:指处于同一个事务中的多条语句是不可分割的。 一致:事务必须使数据库从一个一致状态变换到另外一个一致状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。 隔离:指多线程环境下,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 240,420
精华内容 96,168
关键字:

不可分割性的定义