Henryjiepanli / Uncertainty-aware-Network

UANet: an Uncertainty-Aware Network for Building Extraction from Remote Sensing Images
53 stars 3 forks source link

Cannot reproduce the performance described in the paper! #2

Open epoch8260 opened 1 year ago

epoch8260 commented 1 year ago

Please release the core demo for a fair comparison.

Henryjiepanli commented 1 year ago

Sorry, the release of the code will wait until the paper is accepted, but we have released the results on the test dataset. You can describe the specific guestions that arose duringvour reproduction process, and I will answer and solve them for you. Here is my email address "Jiepanli@whu.edu.cn". Thank you for your interest in our work!

epoch8260 commented 1 year ago

1)一直不能复现,完全按照文章中的描述进行复现训练;2)文中的描述有错误,Q5i的shape是NC,K5i的shape是NC,点乘怎么就变成N*N了,还要加个transpose吧;3)文章似乎没有说PIGM和ACFNet中的区别,也没有引用,这俩不是一回事?

Henryjiepanli commented 1 year ago

谢谢您对我们工作的关注,以下是对您问题的答复:1)因为论文目前还是一审状态,所以等论文接收后我们会把所有代码上传到这里,这个训练是很简单的一个过程,按理来说没有什么不可复现的,这种简单的不确定性分级方法在实验中证明了也确实很有效果,到时候代码公开以后我会第一时间通知您;2)谢谢您的提醒,这个确实,因为我默认k是会转置的,您说的确实是,后面的版本上我会修改过来;3)《ACFNet: Attentional Class Feature Network for Semantic Segmentation》这个工作和我们的PIGM差异还是蛮大的吧,他是利用coarse segmentation来计算属于类别i的全局特征,然后再利用这个全局特征来和coarse segmentation做注意力;而我们的思路是想利用coarse segmentation来依次对highest-level feature的每层特征做空间的注意力,实现一个空间层面的引导增强;然后将增强后的特征再与coarse segmentation来做interaction,在以类似于SENet这种通道来学通道层面的自相关性。我们的PIGM和ACFNet关系不大,因为相关工作的review主要是围绕建筑物提取来开展,注意力机制有很多,所以一些我们认为相关性不太明显的工作就只引用了一些比较有代表性的。最后,谢谢您对我们工作的关注,希望这些回复能帮到您!

epoch8260 commented 1 year ago

import torch import torch.nn as nn

from jyw.src import Classifier, Conv1x1_BN_ReLU, Conv3x3_BN_ReLU, upsample_like, LateralConvLayer, BaseSegModel, DeepSupLoss

class UAFM(nn.Module): """Uncertainty-Aware Fusion Module"""

def __init__(self, in_chs):
    super().__init__()
    self.cls = Classifier(in_chs, num_class=1)

    self.sigmoid = nn.Sigmoid()

    self.conv_l = Conv1x1_BN_ReLU(2 * in_chs, in_chs)
    self.conv_h = Conv1x1_BN_ReLU(2 * in_chs, in_chs)

    self.concat_conv = Conv3x3_BN_ReLU(2 * in_chs, in_chs)

@staticmethod
def ura(u):
    w0 = torch.zeros_like(u)
    # u = torch.floor(u / 0.1)
    # rank
    w1 = torch.where(torch.logical_and(0.0 <= u, u < 0.1),5.0, 0)
    w2 = torch.where(torch.logical_and(0.1 <= u, u < 0.2), 4.0, 0)
    w3 = torch.where(torch.logical_and(0.2 <= u, u < 0.3), 3.0, 0)
    w4 = torch.where(torch.logical_and(0.3 <= u, u < 0.4), 2.0, 0)
    w5 = torch.where(torch.logical_and(0.4 <= u, u <= 0.5), 1.0, 0)

    w = w1 + w2+ w3+ w4+ w5 + w0
    #
    # return w1 + w2+ w3+ w4+ w5
    return w

def forward(self, low_f, high_f):
    p = self.cls(high_f)
    score = self.sigmoid(p)

    # foreground
    uf = score - 0.5
    uf = self.ura(uf)
    ub = 0.5 - score
    ub = self.ura(ub)

    # from jyw.utils import subplot
    # subplot((p, att, uf, ub), 2, 2)

    high_f = self.conv_h(torch.cat([uf * high_f, ub * high_f], dim=1))
    high_f = upsample_like(high_f, low_f)

    uf = upsample_like(uf, low_f, mode='nearest')
    ub = upsample_like(ub, low_f, mode='nearest')
    low_f = self.conv_l(torch.cat([uf * low_f, ub * low_f], dim=1))

    x = torch.cat([low_f, high_f], dim=1)
    y = self.concat_conv(x)
    return y, p

class Decoder(nn.Module): def init(self, enc_chs, r=64, num_class=1): super().init()

    self.squeeze = LateralConvLayer(enc_chs, r)

    self.dec4 = UAFM(r)
    self.dec3 = UAFM(r)
    self.dec2 = UAFM(r)
    self.dec1 = UAFM(r)

    self.cls = Classifier(in_chs=r, num_class=num_class)

def forward(self, feats):
    x1, x2, x3, x4, x5 = self.squeeze(feats)
    y4, p4 = self.dec4(x4, x5)
    y3, p3 = self.dec3(x3, y4)
    y2, p2 = self.dec2(x2, y3)
    y1, p1 = self.dec4(x1, y2)

    p0 = self.cls(y1)
    # from jyw.utils import subplot
    # subplot((p0, p1, p2, p3, p4), 2, 3)
    return p0, p1, p2, p3, p4

class UANet(BaseSegModel): def init(self, in_chs=3, num_class=1, backbone='vgg16', loss_cfg=None, kwargs): if backbone == 'vgg16': kwargs['out_indices'] = (0, 1, 2, 3, 4) super().init(in_chs, num_class, backbone, loss_cfg, kwargs) self.decoder = Decoder(self.enc_chs, num_class) self.loss_fn = DeepSupLoss( criterion=nn.BCEWithLogitsLoss(), loss_weight=(1., 1., 1., 1., 1.), downsample_label=False )

def default_train_cfg(self) -> dict:
    return dict(
        whu=dict(
            optim=dict(
                type='AdamW',
                lr=1e-3,
                param_cfg=dict(
                    backbone=dict(lr_mult=0.1)
                )
            ),
            train=dict(
                batch_size=12
            )
        )
    )