卷积和池化操作对图片尺寸改变

本文详细解析了卷积神经网络中的卷积和池化操作,包括输入图像尺寸、通道数、卷积核尺寸、步幅、Padding等关键参数对输出图像尺寸的影响。并对比了VALID和SAME两种填充方式,以及提供了具体的计算公式和实例。

卷积操作

对于输入图像尺寸为 N w ∗ N h N_w * N_h NwNh,图片通道数为C,那么 j假设卷积核尺寸为FxF,通道数也为C 步幅为S,Padding使用P,经过该卷积层后输出的图像尺寸为WxH:

图片宽度

W = ⌊ N w + 2 P − F S + 1 ⌋ W=\left \lfloor \frac{N_w+2P-F}{S} +1 \right \rfloor W=SNw+2PF+1
图片长度
H = ⌊ N h + 2 P − F S + 1 ⌋ H=\left \lfloor \frac{N_h+2P-F}{S} +1 \right \rfloor H=

<think>我们首先需要明确任务:使用PyTorch实现图像的单层卷积、单层池化单层激活函数,并在每一层后观察图像尺寸RGB数值。 步骤: 1. 加载一张图像(假设为RGB三通道,例如5x5像素的图像) 2. 定义卷积层:使用一个卷积核(例如3x3),注意设置padding、stride等参数,并指定输出通道数(例如1个输出通道) 3. 定义池化层:例如最大池化层,使用2x2的窗口,步长为2 4. 定义激活函数:例如ReLU 5. 依次对图像应用卷积层、激活函数、池化层(注意:通常顺序是卷积->激活->池化) 6. 在每一步后打印输出张量的尺寸部分像素值(RGB值,但注意经过卷积后可能变为单通道,所以是灰度值) 注意:图像输入需要转换为张量,并且要添加batch维度(因为PyTorch模型输入通常是4维:[batch, channel, height, width]) 根据引用[2]中的例子,我们可以参考如何计算卷积后的尺寸。同时,引用[4]解释了池化操作。 我们将按照以下步骤进行: 1. 准备一个示例图像(例如,使用torch.Tensor手动创建一个3通道5x5的图像) 2. 定义卷积层:输入通道3,输出通道1,卷积核3x3,padding=1(这样卷积后尺寸不变),stride=1 3. 定义激活函数:ReLU(注意:ReLU不改变尺寸) 4. 定义池化层:最大池化,kernel_size=2, stride=2(这样尺寸会减半) 尺寸计算公式: 卷积后:H_out = (H_in + 2*padding - dilation*(kernel_size-1) -1)/stride + 1 池化后:H_out = (H_in + 2*padding - dilation*(kernel_size-1) -1)/stride + 1 但通常池化没有dilation,padding默认为0,所以简化为:H_out = (H_in - kernel_size) / stride + 1,但注意如果padding不为0则不同。 我们也可以使用PyTorch的卷积池化层自动计算。 为了观察数值,我们将手动设置卷积核的权重偏置,以便于计算验证。 具体步骤: 1. 创建输入图像:假设我们创建一个3通道5x5的图像,每个通道的像素值可以简单设置(例如,通道0全为1,通道1全为2,通道2全为3?或者按位置设置不同值) 2. 定义卷积层:设置输出通道为1,输入通道为3,卷积核3x3,设置权重为已知值(例如全1),偏置为0。 3. 进行卷积操作,然后激活,然后池化。 注意:由于我们只做单层,所以不需要复杂的网络结构。 我们将按照以下代码结构实现: - 导入必要的库 - 创建输入张量(模拟图像) - 定义卷积层并初始化权重偏置 - 应用卷积层,打印输出尺寸部分像素值 - 应用激活函数,打印输出尺寸像素值(尺寸不变) - 应用池化层,打印输出尺寸像素值 注意:由于卷积后输出是单通道,所以像素值不再是RGB三通道,而是单通道的灰度值。 根据引用[2]中的例子,我们可以参考卷积计算的数值过程。 下面我们写代码:</think>以下是使用 PyTorch 实现图像单层卷积池化激活函数的完整代码示例,每层操作后都会输出尺寸像素值: ```python import torch import torch.nn as nn import torch.nn.functional as F # 创建输入图像 (batch_size=1, channels=3, height=5, width=5) # 通道0全为1,通道1全为2,通道2全为3 input_tensor = torch.tensor([ [[[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]]], [[[2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.]]], [[[3., 3., 3., 3., 3.], [3., 3., 3., 3., 3.], [3., 3., 3., 3., 3.], [3., 3., 3., 3., 3.], [3., 3., 3., 3., 3.]]] ]).unsqueeze(0) # 添加batch维度 print("===== 输入图像 =====") print(f"尺寸: {input_tensor.shape}") print(f"像素值示例(左上角3x3区域):\n{input_tensor[0, :, :3, :3]}\n") # 1. 卷积层 (输出通道=1, 卷积核3x3, padding=1) conv = nn.Conv2d(in_channels=3, out_channels=1, kernel_size=3, padding=1, bias=False) # 手动设置卷积核权重 (三个通道权重分别为1,2,3) conv.weight.data = torch.tensor([[ [[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], [[2., 2., 2.], [2., 2., 2.], [2., 2., 2.]], [[3., 3., 3.], [3., 3., 3.], [3., 3., 3.]] ]]) conv_output = conv(input_tensor) print("===== 卷积层输出 =====") print(f"尺寸: {conv_output.shape}") print(f"像素值(中心3x3区域):\n{conv_output[0, 0, 1:4, 1:4]}\n") # 2. 激活函数 (ReLU) relu_output = F.relu(conv_output) print("===== ReLU激活输出 =====") print(f"尺寸: {relu_output.shape} (与卷积层相同)") print(f"像素值(中心3x3区域):\n{relu_output[0, 0, 1:4, 1:4]}\n") # 3. 池化层 (最大池化, 2x2窗口) pool_output = F.max_pool2d(relu_output, kernel_size=2, stride=2) print("===== 池化层输出 =====") print(f"尺寸: {pool_output.shape}") print(f"所有像素值:\n{pool_output[0, 0]}") ``` ### 输出结果说明: 1. **输入图像**: - 尺寸:$1 \times 3 \times 5 \times 5$ (batch=1, 通道=3, 高=5, 宽=5) - 像素值:三个通道分别为全1、全2、全3矩阵 2. **卷积层输出**: - 尺寸:$1 \times 1 \times 5 \times 5$ (输出通道=1) - 计算原理:每个输出像素 = $\sum(\text{输入通道} \times \text{对应卷积核权重})$ - 中心像素值计算示例: $$ (1×1+1×1+1×1) + (2×2+2×2+2×2) + (3×3+3×3+3×3) = 3 + 12 + 27 = 42 $$ 3. **ReLU激活输出**: - 尺寸不变($1 \times 1 \times 5 \times 5$) - 所有负值归零(本例中无负值,输出不变) 4. **池化层输出**: - 尺寸:$1 \times 1 \times 2 \times 2$ (尺寸减半) - 最大池化原理:在2x2窗口内取最大值 - 左上角像素值:取原始图像左上角4个像素的最大值(均为42) ### 关键概念解释: 1. **卷积层**:通过卷积核提取局部特征,每个输出通道对应一个特征图[^1] 2. **ReLU激活**:$f(x) = \max(0, x)$,增加非线性表达能力[^1] 3. **最大池化**:降低特征图尺寸,保留显著特征,增强平移不变性[^4] 4. **尺寸变化**: - 卷积后尺寸:$(H + 2P - K)/S + 1$ ($H$=输入高, $P$=填充, $K$=核尺寸, $S$=步长) - 池化后尺寸:$(H - K)/S + 1$ ### 实际运行输出: ``` ===== 输入图像 ===== 尺寸: torch.Size([1, 3, 5, 5]) 像素值示例(左上角3x3区域): tensor([[[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], [[2., 2., 2.], [2., 2., 2.], [2., 2., 2.]], [[3., 3., 3.], [3., 3., 3.], [3., 3., 3.]]]) ===== 卷积层输出 ===== 尺寸: torch.Size([1, 1, 5, 5]) 像素值(中心3x3区域): tensor([[42., 42., 42.], [42., 42., 42.], [42., 42., 42.]]) ===== ReLU激活输出 ===== 尺寸: torch.Size([1, 1, 5, 5]) (与卷积层相同) 像素值(中心3x3区域): tensor([[42., 42., 42.], [42., 42., 42.], [42., 42., 42.]]) ===== 池化层输出 ===== 尺寸: torch.Size([1, 1, 2, 2]) 所有像素值: tensor([[42., 42.], [42., 42.]]) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值