输出分组_通过分组卷积的思想,巧妙的代码实现动态卷积(Dynamic Convolution)

论文的题目为《Dynamic Convolution: Attention over Convolution Kernels》

paper的地址https://arxiv.org/pdf/1912.03458.pdf

代码实现地址,其中包含一维,二维,三维的动态卷积;分别可以用于实现eeg的处理,正常图像的处理,医疗图像中三维脑部的处理等等(水漫金山)https://github.com/kaijieshi7/Dynamic-convolution-Pytorch,大家觉得有帮助的话,我就求个star。

一句话描述下文的内容:

的大小视为分组卷积里面的组的大小进行动态卷积。
,那么就转化成
的分组卷积。

文章简单的回顾

这篇文章主要是改进传统卷积,让每层的卷积参数在推理的时候也是随着输入可变的,而不是传统卷积中对任何输入都是固定不变的参数。(由于本文主要说明的是代码如何实现,所以推荐给大家一个讲解论文的连接:Happy:动态滤波器卷积|DynamicConv)

94ae68f395e3dbe031bfd3b6f31abb01.png
推理的时候:红色框住的参数是固定的,黄色框住的参数是随着输入的数据不断变化的。

对于卷积过程中生成的一个特征图

,先对特征图做几次运算,生成
个和为
的参数
,然后对
个卷积核参数进行线性求和,这样推理的时候卷积核是随着输入的变化而变化的。(可以看看其他的讲解文章,本文主要理解怎么写代码)

下面是attention代码的简易版本,输出的是[

,
]大小的加权参数。
对应着要被求和的卷积核数量。
class attention2d(nn.Module):def __init__(self, in_planes, K,):super(attention2d, self).__init__()self.avgpool = nn.AdaptiveAvgPool2d(1)self.fc1 = nn.Conv2d(in_planes, K, 1,)self.fc2 = nn.Conv2d(K, K, 1,)def forward(self, x):x = self.avgpool(x)x = self.fc1(x)x = F.relu(x)x = self.fc2(x).view(x.size(0), -1)return F.softmax(x, 1)

下面是文章中

个卷积核求和的公式。

3a00e67eff8f99bbb07d84c17a8b0484.png

其中

是输入,
是输出;可以看到
进行了两次运算,一次用于求注意力的参数(用于生成动态的卷积核),一次用于被卷积。

但是,写代码的时候如果直接将

个卷积核求和,会出现问题。接下来我们先回顾一下Pytorch里面的卷积参数,然后描述一下可能会出现的问题,再讲解如何通过分组卷积去解决问题。

Pytorch卷积的实现

我会从维度的视角回顾一下Pytorch里面的卷积的实现(大家也可以手写一下,几个重点:输入维度、输出维度、正常卷积核参数维度、分组卷积维度、动态卷积维度、attention模块输出维度)。

输入:输入数据维度大小为[

,
,
,
]。

输出:输出维度为[

,
,
,
]。

卷积核:正常卷积核参数维度为[

,
,
,
]。(在Pytorch中,2d卷积核参数应该是固定这种维度的)

这里我们可以注意到,正常卷积核参数的维度是不存在

的。因为对于正常的卷积来说,不同的输入数据,使用的是相同的卷积核,卷积核的数量与一次前向运算所输入的
大小无关(相同层的卷积核参数只需要一份)。

可能会出现的问题

这里描述一下实现动态卷积代码的过程中可能因为

大于1而出现的问题。

对于图中attention模块最后softmax输出的

个数,他们的维度为[
,
,
,
],可以直接.view成[
,
],紧接着
作用于
卷积核参数上(形成动态卷积)。

问题所在:正常卷积,一次输入多个数据,他们的卷积核参数是一样的,所以只需要一份网络参数即可;但是对于动态卷积而言,每个输入数据用的都是不同的卷积核,所以需要

份网络参数,不符合Pytorch里面的卷积参数格式,会出错。

看下维度运算[

,
]*[
,
,
,
,
],生成的动态卷积核是[
,
,
,
,
],不符合Pytorch里面的规定,不能直接参与运算(大家可以按照这个思路写个代码看看,体会一下,光看可能感觉不出来问题),最简单的解决办法就是
等于1,不会出现错误,但是慢啊!!!

总之,

大于1会导致中间卷积核参数不符合规定。

分组卷积以及如何通过分组卷积实现

大于1的动态卷积

一句话描述分组卷积:对于多通道的输入,将他们分成几部分各自进行卷积,结果concate。

组卷积过程用废话描述:对于输入的数据[

,
,
,
],假设
,那么分组卷积就是将他分为两个
的数据(也可以用其他方法分),那么维度就是[
,
,
,
],换个维度换下视角,[
,
,
,
],
那么
为2的组卷积可以看成
的正常卷积。(
如果还是有点不了解分组卷积,可以阅读其他文章仔细了解一下。

巧妙的转换:上面将

翻倍即可将分组卷积转化成正常卷积,那么反向思考一下,将
变为1,是不是可以将正常卷积变成分组卷积?

我们将

大小看成分组卷积中
的数量,令
所在维度直接变为
!!!直接将输入数据从[
,
,
,
]
变成[1,
,
,
],
就可以用分组卷积解决问题了!!!

详细描述实现过程:将输入数据的维度看成[1,

,
,
](分组卷积的节奏);卷积权重参数初始化为[
,
,
,
,
],attention模块生成的维度为[
,
],直接进行正常的矩阵乘法[
,
]*[
,
*
*
*
]生成动态卷积的参数,
生成的动态卷积权重维度为[
,
,
,
,
],将其看成分组卷积的权重[
,
,
,
](过程中包含reshape)
。这样的处理就完成了,输入数据[
,
,
,
],动态卷积核[
,
,
,
],直接是
的分组卷积,问题解决。

具体代码如下:

class Dynamic_conv2d(nn.Module):def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, K=4,):super(Dynamic_conv2d, self).__init__()assert in_planes%groups==0self.in_planes = in_planesself.out_planes = out_planesself.kernel_size = kernel_sizeself.stride = strideself.padding = paddingself.dilation = dilationself.groups = groupsself.bias = biasself.K = Kself.attention = attention2d(in_planes, K, )self.weight = nn.Parameter(torch.Tensor(K, out_planes, in_planes//groups, kernel_size, kernel_size), requires_grad=True)if bias:self.bias = nn.Parameter(torch.Tensor(K, out_planes))else:self.bias = Nonedef forward(self, x):#将batch视作维度变量,进行组卷积,因为组卷积的权重是不同的,动态卷积的权重也是不同的softmax_attention = self.attention(x)batch_size, in_planes, height, width = x.size()x = x.view(1, -1, height, width)# 变化成一个维度进行组卷积weight = self.weight.view(self.K, -1)# 动态卷积的权重的生成, 生成的是batch_size个卷积参数(每个参数不同)aggregate_weight = torch.mm(softmax_attention, weight).view(-1, self.in_planes, self.kernel_size, self.kernel_size)if self.bias is not None:aggregate_bias = torch.mm(softmax_attention, self.bias).view(-1)output = F.conv2d(x, weight=aggregate_weight, bias=aggregate_bias, stride=self.stride, padding=self.padding,dilation=self.dilation, groups=self.groups*batch_size)else:output = F.conv2d(x, weight=aggregate_weight, bias=None, stride=self.stride, padding=self.padding,dilation=self.dilation, groups=self.groups * batch_size)output = output.view(batch_size, self.out_planes, output.size(-2), output.size(-1))return output

完整的代码在https://github.com/kaijieshi7/Dynamic-convolution-Pytorch,大家觉得有帮助的话,我就求个star。

纸上得来终觉浅,绝知此事要躬行。试下代码,方能体会其中妙处。

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

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

相关文章

java基本数据类型转为String类型的4种常见方法

1.toString 先把基本数据类型装箱,再用对象的toString()方法 2.String类的valueOf方法 这是一个静态方法,几乎可以把各种类型转换为字符串 String.valueOf(); 注意区别包装类的valueOf方法,那个也是静态方法,返回的是包装类型。 3.加一…

北大青鸟消防控制器组网_北大青鸟JBF-61S20防火门监控器控制器接线示意图

北大青鸟JBF-61S20防火门监控器控制器接线示意图一,北大青鸟JBF-61S20防火门监控器控制器接线示意图功能防火门控制及状态 监测功能手动、自动关闭常开防火门;实时监控常开或常闭防火门的状态信息,并进行上报和显示。联网功能监控器可以与青鸟…

Java的Comparator排序(升序降序)理解

Java的Comparator排序(升序降序)理解 int compare(T o1, T o2);   这里o1表示位于前面的对象,o2表示后面的对象 返回-1(或负数),表示不需要交换01和02的位置,o1排在o2前面,asc 返…

sqlserver发布订阅无法初始化快照_SQLServer2008R2 发布订阅及相关问题解决办法

前言:前两天接到领导的任务,将一个系统A的客户数据同步到另一个系统B中,以后客户录入入口只有A系统,B系统不提供录入入口,因为各种原因不能使用接口方式A系统和B系统直接交互同步,只能通过数据库重A库同步到…

JAVA中基本类型Boolean占几个字节

今天在整理JAVA基础知识时发现几大基本数据类型的封装类都有其BYTES值,也就是位数,除了Boolean。特意查了下资料,发现有几大说法,如下: 1.单个的boolean 类型变量在编译的时候是使用的int 类型。 boolean atrue;//这个a在JVM中占4个字节即:32位。 2.bo…

怎么在linux上修改mysql端口映射_如何在Linux中更改默认的MySQL / MariaDB端口

在本指南中,我们将学习如何更改MySQL / MariaDB数据库在CentOS 7和基于Debian的Linux发行版中绑定的默认端口。 MySQL数据库服务器在Linux和Unix下运行的默认端口是3306 / TCP 。为了在Linux中更改默认的MySQL / MariaDB数据库端口,请通过执行以下命令打…

java 泛型的上限与下限、泛型通配符、泛型上下限

java 泛型的上限与下限 设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类&#xff1a; 声明对象&#xff1a;类名<? extends 类> 对象名 定义类&#xff1a;类名<泛型标签 extends 类>{} 设置泛型对象的下限使用super,表示参数类型只能是…

hashmap为什么线程不安全_StringBuilder为什么线程不安全?

点击上方“Java知音”&#xff0c;选择“置顶公众号”技术文章第一时间送达&#xff01;作者&#xff1a;千山juejin.im/post/5d6228046fb9a06add4e37fe引言面试官&#xff1a;StringBuilder和StringBuffer的区别在哪&#xff1f;我&#xff1a;StringBuilder不是线程安全的&am…

java中的重量级与轻量级概念

首先轻量级与重量级是一个相对的概念&#xff0c;主要是对应用框架使用方便性和所提供服务特性等方面做比较的。 比方说EJB就是一个重量级的框架&#xff0c;因为它对所编写的代码有限制&#xff0c;同时它也提供分布式等复杂的功能。 相比之下&#xff0c;Spring就是轻量级框架…

java中持久化是什么意思?

什么是持久化&#xff1f; 要想说明这个名词&#xff0c;还要从上世纪70年代说起&#xff0c;数据库技术兴起&#xff0c;这时的软件结构发展为双层结构。在双层结构中实现了的数据存放与应用程序分离&#xff0c;构成了现代软件模型的雏形。但是&#xff0c;随着软件体量越来越…

mysql主从报错_Mysql主从报错锦集

前言在发生故障切换后&#xff0c;经常遇到的问题就是同步报错&#xff0c;下面是最近收集的报错信息。记录删除失败在master上删除一条记录&#xff0c;而slave上找不到Last_SQL_Error: Could not execute Delete_rows event on table hcy.t1;Cant find record in t1,Error_co…

JAVA中的那些名词解释

1.JDO: (Java Data Object )是Java对象持久化的新的规范&#xff0c;也是一个用于存取某种数据仓库中的对象的标准化API.作用:用于存取某种数据仓库中的对象 2.JPA: JPA是Java Persistence API的简称&#xff0c;中文名Java持久层API&#xff0c;是JDK 5.0注解或XML描述对象&a…

mysql资质_MySQL语句与Java代码实现按需过滤企业员工的资质证书

在企业ERP中&#xff0c;每位员工拥有多个资质证书&#xff0c;资质证书有种类、名称和登记时间&#xff0c;以及变动时间和结束时间的主要属性&#xff1b;现在有一个需求&#xff0c;员工在系统查看自己的信息之时&#xff1a;同一种类、同一名称、同一登记时间的资质证书&am…

java对象的序列化和反序列化详细解释

java对象的序列化和反序列化是什么意思 1、序列化是干啥用的&#xff1f; 序列化的原本意图是希望对一个Java对象作一下“变换”&#xff0c;变成字节序列&#xff0c;这样一来方便持久化存储到磁盘&#xff0c;避免程序运行结束后对象就从内存里消失&#xff0c;另外变换成字…

oracle to mysql demo_oracle to mysql

http://blog.csdn.net/hwhua1986/article/details/53257427oracle到mysql的迁移步骤及各种注意事项http://www.2cto.com/database/201305/210248.htmlhttp://www.cnblogs.com/HondaHsu/p/3641116.htmlhttp://www.cnblogs.com/HondaHsu/p/3641183.htmlhttp://www.cnblogs.com/Ho…

IDEA快捷键调整字体大小 设置 (Ctrl+滚轮) 调整字体大小

IDEA设置Ctrl滚轮调整字体大小 第一步&#xff1a;打开idea 设置界面&#xff1a; 第二步&#xff1a;勾选上下图中红色部分即可实现 保存后&#xff0c;ctrl滚轮就能改变代码字体大小

mysql5.7主从全备恢复_mysql主从,或者全备份

mysql的主从复制依赖bin-log日志&#xff0c;会因为各种问题中断&#xff0c;如flush table&#xff0c;网络问题等&#xff0c;还有一些未知的bug因素&#xff0c;之前使用mysql import方式恢复速度太慢&#xff0c;一个3G的库要恢复一个下午&#xff0c;实在是无法忍受。现在…

IDEA中三种注释方式的快捷键

三种注释方式 单行注释、多行注释、方法或类说明注释&#xff08;文档注释&#xff09;。 单行注释 快捷键&#xff1a;Ctrl /   使用Ctrl /&#xff0c; 添加单行注释&#xff0c;再次使用&#xff0c;去掉行注释    多行注释 快捷键&#xff1a;Ctrl Shift /   使用…

lombok @Accessors用法详解(一看就能懂)

Accessors(chaintrue) 链式访问&#xff0c;该注解设置chaintrue&#xff0c;生成setter方法返回this&#xff08;也就是返回的是对象&#xff09;&#xff0c;代替了默认的返回void。 package com.pollyduan;import lombok.Data; import lombok.experimental.Accessors;Data …

随机森林特征重要性计算_R语言随机森林模型中具有相关特征的变量重要性

原文链接&#xff1a;http://tecdat.cn/?p13546​tecdat.cn变量重要性图是查看模型中哪些变量有趣的好工具。由于我们通常在随机森林中使用它&#xff0c;因此它看起来非常适合非常大的数据集。大型数据集的问题在于许多特征是“相关的”&#xff0c;在这种情况下&#xff0c;…