Как видно, я использовал декоратор tf.function в error_giving_notebook, и он выдает ошибку ValueError, в то время как тот же блокнот без каких-либо изменений, за исключением удаления декоратора tf.function, плавно работает в non_problematic_notebook. В чем может быть причина?
Выполнение кода Tensorflow 2.0 дает сообщение «ValueError: функция, украшенная tf.function, пыталась создать переменные не при первом вызове». Что я делаю неправильно?
Ответы (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.Variable (s) создаются (веса, смещение слоя conv) каждый раз, когда вы вызываете
predictions = model(images)
в вашей tf-украшенной функции. Следовательно, исключение.
Один из возможных способов решения этой проблемы - изменить метод сборки и вызова в вашем классе conv2d следующим образом:
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, я предлагаю взглянуть на это
Поскольку вы пытаетесь использовать декоратор функций в TF 2.0, пожалуйста, сразу же включите функцию запуска, используя строку ниже после импорта TensorFlow:
tf.config.experimental_run_functions_eagerly(True)
Поскольку указанное выше устарело (больше не является экспериментальным?), Используйте вместо этого следующее:
tf.config.run_functions_eagerly(True)
Если вы хотите узнать больше, перейдите по этой ссылке.
import tensorflow as tf
, затем tf.config...
- person YScharf; 05.04.2021
@tf.function
для обучающих циклов, есть ли особая причина, по которой вы хотите его использовать? - person Daniel Möller   schedule 12.10.2019tf.gradients
вместо градиентной ленты. Но дляtf.gradients
, чтобы работать, вся модель от начала до конца тоже должна быть графиком. (Что в вашем случае кажется нормальным). Теперь, если ваш код - это только то, что находится в записной книжке, вы действительно можете подумать об использованииmodel.fit()
с обратным вызовом вместо настраиваемого цикла обучения. - person Daniel Möller   schedule 12.10.2019