pytorch和tensorflow对于Conv2d卷积的差异

两者的差异主要体现在padding上,卷积本身是没有差异

注:此处只对比说明padding为‘same’和‘valid’,stride为1和2,kernel为1和3的情况,对于更大的stride和kernel,可能会不一样,目前没有测试,可以根据本测试方法另行测试。

1、对于卷积核为1×1的情况,两者没有差异

2、对于padding为valid模式的情况,两者没有差异

3、对于步长(stride)为1的情况,两者没有差异

4、对于输入为奇数分辨率(如输入为 225*225*channals )的情况,两者没有差异

5、对于输入为偶数分辨率(如输入为 224*224*channals )的情况,两者有差异,具体如下:

注:此情况下为same模式,3×3卷积核,步长(stride)为2

对于这种情况,卷积需要进行单边填充(假设只填充1行和1列,填充3行和3列是一样的),而pytorch和tensorflow对填充的边是不一样的,pytorch是对左边和上边进行填充,而tensorflow是对右边和下边进行填充

 

                   pytorch和tensorflow对于Conv2d卷积的差异_第1张图片                           pytorch和tensorflow对于Conv2d卷积的差异_第2张图片

具体测试代码:

import torch
import torch.nn.functional as F
import torchvision.transforms as transforms
import tensorflow as tf
import numpy as np
from tensorflow.keras import initializers


def model_th(x, kernel_init):
    x = F.conv2d(x, weight=kernel_init, stride=2, padding=1)

    return x


def model_tf(k_init):
    kernel_init = initializers.Constant(k_init)

    x0 = tf.keras.layers.Input(shape=[6, 6, 1])
    x = tf.pad(x0, paddings=[[0, 0], [1, 0], [1, 0], [0, 0]])
    x = tf.keras.layers.Conv2D(filters=32, kernel_size=3, strides=2, padding='valid', use_bias=False, kernel_initializer=kernel_init)(x)

    out = tf.keras.models.Model(inputs=x0, outputs=x)

    return out


if __name__ == '__main__':
    img = np.random.uniform(0, 255, [6, 6, 1])

    kernel = np.random.uniform(-5, 5, [32, 1, 3, 3])

    tf_kernel = kernel.transpose([2, 3, 1, 0])
    th_kernel = torch.from_numpy(kernel).float()

    totensor = transforms.ToTensor()
    th_img = totensor(img).unsqueeze(0).float()
    tf_img = tf.expand_dims(img, axis=0)
    tf_img = tf.cast(tf_img, tf.float32)

    th_out = model_th(th_img, th_kernel)
    tf_out = model_tf(tf_kernel)(tf_img)

    print('--------------out-------------------')
    # print(tf_out)
    # print(th_out.permute([0, 2, 3, 1]))
    print(tf_out.numpy() - th_out.permute([0, 2, 3, 1]).numpy())

 

你可能感兴趣的:(pytorch,tensorflow,深度学习)