R2O语义分割: Refine and Represent: Region-to-Object Representation Learning

paper: arxiv.org/pdf/2208.11821v2.pdf

repo link: KKallidromitis/r2o: PyTorch implementation of Refine and Represent: Region-to-Object Representation Learning. (github.com)

摘要:

在本文中提出了区域到对象表示学习(Region-to-Object Representation Learning,R2O),它在预测分割掩码和使用这些掩码预训练编码网络之间振荡。R2O通过对编码特征进行聚类来确定分割掩码。R2O然后通过执行区域到区域的相似性学习来预训练编码网络,其中编码网络获取图像的不同视图,并将分割的区域映射到相似的编码特征。

引言:

R2O是一个框架,通过在整个预训练过程中进化预测分割掩码来学习基于区域和以对象为中心的特征,并鼓励与预测掩码内容相对应的特征的表示相似性。R2O使用掩模预测模块来使用所学习的特征将多个小规模图像区域转换为较大的以对象为中心的区域。在预训练过程中,预测掩码被用于学习表示,这反过来又会在未来的时代中导致更准确的、以对象为中心的分割(见图1)。这使得R2O能够在不依赖于分割启发式的情况下训练以对象为中心的特征。

图1. R2O通过联合学习发现和表示区域和对象,将基于区域和以对象为中心的自监督学习统一起来。以前的以对象为中心的预训练方法使用现成的分割先验来学习以对象为核心的表示。相反,R2O通过在预测分割掩模(这取决于表示)和训练表示(使用分割掩模)之间进行振荡来学习以对象为中心的表示。具体而言,R2O汇集与分割区域相对应的特征(区域相似性损失),并在视图之间强制这些特征的表示相似性。然后,习得的表示会导致改进的、越来越以对象为中心的掩膜,进而导致改进的表示。

论文贡献总结如下:

我们提出了R2O:一种自监督预训练方法,通过预测分割掩模、使用学习的图像特征和学习掩模内内容的表示来学习基于区域和以对象为中心的表示。

•我们为R2O引入了一个区域到对象的预训练课程,该课程从训练与简单图像区域相对应的局部特征开始,例如共享相似颜色值的相邻像素,然后逐渐学习以对象为中心的特征。

•与以前的方法相比,R2O预训练提高了ImageNet在MS COCO 1×(+0:2 APbb,+0:3 APmk)和2×(+0:9 APbb,+0.0:4 APmk)。在对COCO进行预训练后,R2O的PASCAL VOC和Cityscapes分别比早期方法高出+1:9mIOU和+2:4mIOU。此外,R2O在加州理工大学UCSD Birds 200-2011(CUB200-2011)上进一步提高了最先进的无监督分割性能+3:3mIOU,尽管没有对CUB200-202011进行微调。

相关工作:

基于区域和以对象为中心的自监督预训练

我们的工作扩展了基于区域的预训练,首先训练区域级特征,然后逐渐发现以对象为中心的分割,最终训练以对象为核心的特征。Odin[31]和SlotCon[62]等并行工作已经提出了对象级预训练方法,该方法不依赖于分割启发式,而是使用学习的特征来分割输入图像。与Odin类似,R2O对图像特征使用Kmeans聚类来帮助发现类对象区域。然而,与只关注训练对象级特征的Odin或SlotCon不同,R2O预训练涉及训练局部特征和对象级特征。

区域聚类

在这项工作中,我们使用聚类将小图像区域细化为以对象为中心的掩码。聚类在无监督语义分割中有着悠久的历史[1,13,14,17,21,33]。这一趋势在深度学习时代仍在继续。当前的方法利用聚类分配来学习空间和语义一致的嵌入[12,34,36,37]。例如,一种流行的方法[34, 37]是对像素嵌入进行聚类训练,并使用聚类分配作为伪标签。其他方法 [12, 36] 则使用相似性损失和特定任务数据增强来训练嵌入。我们的工作并不侧重于无监督语义分割任务,而是侧重于使用聚类来定位对象,以便学习可迁移的表征。我们的方法使用 K-means 聚类[39],因为它简单有效。

方法:

我们提出了R2O,这是一种自监督的预训练方法,可以实现区域级和以对象为中心的表示学习。在高水平上,R2O通过掩模预测模块将区域级图像先验转换为以对象为中心的掩模,并鼓励与所发现的掩模的内容相对应的特征的代表不变性(见图2)。

图2:R2O架构。R2O由两个相互依存的步骤组成:(1)掩模预测,其中使用学习的特征将小图像区域(由区域级先验给定)转换为以对象为中心的掩模;(2)表示学习,其中学习对象级表示。

步骤1通过计算由区域级先验给出的每个区域的特征并对这些区域级嵌入执行K-means聚类来产生以对象为中心的分割。

步骤2鼓励与每个视图中的掩码的内容相对应的特征的表示相似性。通过这个过程,我们发现通过第二步学习到的特征会导致越来越多的以对象为中心的分割,从而训练以对象为核心的表示。考虑到区域级特征在我们的掩模预测过程中的重要性,R2O采用了一种区域到对象的课程(备注:课程学习curriculum learning),该课程在掩模预测期间将聚类(K)的数量从非常高的值(K=128)逐渐减少到较低的值(K=4),正如我们所示,这使得能够在训练期间早期进行基于区域的预训练,并慢慢发展为以对象为中心的关联。我们将在线网络和目标网络分别表示为ON,TN。

图3. COCO预训练过程中掩码预测的可视化。在后期的预训练中,R2O预测的掩码能够发现以对象为中心的区域,即使是在多对象、以场景为中心的数据集中,如COCO。

结果

表1. 在ImageNet预训练后的PASCAL VOC和Cityscapes的COCO对象检测和实例分割以及语义分割方面的性能。所有方法都预训练了ResNet-50主干,并微调了用于COCO的Mask RCNN(R50-FPN)和用于PASCAL VOC和Cityscapes的FCN。*:表示并行工作。†:重新实施的结果。

表2. COCO预训练后PASCAL VOC和Cityscapes语义分割(mIOU)的性能。在对以场景为中心的数据进行预训练后,R2O在PASCAL VOC和Cityscapes上展示了最先进的语义分割传输性能。*:表示并行工作。†:重新实施的结果。

表3. CUB200-2011细分市场表现。结果报告了Caltech UCSD Birds 200-2011(CUB200-2011)测试集中图像前景背景分割的平均联合交集(mIOU)。有趣的是,在不微调ImageNet预训练编码器的情况下,我们能够优于现有方法[4,5,7,58]。†:重新实施的结果。

消融实验

表4. R2O组件的重要性。我们烧蚀了R2O的关键组件,即:掩模预测模块、先验(SLIC)的使用以及区域到对象调度。我们在ImageNet-100上评估了PASCAL VOC语义分割(mIOU)和k-NN分类(%)的性能。如图所示,使用Mask Prediction、SLIC Prior和Region to Object Schedule的组合对于获得最佳性能结果(62.3 mIOU)是必要的——删除任何组件都会影响性能至少−2:6 mIOU和−5:1%。

Code_R2O

class R2OModel(torch.nn.Module):def __init__(self, config):super().__init__()# online networkself.online_network = EncoderwithProjection(config)# target networkself.target_network = EncoderwithProjection(config)# predictorself.predictor = Predictor(config)self.over_lap_mask = config['data'].get('over_lap_mask',True)self._initializes_target_network()self._fpn = None # not actual FPN, but pesudoname to get c4, TODO: Change the confusing nameself.slic_only = Trueself.slic_segments = config['data']['slic_segments']self.n_kmeans = config['data']['n_kmeans']if self.n_kmeans < 9999:self.kmeans = KMeans(self.n_kmeans,)else:self.kmeans = Noneself.rank = config['rank']self.agg = AgglomerativeClustering(affinity='cosine',linkage='average',distance_threshold=0.2,n_clusters=None)self.agg_backup = AgglomerativeClustering(affinity='cosine',linkage='average',n_clusters=16)@torch.no_grad()def _initializes_target_network(self):for param_q, param_k in zip(self.online_network.parameters(), self.target_network.parameters()):param_k.data.copy_(param_q.data)  # initializeparam_k.requires_grad = False     # not update by gradient@torch.no_grad()def _update_target_network(self, mm):"""Momentum update of target network"""for param_q, param_k in zip(self.online_network.parameters(), self.target_network.parameters()):param_k.data.mul_(mm).add_(1. - mm, param_q.data)@torch.no_grad()def _update_mask_network(self, mm):"""Momentum update of maks network"""for param_q, param_k in zip(self.online_network.encoder.parameters(), self.masknet.encoder.parameters()):param_k.data.mul_(mm).add_(1. - mm, param_q.data)@propertydef fpn(self):if self._fpn:return self._fpnelse:self._fpn = IntermediateLayerGetter(self.target_network.encoder, return_layers={'7':'out','6':'c4'})return self._fpndef handle_flip(self,aligned_mask,flip):'''aligned_mask: B X C X 7 X 7flip: B '''_,c,h,w = aligned_mask.shapeb = len(flip)flip = flip.repeat(c*h*w).reshape(c,h,w,b) # C X H X W X Bflip = flip.permute(3,0,1,2)flipped = aligned_mask.flip(-1)out = torch.where(flip==1,flipped,aligned_mask)return outdef get_label_map(self,masks):#b,c,h,w = masks.shapebatch_data = masks.permute(0,2,3,1).reshape(b,h*w,32).detach().cpu()labels = []for data in batch_data:agg = self.agg.fit(data)if np.max(agg.labels_)>15:agg = self.agg_backup.fit(data)label = agg.labels_.reshape(h,w)labels.append(label)labels = np.stack(labels)labels = torch.LongTensor(labels).cuda()return labelsdef do_kmeans(self,raw_image,slic_mask):b = raw_image.shape[0]feats = self.fpn(raw_image)['c4']super_pixel = to_binary_mask(slic_mask,-1,resize_to=(14,14))pooled, _ = maskpool(super_pixel,feats) #pooled B X 100 X d_embsuper_pixel_pooled = pooled.view(-1,1024).detach()super_pixel_pooled_large = super_pixel_pooledlabels = self.kmeans.fit_transform(F.normalize(super_pixel_pooled_large,dim=-1)) # B X 100labels = labels.view(b,-1)raw_mask_target =  torch.einsum('bchw,bc->bchw',to_binary_mask(slic_mask,-1,(56,56)) ,labels).sum(1).long().detach()raw_masks = torch.ones(b,1,0,0).cuda() # to make logging happyconverted_idx = raw_mask_targetconverted_idx_b = to_binary_mask(converted_idx,self.n_kmeans)return converted_idx_b,converted_idxdef forward(self, view1, view2, mm,raw_image,roi_t,slic_mask,clustering_k=64):im_size = view1.shape[-1]b = view1.shape[0] # batch sizeassert im_size == 224idx = torch.LongTensor([1,0,3,2]).cuda()# reset k means if necessaryif self.n_kmeans != clustering_k:self.n_kmeans = clustering_kif self.n_kmeans < 9999:self.kmeans = KMeans(self.n_kmeans,)else:self.kmeans = None# Get spanning view embeddingswith torch.no_grad():if self.n_kmeans < 9999:converted_idx_b,converted_idx = self.do_kmeans(raw_image,slic_mask) # B X C X 56 X 56, B X 56 X 56else:converted_idx_b = to_binary_mask(slic_mask,-1,(56,56))converted_idx = torch.argmax(converted_idx_b,1)raw_masks = torch.ones(b,1,0,0).cuda()raw_mask_target = converted_idxmask_dim = 56rois_1 = [roi_t[j,:1,:4].index_select(-1, idx)*mask_dim for j in range(roi_t.shape[0])]rois_2 = [roi_t[j,1:2,:4].index_select(-1, idx)*mask_dim for j in range(roi_t.shape[0])]flip_1 = roi_t[:,0,4]flip_2 = roi_t[:,1,4]aligned_1 = self.handle_flip(ops.roi_align(converted_idx_b,rois_1,7),flip_1) # mask output is B X 16 X 7 X 7aligned_2 = self.handle_flip(ops.roi_align(converted_idx_b,rois_2,7),flip_2) # mask output is B X 16 X 7 X 7mask_b,mask_c,h,w =aligned_1.shapealigned_1 = aligned_1.reshape(mask_b,mask_c,h*w).detach()aligned_2 = aligned_2.reshape(mask_b,mask_c,h*w).detach()mask_ids = Nonemasks = torch.cat([aligned_1, aligned_2])masks_inv = torch.cat([aligned_2, aligned_1])num_segs = torch.FloatTensor([x.unique().shape[0] for x in converted_idx]).mean()q,pinds = self.predictor(*self.online_network(torch.cat([view1, view2], dim=0),masks.to('cuda'),mask_ids,mask_ids))# target network forwardwith torch.no_grad():self._update_target_network(mm)target_z, tinds = self.target_network(torch.cat([view2, view1], dim=0),masks_inv.to('cuda'),mask_ids,mask_ids)target_z = target_z.detach().clone()return q, target_z, pinds, tinds,masks,raw_masks,raw_mask_target,num_segs,converted_idx

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218984.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell编程-cut命令详解(超详细)

前言 cut 命令是一个在命令行中使用的用于提取文件内容的工具。它可以根据指定的字段或字符位置来截取文件中的数据&#xff0c;并将结果输出到标准输出或指定的文件中。本文将详细介绍 cut 命令的常用选项和参数&#xff0c;帮助您更好地理解和使用 cut 命令。 一、cut命令介…

js 转换为数组并返回(Array.of())

Array提供了方法直接将一组值转换为数组并返回 Array.of()方法 Array.of(1,2,3) 结果

【NSX-T】2. 搭建NSX-T环境 —— 配置 NSX-T 基本设置

目录 2. 配置 NSX-T 基本设置2.1 访问 NSX Manager UI2.2 添加和查看 NSX Manager 许可证2.3 设置用户界面模式 参考资料 2. 配置 NSX-T 基本设置 2.1 访问 NSX Manager UI 打开跳板机浏览器&#xff0c;在URL中输入&#xff1a;https://192.168.1.23/ 或 https://manager32.…

【教程】 Vue混淆加密与还原

目录 引言 混淆 使用ipaguard来对程序进行加固 还原 总结 参考资料 引言 Vue是一种流行的JavaScript框架&#xff0c;用于构建用户界面。它简单易用且功能强大&#xff0c;备受开发者喜爱。然而&#xff0c;在传输和存储过程中&#xff0c;我们需要保护Vue代码的安全性。混…

centos7中的管道和重定向

重定向 0 标准输入 1 标准输出 2 标准错误 3 进程在执行的过程中打开的其他文件 & 标准正确和标准错误的混合输出 输出重定向 &g…

【Linux】锁的简单封装以及原理解析

文章目录 一、锁的原理过程1&#xff1a;过程2过程3过程4 二、 锁的简单封装1.LockGuard.hpp2.使用1.正常锁的使用2.使用封装后的 总结 一、锁的原理 为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条…

算法Day31 房间收纳

房间收纳 Description 对于零落的玩具&#xff0c;你需要进行收纳&#xff0c;为了将最多的玩具进行收纳&#xff0c;请你合理分配收纳柜和房间数量。 请你将一些玩具收纳在一个房间中&#xff0c;给你一个二维数组 roomTypes&#xff0c;其中的roomTypes[i] {numberOfBoxes_…

Narak

靶场下载 https://download.vulnhub.com/ha/narak.ova 信息收集 # nmap -sn 192.168.1.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2023-12-09 22:18 CST Nmap scan report for 192.168.1.1 (192.168.1.1) Host is up (0.…

AI智能视界,视频监控技术的革新与突破

智能视频监控概述 TSINGSEE青犀智能监控系统是通过摄像头采集视频数据&#xff0c;经过压缩技术处理后传输至服务器&#xff0c;再由服务器进行存储和管理并汇聚到EasyCVR视频融合平台之中&#xff0c;进行统一的分发处理。采用先进的视频压缩技术&#xff0c;确保视频质量&am…

锂电池基础知识及管理方式总结

这两天在排查一个锂电池无法充电的问题&#xff0c;用的是电池管理芯片BQ25713&#xff0c;网上相关的资料也很少&#xff0c;查看数据手册时&#xff0c;里面也有很多术语参数等不是很理解&#xff0c;所以&#xff0c;在此对锂电池的基础知识做个简单的总结&#xff0c;方面后…

如何通过控制台排查定位EasyCore?

过去当数据库出现了问题&#xff0c;我们只能通过日志去查看问题&#xff0c;可能是数据库有了重启、主节点发生了漂移或查询语句太复杂&#xff0c;这一整套逻辑走下来只能winsen, karel。 我们经常说数据库负载过高&#xff0c;请求很多&#xff0c;但我们却不能直接告诉哪个…

MacOS系统使用ESP8266(CP2102)开发板

开发板实物 连接开发板到macos 终端输入lsusb查看,开发板硬件成功识别 打开Arduino IDE并选择开发板 开发板连接成功 编译代码 上传成功 打开串口监视器,按一下RST键,可看到WIFI名输出及WIFI的IP输出 WIFI热点功能启用

Python 自动化之修理PDF文件(二)

PDF文件_合并与拆分PDF文档Pro版本 文章目录 PDF文件_合并与拆分PDF文档Pro版本前言一、要做成什么样子二、主要用到的函数三、基本思路1.引入库2.创建用户输入模块3.确定主框架 四、文档合并代码模块1.用户输入和函数调用2.引导用户输入文档信息3.合并文档内容4.命名新文档生成…

传输层协议:TCP协议和UDP协议

文章目录 传输层协议&#xff1a;TCP协议和UDP协议一、TCP协议介绍&#xff08;面向连接&#xff0c;稳定&#xff0c;慢&#xff09;1、TCP特性2、TCP报文格式3、TCP三次握手4、TCP四次挥手5、常用的TCP端口号及其功能 二、UDP协议介绍&#xff08;无连接&#xff0c;不稳定&a…

【ET8】4.ET8入门-ECS解析

ECS ECS组件生命周期 参考连接 ⼀种类ECS设计范式的介绍 3.3一切皆实体 4.1组件式设计 【ET框架课程】04-Entity&Component&System_哔哩哔哩_bilibili 【ET框架课程】05-ECS组件生命周期_哔哩哔哩_bilibili

深度学习学习顺序梳理

https://www.bilibili.com/video/BV1to4y1G7xq/?spm_id_from333.999.0.0&vd_source9607a6d9d829b667f8f0ccaaaa142fcb 1.吴恩达机器学习课程 已学完&#xff0c;时间较久了&#xff0c;后续可以重新听一遍&#xff0c;整理一下笔记 2. 白板推导读西瓜书 统计学习方法看…

选择流量回溯分析系统的关键因素

在网络安全和性能优化的背景下&#xff0c;选择适用的流量回溯分析系统变得至关重要。这些系统帮助组织深入了解网络流量&#xff0c;追踪异常行为&#xff0c;并提供关键的信息以加强网络安全。本文将介绍选择流量回溯分析系统时需要考虑的关键因素&#xff0c;以帮助组织做出…

微信小程序、uniapp仿网易云UImusic播放器(附源码)

一、uni-app框架介绍 1.什么是 uni-app uni-app 是一个使用vue的语法 微信小程序的标签和API的跨平台前端框架&#xff0c;开发者编写一套代码&#xff0c;可编译到iOS、Android、H5、小程序等多个平台&#xff0c;几乎覆盖所有流量端。 uni-app 具有跨端数量更多、性能体验…

Python去除字符串中空格(删除指定字符)的3种方法

str 提供了如下常用的方法来删除空白&#xff1a; strip()&#xff1a;删除字符串前后的空白。 lstrip()&#xff1a;删除字符串前面&#xff08;左边&#xff09;的空白。 rstrip()&#xff1a;删除字符串后面&#xff08;右边&#xff09;的空白。 需要说明的是&#xff…

【数据结构】贪心算法

一.贪心算法的定义 贪心算法是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;只做出在某种意义上的局部最优解。 贪心算法的结果是最优解的最好近似。 优点&#xff1a;简单&#xff0c;高效。 缺点&…