新闻中心

【论文复现赛第六期-语义分割】CCNet

2025-07-31
浏览次数:
返回列表
本文复现了CCNet语义分割模型,其核心为Criss-Cross Attention模块,通过循环操作让像素建立联系以获取丰富语义。使用PaddleSeg复现,采用ResNet101骨干网,在Cityscapes验证集上mIoU达80.95%,已合入PaddleSeg,还提供了训练、验证等流程及复现经验。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【论文复现赛第六期-语义分割】ccnet -

【论文复现赛第六期-语义分割】CCNet: Criss-Cross Attention for Semantic Segmentation

paper:CCNet: Criss-Cross Attention for Semantic Segmentation
github:https://github.com/speedinghzl/CCNet/tree/pure-python
复现地址: https://github.com/justld/CCNet_paddle

上下文信息在语义分割任务中非常重要,CCNet提出了criss-cross attention模块,同时引入循环操作,使得图片中每个像素都可以和其他像素建立联系,从而使得每个像素都可以获得丰富的语义信息。本项目使用PaddleSeg复现CCNet,在Cityscapes验证集上miou为80.95%,该算法已被PaddleSeg合入。

模型预测结果如下(图片来自cityscapes val):【论文复现赛第六期-语义分割】CCNet -        

一、Criss-Cross Attention Module

Criss-Cross Attention Module是本文的核心,该模块使得不同位置的像素建立联系,从而丰富语义信息。特征图经过该模块每个像素即可得到其横向和纵向所有像素的语义信息,故只需要2个Criss-Cross Attention Module,每个像素即可与其他所有像素建立联系,从而其丰富语义特征。 【论文复现赛第六期-语义分割】CCNet -  假设输入为X:[N, C, H, W],以纵向为例说明计算过程:

①通过1x1卷积,得到 Q_h:[N, Cr, H, W],K_h:[N, Cr, H, W], V_h:[N, C, H, W] (Q_w\K_w\V_w同理);

②维度变换,reshape得到 Q_h:[N * W,H,Cr],K_h:[N * W,Cr,H], V_h: [N * W,C,H] ;

③Q_h和K_h矩阵乘法,得到energy_h:[N * W, H, H];(源码中Enegy_H计算时加上了个维度为[N*W, H, H]的对角-inf矩阵,但是energy_w计算时没加,有点没搞懂。。)

④类似上面的流程,得到energy_h:[N * W, H, H]和energy_w:[N * H, W, W],reshape后维度变换得到energy_h:[N, H, W, H]和energy_w:[N, H, W, W],拼接得到energy:[N, H, W, H + W];

⑤在energy最后一个维度使用softmax,得到attention系数;

⑥将attention系数拆分为attn_h:[N, H, W, H]和attn_w:[N, H, W, W],维度变换后与V_h和V_w分别相乘得到输出out_h和out_w;

Motiff妙多 Motiff妙多

Motiff妙多是一款AI驱动的界面设计工具,定位为“AI时代设计工具”

Motiff妙多 334 查看详情 Motiff妙多

⑦将out_h+out_w,并乘上一个系数γ(可学习参数),再加上residual connection,得到最终输出。

其pytorch源码如下:

def INF(B,H,W):
     return -torch.diag(torch.tensor(float("inf")).cuda().repeat(H),0).unsqueeze(0).repeat(B*W,1,1) 
 
class CrissCrossAttention(nn.Module):
    """ Criss-Cross Attention Module"""
    def __init__(self, in_dim):
        super(CrissCrossAttention,self).__init__()
        self.query_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim//8, kernel_size=1)
        self.key_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim//8, kernel_size=1)
        self.value_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim, kernel_size=1)
        self.softmax = Softmax(dim=3)
        self.INF = INF
        self.gamma = nn.Parameter(torch.zeros(1)) 
 
    def forward(self, x):
        m_batchsize, _, height, width = x.size()
        proj_query = self.query_conv(x)
        proj_query_H = proj_query.permute(0,3,1,2).contiguous().view(m_batchsize*width,-1,height).permute(0, 2, 1)
        proj_query_W = proj_query.permute(0,2,1,3).contiguous().view(m_batchsize*height,-1,width).permute(0, 2, 1)
        proj_key = self.key_conv(x)
        proj_key_H = proj_key.permute(0,3,1,2).contiguous().view(m_batchsize*width,-1,height)
        proj_key_W = proj_key.permute(0,2,1,3).contiguous().view(m_batchsize*height,-1,width)
        proj_value = self.value_conv(x)
        proj_value_H = proj_value.permute(0,3,1,2).contiguous().view(m_batchsize*width,-1,height)
        proj_value_W = proj_value.permute(0,2,1,3).contiguous().view(m_batchsize*height,-1,width)
        energy_H = (torch.bmm(proj_query_H, proj_key_H)+self.INF(m_batchsize, height, width)).view(m_batchsize,width,height,height).permute(0,2,1,3)
        energy_W = torch.bmm(proj_query_W, proj_key_W).view(m_batchsize,height,width,width)
        concate = self.softmax(torch.cat([energy_H, energy_W], 3))
 
        att_H = concate[:,:,:,0:height].permute(0,2,1,3).contiguous().view(m_batchsize*width,height,height)        #print(concate)
        #print(att_H) 
        att_W = concate[:,:,:,height:height+width].contiguous().view(m_batchsize*height,width,width)
        out_H = torch.bmm(proj_value_H, att_H.permute(0, 2, 1)).view(m_batchsize,width,-1,height).permute(0,2,3,1)
        out_W = torch.bmm(proj_value_W, att_W.permute(0, 2, 1)).view(m_batchsize,height,-1,width).permute(0,2,1,3)        #print(out_H.size(),out_W.size())
        return self.gamma*(out_H + out_W) + x

       

二、Recurrent Criss-Cross Attention (RCCA)

如下图左,单个Criss-Cross Attention Module可以使得某像素与其横向和纵向其他像素建立联系,当2个Criss-Cross Attention Module串行时,即可与其他所有像素建立联系。【论文复现赛第六期-语义分割】CCNet -        

三、网络结构

CCNet网络结构如下图所示,CNN表示特征提取器(backbone),Reduction减少特征图的通道数以减少后续计算量,Criss-Cross Attention用来建立不同位置像素间的联系从而丰富其语义信息,R表示Criss-Cross Attention Module的循环次数,注意多个Criss-Cross Attention Module共享参数。

【论文复现赛第六期-语义分割】CCNet -        

四、实验结果

在cityscapes验证集上,CCNet表现如下(每个配置训练3次,数据来自官方repo):

R cityscapes val miou link
1 77.31 & 77.91 & 76.89 77.91
2 79.74 & 79.22 & 78.40 79.74
2+OHEM 78.67 & 80.00 & 79.83 80.00

五、复现结果

本次复现的目标是CCNet-resnet101 R=2+OHEM在cityscapes验证集 mIOU= 80.0%,复现的miou为80.95%。详情见下表:

Model Backbone Resolution Training Iters mIoU mIoU (flip) mIoU (ms+flip) Links
CCNet ResNet101_OS8 769x769 60000 80.95% 81.23% 81.32% model|log|vdl

六、快速体验

运行以下cell,快速体验CCNet。

In [ ]
# step 1: unzip data%cd ~/PaddleSeg/
!mkdir data
!tar -xf ~/data/data64550/cityscapes.tar -C data/
%cd ~/
    In [ ]
# step 2: 训练%cd ~/PaddleSeg
!python train.py --config configs/ccnet/ccnet_resnet101_os8_cityscapes_769x769_60k.yml \
    --do_eval --use_vdl --log_iter 100 --s*e_interval 4000 --s*e_dir output
    In [ ]
# step 3: val%cd ~/PaddleSeg/
!python val.py \
       --config configs/ccnet/ccnet_resnet101_os8_cityscapes_769x769_60k.yml \
       --model_path output/best_model/model.pdparams       # --model_path /home/aistudio/converted_ddrnet23_imagenet.pdparams
    In [ ]
# step 4: val flip%cd ~/PaddleSeg/
!python val.py \
       --config configs/ccnet/ccnet_resnet101_os8_cityscapes_769x769_60k.yml \
       --model_path output/best_model/model.pdparams \
       --aug_eval \
       --flip_horizontal
    In [ ]
# step 5: val ms flip %cd ~/PaddleSeg/
!python val.py \
       --config configs/ccnet/ccnet_resnet101_os8_cityscapes_769x769_60k.yml \
       --model_path output/best_model/model.pdparams \
       --aug_eval \
       --scales 0.75 1.0 1.25 \
       --flip_horizontal
    In [ ]
# step 6: 预测, 预测结果在~/PaddleSeg/output/result文件夹内%cd ~/PaddleSeg/
!python predict.py \
       --config configs/ccnet/ccnet_resnet101_os8_cityscapes_769x769_60k.yml \
       --model_path output/best_model/model.pdparams \
       --image_path data/cityscapes/leftImg8bit/val/frankfurt/frankfurt_000000_000294_leftImg8bit.png \
       --s*e_dir output/result
    In [ ]
# step 7: export%cd ~/PaddleSeg
!python export.py \
       --config configs/ccnet/ccnet_resnet101_os8_cityscapes_769x769_60k.yml \
       --model_path output/best_model/model.pdparams \
       --s*e_dir output
    In [ ]
# test tipc 1: prepare data%cd ~/PaddleSeg/
!bash test_tipc/prepare.sh ./test_tipc/configs/ccnet/train_infer_python.txt 'lite_train_lite_infer'
    In [ ]
# test tipc 2: pip install%cd ~/PaddleSeg/test_tipc/
!pip install -r requirements.txt
    In [ ]
# test tipc 3: 安装auto_log%cd ~/# !git clone https://github.com/LDOUBLEV/AutoLog            # 可以跳过git clone%cd AutoLog/
!pip3 install -r requirements.txt
!python3 setup.py bdist_wheel
!pip3 install ./dist/auto_log-1.2.0-py3-none-any.whl
    In [ ]
# test tipc 4: test train inference%cd ~/PaddleSeg/
!bash test_tipc/test_train_inference_python.sh ./test_tipc/configs/ccnet/train_infer_python.txt 'lite_train_lite_infer'
   

七、复现经验

1、使用paddleseg套件复现论文,可以赢在起跑线;
2、为了防止组网错误,可以把官方权重转换为paddlepaddle,加载测试,确保模型组网无误;
3、模型组网完成后,一定要先测试模型导出是否有问题,确保无误再训练,否则test tipc不通过,会浪费很多时间。

以上就是【论文复现赛第六期-语义分割】CCNet的详细内容,更多请关注其它相关文章!


# 多个  # 肥东网站推广优点和缺点  # 武汉美容网站建设  # 兰州新网站seo收费  # 湖北网站建设怎样开发  # 贺州工厂网站建设对比  # 山西本地网站推广多少钱  # 秋冬童装网站推广  # 校园推广新产品营销策划  # 昆明网站建设教学视频  # 零付费推广营销方案  # 提出了  # 已被  # 上了  # python  # 与其他  # 如下图  # 官网  # 一言  # 第六期  # 中文网  # fig  # whee  # udio  # igs  # red  # ai  # git 


相关栏目: 【 行业资讯67740 】 【 技术百科0 】 【 网络运营39195


相关推荐: 联想的固态硬盘如何  typescript为什么现在才火  如何以命令符运行程序  固态硬盘如何装入机箱  爱奇艺中下载的视频怎么在PPT中播放操作方法  苹果16有哪些黑科技  怎么在项目中使用typescript  ai怎么找链接文件位置教程  苹果16日发售哪些机型  满射为什么没有逆映射  如何提高import命令的性能  power在坐标轴中是什么意思  如何管理员打开cmd命令行窗口  春运预约抢票能抢到吗  选哪个折叠屏手机好用  meet是什么意思  市盈率tt的扣非是什么意思  位置控制单片机怎么用的  如何用命令下载服务器网站  1s等于多少ms  juice是什么意思  望远镜上power是什么意思  8英寸等于多少厘米  税负是什么意思  课程伴侣电脑怎么登录  如何拍屏幕不出条纹详细方法  如何打开命令框  put linux命令如何书写  typescript性能如何  汽车的type-c接口是什么  j*a数组怎么比较abc  如何以管理员身份打开命令提示符  debug中如何用n命令命名程序文件名  mysql的datediff函数怎么用  净水器上的power是什么意思  typescript是什么软件  j*a怎么把数组输出  360n5锁屏壁纸怎么设置  混合固态硬盘如何分区  春运抢票可以抢几次票  羽毛球拍power9是什么意思  如何正确使用固态硬盘  折叠屏手机哪款最好  为什么要出折叠屏手机  怎么用typescript 写js  远程桌面如何发送命令  为什么夸克下载不到  vue中datediff函数怎么用  手机如何运行ping命令  如何安装m.2固态硬盘 

搜索