我试图在Tensorflow 2.1.0-rc1中使用Spearman相关性创建自定义损失函数。但是,我遇到了“无渐变”错误。我有多个目标。为了避免spearman给nan
给出只有一个唯一值的标签,我只是通过了什么也不做。这是我的代码:
import tensorflow as tf
from scipy.stats import spearmanr
def spear_func(a, b):
return spearmanr(a, b).correlation.astype('float32')
def custom_loss(num_targets):
def custom_rhos(y_true, y_pred):
rhos = tf.constant(0, dtype='float32')
for ind in range(num_targets):
a = tf.slice(y_true, [0, ind], [-1, 1])
a = tf.reshape(a, [-1])
b = tf.slice(y_pred, [0, ind], [-1, 1])
b = tf.reshape(b, [-1])
rhos = tf.cond(tf.equal(tf.argmax(a), tf.argmin(a)),
lambda: rhos, # <-- Here is the problem
lambda: tf.subtract(rhos,
tf.compat.v1.py_func(spear_func, [a, b], Tout=tf.float32)))
return rhos
return custom_rhos
错误消息是:
/tensorflow-2.1.0/python3.6/tensorflow_core/python/keras/optimizer_v2/optimizer_v2.py in _filter_grads(grads_and_vars)
1037 if not filtered:
1038 raise ValueError("No gradients provided for any variable: %s." %
-> 1039 ([v.name for _, v in grads_and_vars],))
1040 if vars_with_empty_grads:
1041 logging.warning(
ValueError: No gradients provided for any variable:
我试图编写自己的spearman函数。但这仍然会产生相同的错误。
from scipy.stats import rankdata
BATCH_SIZE = 4
def custom_loss(num_targets):
def custom_rhos(y_true, y_pred):
rhos = []
for ind in range(num_targets):
a = tf.squeeze(tf.slice(y_true, [0, ind], [-1, 1]))
# a = tf.reshape(a, [-1])
b = tf.squeeze(tf.slice(y_pred, [0, ind], [-1, 1]))
# b = tf.reshape(b, [-1])
rank_a, rank_b = tf.numpy_function(rankdata, [a], Tout=tf.float32), tf.numpy_function(rankdata, [b], Tout=tf.float32)
rho = 1 - 6 * tf.reduce_sum((rank_a - rank_b) ** 2) / (BATCH_SIZE ** 3 - BATCH_SIZE)
rhos.append(rho)
return -tf.reduce_sum(rhos)
return custom_rhos