具有 padding='SAME' 的 Tensorflow/Keras Conv2D 层表现异常

Posted

技术标签:

【中文标题】具有 padding=\'SAME\' 的 Tensorflow/Keras Conv2D 层表现异常【英文标题】:Tensorflow/Keras Conv2D layers with padding='SAME' behave strangely具有 padding='SAME' 的 Tensorflow/Keras Conv2D 层表现异常 【发布时间】:2020-06-05 00:18:03 【问题描述】:

我的问题:

我进行的一个简单实验表明,在 Keras/TF 的 conv2d 层中使用 padding='SAME' 与在前面的零填充层中使用 padding='VALID' 是不同的。

    这怎么可能? Keras/TF 是否在张量周围对称填充零?

实验说明 - 如果您有兴趣进一步阅读:

我使用onnx2keras 包将我的 Pytorch 模型转换为 keras/TF。

onnx2keras 在 ONNX 模型中遇到带有 padding > 0 的卷积层时,它会将其转换为 Keras 的 Conv2D 并带有 valid 填充(即没有填充!),前面是 Keras 的 ZeroPadding2D 层.这非常有效,并且返回的输出与 Pytorch 网络产生的输出相同。

我觉得奇怪的是它没有简单地使用 padding='SAME',因为大多数参考资料都说 Keras/TF 使用零填充,就像 Pytorch 一样。

尽管如此,我修补了onnx2keras 并让它产生了我的Conv2D 层与padding='SAME',而不是现有的'VALID' 填充解决方案与前面的零填充层。这使得生成的模型返回的输出与具有零填充层的模型不同,当然也与我的 Pytorch 模型不同,后者在补丁之前是相同的。

【问题讨论】:

根据documentation,“valid”没有填充,而“same”导致填充输入,使输出与原始输入具有相同的长度。 @nickthefreak 当然。但我希望“相同”的工作方式与在卷积之前手动添加填充层然后使用“有效”时相同,但这不是发生的情况 @SomethingSomething - 如果您发布您试验过的简单的可重现代码,就会清楚地解释或识别错误。 【参考方案1】:

padding='Same' 在 Keras 中表示当输入大小和内核大小不完全匹配时,根据需要添加填充以弥补重叠。

padding='Same' 的示例:

# Importing dependency
import keras
from keras.models import Sequential
from keras.layers import Conv2D

# Create a sequential model
model = Sequential()

# Convolutional Layer
model.add(Conv2D(filters=24, input_shape=(5,5,1), kernel_size=(2,2), strides =(2,2) ,padding='Same'))

# Model Summary
model.summary()

代码的输出-

Model: "sequential_20"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_28 (Conv2D)           (None, 3, 3, 24)          120       
=================================================================
Total params: 120
Trainable params: 120
Non-trainable params: 0
_________________________________________________________________

图示: 下图显示了当 padding='Same' 时输入 (input_shape=(5,5,1), kernel_size=(2,2), strides =(2,2)) 的填充情况。

----------------------------------------------- -------------------------------------------------- -----------------

Keras 中的padding='Valid' 表示不添加填充。

padding='Valid' 的示例: Conv2D 使用的输入与我们上面用于 padding = 'Same' 的输入相同。即(input_shape=(5,5,1), kernel_size=(2,2), strides =(2,2))

# Importing dependency
import keras
from keras.models import Sequential
from keras.layers import Conv2D

# Create a sequential model
model = Sequential()

# Convolutional Layer
model.add(Conv2D(filters=24, input_shape=(5,5,1), kernel_size=(2,2), strides =(2,2) ,padding='Valid'))

# Model Summary
model.summary()

代码的输出-

Model: "sequential_21"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_29 (Conv2D)           (None, 2, 2, 24)          120       
=================================================================
Total params: 120
Trainable params: 120
Non-trainable params: 0
_________________________________________________________________

图示: 下图显示,当 padding='Valid' 时,输入 (input_shape=(5,5,1), kernel_size=(2,2), strides =(2,2)) 没有添加填充。

----------------------------------------------- -------------------------------------------------- -----------------

现在让我们尝试使用与 padding='Valid' 相同的代码作为输入 (input_shape=(6,6,1), kernel_size=(2,2), strides =(2,2))。 此处padding='Valid' 的行为应与padding='Same' 相同。

代码 -

# Importing dependency
import keras
from keras.models import Sequential
from keras.layers import Conv2D

# Create a sequential model
model = Sequential()

# Convolutional Layer
model.add(Conv2D(filters=24, input_shape=(6,6,1), kernel_size=(2,2), strides =(2,2) ,padding='Valid'))

# Model Summary
model.summary()

代码的输出-

Model: "sequential_22"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_30 (Conv2D)           (None, 3, 3, 24)          120       
=================================================================
Total params: 120
Trainable params: 120
Non-trainable params: 0
_________________________________________________________________

【讨论】:

非常感谢您提供非常详细的回答。那么如果我从第一个图中理解正确的话,TF中的填充是通过复制右下角向量来完成的? 是的。你是对的。 padding='Same' 导致填充输入,以使内核覆盖 input_shape=(5,5,1) 且 Stride=(2,2) 的所有像素。如果 Stride=(1,1) 那么,padding='Same' 会填充输入,以使输出与原始输入具有相同的长度。 很高兴知道。这与 PyTorch 相矛盾,PyTorch 用零填充。这就是onnx2keras 将带有填充的 conv2d 层转换为 TF 中两个不同层的原因 - 首先是零填充层,然后是“有效”的 conv2d 层

以上是关于具有 padding='SAME' 的 Tensorflow/Keras Conv2D 层表现异常的主要内容,如果未能解决你的问题,请参考以下文章

在pytorch中实现与TensorFlow类似的"same"方式padding

padding='same' 和 strides > 1 的 tf.keras.layers.Conv2D 表现如何?

PyTorch 的 Conv2d 真的没有 padding=same 选项吗?

keras中卷积的两种padding方式

tensorflow Conv2D 中的 padding='same' 到底是啥意思?是最小填充还是 input_shape == output_shape

tf.nn.conv2d 和 tf.nn.max_pool 中 padding 分别为 'VALID' 和 'SAME' 的直觉上的经验和测试代码