具有 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 选项吗?
tensorflow Conv2D 中的 padding='same' 到底是啥意思?是最小填充还是 input_shape == output_shape
tf.nn.conv2d 和 tf.nn.max_pool 中 padding 分别为 'VALID' 和 'SAME' 的直觉上的经验和测试代码