Paper Reading:SESS(Self-Ensembling Semi-supervised3D ObjectDetction)

article/2025/9/26 19:03:05

BackGround

虽然3D点云的目标检测当前运用十分广泛,但是当前大部分3D目标检测的方法强依赖于带有标注的数据。这些带有标注的数据往往是需要付出昂贵的代价,在2021年的水平大概是¥0.1一个框,那么一帧数据也就是对应的¥1-2不等。然而往往标注量需求往往是数以千计的,可想当前对于标注数据的消耗之大。本篇文章先要使用半监督的方法,缓解数据标注的问题。

Progress

  • 提出了一个自集成半监督的3D目标检测框架;
  • 设计了一个彻底的扰动方案,增强了网络在标记数据和未标记数据的泛化能力;
  • 提出了三个一致性损失的方法来强制两组预测的结果建议的一致性

Solved problem

  • 在之前的Transferable semi-supervised 3d object detection from rgb-d data这篇文章中强依赖于2D标记数据对3D目标检测,本文直接处理3D原始点云,消除对2D标注数据的依赖。
  • 将半监督的方法直接运用在了点云上
  • 解决了点云在经过老师和学生网络后无法对其的问题(Stochatic transform)
  • 解决了在经过学生和老师网络后一致性无法计算的问题(Consistency loss)

SESS_Pipline

SESS Architecture

在SESS架构中,作者使用Mean Teacher paradigm作为半监督的3D目标检测架构。其中学生和教师网络是3D对象的检测器,使用的是VoteNet(过几天更一个VoteNet的Paper Reading)。具体的操作如下上图的Pipline。

在Pipline中,分别会有两种数据作为输入。一种是标记的数据(角标带L),另一种是没有标记的数据(角标带U)。其中,标记的数据划分为y^Lx^L两个部分。首先会将x^Lx^U送入随机采样层。之后的输出一部分会经过Stochatic transform(其实就是Transformer)送给学生部分,在这部分数据中包含有带有标签和没有标签的两种。从随机采样层出来的另一部分数据会送给教师部分,在这部分输出的数据也包括带有标签和没有标签的两种。因为教师输出的数据需要和学生输出的数据计算损失,所以需要将教师输出的\left \{ {y^L_t} \right \} \cup \left \{​{y^U_t} \right \}和学生输出的对齐,所以需要做也经过Stochatic transform。 对于另一组输入的有标签数据y^L,因为需要作为\hat{y}^L_s的监督损失的输出比较。对于学生网络和教师网络的输出,需要基于欧氏距离并根据三个一致性损失(Center,Class,Size)来计算两者输出之间的误差,通过梯度下降更新学生网络中的参数,并且从学生网络中的参数使用exponential moving average(EMA)的方法更行教师网络的参数。具体更新策略如下图公式,其中\alpha是一个平滑的超参数,用于控制从教师和学生网络中的信息获取量。

以上就是SESS的Pipline的基本流程。

对于上述计算EMA的代码如下:

def huber_loss(error, delta=1.0):"""Args:error: Torch tensor (d1,d2,...,dk)Returns:loss: Torch tensor (d1,d2,...,dk)x = error = pred - gt or dist(pred,gt)0.5 * |x|^2                 if |x|<=d0.5 * d^2 + d * (|x|-d)     if |x|>dRef: https://github.com/charlesq34/frustum-pointnets/blob/master/models/model_util.py"""abs_error = torch.abs(error)#quadratic = torch.min(abs_error, torch.FloatTensor([delta]))quadratic = torch.clamp(abs_error, max=delta)linear = (abs_error - quadratic)loss = 0.5 * quadratic**2 + delta * linear

扰动方案(Transform)

在SESS中扰动方案是为了提高模型性能。具体在SESS中加入了两种扰动方案,分别是Random sub-sampling和Stochatic transform这两种,接下来分别介绍这两种方法;

Radom sub-sampling:

对于输入到教师网络和学生网络的未标记和标记的数据都经过了随机采样。因为给定的两个点云的样本中点的局部几何关系可能存在一些差异,但全局几何关系应该保持不变。因此,在SESS中通过使学生网络和老师网络输出之间的一致来利用全局环境中的潜在集合关系。

对应代码如下:

# ----------------------------------------
# Point Cloud Sampling
# ----------------------------------------def random_sampling(pc, num_sample, replace=None, return_choices=False):""" Input is NxC, output is num_samplexC"""if replace is None: replace = (pc.shape[0]<num_sample)choices = np.random.choice(pc.shape[0], num_sample, replace=replace)if return_choices:return pc[choices], choiceselse:return pc[choices]

Stochatic Transform:

在Stochatic Transform中进行了翻转,旋转和缩放的随机变换。为\tau =\left \{ F_x,F_y,R,S \right \}

对于F_x随机翻转表示沿着x轴旋转(对于F_yF_x一致):

 对于R来说(范围为\left [ -\vartheta,+\vartheta \right ]):

 对于S来说表示对于点的缩放(范围在\left [ a,b \right ]

对应代码如下:

# ----------------------------------------
# Simple Point manipulations
# ----------------------------------------
def rotate_point_cloud(points, rotation_matrix=None):""" Input: (n,3), Output: (n,3) """# Rotate in-place around Z axis.if rotation_matrix is None:rotation_angle = np.random.uniform() * 2 * np.pisinval, cosval = np.sin(rotation_angle), np.cos(rotation_angle)     rotation_matrix = np.array([[cosval, sinval, 0],[-sinval, cosval, 0],[0, 0, 1]])ctr = points.mean(axis=0)rotated_data = np.dot(points-ctr, rotation_matrix) + ctrreturn rotated_data, rotation_matrixdef rotate_pc_along_y(pc, rot_angle):''' Input ps is NxC points with first 3 channels as XYZz is facing forward, x is left ward, y is downward'''cosval = np.cos(rot_angle)sinval = np.sin(rot_angle)rotmat = np.array([[cosval, -sinval],[sinval, cosval]])pc[:,[0,2]] = np.dot(pc[:,[0,2]], np.transpose(rotmat))return pcdef roty(t):"""Rotation about the y-axis."""c = np.cos(t)s = np.sin(t)return np.array([[c,  0,  s],[0,  1,  0],[-s, 0,  c]])def roty_batch(t):"""Rotation about the y-axis.t: (x1,x2,...xn)return: (x1,x2,...,xn,3,3)"""input_shape = t.shapeoutput = np.zeros(tuple(list(input_shape)+[3,3]))c = np.cos(t)s = np.sin(t)output[...,0,0] = coutput[...,0,2] = soutput[...,1,1] = 1output[...,2,0] = -soutput[...,2,2] = creturn outputdef rotz(t):"""Rotation about the z-axis."""c = np.cos(t)s = np.sin(t)return np.array([[c, -s,  0],[s,  c,  0],[0,  0,  1]])

Consistency loss

因为两组3D检测方案的一致性不能直接计算,所以我们将通过学生和老师的预测方案和对齐方案配对。对成对的方案引入三个损失函数(采用欧氏距离来测量),分别是位置,语义类别和大小。最后的输出可以描述为以下的公式(其中t代表老师模型,s代表学生模型)。

实现代码如下:

#Losses = L_center+L_class+L_size
def get_consistency_loss(end_points, ema_end_points, config):"""Args:end_points: dict{center, size_scores, size_residuals_normalized, sem_cls_scores,flip_x_axis, flip_y_axis, rot_mat}ema_end_points: dict{center, size_scores, size_residuals_normalized, sem_cls_scores,}Returns:consistency_loss: pytorch scalar tensorend_points: dict"""center_consistency_loss, map_ind = compute_center_consistency_loss(end_points, ema_end_points)class_consistency_loss = compute_class_consistency_loss(end_points, ema_end_points, map_ind)size_consistency_loss = compute_size_consistency_loss(end_points, ema_end_points, map_ind, config)consistency_loss =  center_consistency_loss +class_consistency_loss + size_consistency_lossend_points['center_consistency_loss'] = center_consistency_lossend_points['class_consistency_loss'] = class_consistency_lossend_points['size_consistency_loss'] = size_consistency_lossend_points['consistency_loss'] = consistency_lossreturn consistency_loss, end_points

接下来分别对这三个量进行描述,其中对于中心距离的一致性损失为:

对于中心距离的实现如下:

#Center
def compute_center_consistency_loss(end_points, ema_end_points):center = end_points['center'] #(B, num_proposal, 3)ema_center = ema_end_points['center'] #(B, num_proposal, 3)flip_x_axis = end_points['flip_x_axis'] #(B,)flip_y_axis = end_points['flip_y_axis'] #(B,)rot_mat = end_points['rot_mat'] #(B,3,3)scale_ratio = end_points['scale'] #(B,1,3)# align ema_center with center based on the input augmentation stepsinds_to_flip_x_axis = torch.nonzero(flip_x_axis).squeeze(1)ema_center[inds_to_flip_x_axis, :, 0] = -ema_center[inds_to_flip_x_axis, :, 0]inds_to_flip_y_axis = torch.nonzero(flip_y_axis).squeeze(1)ema_center[inds_to_flip_y_axis, :, 1] = -ema_center[inds_to_flip_y_axis, :, 1]ema_center = torch.bmm(ema_center, rot_mat.transpose(1,2)) #(B, num_proposal, 3)ema_center = ema_center * scale_ratiodist1, ind1, dist2, ind2 = nn_distance(center, ema_center)  #ind1 (B, num_proposal): ema_center index closest to center#TODO: use both dist1 and dist2 or only use dist1dist = dist1 + dist2return torch.mean(dist), ind2

对于类别损失,作者只考虑了单向的对其(老师向学生):

实现代码如下:

#Clas loss
def compute_class_consistency_loss(end_points, ema_end_points, map_ind):cls_scores = end_points['sem_cls_scores'] #(B, num_proposal, num_class)ema_cls_scores = ema_end_points['sem_cls_scores'] #(B, num_proposal, num_class)cls_log_prob = F.log_softmax(cls_scores, dim=2) #(B, num_proposal, num_class)# cls_log_prob = F.softmax(cls_scores, dim=2)ema_cls_prob = F.softmax(ema_cls_scores, dim=2) #(B, num_proposal, num_class)cls_log_prob_aligned = torch.cat([torch.index_select(a, 0, i).unsqueeze(0) for a, i in zip(cls_log_prob, map_ind)])class_consistency_loss = F.kl_div(cls_log_prob_aligned, ema_cls_prob)# class_consistency_loss = F.mse_loss(cls_log_prob_aligned, ema_cls_prob)return class_consistency_loss*2

对于大小的损失,表示为:

实现代码如下:

#Size loss
def compute_size_consistency_loss(end_points, ema_end_points, map_ind, config):mean_size_arr = config.mean_size_arrmean_size_arr = torch.from_numpy(mean_size_arr.astype(np.float32)).cuda() #(num_size_cluster,3)B, K = map_ind.shapescale_ratio = end_points['scale'] #(B,1,3)size_class = torch.argmax(end_points['size_scores'], -1) # B,num_proposalsize_residual = torch.gather(end_points['size_residuals'], 2, size_class.unsqueeze(-1).unsqueeze(-1).expand(-1,-1,-1,3)) # B,num_proposal,1,3size_residual.squeeze_(2)ema_size_class = torch.argmax(ema_end_points['size_scores'], -1) # B,num_proposalema_size_residual = torch.gather(ema_end_points['size_residuals'], 2, ema_size_class.unsqueeze(-1).unsqueeze(-1).expand(-1,-1,-1,3)) # B,num_proposal,1,3ema_size_residual.squeeze_(2)size_base = torch.index_select(mean_size_arr, 0, size_class.view(-1))size_base = size_base.view(B,K,3)size = size_base + size_residualema_size_base = torch.index_select(mean_size_arr, 0, ema_size_class.view(-1))ema_size_base = ema_size_base.view(B,K,3)ema_size = ema_size_base + ema_size_residualema_size = ema_size * scale_ratiosize_aligned = torch.cat([torch.index_select(a, 0, i).unsqueeze(0) for a, i in zip(size, map_ind)])size_consistency_loss = F.mse_loss(size_aligned, ema_size)return size_consistency_loss

Experience

作者在实现的过程中将已标注的样本运用VoteNet进行了预训练,然后使用预训练的权重加入到SESS中进行接下来的工作。

下图是SESS(半监督)和VoteNet(全监督)在不同的标记样本的比例下的性能表现。可以看出,随着标记样本比例的变少,SESS相比VoteNet的提升变大。

对于示例检测结果如下:

可以看出,半监督的SESS的方法在标注两较少的情况下对比全监督的方法检测结果有质的提升。

Testing

这个git中给的CUDA版本好像有问题啊,我按照git中的配置并且尝试了更高的配置都没有跑通,后续跑通我更上来。


http://chatgpt.dhexx.cn/article/IijaykBo.shtml

相关文章

SESS: Self-Ensembling Semi-Supervised 3D Object Detection论文阅读及理解

SESS: Self-Ensembling Semi-Supervised 3D Object Detection Abstract 3d检测通常以来目标的标签和注释&#xff0c;然而获得这些注释是十分困难的。 SESS一种自集成的半监督三维目标检测框架。 设计了一种扰动方案&#xff0c;加强对未标记数据和新的为可见数据的泛化。 …

Elasticsearch——》ngram分词器

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

Elasticsearch 的 NGram 分词器使用技巧

一、什么是NGram 分词器&#xff1f; NGram分词器是ES自带的具有前缀匹配搜索功能的一个文本分词器。它能根据文本的步长逐步对写入的文本内容进行约束切割; 二、NGram和index-time搜索推荐原理 搜索的时候&#xff0c;不用再根据一个前缀&#xff0c;然后扫描整个倒排索引了…

Ngram模型

N-Gram是大词汇连续语音识别中常用的一种语言模型&#xff0c;对中文而言&#xff0c;我们称之为汉语语言模型(CLM, Chinese Language Model)。汉语语言模型利用上下文中相邻词间的搭配信息&#xff0c;在需要把连续无空格的拼音、笔划&#xff0c;或代表字母或笔划的数字&…

ElasticSearch之ngram分词器

一、什么是NGram 分词器&#xff1f; edge_ngram和ngram是ElasticSearch自带的两个分词器&#xff0c;一般设置索引映射的时候都会用到&#xff0c;设置完步长之后&#xff0c;就可以直接给解析器analyzer的tokenizer赋值使用。 二、怎么使用 完整的索引结构&#xff1a; {&…

MySql的Ngram全文索引

前言 在我们日常开发中&#xff0c;很多时候会遇到对数据库中某个字段模糊查询的需求&#xff0c;也就是like某个字段&#xff0c;但是很多公司像阿里&#xff0c;京东都禁止使用like来对数据库进行模糊查询&#xff0c;原因是啥呢&#xff1f; 我们先来看下面三条语句 其中t…

语言模型-Ngram

总结工作中用到和学习的知识,也算自己的一个笔记。 语言模型 语言模型简单来讲,就是计算一个句子的概率,更确切的说是计算组成这个句子一系列词语的概率。 举个简单的例子,我们知道“武松打死了老虎”相比于“老虎了死武松打”,更像是一句正常的话,这是因为前者出…

N-gram算法

语言模型 语言模型起源于语音识别(speech recognition)&#xff0c;输入一段音频数据&#xff0c;语音识别系统通常会生成多个句子作为候选&#xff0c;究竟哪个句子更合理&#xff1f;就需要用到语言模型对候选句子进行排序。 语言模型&#xff1a;对于任意的词序列&#xf…

N-Gram语言模型

一、n-gram是什么 wikipedia上有关n-gram的定义&#xff1a; n-gram是一种统计语言模型&#xff0c;用来根据前(n-1)个item来预测第n个item。在应用层面&#xff0c;这些item可以是音素&#xff08;语音识别应用&#xff09;、字符&#xff08;输入法应用&#xff09;、词&am…

MATLAB 离散傅里叶变换(DFT)、逆离散傅里叶变换(IDFT)、快速傅里叶变换(FFT)的实现

离散傅里叶变换&#xff08;DFT&#xff09;、逆离散傅里叶变换&#xff08;IDFT&#xff09;的实现 代码如下&#xff0c;其中xn为时序序列 clc;clear; xn[7,6,5,4,3,2]; Xkdft(xn,6); xidft(Xk,6);subplot(2,2,1);stem(0:5,abs(Xk),filled); axis([0,5,0,1.1*max(abs(Xk))]…

图像处理基础(三)DFT与IDFT变换

傅里叶变换(DFT) 首先来看看傅里叶(DFT)变换的公式 (1) FP\frac {1}{N}\sum_{x0}^{N-1}\sum_{y0}^{N-1}P_{x,y}\exp(-j(\frac{2 \pi}{N})(uxvy)) 幅度 (2) w\sqrt{u^2v^2} 其中 u,v代表空间频率&#xff0c;即灰度梯度&#xff0c;梯度由坐标与灰度值求导的向量 w代表 振幅…

第4章 Python 数字图像处理(DIP) - 频率域滤波7 - 二维DFT和IDFT的一些性质 - 傅里叶频谱和相角

目录 二维DFT和IDFT的一些性质傅里叶频谱和相角 二维DFT和IDFT的一些性质 傅里叶频谱和相角 F ( u , v ) R ( u , v ) j I ( u , v ) ∣ F ( u , v ) ∣ e j ϕ ( u , v ) (4.86) F(u, v) R(u, v) jI(u, v) |F(u, v)|e^{j\phi(u,v)} \tag{4.86} F(u,v)R(u,v)jI(u,v)∣F(…

实数序列频谱的共轭对称性(DFT与IDFT仿真实现)

一、基础知识 1、傅里叶变换&#xff1a;通俗来讲&#xff0c;是以时间为自变量的信号与以频率为自变量的“频谱函数”之间的某种转换关系。 DFT&#xff1a;即离散傅里叶变换&#xff0c;对离散序列进行傅里叶变换。设x(n)为长度为M的有限长序列&#xff0c;其N点DFT定义(公…

第4章 Python 数字图像处理(DIP) - 频率域滤波8 - 二维DFT和IDFT的一些性质 - 二维离散卷积定理

目录 二维DFT和IDFT的一些性质二维离散卷积定理二维离散傅里叶变换性质的小结 二维DFT和IDFT的一些性质 二维离散卷积定理 二维循环卷积表达式&#xff1a; ( f ⋆ h ) ( x , y ) ∑ m 0 M − 1 ∑ n 0 N − 1 f ( m , n ) h ( x − m , y − n ) (4.94) (f \star h)(x, …

FFT学习笔记(DFT,IDFT)

昨天参悟了一天FFT,总算是理解了&#xff0c;今天的莫比乌斯反演也不太懂&#xff0c;干脆弃疗&#xff0c;决定来认真水一发博客。 什么是FFT&#xff1f; FFT&#xff08;Fast Fourier Transformation&#xff09;&#xff0c;即为快速傅氏变换&#xff0c;是离散傅氏变换&…

【OpenCV4】图像的傅里叶变换 cv::dft() 和逆变换 cv::idft() 解析(c++)

图像傅里叶变换的作用&#xff1a; 频谱分析&#xff0c;获取图像中高频低频的分布情况快速卷积&#xff0c;两个矩阵的傅里叶变换结果相乘 案例代码&#xff1a; cv::Mat TestOpencvDft() {cv::Mat lena cv::imread("lena.jpg", 0);cv::resize(lena, lena, cv::…

Matlab如何进行利用离散傅里叶逆变换iDFT 从频谱恢复时域信号

文章目录 1. 定义2. 变换和处理3. 函数4. 实例演示例1&#xff1a;单频正弦信号&#xff08;整数周期采样&#xff09;例2&#xff1a;含有直流分量的单频正弦信号例3&#xff1a;正弦复合信号例4&#xff1a;含有随机干扰的正弦信号例5&#xff1a;实际案例 5. 联系作者 1. 定…

离散傅里叶变换(DFT/IDFT、FFT/IFFT)运算量的讨论

前言&#xff1a;关于为什么要写这个博客 最近在重新看《合成孔径雷达成像 算法与实现》这本书&#xff0c;看到“离散傅里叶变换记其逆变换的运算量级为”这句话&#xff0c;就想起当初在学《数字信号处理》中FFT那章节时&#xff0c;书中有对比DFT和FFT的运算量的一些文字&am…

OpenCV-离散傅里叶变换cv::dftcv::idft

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 函数原型 void dft(InputArray src, OutputArray dst, int flags 0, int nonzeroRows 0); void idft(InputArray src, Output…

12点的idft c语言,【整理】用IDFT实现UF-OFDM和OFDM的模拟调制

cooperate with Liu Lei 用IDFT实现OFDM的代码如下&#xff1a; N32; xrandint(1,N,[0 3]); x1qammod(x,4); f1:N; t0:0.001:1-0.001; w2*pi*f.*t; % w12*pi*(f0.2).*t; y1x1*exp(j*w);%子载波调制 x2ifft(x1,N); %ifft figure(1); plot(t,abs(y1)); hold on; stem(0:1/N:1-1/N…