当前位置:   article > 正文

26-27 逐行实现二维空洞卷积dilation与群卷积groups_dilation卷积

dilation卷积

1. Dilation

Dilation 的作用是对卷积核进行扩充;默认dilation=1不扩充,dilation>1 表示卷积核内两两行两两列之间填充dilation-1个0;如下图所示:
在这里插入图片描述
在这里插入图片描述

2. Groups

groups的作用是将输入和输出通道进行分组,避免所有的通道都进行融合,而是以组为单位进行融合,可以大大的减少训练参数;
在这里插入图片描述

  • groups=1时的操作:
    在这里插入图片描述
  • groups=2时的操作:
    在这里插入图片描述

3. 撸代码

import torch
from torch.nn import functional as F
import math


# input  = (bs,groups,                      in_channel//groups,  input_h,   input_w)
# kernel =    (groups,out_channel//groups,  in_channel//groups,  kernel_h,  kernel_w)
# Output1 = input * kernel
# Output1 = (bs,groups,out_channel//groups,output_h,output_w)
# Output2 = (bs,out_channel,output_h,output_w)


# 自定义卷积操作,
def matrix_multiplication_for_conv2d_final(input, kernel, bias=None, stride=1, padding=0, dilation=1, groups=1):
	# 如果有填充,就需要在卷积核的上下作用进行填充padding,pytorch中的pad函数是从里到外的,注意顺序
	if padding > 0:
		# input.shape = torch.Size((batch_size,in_channel,input_h,input_w))
		input = F.pad(input, (padding, padding, padding, padding, 0, 0, 0, 0))
	# 获取输入input相关参数
	bs, in_channel, input_h, input_w = input.shape
	# 获取相关卷积核参数
	out_channel, m, kernel_h, kernel_w = kernel.shape
	# reshape input and kernel
	assert out_channel % groups == 0 and in_channel % groups == 0, "groups必须同时被输入通道数和输出通道数整除"
	# 将input进行分组
	# before: (bs,in_channel,input_h,input_w)
	#  after: (bs,groups,in_channel//groups,input_h,input_w)

	input = input.reshape((bs, groups, in_channel // groups, input_h, input_w))
	# before: kernel.shape = (out_channel,in_channel//groups,kernel_h,kernel_w)
	# after : kernel.shape = (groups,out_channel//groups,in_channel//groups,kernel_h,kernel_w)
	kernel = kernel.reshape((groups, out_channel // groups, in_channel // groups, kernel_h, kernel_w))

	# 得到扩张后的卷积核大小 kernel_h,kernel_w
	kernel_h = (kernel_h - 1) * (dilation - 1) + kernel_h
	kernel_w = (kernel_w - 1) * (dilation - 1) + kernel_w

	# 得到输出卷积的大小 output_h and output_w
	output_h = math.floor((input_h - kernel_h) / stride) + 1
	output_w = math.floor((input_w - kernel_w) / stride) + 1

	# 为了计算,需要将output添加一个groups维度
	output_shape = (bs, groups, out_channel // groups, output_h, output_w)
	output = torch.zeros(output_shape)
	if bias is None:
		bias = torch.zeros(out_channel)
	for ind in range(bs):  # 对batch_size进行遍历
		for g in range(groups):  # 对群组进行遍历
			for oc in range(out_channel // groups):  # 对分组后的输出通道进行遍历
				for ic in range(in_channel // groups):  # 对分组后的输入通道进行遍历
					for i in range(0, input_h - kernel_h + 1, stride):  # 对高度进行遍历
						for j in range(0, input_w - kernel_w + 1, stride):  # 对宽度进行遍历
							# input_shape = [bs,groups,in_channel//groups,input_h,input_w]
							region = input[ind, g, ic, i:i + kernel_h:dilation, j:j + kernel_w:dilation]  # 特征区域
							# kernel_shape = [groups,out_channel//groups,in_channel//groups,kernel_h,kernel_w]
							# output_shape = [bs,groups,out_channel//groups,output_h,output_w]
							output[ind, g, oc, int(i / stride), int(j / stride)] += torch.sum(
								region * kernel[g, oc, ic])
				output[ind, g, oc] += bias[g * (out_channel // groups) + oc]  # 考虑偏置
	# (bs,groups,out_channel//groups,output_h,output_w) -> (bs,out_channel,output_h,output_w)
	output = output.reshape((bs, out_channel, output_h, output_w))  # 还原成四维

	return output


kernel_size = 3
bs, in_channel, input_h, input_w = 2, 2, 5, 5
out_channel = 4
groups, dilation, stride, padding = 2, 2, 2, 1

input = torch.randn((bs, in_channel, input_h, input_w))
kernel = torch.randn(out_channel, in_channel // groups, kernel_size, kernel_size)
bias = torch.randn(out_channel)

pytorch_conv2d_api_ouput = F.conv2d(input, kernel, bias=bias, padding=padding, stride=stride, dilation=dilation,
									groups=groups)
mm_conv2d_final_output = matrix_multiplication_for_conv2d_final(input, kernel, bias=bias, padding=padding,
																stride=stride, dilation=dilation, groups=groups)

# 验证手写的卷积操作跟pytorch自带的卷积操作结果是否一致
flag = torch.allclose(pytorch_conv2d_api_ouput, mm_conv2d_final_output)
# 如果flag=True表示计算结果与pytorch官网结果一致
print(f"flag={flag}")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 结果:
flag=True
  • 1

4. 小结

groups可以减少操作,将in_channel和out_channel进行分组后,每组之间进行通道融合

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/346269
推荐阅读
相关标签
  

闽ICP备14008679号