无法将数据输入自定义损失:急切执行函数的输入不能是 Keras 符号张量
Can't input data to custom loss: Inputs to eager execution function cannot be Keras symbolic tensors
当我测试我的tensorflow keras custom loss(使用额外的输入数据来计算损失)时,如下:
@tf.function
def build_walker_loss(labeled_output_t, unlabeled_output_t, label):
similarity = tf.matmul(labeled_output_t, unlabeled_output_t, transpose_b=True)
transition_prob_to_unlabeled = tf.nn.softmax(similarity, name="transition_prob_to_unlabeled")
transition_prob_to_labeled = tf.nn.softmax(tf.transpose(similarity), name="transition_prob_to_labeled")
roundtrip_prob = tf.matmul(transition_prob_to_unlabeled, transition_prob_to_labeled, name="roundtrip_prob")
label = tf.reshape(label, [-1, 1])
target_distribution = tf.cast(tf.equal(label, tf.transpose(label)),dtype=tf.float32)
num_class = tf.compat.v1.reduce_sum(target_distribution, axis=1, keep_dims=True)
target_distribution = target_distribution / num_class
loss = tf.keras.losses.categorical_crossentropy(from_logits=False,
y_true = target_distribution,
y_pred = tf.math.log(1e-8 + roundtrip_prob),
)
print(loss)
return loss
X = np.random.uniform(0,1, (1000,10))
y = np.random.uniform(0,1, 1000)
W = np.random.uniform(1,2, 1000)
inp = Input((10,))
true = Input((10,))
sample_weight = Input((10,))
x = Dense(32, activation='relu')(inp)
out = Dense(10)(x)
print(true)
print(out)
m = Model([inp,true, sample_weight], out)
m.add_loss( build_walker_loss( true, out, sample_weight ) )
m.compile(loss=None, optimizer='adam')
我收到一条错误消息:
_SymbolicException Traceback (most recent call last)
<ipython-input-13-a0b380ce314d> in <module>
37 print(out)
38 m = Model([inp,true, sample_weight], out)
---> 39 m.add_loss( build_walker_loss( true, out, sample_weight ) )
40 m.compile(loss=None, optimizer='adam')
41 # history = m.fit([X, y, W], y=None, epochs=10)
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\def_function.py in __call__(self, *args, **kwds)
578 xla_context.Exit()
579 else:
--> 580 result = self._call(*args, **kwds)
581
582 if tracing_count == self._get_tracing_count():
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\def_function.py in _call(self, *args, **kwds)
648 *args, **kwds)
649 # If we did not create any variables the trace we have is good enough.
--> 650 return self._concrete_stateful_fn._filtered_call(canon_args, canon_kwds) # pylint: disable=protected-access
651
652 def fn_with_cond(*inner_args, **inner_kwds):
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\function.py in _filtered_call(self, args, kwargs)
1663 if isinstance(t, (ops.Tensor,
1664 resource_variable_ops.BaseResourceVariable))),
-> 1665 self.captured_inputs)
1666
1667 def _call_flat(self, args, captured_inputs, cancellation_manager=None):
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\function.py in _call_flat(self, args, captured_inputs, cancellation_manager)
1744 # No tape is watching; skip to running the function.
1745 return self._build_call_outputs(self._inference_function.call(
-> 1746 ctx, args, cancellation_manager=cancellation_manager))
1747 forward_backward = self._select_forward_and_backward_functions(
1748 args,
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\function.py in call(self, ctx, args, cancellation_manager)
596 inputs=args,
597 attrs=attrs,
--> 598 ctx=ctx)
599 else:
600 outputs = execute.execute_with_cancellation(
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
72 raise core._SymbolicException(
73 "Inputs to eager execution function cannot be Keras symbolic "
---> 74 "tensors, but found {}".format(keras_symbolic_tensors))
75 raise e
76 # pylint: enable=protected-access
_SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'input_14:0' shape=(None, 10) dtype=float32>, <tf.Tensor 'dense_9/Identity:0' shape=(None, 10) dtype=float32>, <tf.Tensor 'input_15:0' shape=(None, 10) dtype=float32>]
我按照中的答案,但是没有考虑输入数据的正确性,当我将mse loss改成自己的损失函数时,还是报这个错。
我不知道是哪一步让我的功能出错了。
我该怎么做才能将此损失函数添加到我的模型中?
我试过你的代码,但得到了一个不同的错误:
TypeError: You are passing
KerasTensor(type_spec=TensorSpec(shape=(None, 10), dtype=tf.float32,
name='true'), name='true', description="created by layer 'true'"), an
intermediate Keras symbolic input/output, to a TF API that does not
allow registering custom dispatchers, such as tf.cond
,
tf.function
, gradient tapes, or tf.map_fn
.
这意味着问题出在 @tf.function
。如果你注释掉这一行,它将起作用
可以通过子类化 tf.keras.losses.Loss
来创建自定义损失。以这种方式产生的损失可以直接传递给优化器。让我用焦点损失 (arXiv:1708.02002) 的例子来证明这一点。
class focal_loss(tf.keras.losses.Loss):
# function to initilize loss parameters
def __init__(self, gamma):
super().__init__()
self.gamma = gamma
# function to evaluate loss
# must accept exectly 3 parameters: true labels, predicted labels, and, possible,samples weights
# must return loss value
def __call__(self, y_true, y_pred, sample_weight=None):
entropy = tf.keras.losses.binary_crossentropy( y_true, y_pred )
focal_weight = tf.reduce_sum( y_true*tf.math.pow((1-y_pred),self.gamma), axis=-1 )
loss = tf.math.multiply(entropy,focal_weight)
# use sample weights, if provided
if sample_weight is not None:
sample_weight = tf.squeeze(sample_weight)
loss = tf.math.multiply(loss,sample_weight)
loss = tf.math.reduce_sum( loss )
return loss
此外,您可以将其直接传递给优化器:
f_loss = focal_loss(2.)
model.compile(loss=f_loss, optimizer='adam')
如果以这种方式重写你的损失不起作用,那么这显然是一个实现错误(以你计算损失的方式)。需要更仔细的研究。
当我测试我的tensorflow keras custom loss(使用额外的输入数据来计算损失)时,如下:
@tf.function
def build_walker_loss(labeled_output_t, unlabeled_output_t, label):
similarity = tf.matmul(labeled_output_t, unlabeled_output_t, transpose_b=True)
transition_prob_to_unlabeled = tf.nn.softmax(similarity, name="transition_prob_to_unlabeled")
transition_prob_to_labeled = tf.nn.softmax(tf.transpose(similarity), name="transition_prob_to_labeled")
roundtrip_prob = tf.matmul(transition_prob_to_unlabeled, transition_prob_to_labeled, name="roundtrip_prob")
label = tf.reshape(label, [-1, 1])
target_distribution = tf.cast(tf.equal(label, tf.transpose(label)),dtype=tf.float32)
num_class = tf.compat.v1.reduce_sum(target_distribution, axis=1, keep_dims=True)
target_distribution = target_distribution / num_class
loss = tf.keras.losses.categorical_crossentropy(from_logits=False,
y_true = target_distribution,
y_pred = tf.math.log(1e-8 + roundtrip_prob),
)
print(loss)
return loss
X = np.random.uniform(0,1, (1000,10))
y = np.random.uniform(0,1, 1000)
W = np.random.uniform(1,2, 1000)
inp = Input((10,))
true = Input((10,))
sample_weight = Input((10,))
x = Dense(32, activation='relu')(inp)
out = Dense(10)(x)
print(true)
print(out)
m = Model([inp,true, sample_weight], out)
m.add_loss( build_walker_loss( true, out, sample_weight ) )
m.compile(loss=None, optimizer='adam')
我收到一条错误消息:
_SymbolicException Traceback (most recent call last)
<ipython-input-13-a0b380ce314d> in <module>
37 print(out)
38 m = Model([inp,true, sample_weight], out)
---> 39 m.add_loss( build_walker_loss( true, out, sample_weight ) )
40 m.compile(loss=None, optimizer='adam')
41 # history = m.fit([X, y, W], y=None, epochs=10)
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\def_function.py in __call__(self, *args, **kwds)
578 xla_context.Exit()
579 else:
--> 580 result = self._call(*args, **kwds)
581
582 if tracing_count == self._get_tracing_count():
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\def_function.py in _call(self, *args, **kwds)
648 *args, **kwds)
649 # If we did not create any variables the trace we have is good enough.
--> 650 return self._concrete_stateful_fn._filtered_call(canon_args, canon_kwds) # pylint: disable=protected-access
651
652 def fn_with_cond(*inner_args, **inner_kwds):
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\function.py in _filtered_call(self, args, kwargs)
1663 if isinstance(t, (ops.Tensor,
1664 resource_variable_ops.BaseResourceVariable))),
-> 1665 self.captured_inputs)
1666
1667 def _call_flat(self, args, captured_inputs, cancellation_manager=None):
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\function.py in _call_flat(self, args, captured_inputs, cancellation_manager)
1744 # No tape is watching; skip to running the function.
1745 return self._build_call_outputs(self._inference_function.call(
-> 1746 ctx, args, cancellation_manager=cancellation_manager))
1747 forward_backward = self._select_forward_and_backward_functions(
1748 args,
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\function.py in call(self, ctx, args, cancellation_manager)
596 inputs=args,
597 attrs=attrs,
--> 598 ctx=ctx)
599 else:
600 outputs = execute.execute_with_cancellation(
E:\Anaconda3\envs\lrc\lib\site-packages\tensorflow\python\eager\execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
72 raise core._SymbolicException(
73 "Inputs to eager execution function cannot be Keras symbolic "
---> 74 "tensors, but found {}".format(keras_symbolic_tensors))
75 raise e
76 # pylint: enable=protected-access
_SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'input_14:0' shape=(None, 10) dtype=float32>, <tf.Tensor 'dense_9/Identity:0' shape=(None, 10) dtype=float32>, <tf.Tensor 'input_15:0' shape=(None, 10) dtype=float32>]
我按照
我不知道是哪一步让我的功能出错了。 我该怎么做才能将此损失函数添加到我的模型中?
我试过你的代码,但得到了一个不同的错误:
TypeError: You are passing KerasTensor(type_spec=TensorSpec(shape=(None, 10), dtype=tf.float32, name='true'), name='true', description="created by layer 'true'"), an intermediate Keras symbolic input/output, to a TF API that does not allow registering custom dispatchers, such as
tf.cond
,tf.function
, gradient tapes, ortf.map_fn
.
这意味着问题出在 @tf.function
。如果你注释掉这一行,它将起作用
可以通过子类化 tf.keras.losses.Loss
来创建自定义损失。以这种方式产生的损失可以直接传递给优化器。让我用焦点损失 (arXiv:1708.02002) 的例子来证明这一点。
class focal_loss(tf.keras.losses.Loss):
# function to initilize loss parameters
def __init__(self, gamma):
super().__init__()
self.gamma = gamma
# function to evaluate loss
# must accept exectly 3 parameters: true labels, predicted labels, and, possible,samples weights
# must return loss value
def __call__(self, y_true, y_pred, sample_weight=None):
entropy = tf.keras.losses.binary_crossentropy( y_true, y_pred )
focal_weight = tf.reduce_sum( y_true*tf.math.pow((1-y_pred),self.gamma), axis=-1 )
loss = tf.math.multiply(entropy,focal_weight)
# use sample weights, if provided
if sample_weight is not None:
sample_weight = tf.squeeze(sample_weight)
loss = tf.math.multiply(loss,sample_weight)
loss = tf.math.reduce_sum( loss )
return loss
此外,您可以将其直接传递给优化器:
f_loss = focal_loss(2.)
model.compile(loss=f_loss, optimizer='adam')
如果以这种方式重写你的损失不起作用,那么这显然是一个实现错误(以你计算损失的方式)。需要更仔细的研究。