tape.gradient返回的渐变在“自定义训练循环”中为“无”

时间:2020-06-12 13:33:22

标签: python tensorflow neural-network conv-neural-network tf.keras

我正在尝试实现加权二进制交叉熵损失函数 另外,我在训练中使用了自定义训练循环

def grads_ds(model_ds, ds_inputs,y_true,cw):
    with tf.GradientTape() as ds_tape:
        #ds_tape.watch(tf.convert_to_tensor(y_true.astype('float')))
        #ds_tape.watch(tf.convert_to_tensor(ds_inputs))

        y_pred = model_ds(ds_inputs)
        #print(y_true,y_pred)

        log_logits = np.append(np.log(y_pred),np.log(1-y_pred),axis=0).T
        org_labs = np.append(y_true,1-y_true,axis=0).T
        loss = K.sum(-1*org_labs*cw*log_logits,axis=1)
        loss_value_ds = K.sum(loss)

    ds_grads = ds_tape.gradient(loss_value_ds,model_ds.trainable_variables)

    return loss_value_ds, ds_grads

y_truey_pred的形状均为(1,3),而cw的形状为(3,2)

cw

[[0.5145 3.6036]
 [1.7163 0.7127]
 [2.4231 0.6708]]

ds_tape.gradient返回None渐变。 我什至尝试为输入添加ds_tape.watch和真实标签y_true。但仍然收到None

在我的网络中,经过一定层后,我使用了tf.math.reduce_max。这可能是问题的根源吗?

还是因为我在张量y_pred上使用了numpy函数?

当目标和源为tf.GradientTape().gradient()时,

None返回UNCONNECTED。我不知道它是如何断开的。

注意:当我使用tf.keras.losses.binary_crossentropy(y_true,y_pred)时,没有发生如上所述的错误。仅当我使用自定义损失计算代码而不是keras函数时,才会发生此错误

有解决方案吗? 我在网络上看不到任何方法。

2 个答案:

答案 0 :(得分:0)

我这样运行您的代码:

import statistics

statistics.median(data)

最终,您的函数返回了一堆import tensorflow as tf import numpy as np K = tf.keras.backend (x_trn,y_trn),(x_val,y_val) = tf.keras.datasets.mnist.load_data() model = get_simple_1conv_1dense_model(x_trn,y_trn) g = grads_ds(model, x_tst, y_tst, cw=1) # hopefully cw=1 makes sense 渐变:

None

但是,原因似乎很简单。在运行时,它产生了一个错误:

(<tf.Tensor: shape=(), dtype=float32, numpy=nan>, [None, None, None, None])

除以零很可能是您的罪魁祸首。

多花点时间,我发现这条线会导致错误:

/path/to/anaconda3/bin/ipython:9: RuntimeWarning: divide by zero encountered in log
  if __name__ == '__main__':
/path/to/anaconda3/bin/ipython:11: RuntimeWarning: invalid value encountered in multiply
  sys.exit(start_ipython())

答案 1 :(得分:0)

我通过使用tf.keras.backend中的函数重写代码来解决了这个问题

def grads_ds(model_ds, ds_inputs,y_true,cw):
    with tf.GradientTape() as ds_tape:
        y_pred = model_ds(ds_inputs)
        logits_1 = -1*y_true*K.log(y_pred)*cw[:,0]
        loss = logits_1 + logits_0
        loss_value_ds = K.sum(loss)
    ds_grads = ds_tape.gradient(loss_value_ds,model_ds.trainable_variables,unconnected_gradients=tf.UnconnectedGradients.NONE)
    return loss_value_ds, ds_grads

故事的寓意:numpy函数不能在张量上使用。如果使用,则计算图不会保持连接状态。