可以看出,我在'error_giving_notebook'中使用了tf.function装饰器,它抛出ValueError,而同一笔记本没有任何更改,只是删除了tf.function装饰器在'non_problematic_notebook'中运行流畅。可能是什么原因?
答案 0 :(得分:2)
这里的问题在于conv2d类的调用方法的返回值:
if self.bias:
if self.pad == 'REFLECT':
self.p = (self.filter_size - 1) // 2
self.x = tf.pad(inputs, [[0, 0], [self.p, self.p], [self.p, self.p], [0, 0]], 'REFLECT')
return Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride),
padding='VALID', use_bias=True, kernel_initializer=self.w, bias_initializer=self.b)(self.x)
else:
return Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride),
padding=self.pad, use_bias=True, kernel_initializer=self.w, bias_initializer=self.b)(inputs)
else:
if self.pad == 'REFLECT':
self.p = (self.filter_size - 1) // 2
self.x = tf.pad(inputs, [[0, 0], [self.p, self.p], [self.p, self.p], [0, 0]], 'REFLECT')
return Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride),
padding='VALID', use_bias=False, kernel_initializer=self.w)(self.x)
else:
return Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride),
padding=self.pad, use_bias=False, kernel_initializer=self.w)(inputs)
通过返回一个Conv2D对象tf。每次调用时都会创建变量(权重,conv层的偏差)
predictions = model(images)
用tf装饰的功能中的。因此,例外。
解决此问题的一种可能方法是更改conv2d类中的build和call方法,如下所示:
def build(self, inputs):
self.w = tf.random_normal_initializer(mean=0.0, stddev=1e-4)
if self.bias:
self.b = tf.constant_initializer(0.0)
else:
self.b = None
self.conv_a = Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride), padding='VALID', use_bias=True, kernel_initializer=self.w, bias_initializer=self.b)
self.conv_b = Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride), padding=self.pad, use_bias=True, kernel_initializer=self.w, bias_initializer=self.b)
self.conv_c = Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride), padding='VALID', use_bias=False, kernel_initializer=self.w)
self.conv_d = Conv2D(filters=self.filter_num, kernel_size=(self.filter_size, self.filter_size), strides=(self.stride, self.stride),padding=self.pad, use_bias=False, kernel_initializer=self.w)
def call(self, inputs):
if self.bias:
if self.pad == 'REFLECT':
self.p = (self.filter_size - 1) // 2
self.x = tf.pad(inputs, [[0, 0], [self.p, self.p], [self.p, self.p], [0, 0]], 'REFLECT')
return self.conv_a(self.x)
else:
return self.conv_b(inputs)
else:
if self.pad == 'REFLECT':
self.p = (self.filter_size - 1) // 2
self.x = tf.pad(inputs, [[0, 0], [self.p, self.p], [self.p, self.p], [0, 0]], 'REFLECT')
return self.conv_c(self.x)
else:
return self.conv_d(inputs)
为了更好地了解AutoGraph以及@ tf.function的工作原理,我建议看看this
答案 1 :(得分:2)
当您尝试在TF 2.0中使用函数装饰器时,请在导入TensorFlow之后通过使用以下行急于启用运行功能:
tf.config.experimental_run_functions_eagerly(True)
如果您想了解更多信息,请参考this链接。