Padding\Valid convolutions\Same convolutions

本文探讨了卷积神经网络中Padding的概念及其作用,详细解释了如何通过填充边缘像素来避免图像尺寸减小和边缘信息丢失的问题。文章介绍了Valid和Same卷积的区别,并讨论了选择奇数滤波器大小的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整理并翻译自吴恩达深度学习系列视频:卷积神经网络1.4。

Padding

在这里插入图片描述
在对一张6X6图片进行卷积后,它变成了一张4X4的图片。直接卷积有以下2个缺点:

  • Shrinking the output(缩小输出图像大小)
  • Throw away info from edge(相对于中间经过多次卷积计算的部分,图像边缘信息被抛弃了)

为了解决这一点问题,我们可以在图像的边缘填充(padding)0,来使得边缘部分也能够被经过多次卷积计算。

假设原图是n×nn\times nn×n,filter是f×ff\times ff×f,那么卷积后的图像大小是(n−f+1)×(n−f+1)(n-f+1)\times(n-f+1)(nf+1)×(nf+1)

假设填充p=1p=1p=1,填充之后再卷积得到的图像大小是(n+2p−f+1)×(n+2p−f+1)(n+2p-f+1)\times(n+2p-f+1)(n+2pf+1)×(n+2pf+1)

如果要维持原图大小,令(n+2p−f+1)=n(n+2p-f+1)=n(n+2pf+1)=n,得p=f−12p=\frac{f-1}{2}p=2f1

Valid convolutions\Same convolutions

在这里插入图片描述

Valid convolution,即不填充,卷积后的图像大小是(n−f+1)×(n−f+1)(n-f+1)\times(n-f+1)(nf+1)×(nf+1)

Same convolution,即填充使其保持原图大小,选择p=f−12p=\frac{f-1}{2}p=2f1

通过上式你也能够理解,为什么通过选fff是奇数,如果fff是偶数,也能达到我们的目的,但填充使得图像不对称了,左边填的比右边多或者反过来。选择fff奇为数也可以使得filter有明确的中心点。

当然这些理由并没有那么的有说服力。

3X3、7X7、9X9,都是论文里常见的filter大小。

<think>好的,我现在需要解决用户在使用strided convolutions时,当设置padding='same'出现的ValueError问题。用户提到了TensorFlow或PyTorch,所以我需要考虑这两个框架的可能情况。 首先,我得回忆一下在卷积层中padding='same'的作用。它通常是为了保持输出尺寸与输入尺寸相同,特别是在步长(stride)为1的情况下。但当步长大于1时,输出尺寸的计算可能会有不同的结果,这时候可能会引发问题。例如,当输入尺寸不能被步长整除时,padding的计算可能会有小数,导致错误。 接下来,我应该考虑可能的错误原因。用户遇到的ValueError可能和输入数据的形状有关。例如,在TensorFlow中,如果输入的高度或宽度加上padding后无法被步长整除,可能会导致输出形状无法确定,从而报错。或者,可能是在使用某些层时参数配置不正确,比如卷积核大小、步长和输入尺寸的组合不合适。 在TensorFlow中,比如使用Conv2D层,当stride>1时,padding='same'的输出尺寸计算是ceil(input_size / stride),这需要输入尺寸加上padding后满足这个条件。如果输入尺寸本身不符合,就可能出错。例如,输入尺寸为32x32,步长为3,此时输出尺寸应为11(因为32/3≈10.666,向上取整为11)。这时候需要的总padding是 (11*3 - 32 + filter_size -1)/2。假设filter_size是3,那么总padding为 (33 -32 +2)/2 = 3/2=1.5,但padding必须是整数,所以这时候TensorFlow可能会报错,因为无法均匀地添加padding。 同样在PyTorch中,使用Conv2d时,padding参数需要是整数,当使用padding='same'时(PyTorch的F.pad可能有不同的处理方式),或者用户手动计算padding时,如果计算出的padding非整数,也会导致错误。 所以,解决方案可能包括: 1. 检查输入尺寸是否与步长和卷积核大小兼容。例如,输入尺寸是否能被步长整除,或者在加上padding后是否能满足条件。 2. 调整输入尺寸,使其满足特定条件,比如让输入的长宽是步长的整数倍,或者在构建网络时使用合适的padding值。 3. 手动计算padding,并设置为整数,而不是依赖框架的'same'模式,特别是在步长较大的情况下。 比如,在TensorFlow中,如果输入尺寸是HxW,卷积核大小K,步长S,那么padding='same'时,输出尺寸为ceil(H/S)。所需的总padding为:max( (ceil(H/S) -1)*S + K - H , 0 ),然后分成左右或上下两边。但如果这个总padding是奇数,TensorFlow会自动分配,比如左边1,右边2。但如果某些情况下这仍然导致问题,可能需要手动调整输入尺寸。 或者,可能用户在使用某些自定义层或特定版本的框架时,存在已知的bug。例如,旧版本的TensorFlow可能在处理某些padding情况时出现错误,而更新版本可能已经修复。 另外,用户提到的错误信息可能与依赖库版本有关,比如引用中提到的tensorflow-gpu-1.15.0的依赖问题。可能用户的环境存在版本冲突,导致某些功能异常。比如,如果用户安装的numpy或其他库版本不兼容,可能引发意外的错误。需要检查是否安装了正确的依赖版本,如引用[^2]中提到的numpy==1.16.1等。 所以,可能的解决步骤包括: 1. 检查输入数据的形状是否符合要求,特别是高度和宽度是否能与步长和卷积核大小配合。 2. 确保使用的框架版本正确,没有已知的padding相关bug。 3. 如果自动padding不可行,手动计算所需的padding值并明确设置。 4. 调整输入尺寸,例如通过填充或裁剪,使其满足条件。 5. 检查依赖库的版本兼容性,确保没有冲突。 例如,在TensorFlow中,如果输入尺寸为H,步长S,卷积核大小K,那么当使用padding='same'时,输出尺寸为ceil(H/S)。为了保证H + padding_total >= (ceil(H/S) -1)*S + K,即padding_total >= (ceil(H/S) -1)*S + K - H。如果H=5,S=2,K=3,那么输出尺寸为ceil(5/2)=3。所需的总padding为 (3-1)*2 +3 -5 = 2*2 +3 -5=4+3-5=2,所以padding_total=2,分为左右各1。这样就能正常工作。但如果H=6,S=2,K=3,padding_total= (3-1)*2 +3 -6=4+3-6=1,这样总padding是1,分为0和1,此时也能工作。 但如果H=7,S=3,K=3,那么输出尺寸是ceil(7/3)=3。总padding= (3-1)*3 +3 -7=6+3-7=2,所以padding_total=2,分为1和1。这样没问题。但如果H=8,S=3,K=3,则输出尺寸为ceil(8/3)=3。总padding= (3-1)*3 +3 -8=6+3-8=1。这时候padding_total=1,分为0和1,这也可以处理。 但如果输入尺寸无法满足这样的情况,比如H=5,S=3,K=3,输出尺寸是ceil(5/3)=2。总padding= (2-1)*3 +3 -5=3+3-5=1。这时候padding_total=1,分成0和1。没有问题。 但如果当H和S的组合导致总padding为负数,比如H=3,S=3,K=3。此时输出尺寸为1。总padding= (1-1)*3 +3 -3=0+3-3=0,没问题。 所以,可能的问题出现在输入尺寸、步长和卷积核大小的组合导致padding无法正确计算。例如,当H=4,S=3,K=3时,输出尺寸是ceil(4/3)=2。总padding= (2-1)*3 +3 -4=3+3-4=2。所以padding是2,分成1和1,没问题。所以可能用户的情况是输入尺寸在某些维度上无法满足这样的计算,导致错误。 另一个可能性是,用户在使用转置卷积(反卷积)时,设置padding='same',此时计算方式不同,可能更容易出现错误。例如,在转置卷积中,输出尺寸的计算涉及到更多的参数,如output_padding等。 此外,在PyTorch中,padding参数需要是整数,当使用padding='same'时,可能用户自己实现的代码或者第三方库有误。因为PyTorch的官方Conv2d的padding参数只接受int或tuple,不支持字符串,所以可能需要用户自己计算padding值。 例如,在PyTorch中要实现与TensorFlow的padding='same'相同效果,可能需要手动计算padding值。例如,对于输入尺寸H,卷积核大小K,步长S,padding的计算为: padding = ((H - 1)*S - H + K) // 2 这可能在某些情况下出现奇数的情况,需要调整。 或者,可能存在其他层的影响,比如池化层后的尺寸变化导致后续卷积层的输入尺寸不符合要求。 综上所述,可能的解决方案包括: 1. 检查输入尺寸是否合理,调整输入尺寸使其满足 (H + padding_total) 能够被步长整除或者符合框架的计算方式。 2. 手动计算padding值,而不是依赖padding='same'。 3. 更新框架版本,以修复可能的bug。 4. 检查依赖库版本是否正确,避免版本冲突。 例如,在TensorFlow中,可以尝试手动计算padding: 对于H_in,希望H_out = ceil(H_in / S) 则: padding_needed = max( (H_out - 1)*S + K - H_in, 0 ) padding_top = padding_needed // 2 padding_bottom = padding_needed - padding_top 然后在卷积层中使用padding='valid',并在输入前使用ZeroPadding2D层添加计算出的padding。 或者在PyTorch中,使用nn.ZeroPad2d来手动添加padding,再使用卷积层。 例如,对于一个输入尺寸为(256, 256),卷积核3x3,步长2,padding='same'的情况: H_out = ceil(256 / 2) = 128 padding_needed = (128 - 1)*2 +3 -256 = 254 +3 -256 = 1 所以,上下各padding 0和1,或者左右各0和1。 因此,在PyTorch中可以设置padding=(0,1,0,1)或者其他方式。 如果用户在使用时没有正确计算这些值,就会出现错误。因此,建议用户手动计算并设置padding,或者调整输入尺寸。 另外,用户可能需要检查是否在模型的其他部分,如池化层,改变了输入尺寸,导致后续卷积层的输入尺寸不符合要求。例如,一个卷积层后面接一个池化层,再后面另一个卷积层,可能导致尺寸无法满足。 最后,用户可能需要提供具体的错误信息,以便更准确地诊断问题。例如,错误信息可能指出具体的张量形状不符合预期,这时候需要根据错误提示调整相应的层参数或输入尺寸。</think>### 解决使用`padding='same'`的步进卷积时的ValueError 在使用TensorFlow或PyTorch进行步进卷积(strided convolutions)时,若设置`padding='same'`出现`ValueError`,通常与**输入尺寸、卷积核大小、步长的组合不兼容**有关。以下是具体原因及解决方案: --- ### 原因分析 1. **输入尺寸与步长不兼容** `padding='same'`的目标是保持输出尺寸为`ceil(输入尺寸/步长)`。若输入尺寸无法满足以下条件,则会导致计算出的填充(padding)非整数或无效: $$ \text{总填充} = (\text{输出尺寸} - 1) \times \text{步长} + \text{卷积核大小} - \text{输入尺寸} $$ 当总填充为负数或奇数时,框架可能无法自动分配填充值[^1]。 2. **框架版本问题** 旧版本的TensorFlow/PyTorch可能存在对`padding='same'`的支持缺陷,例如无法处理特定步长和输入尺寸的组合。 3. **依赖库版本冲突** 若环境中的依赖项(如NumPy、Protobuf)版本不兼容,可能间接引发形状计算错误[^2]。 --- ### 解决方案 #### 1. 手动计算并设置填充值 若自动填充失败,可手动计算所需填充值: - **TensorFlow**示例: ```python # 计算padding def calculate_same_padding(input_size, kernel_size, stride): output_size = (input_size + stride - 1) // stride # ceil(input_size/stride) total_padding = max((output_size - 1) * stride + kernel_size - input_size, 0) return total_padding // 2, total_padding - total_padding // 2 # 分配左右/上下填充 pad_top, pad_bottom = calculate_same_padding(256, 3, 2) pad_left, pad_right = calculate_same_padding(256, 3, 2) model = tf.keras.Sequential([ tf.keras.layers.ZeroPadding2D(padding=((pad_top, pad_bottom), (pad_left, pad_right))), tf.keras.layers.Conv2D(filters=32, kernel_size=3, strides=2, padding='valid') ]) ``` - **PyTorch**示例: ```python import torch.nn as nn class CustomConv(nn.Module): def __init__(self, in_channels, out_channels, kernel_size, stride): super().__init__() self.pad_top, self.pad_bottom = calculate_same_padding(256, 3, 2) self.pad_left, self.pad_right = calculate_same_padding(256, 3, 2) self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding=0) def forward(self, x): x = nn.functional.pad(x, (self.pad_left, self.pad_right, self.pad_top, self.pad_bottom)) return self.conv(x) ``` #### 2. 调整输入尺寸 确保输入的长宽满足: $$ \text{输入尺寸} + \text{总填充} \equiv 0 \ (\text{mod}\ \text{步长}) $$ 例如,若步长为2,输入尺寸应为偶数,或通过裁剪/填充调整为偶数。 #### 3. 更新框架版本 升级TensorFlow/PyTorch至最新版本,修复已知问题: ```bash # TensorFlow pip install --upgrade tensorflow # PyTorch conda install pytorch torchvision torchaudio -c pytorch ``` #### 4. 检查依赖项兼容性 确保依赖库版本匹配(参考TensorFlow官方文档或错误提示): ```bash pip install numpy==1.16.1 protobuf==3.20.* h5py==2.9.0 ``` --- ### 示例代码(TensorFlow) ```python import tensorflow as tf # 输入尺寸为256x256,步长为2,卷积核3x3 inputs = tf.keras.Input(shape=(256, 256, 3)) x = tf.keras.layers.Conv2D(32, 3, strides=2, padding='same')(inputs) model = tf.keras.Model(inputs=inputs, outputs=x) # 若报错,改用手动填充 pad_top = 0 # 根据calculate_same_padding计算结果调整 pad_bottom = 1 pad_left = 0 pad_right = 1 inputs = tf.keras.Input(shape=(256, 256, 3)) x = tf.keras.layers.ZeroPadding2D(((pad_top, pad_bottom), (pad_left, pad_right)))(inputs) x = tf.keras.layers.Conv2D(32, 3, strides=2, padding='valid')(x) model = tf.keras.Model(inputs=inputs, outputs=x) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值