首页 > 解决方案 > Keras 中的 conv2d 和 Conv2D 有什么区别?

问题描述

我对 Keras 感到Conv2D困惑conv2d。它们之间有什么区别?我认为第一个是层,第二个是后端功能,但这是什么意思?在 Conv2D 中,我们发送过滤器的数量、过滤器的大小和步幅(Conv2D(64,(3,3),stride=(8,8))(input))但在 conv2d 中,我们使用conv2d(input, kernel, stride=(8,8))内核是什么(64,3,3),我们将过滤器的数量和大小放在一起?我应该在哪里输入内核?你能帮我解决这个问题吗?谢谢。

pytorch中的代码

def apply_conv(self, image, filter_type: str):

        if filter_type == 'dct':
            filters = self.dct_conv_weights
        elif filter_type == 'idct':
            filters = self.idct_conv_weights
        else:
            raise('Unknown filter_type value.')

        image_conv_channels = []
        for channel in range(image.shape[1]):
            image_yuv_ch = image[:, channel, :, :].unsqueeze_(1)
            image_conv = F.conv2d(image_yuv_ch, filters, stride=8)
            image_conv = image_conv.permute(0, 2, 3, 1)
            image_conv = image_conv.view(image_conv.shape[0], image_conv.shape[1], image_conv.shape[2], 8, 8)
            image_conv = image_conv.permute(0, 1, 3, 2, 4)
            image_conv = image_conv.contiguous().view(image_conv.shape[0],
                                                  image_conv.shape[1]*image_conv.shape[2],
                                                  image_conv.shape[3]*image_conv.shape[4])

            image_conv.unsqueeze_(1)

            # image_conv = F.conv2d()
            image_conv_channels.append(image_conv)

        image_conv_stacked = torch.cat(image_conv_channels, dim=1)

        return image_conv_stacked

Keras 中更改的代码

def apply_conv(self, image, filter_type: str):

        if filter_type == 'dct':
            filters = self.dct_conv_weights
        elif filter_type == 'idct':
            filters = self.idct_conv_weights
        else:
            raise('Unknown filter_type value.')
        print(image.shape)

        image_conv_channels = []
        for channel in range(image.shape[1]):
            print(image.shape)
            print(channel)
            image_yuv_ch = K.expand_dims(image[:, channel, :, :],1)
            print( image_yuv_ch.shape)
            print(filters.shape)
            image_conv = Kr.backend.conv2d(image_yuv_ch,filters,strides=(8,8),data_format='channels_first')
           image_conv = Kr.backend.permute_dimensions(image_conv,(0, 2, 3, 1))
            image_conv = Kr.backend.reshape(image_conv,(image_conv.shape[0], image_conv.shape[1], image_conv.shape[2], 8, 8))
            image_conv =  Kr.backend.permute_dimensions(image_conv,(0, 1, 3, 2, 4))
            image_conv = Kr.backend.reshape(image_conv,(image_conv.shape[0],
                                                  image_conv.shape[1]*image_conv.shape[2],
                                                  image_conv.shape[3]*image_conv.shape[4]))

            Kr.backend.expand_dims(image_conv,1)

            # image_conv = F.conv2d()
            image_conv_channels.append(image_conv)

        image_conv_stacked = Kr.backend.concatenate(image_conv_channels, axis=1)

        return image_conv_stacked

但是当我执行代码时,它会产生以下错误:

回溯(最近一次通话最后):

文件“”,第 383 行,在 decoded_noise=JpegCompression()(act11)#16

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\base_layer.py”,第 457 行,调用 输出 = self.call(inputs, **kwargs)

文件“”,第 169 行,调用 image_dct = self.apply_conv(noised_image, 'dct')

文件“”,第 132 行,在 apply_conv image_conv = Kr.backend.conv2d(image_yuv_ch,filters,strides=(8,8),data_format='channels_first')

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\keras\backend\tensorflow_backend.py”,第 3650 行,conv2d data_format=tf_data_format)

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\ops\nn_ops.py”,第 779 行,卷积 data_format=data_format)

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\ops\nn_ops.py”,第 839 行,在init filter_shape[num_spatial_dims]))

ValueError:输入通道的数量与过滤器的相应维度不匹配,1!= 8

新代码

for channel in range(image.shape[1]):
            image_yuv_ch = K.expand_dims(image[:, channel, :, :],axis=1)
            image_yuv_ch = K.permute_dimensions(image_yuv_ch, (0, 2, 3, 1))
            image_conv = tf.keras.backend.conv2d(image_yuv_ch,kernel=filters,strides=(8,8),padding='same')
            image_conv = tf.keras.backend.reshape(image_conv,(image_conv.shape[0],image_conv.shape[1], image_conv.shape[2],8,8))

错误:

回溯(最近一次通话最后):

文件“”,第 263 行,在 decoded_noise=JpegCompression()(act11)#16

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\base_layer.py”,第 457 行,调用 输出 = self.call(inputs, **kwargs)

文件“”,第 166 行,调用 image_dct = self.apply_conv(noised_image, 'dct')

文件“”,第 128 行,在 apply_conv image_conv = tf.keras.backend.reshape(image_conv,(image_conv.shape[0],image_conv.shape[1], image_conv.shape[2],8,8))

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\keras\backend.py”,第 2281 行,reshape return array_ops.reshape(x, shape)

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\ops\gen_array_ops.py”,第 6482 行,在 reshape “Reshape”中,tensor=tensor,shape=shape,name=name )

_apply_op_helper 中的文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\framework\op_def_library.py”,第 513 行,引发错误

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\framework\op_def_library.py”,第 510 行,在 _apply_op_helper preferred_dtype=default_dtype 中)

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\framework\ops.py”,第 1146 行,internal_convert_to_tensor ret = conversion_func(value, dtype=dtype, name=name, as_ref =as_ref)

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\framework\constant_op.py”,第 229 行,在 _constant_tensor_conversion_function 返回常量(v,dtype=dtype,name=name)

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\framework\constant_op.py”,第 208 行,常量值,dtype=dtype,shape=shape,verify_shape=verify_shape))

文件“D:\software\Anaconda3\envs\py36\lib\site-packages\tensorflow\python\framework\tensor_util.py”,第 531 行,make_tensor_proto“支持的类型”。%(类型(值),值))

TypeError:无法将类型对象转换为张量。内容:(维度(无)、维度(4)、维度(4)、8、8)。考虑将元素转换为支持的类型。

标签: pythontensorflowkeras

解决方案


Tensorflow 和 Keras 现在都在使用channel_last约定。因此,首先您应该将通道调暗到最后使用K.permute_dimension. 您可以在 colab.research.google.com 中尝试此代码来弄清楚自己。

第一个问题:

  • conv2d是执行 2D 卷积文档的函数
  • keras.layers.Conv2D()Conv2D将返回执行卷积功能的类的实例。在这里查看更多
# The second 
import keras
conv_layer = keras.layers.Conv2D(filters=64, kernel_size=8, strides=(4, 4), padding='same')

基本上,它们的定义方式和使用方式都不同。在对某些输入应用卷积时在K.conv2d内部使用,例如.keras.layers.Conv2Dconv_layerxconv_layer

say_hello下面的示例可以帮助您更轻松地理解和之间的区别SayHello

def say_hello(word, name):
    print(word, name)


class SayHello():

    def __init__(self, word='Hello'):
        self.word = word
        pass

    def __call__(self, name):
        say_hello(self.word, name)


say_hello('Hello', 'Nadia') #Hello Nadia

sayhello = SayHello(word='Hello') # you will get an instance `sayhello` from class SayHello

sayhello('Nadia') # Hello Nadia

第二个问题:

  • kernel这是一个形状张量 (kernel_size, kernel_size, in_channels, out_channels)
  • 如果你想得到image_conv形状 (8, 8, 64) 那么strides=(4,4).
import tensorflow as tf
import tensorflow.keras.backend as K

image = tf.random_normal((10,3, 32, 32))
print(image.shape) # shape=(10, 3, 32, 32)

channel = 1
image_yuv_ch = K.expand_dims(image[:, channel,:,:], axis=1) # shape=(10, 1, 32, 32)
image_yuv_ch = K.permute_dimensions(image_yuv_ch, (0, 2, 3, 1)) # shape=(10, 32, 32, 1)

# The first K.conv2d
in_channels = 1
out_channels = 64 # same as filters
kernel = tf.random_normal((8, 8, in_channels, out_channels)) # shape=(8, 8, 1, 64)

image_conv = tf.keras.backend.conv2d(image_yuv_ch, kernel=kernel, strides=(4, 4), padding='same')
print(image_conv.shape) #shape=(10, 8, 8, 64)


# The second 
import keras
conv_layer = keras.layers.Conv2D(filters=64, kernel_size=8, strides=(4, 4), padding='same')
image_conv = conv_layer(image_yuv_ch)
print(image_conv.shape) #shape=(10, 8, 8, 64)

推荐阅读