cond conv 代码-思想

参考博客:
1 解析图示最清楚
动态卷积之CondConv思想和代码实现_&永恒的星河&的博客-CSDN博客
2 知乎的解释,简洁明了
CondConv代码解析 - 知乎
知乎提供code:External-Attention-pytorch/CondConv.py at master · xmu-xiaoma666/External-Attention-pytorch · GitHub
2 中知乎的评论给出的更好的代码
CondConv-pytorch/condconv.py at master · nibuiro/CondConv-pytorch · GitHub

论文题目: CondConv: Conditionally Parameterized Convolutions for Efficient Inference

论文地址:  https://link.zhihu.com/?target=https%3A//arxiv.org/abs/1904.04971

代码地址:  https://link.zhihu.com/?target=https%3A//github.com/tensorflow/tpu/tree/master/models/official/efficientnet/condconv

1 介绍

Cond conv: 是2019年发表在Google Brains上关于卷积CondConv的文章
即插即用的模块

常规卷积进行构建网络,有如下假设:所有的样本共享卷积网络中的卷积参数.
需求:
提升模型容量就需要增加网络的参数,深度,通道数,这将导致模型的计算量和参数量增加,模型部署难度大。若要模型的实时性高,这就需要模型拥有较低的参数量和计算量.
 

cond conv目的提升模型的容量,同时保持实时性。
cond conv核心思想:为了打破传统卷积的特性,CondConv将卷积核参数化为多个专家知识的线性组合
公式: (a1*W1+a2*W2+...+an*Wn)*x
a1,a2,a3,...an是通过梯度下降法学习的权重系数
x是输入样本.可以通过提升专家的数量来提升模型的容量,这比提升卷积核的尺寸更有效,同时专家知识只需要一次线性组合,就可以提升模型容量的同时保持高效的推理.

Mixture of Experts(MoE)公式:α1*(W1∗x)+. . .+αn(Wn∗x)
Mixture of Experts(MoE)结构: 采用更细粒度的集成方式,每一个卷积层都拥有多套权重,卷积层的输入分别经过不同的权重卷积之后组合输出,缺点是但这计算量依旧很大.


CondConv公式: (α1*W 1+ . . . + αn*Wn)∗x       =α1*(W1∗x)+. . .+αn(Wn∗x) 与MoE等同
Cond conv结构:可以解决MoE计算大问题,降低计算量。
既然输入相同,卷积是一种线性计算,COMBINE也是一个线性计算(比如加权求和),作者将多套权重加权组合之后,只做一次卷积就能完成相当的效果!
2者区别: MoE是每个卷积核分别与x计算再组合,cond conv是先组合卷积核,在与x计算。

细致实现流程图(感谢这位博主的绘制,参考博客1)(tensorflow version)

输入:X(N,H,W,C)
N:数据Batch的大小
H和W:输入图片的高和宽
C:输入图片的通道数
两条输出:右边输出,左边输出,最后对各自的输出进行整合.
(h,w,cin,cout)表示卷积核大小
h和w分别表示卷积核的高和宽
cin,cout分别表示卷积核的输入和输出通道数.

右边线路:由计算样本生成多个卷积核的各自权重
step1: 对输入X,进行GAP操作(GlobalAveragePooling2D)操作,具体在维度(H,W),
输出大小为(N,C)
step2: 之后经过FC层,学习不同输入样本对用num_experts个卷积的各自的权重系数,输出为(N,num_experts)
step3: 采用Sigmoid归一化到(0,1)之间,输出为(N,num_experts)
step4: step3输出权重系数和num_experts个卷积核权重通过矩阵的相乘,赋予到相应的卷积上,输出各个样本对应加权后的卷积核权重,输出大小为:(N,h*w*cin*cout)
step5: step4中的输出在N维度进行Split操作,得到各个样本对应加权后卷积核

左边线路:对输入X依次通过对应加权输出的卷积核权重,完成CondConv。
step1:将X在N维度进行split操作
step2:step1中输出结果和右边线输出对应卷积权重进行卷积操作,之后进行Concat。

上面已经说的很细致了,下面介绍实验效果


总结:
CondConv打破了静态卷积的假设:卷积核对所有输入“一视同仁”。
提升模型容量保持高效推理:提升卷积核生成函数的尺寸与复杂度。
由于卷积核参数仅需计算一次,相比卷积计算,这些额外的计算量可以忽略。
即:提升卷积核生成的计算量>(优于)添加更多卷积更多通道数

2 代码详解torch(来自知乎条件参数化卷积(CondConv))

为了方便理解 ,下面把原代码中的 initial_weights 和 bias 相关的部分删掉了。
rount_fn部分:是 attention 函数,输入为 [N, C, H, W]
需要两个参数,in_planes为输特征通道数,K为专家个数。
输出shape为[N, K],即这里是针对N个批次的K个卷积核的权重。

# 输入为 [N, C, H, W],需要两个参数,Cin为输入特征通道数,K 为专家个数
class Attention(nn.Module):
    def __init__(self,Cin,K):
        super().__init__()
        self.avgpool=nn.AdaptiveAvgPool2d(1)  # 池化操作
        self.net=nn.Conv2d(Cin, K, kernel_size=1)  # Cin通道变为K
        self.sigmoid=nn.Sigmoid()  # 归一化

    def forward(self,x):
        # 将输入特征全局池化为 [N,Cin,H,W]->[N, Cin, 1, 1]
        att=self.avgpool(x)
        # 使用1*1卷积,转化为 [N, Cin, 1, 1]->[N, K, 1, 1]
        att=self.net(att)
        # 将特征转化为二维 [N, K, 1, 1]->[N, K]
        att=att.view(x.shape[0],-1) 
        # 使用 sigmoid 函数输出归一化到 [0,1] 区间
        return self.sigmoid(att)

CondConv 是一种特殊的动态卷积,增加卷积核生成函数的大小和复杂性(增加capacity容量)
CondConv还利用样本的特点来提高模型性能(权重是基于样本生成的类似SE block)
 

class CondConv(nn.Module):
    def __init__(self,Cin,Cout,kernel_size,stride,padding=0,
                 groups=1,K=4):
        super().__init__()
        self.Cin = Cin  # 输入通道
        self.Cout = Cout  # 输出通道
        self.K = K  # K个权重
        self.groups = groups
        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        self.attention = Attention(Cin=Cin,K=K)
        # weight [K, Cout, Cin, kernelz_size, kernel_size]
        self.weight = nn.Parameter(torch.randn(K,Cout,Cin//groups,
                                             kernel_size,kernel_size),requires_grad=True)

    def forward(self,x):
        ### part1 weight
        # 调用 attention 函数得到归一化的权重 [N,Cin,H,W]->[N, K]
        N,Cins, H, W = x.shape
        softmax_att=self.attention(x)
        
        ### part2 x
        # [N, Cin, H, W]->[1, N*Cin, H, W]
        x=x.view(1, -1, H, W)
        
        ### part3 conv
        # 生成随机weight[K, Cout, C_in/groups, 3, 3] (卷积核一般为3*3)
        # 注意添加了 requires_grad=True,这样里面的参数是可以优化的
        weight = self.weight
        # 改变 weight 形状为 [K,Cout,Cin,3,3]->[K, C_out*(C_in/groups)*3*3]
        weight = weight.view(self.K, -1) 

        # part4: 新的wconv = weight*conv
        # 矩阵相乘:[N, K]*[K, Cout*(Cin/groups)*3*3] = [N, Cout*(Cin/groups)*3*3]
        aggregate_weight = torch.mm(softmax_att,weight)
        # 改变形状为:[N, Cout*Cin/groups*3*3]->[N*Cout, Cin/groups, 3, 3],即新的卷积核权重
        aggregate_weight = aggregate_weight.view(
            N*self.Cout, self.Cin//self.groups,
            self.kernel_size, self.kernel_size)
        # 用新生成的卷积核进行卷积,[1, N*Cin, H, W] conv [N*Cout, Cin/groups, 3, 3]
        # 输出为 [1, N*Cout, H, W]
        output=F.conv2d(x,weight=aggregate_weight,
                        stride=self.stride, padding=self.padding,
                        groups=self.groups*N)
        # 形状恢复为 [N, C_out, H, W]        
        output=output.view(N, self.out_planes, H, W)
        return output

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: calib_check_cond - ill-conditioned matrix for input array 0是一个计算机程序中的错误信息。这个错误信息通常出现在进行矩阵运算时,输入矩阵存在不良条件(ill-conditioned)的情况下。 矩阵的条件数(condition number)是矩阵的一个数值特征,用于描述矩阵在数值计算中的稳定性。当矩阵的条件数很大时,说明矩阵很不稳定,即很容易出现数值误差,这样的矩阵被称作不良条件的矩阵。 在程序运行中,如果输入的矩阵是不良条件的矩阵,就会出现上述的错误信息。这意味着程序无法进行矩阵运算,因为输入矩阵的条件数过大,导致程序不稳定,进而出错。 如果遇到这样的错误信息,我们应该首先检查输入矩阵是否正确。如果输入矩阵本身就存在问题,例如存在无穷或未定义的元素等,就需要修正输入矩阵,再重新运行程序。如果输入矩阵本身没有问题,那么可能需要使用更高精度的算法或者调整算法参数来改善程序的数值稳定性,同时提高程序的精度和效率。 ### 回答2: calib_check_cond是用于检查矩阵条件数的函数,通常被用于计算机视觉和机器学习领域。在使用calib_check_cond时,如果发现输入数组中的矩阵条件数过差,就会出现这种错误信息。 所谓条件数,是用于描述矩阵变形的一个指标。矩阵的条件数越大,就说明在矩阵变形时数据的精度越容易受到影响。因此,在使用calib_check_cond之前,需要先对数据集进行预处理,以确保输入矩阵在变形时不会出现过多的误差。 如果出现了calib_check_cond - ill-conditioned matrix for input array 0的错误信息,通常会有两种解决方案。第一种是通过重新选择、清洗或规范化数据集来降低矩阵的条件数。第二种则是通过增加算法的鲁棒性,让算法能在低条件数的矩阵中正常运行。 总之,在使用calib_check_cond时,需要注意输入矩阵的条件数,避免出现过大的误差。同时,也需要根据具体的情况选择合适的解决方案,以确保算法的稳定性和准确性。 ### 回答3: calib_check_cond - ill-conditioned matrix for input array 0 in function 'cal',这个错误提示是,在计算过程中使用了病态矩阵,导致计算的精度出现了问题,从而得到了不合理的结果。病态矩阵是指条件数非常大的矩阵,即矩阵中部分数值非常小或非常大,导致计算误差非常大。当一个矩阵的条件数很大时,意味着微小的误差会被放大,从而导致数值计算的不准确。 要解决这个问题,可以尝试使用数值稳定的算法或者重新设计算法,以克服矩阵条件数大的问题。另外,检查输入数据的有效性也是必要的。可以分析出错的数据,看看是不是存在错误的输入,或者数据本身就不合理。若是因为输入数据不合理导致的问题,需要调整输入数据以保证矩阵的条件数在一个合理的范围内。同时,也可以尝试使用数值精度更高的数据类型,例如Double precision浮点数,从而提高计算精度。 总之,遇到calib_check_cond - ill-conditioned matrix for input array 0 in function 'cal'这个错误提示,需要注意输入数据的有效性和矩阵的条件数,并采用合理的算法和数据类型进行优化,以获得更精确的计算结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机视觉-Archer

图像分割没有团队的同学可加群

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值