numpy Tensorflow Keras TypeError:渴望执行tf,无支撑形状的常数

h7appiyu  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(119)

我的目标是使用以下代码对具有自定义形状和自定义内核的数组执行Conv2d

import tensorflow as tf
import numpy as np
import sys
tf.compat.v1.enable_eager_execution()

# kernel
kernel_array = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]])
kernel = tf.keras.initializers.Constant(kernel_array)
print('kernel shape:', kernel_array.shape)
print('kernel:',kernel_array)

# input
input_shape = (3, 3, 4, 1)
x = tf.random.normal(input_shape)
print('x shape:', x.shape)
print('x:',x.numpy())

# output
y = tf.keras.layers.Conv2D(
    3, kernel_array.shape, padding="same", strides=(1, 1),
    kernel_initializer=kernel,
    input_shape=input_shape[1:])(x)
print('y shape:', y.shape)
print('y:',y.numpy())

上面的代码给予我一个这样的错误:

kernel shape: (3, 3)
kernel: [[1 1 1]
 [1 1 1]
 [1 1 1]]
x shape: (3, 3, 4, 1)
x: [[[[-0.01953345]
   [-0.7110965 ]
   [ 0.15634525]
   [ 0.1707633 ]]

  [[-0.70654714]
   [ 2.7564087 ]
   [ 0.60063267]
   [ 2.8321717 ]]

  [[ 1.4761941 ]
   [ 0.34693545]
   [ 0.85550934]
   [ 2.2514896 ]]]

 [[[ 0.82585895]
   [-0.6421492 ]
   [ 1.2688193 ]
   [-0.9054445 ]]

  [[ 1.1591591 ]
   [ 0.7465941 ]
   [ 1.2531661 ]
   [ 2.2717664 ]]

  [[-0.48740315]
   [-0.42796597]
   [ 0.4480274 ]
   [-1.1502023 ]]]

 [[[-0.7792355 ]
   [-0.801604  ]
   [ 1.6724508 ]
   [ 0.25857568]]

  [[ 0.09068593]
   [-0.4783198 ]
   [-0.02883703]
   [-2.1400564 ]]

  [[-0.5518157 ]
   [-1.4513488 ]
   [-0.07611077]
   [ 1.4752681 ]]]]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[6], line 19
     16 print('x:',x.numpy())
     18 # output
---> 19 y = tf.keras.layers.Conv2D(
     20     3, kernel_array.shape, padding="same", strides=(1, 1),
     21     kernel_initializer=kernel,
     22     input_shape=input_shape[1:])(x)
     23 print('y shape:', y.shape)
     24 print('y:',y.numpy())

File c:\Users\xxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\utils\traceback_utils.py:70, in filter_traceback..error_handler(*args, **kwargs)
     67     filtered_tb = _process_traceback_frames(e.__traceback__)
     68     # To get the full stack trace, call:
     69     # `tf.debugging.disable_traceback_filtering()`
---> 70     raise e.with_traceback(filtered_tb) from None
     71 finally:
     72     del filtered_tb

File c:\Users\xxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\keras\initializers\initializers.py:265, in Constant.__call__(self, shape, dtype, **kwargs)
    261 if layout:
    262     return utils.call_with_layout(
    263         tf.constant, layout, self.value, shape=shape, dtype=dtype
    264     )
--> 265 return tf.constant(self.value, dtype=_get_dtype(dtype), shape=shape)

TypeError: Eager execution of tf.constant with unsupported shape. Tensor [[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]] (converted from [[1 1 1]
 [1 1 1]
 [1 1 1]]) has 9 elements, but got `shape` (3, 3, 1, 3) with 27 elements).

我不知道错在哪里。我已经尝试改变输入形状,但仍然没有工作了。我错过了什么?

sf6xfgos

sf6xfgos1#

从代码的这一部分:

y = tf.keras.layers.Conv2D(
    3, kernel_array.shape,
...

我们看到,您正在尝试使用形状为(3, 3)的内核进行卷积,并使用3个过滤器。这意味着,在您的输出中,您最终将获得3个通道。然而,我们从x.shape看到输入有1个通道。因此,我们的内核必须处理3x3窗口中图像的卷积,从1个通道到3个通道。把这些放在一起,这就是为什么我们有(3, 3, 1, 3)的形状。

换句话说,这就是Tensorflow中2D卷积的内核应该是什么样子:(kernel_x, kernel_y, input_channels, output_channels)

不妨试着这样想:如果你的内核没有最后3个维度来处理输出通道,那么当你卷积的时候,它是如何从1个通道变成3个通道的呢?唯一的逻辑可能性可能是使用相同的内核3次产生相同的3个通道。但这说不通
所以你可以做一些事情:
1.拥有一个具有正确形状的内核初始化器(考虑内核形状、输入通道和输出通道)

# kernel
kernel_array = np.ones((3, 3, 1, 3))
kernel = tf.keras.initializers.Constant(kernel_array)

1.更改输出通道数

y = tf.keras.layers.Conv2D(
    1, (3, 3), padding="same", strides=(1, 1),
    kernel_initializer=kernel,
    input_shape=input_shape[1:])(x)

1.初始化时忽略形状并更改卷积的执行方式:

# kernel
kernel = tf.keras.initializers.Constant(1.)
...
y = tf.keras.layers.Conv2D(
    3, (3, 3), padding="same", strides=(1, 1),
    kernel_initializer=kernel,
    input_shape=input_shape[1:])(x)

根据您的最终目标和您希望的运营灵活性,这些解决方案中的每一个都将提供可行的结果。

相关问题