TypeError: <tf.Tensor ‘model/attention_layer/Reshape:0’ shape=(50, 1) dtype=float32> is out of scope and cannot be used here. Use return values, explicit Python locals or TensorFlow collections to access it.
Please see https://www.tensorflow.org/guide/function#all_outputs_of_a_tffunction_must_be_return_values for more information.
我们先了解一下tensorflow的泄露问题
x = None
@tf.function
def leaky_function(a):
global x
x = a + 1 # Bad - leaks local tensor
return a + 2
correct_a = leaky_function(tf.constant(1))
print(correct_a.numpy()) # Good - value obtained from function's returns
try:
x.numpy() # Bad - tensor leaked from inside the function, cannot be used here
except AttributeError as expected:
print(expected)
这段代码是一个使用TensorFlow的Python函数。它定义了一个名为leaky_function
的函数,该函数接受一个参数a
,并返回a+2
。在函数内部,它还定义了一个名为x
的全局变量,并将其设置为a+1
。但是,由于这个变量是在函数内部定义的,因此它只能在函数内部使用。如果您尝试在函数外部访问它,您将收到一个错误消息。
这段代码中的问题是,在函数内部定义的变量x
泄漏到了全局作用域中。这意味着,即使您无法从函数外部访问它,但在其他地方定义的代码可能会意外地使用它。为了解决这个问题,可以将变量定义为局部变量,或者将其作为函数返回值返回。
对于这段代码:
class AttentionLayer(Layer):
def __init__(self, attention_size=None, **kwargs):
self.attention_size = attention_size
super(AttentionLayer, self).__init__(**kwargs)
def get_config(self):
config = super().get_config()
config['attention_size'] = self.attention_size
return config
def build(self, input_shape):
assert len(input_shape) == 3
self.time_steps = input_shape[1]
hidden_size = input_shape[2]
if self.attention_size is None:
self.attention_size = hidden_size
self.W = self.add_weight(name='att_weight', shape=(hidden_size, self.attention_size),
initializer='uniform', trainable=True)
self.b = self.add_weight(name='att_bias', shape=(self.attention_size,),
initializer='uniform', trainable=True)
self.V = self.add_weight(name='att_var', shape=(self.attention_size,),
initializer='uniform', trainable=True)
super(AttentionLayer, self).build(input_shape)
def call(self, inputs):
self.V = K.reshape(self.V, (-1, 1))
H = K.tanh(K.dot(inputs, self.W) + self.b)
score = K.softmax(K.dot(H, self.V), axis=1)
outputs = K.sum(score * inputs, axis=1)
return outputs
def compute_output_shape(self, input_shape):
return input_shape[0], input_shape[2]
attention = AttentionLayer(attention_size=50)(layer)
修改办法:
为了避免这个错误,您可以使用Python本地变量来存储self.V
的新形状,并且不要修改该层的权重。例如,在call
方法中,您可以创建一个名为v
的新变量来存储V
的新形状,并在稍后的运算中使用它,例如:
def call(self, inputs):
v = K.reshape(self.V, (-1, 1))
H = K.tanh(K.dot(inputs, self.W) + self.b)
score = K.softmax(K.dot(H, v), axis=1)
outputs = K.sum(score * inputs, axis=1)
return outputs
这样就避免了将self.V
重新分配给一个新的形状,并且可以确保不会修改该层的权重。