自定义 Keras 层中的 ValueError

ValueError in Custom Keras Layer

我为小批量标准差实现了一个自定义层:

class MinibatchStd(Layer): 
def __init__(self, group_size=4, epsilon=1e-8): 

    super(MinibatchStd, self).__init__() 
    self.epsilon = epsilon 
    self.group_size = group_size 
    
def call(self, input_tensor): 
    
    n, h, w, c = input_tensor.shape 
    self.group_size = tf.keras.backend.minimum(self.group_size, tf.cast(input_tensor[0], dtype=tf.int32))
    x = tf.reshape(input_tensor, [self.group_size, -1, h, w, c]) 
    group_mean, group_var = tf.nn.moments(x, axes=(0), keepdims=False) 
    group_std = tf.sqrt(group_var + self.epsilon) 
    avg_std = tf.reduce_mean(group_std, axis=[1,2,3], keepdims=True) 
    x = tf.tile(avg_std, [self.group_size, h, w, 1]) 

    return tf.concat([input_tensor, x], axis=-1) 

执行后出现如下错误:

ValueError: in user code:

<ipython-input-30-9b80a1ea4799>:20 call  *
    x = tf.reshape(input_tensor, [self.group_size, -1, h, w, c])
C:\ProgramData\Anaconda3\envs\gputest\lib\site-packages\tensorflow\python\ops\array_ops.py:193 reshape  **
    result = gen_array_ops.reshape(tensor, shape, name)
C:\ProgramData\Anaconda3\envs\gputest\lib\site-packages\tensorflow\python\ops\gen_array_ops.py:8087 reshape
    "Reshape", tensor=tensor, shape=shape, name=name)
C:\ProgramData\Anaconda3\envs\gputest\lib\site-packages\tensorflow\python\framework\op_def_library.py:488 _apply_op_helper
    (input_name, err))

ValueError: Tried to convert 'shape' to a tensor and failed. Error: Shapes must be equal rank, but are 3 and 0
    From merging shape 0 with other shapes. for '{{node minibatch_std_4/Reshape/packed}} = Pack[N=5, T=DT_INT32, axis=0](minibatch_std_4/Minimum, minibatch_std_4/Reshape/packed/1, minibatch_std_4/Reshape/packed/2, minibatch_std_4/Reshape/packed/3, minibatch_std_4/Reshape/packed/4)' with input shapes: [4,4,256], [], [], [], [].

它只在我添加行时出现:

self.group_size = tf.keras.backend.minimum(self.group_size, tf.cast(input_tensor[0], dtype=tf.int32))

我也试过tf.math.minimum但也失败了。

我用Keras = 2.4.3TF = 2.2.0

有两种方法可以获得某些张量的张量形状(比如 x):x.shapetf.shape(x)。这两者根本不同:前者简单地returns一个python形状的列表,后者在动态计算图中添加一个op,包括None维度的占位符[=16] =]

简而言之,而不是

 n, h, w, c = input_tensor.shape

使用

 shape = tf.shape(input_tensor)
 n = shape[0]
 h = shape[1]
 w = shape[2]
 c = shape[3]