(C3)卷积层特点及torch.nn.Conv2d()

卷积层

一、常规卷积

参考资料
卷积神经网络之卷积层中的多输入多输出通道
卷积中参数量和计算量
有图文讲解,更通俗易懂。

在这里插入图片描述

1.1 特点

1、每一个输入通道都有一个卷积核,输出的通道结果是所有输入通道和对应卷积核作用后结果的和
2、1×1的卷积核用于融合通道数据
在这里插入图片描述

1.2 参数量 和 计算量

直接截图记录

参数量

计算量

注:浮点运算量 FLOPs 和计算量不同,需要时再仔细查。


二、分组卷积

分组卷积(Group conv)与深度可分离卷积(Depthwise separable conv)

在这里插入图片描述
在这里插入图片描述


三、可分离卷积

空间可分离卷积(Spatially Separable Convolutions):不知道哪里提出来的

深度可分离卷积(depthwise separable convolution):逐深度卷积(Depthwise Convolution)、逐点卷积(Pointwise Convolution)。

这个感觉上更常用

3.1 逐深度卷积(Depthwise Convolution)

在这里插入图片描述

Depthwise Convolution完成后的Feature map数量与输入层的depth相同,但是这种运算对输入层的每个channel独立进行卷积运算后就结束了,没有有效的利用不同map在相同空间位置上的信息。因此需要增加另外一步操作来将这些map进行组合生成新的Feature map,即接下来的Pointwise Convolution。

3.2 逐点卷积(Pointwise Convolution)

在这里插入图片描述

在这里插入图片描述
Dk:卷积核大小

M:输入尺寸

N:输出尺寸

3.3 代码实现 ⭐

参考资料
可分离卷积及深度可分离卷积详解

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')

在这里插入图片描述

``` import torch import torch.nn as nn from skimage.segmentation import chan_vese import numpy as np from torch.nn import Conv2d from torchvision.ops import FeaturePyramidNetwork from torchvision.models import resnet50 import os os.environ['KMP_DUPLICATE_LIB_OK']='TRUE' class ImageSegmentationModel(nn.Module): def __init__(self): super(ImageSegmentationModel,self).__init__() self.conv_layers = nn.Sequential( nn.Conv2d(1,128,kernel_size=3,stride=2), nn.MaxPool2d(kernel_size=3,stride=2), nn.ReLU(), nn.Conv2d(128,64, kernel_size=3, stride=2), nn.MaxPool2d(kernel_size=3, stride=2), nn.ReLU(), nn.Conv2d(64,32,kernel_size=3,stride=2), nn.MaxPool2d(kernel_size=3,stride=2), nn.ReLU(), nn.Conv2d(32,16,kernel_size=3,stride=2) ) #使用resnet作为特征提取器 self.resnet = resnet50(pretrained=True) self.initial_layer = nn.Sequential( self.resnet.conv1, # 输出通道64 self.resnet.bn1, self.resnet.relu, self.resnet.maxpool # 输出通道64 ) self.layer1 = self.resnet.layer1 # 输出256通道 self.layer2 = self.resnet.layer2 # 输出512通道 self.layer3 = self.resnet.layer3 # 输出1024通道 self.layer4 = self.resnet.layer4 # 输出2048通道 #修改,调整fpn输入通道 self.fpn = FeaturePyramidNetwork([256,512,1024,2048],256) self.conv_layers11 = nn.Conv2d(256,1,kernel_size=1,stride=1) self.final_conv = nn.Conv2d(16,21,kernel_size=1,stride=1) self.softmax = nn.Softmax(dim=1) def preprocess(self,x): #将输入图像尺寸调整为511×511,使用双线性插值法 x = torch.nn.functional.interpolate(x,size=(511,511),mode='bilinear',align_corners=False) #将输入图像转换为灰度图像,通过对通道维度求均值 x = torch.mean(x,dim=1,keepdim=True) x_np = x.detach().cpu().numpy() segmented = [] for i in range(x_np.shape[0]): img = x_np[i,0] #init =np.array([[img.shape[1]-1,0],[img.shape[1]-1,img.shape[0]-1],[0,img.shape[0]-1,],[0,0]]) snake = chan_vese(img,mu=0.25, lambda1=1.0, lambda2=1.0, tol=0.001, max_num_iter=500, dt=0.5) seg = np.zeros_like(img) from skimage.draw import polygon rr, cc = polygon(snake[:,1],snake[:,0],seg.shape) seg[rr, cc] = 1 segmented.append(seg) segmented = np.array(segmented) segmented = torch.from_numpy(segmented).unsqueeze(1).float().to(x.device) return segmented def forward(self,x): y = torch.nn.functional.interpolate(x,size=(511,511),mode='bilinear',align_corners=False) x = self.preprocess(x) conv_output = self.conv_layers(x) conv_output[0,:,:,:] = 16 print("conv_output:", conv_output.shape) z = self.initial_layer(y) c1 = self.layer1(z) # [batch,256,H,W] c2 = self.layer2(c1) # [batch,512,H,W] c3 = self.layer3(c2) # [batch,1024,H,W] c4 = self.layer4(c3) # [batch,2048,H,W] fpn_input = { 'feat1': c1, 'feat2': c2, 'feat3': c3, 'feat4': c4 } fpn_output = self.fpn(fpn_input) fpn_output_upsampled = torch.nn.functional.interpolate(fpn_output['feat1'], size=(511, 511), mode='bilinear', align_corners=False) final_output = nn.functional.conv2d(fpn_output_upsampled,conv_output,stride=1,padding=1,groups=16) final_output = self.final_conv(final_output) final_output = self.softmax(final_output) return final_output```目前conv_output的shape为[batch_size=64,16,3,3],我想让这之后的conv_output变为4个shape为[16,16,3,3]进行之后的操作
最新发布
03-20
``` import torch import torch.nn as nn from skimage.segmentation import active_contour import numpy as np from torchvision.ops import FeaturePyramidNetwork from torchvision.models import resnet50 import os os.environ['KMP_DUPLICATE_LIB_OK']='TRUE' class ImageSegmentationModel(nn.Module): def __init__(self): super(ImageSegmentationModel,self).__init__() self.conv_layers = nn.Sequential( nn.Conv2d(1,1,kernel_size=3,stride=2), nn.MaxPool2d(kernel_size=3,stride=2), nn.ReLU(), nn.Conv2d(1, 1, kernel_size=3, stride=2), nn.MaxPool2d(kernel_size=3, stride=2), nn.ReLU(),nn.Conv2d(1,1,kernel_size=3,stride=2), nn.MaxPool2d(kernel_size=3,stride=2), nn.ReLU(), nn.Conv2d(1,1,kernel_size=3,stride=2) ) #使用resnet作为特征提取器 self.resnet = resnet50(pretrained=True) #移除resnet最后一层全连接层 self.resnet = nn.Sequential(*list(self.resnet.children())[:-2]) #修改,调整fpn输入通道 self.fpn = FeaturePyramidNetwork([256,512,1024,2048],256) def preprocess(self,x): #将输入图像尺寸调整为511×511,使用双线性插值法 x = torch.nn.functional.interpolate(x,size=(511,511),mode='bilinear',align_corners=False) #将输入图像转换为灰度图像,通过对通道维度求均值 x = torch.mean(x,dim=1,keepdim=True) #将张量转换为numpy数组,以便使用skimage库进行处理 x_np = x.detach().cpu().numpy() segmented = [] #对每个样本进行chan—vese分割 for i in range(x_np.shape[0]): img = x_np[i,0] #初始化活动轮廓的点 init =np.array([[img.shape[1]-1,0],[img.shape[1]-1,img.shape[0]-1],[0,img.shape[0]-1,],[0,0]]) #使用c-v函数进行分割 snake = active_contour(img,init,alpha=0.015,beta=10,gamma=0.001) #初始化分割结果矩阵 seg = np.zeros_like(img) from skimage.draw import polygon #绘制多边形区域(有无绘制必要?) rr, cc = polygon(snake[:,1],snake[:,0],seg.shape) #将多边形区域标记为1 seg[rr, cc] = 1 segmented.append(seg) #将分割结果转换为numpy数组 segmented = np.array(segmented) #将数组转换为张量,并添加通道维度 segmented = torch.from_numpy(segmented).unsqueeze(1).float().to(x.device) return segmented def forward(self,x): y = torch.nn.functional.interpolate(x,size=(511,511),mode='bilinear',align_corners=False) #对输入图像进行预处理 x = self.preprocess(x) #通过卷积层序列进行特征提取 conv_output = self.conv_layers(x) #通过resnet50提取特征 resnet_features = self.resnet(y) #构建fpn输入特征字典 fpn_input = { 'feat1': resnet_features[0], 'feat2': resnet_features[1], 'feat3': resnet_features[2], 'feat4': resnet_features[3] } #通过fpn网络 fpn_output = self.fpn(fpn_input) #最终卷积操作 fpn_output_upsampled = torch.nn.functional.interpolate(fpn_output['feat1'], size=(511, 511), mode='bilinear', align_corners=False) final_output = nn.functional.conv2d(fpn_output_upsampled,conv_output,stride=1,paddong=0) return final_output```运行上述代码时发生报错:RuntimeError: Given groups=1, weight of size [256, 1024, 1, 1], expected input[1, 2048, 16, 16] to have 1024 channels, but got 2048 channels instead。该怎么解决?
03-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值