PyTorch学习之torch.nn.functional.conv2d函数
一、简介
torch.nn.functional.conv2d
是 PyTorch 中用于进行二维卷积操作的函数。卷积操作是深度学习中卷积神经网络(CNN)的核心部分,用于提取图像特征,常见于图像分类、目标检测和语义分割等任务中。
二、基本语法
torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1)
三、参数说明
input
(Tensor): 输入张量,形状为(N, C_in, H, W)
,其中N
是批量大小,C_in
是输入通道数,H
是高度,W
是宽度。weight
(Tensor): 卷积核权重,形状为(C_out, C_in // groups, kH, kW)
,其中C_out
是输出通道数,kH
是卷积核高度,kW
是卷积核宽度。bias
(Tensor, 可选): 偏置,形状为(C_out)
。如果为None
,则不添加偏置。stride
(int 或 tuple, 可选): 卷积步长,默认值为1
。padding
(int 或 tuple, 可选): 输入的每一边填充的大小,默认值为0
。dilation
(int 或 tuple, 可选): 卷积核元素之间的间距,默认值为1
。groups
(int, 可选): 将输入分组,默认值为1
。groups
的值大于1
时,相当于对输入进行组卷积。- 默认是1是因为我们一般对图像的卷积是将图像的RGB通道卷积后合并。
- 如果你卷积后不想合并通道,即卷积后仍然是彩色图像,groups应该设置为3
四、返回值
返回一个张量,形状为 (N, C_out, H_out, W_out)
,表示卷积后的输出。
五、示例
示例 1: 基本卷积操作
import torch
import torch.nn.functional as F# 创建一个形状为 (1, 1, 5, 5) 的输入张量
input = torch.tensor([[[[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]]]], dtype=torch.float32)# 创建一个形状为 (1, 1, 3, 3) 的卷积核
weight = torch.tensor([[[[1, 0, -1],[1, 0, -1],[1, 0, -1]]]], dtype=torch.float32)# 执行卷积操作
output = F.conv2d(input, weight)print("卷积后的输出:\n", output)
输出:
卷积后的输出:tensor([[[[-6., -6., -6.],[-6., -6., -6.],[-6., -6., -6.]]]])
示例 2: 添加偏置、设置步长和填充
import torch
import torch.nn.functional as F# 创建一个形状为 (1, 1, 5, 5) 的输入张量
input = torch.tensor([[[[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]]]], dtype=torch.float32)# 创建一个形状为 (1, 1, 3, 3) 的卷积核
weight = torch.tensor([[[[1, 0, -1],[1, 0, -1],[1, 0, -1]]]], dtype=torch.float32)# 添加偏置
bias = torch.tensor([1], dtype=torch.float32)# 设置步长和填充
stride = 2
padding = 1# 执行卷积操作
output = F.conv2d(input, weight, bias=bias, stride=stride, padding=padding)print("卷积后的输出:\n", output)
输出:
卷积后的输出:tensor([[[[ -8., -3., 14.],[-35., -5., 43.],[-38., -3., 44.]]]])
示例3 真实图像卷积
import torch
import torch.nn.functional as F
import cv2
import numpy as np# 读取图像,读者应该修改图片路径
input_image = cv2.imread('2015.jpg')# 创建一个形状为 (3, 1, 3, 3) 的卷积核
conv_kernel = torch.tensor([[[[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]],[[[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]],[[[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]]], dtype=torch.float32)print(conv_kernel.shape) # 应输出 (3, 1, 3, 3)# 将图像转换为 tensor 并调整形状
input_tensor = torch.tensor(input_image, dtype=torch.float32)
input_tensor = torch.unsqueeze(input_tensor, 0) # 变为 (1, 高, 宽, 通道)
input_tensor = torch.permute(input_tensor, (0, 3, 1, 2)) # 变为 (1, 通道, 高, 宽)
print(input_tensor.shape) # 应输出 (1, 3, 高, 宽)# 执行卷积操作
conv_output = F.conv2d(input_tensor, conv_kernel, groups=3)
print(conv_output.shape) # 应输出 (1, 3, 高, 宽)# 调整输出形状并裁剪到 0-255 范围
output_image = torch.permute(conv_output, (0, 2, 3, 1)) # 变为 (1, 高, 宽, 通道)
output_image = output_image.squeeze() # 变为 (高, 宽, 通道)
output_image = torch.clamp(output_image, 0, 255) # 裁剪到 0-255 范围
cv2.imshow('Convolved Image', output_image.numpy().astype(np.uint8))
cv2.waitKey()
cv2.destroyAllWindows()