首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自定义训练循环中tape.gradient返回的渐变为None

自定义训练循环中tape.gradient返回的渐变为None
EN

Stack Overflow用户
提问于 2020-06-12 21:33:23
回答 2查看 426关注 0票数 0

我正在尝试实现一个加权的二进制交叉熵损失函数,我正在使用一个自定义的训练循环进行训练

代码语言:javascript
复制
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

代码语言:javascript
复制
[[0.5145 3.6036]
 [1.7163 0.7127]
 [2.4231 0.6708]]

ds_tape.gradient正在返回None渐变。我甚至尝试为输入和真正的标签y_true添加ds_tape.watch。但仍在接收None

在我的网络中,我在某个层之后使用了tf.math.reduce_max。这会是问题的根源吗?

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

当目标和源为UNCONNECTED时,tf.GradientTape().gradient()返回None。我搞不懂它是怎么断线的。

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

有什么解决方案吗?我在网上看到的方法都不管用。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-12 22:32:32

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

代码语言:javascript
复制
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函数不能用于张量。如果使用,计算图将不会保持连接。

票数 0
EN

Stack Overflow用户

发布于 2020-06-12 21:59:43

我像这样运行你的代码:

代码语言:javascript
复制
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渐变:

代码语言:javascript
复制
(<tf.Tensor: shape=(), dtype=float32, numpy=nan>, [None, None, None, None])

然而,原因似乎相当简单。在运行时,它产生了一个错误:

代码语言:javascript
复制
/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())

除以0很可能是你的罪魁祸首。

通过更多的欺骗,我发现这一行导致了错误:

代码语言:javascript
复制
log_logits = np.append(np.log(y_pred),np.log(1-y_pred),axis=0).T
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62345351

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档