自定义损失函数没有梯度

时间:2020-01-09 15:30:32

标签: python tensorflow keras

我试图在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

0 个答案:

没有答案