代码之家  ›  专栏  ›  技术社区  ›  thebeancounter

TensorFlow梯度-获取所有NaN值

  •  2
  • thebeancounter  · 技术社区  · 7 年前

    我用的是蟒蛇3和蟒蛇,用的是TensorFlow 1.12。

    我正在使用它为暹罗网络创建一个三重丢失函数,需要计算不同数据样本之间的距离。

    我创建了一个函数来创建距离计算,但是不管我做什么,当我试图计算它相对于网络输出的梯度时,它总是给我所有的NaN梯度。

    这是代码:

    def matrix_row_wise_norm(matrix):
        import tensorflow as tf
        tensor = tf.expand_dims(matrix, -1)
    
        tensor = tf.transpose(tensor, [0, 2, 1]) - tf.transpose(tensor, [2, 0, 1])
        norm = tf.norm(tensor, axis=2)
        return norm
    

    在我使用的损失函数中

    def loss(y_true, p_pred):
        with tf.GradientTape() as t:
        t.watch(y_pred)
            distance_matrix = matrix_row_wise_norm(y_pred)
            grad = t.gradient(distance_matrix, y_pred)
    

    毕业生就是这样 nan S. 我检查过了 y_pred 是由合法的价值观构成的——确实如此。 我试图创造一个梯度 y_pred * 2 关于它本身,得到了合法的梯度值。

    我这里缺什么?创建距离矩阵的索引有问题吗?


    编辑:

    两者的数据类型 耶普雷德 loss tf.float32

    编辑:找到一个 open bug report 在特遣部队,这会是问题吗?


    编辑:

    当我把范数轴改为0或1时,我得到了合法的值,但没有任何结果。 . 我要用Norm做的手术 axis=2 是矩阵中行对之间的成对距离,我怀疑这可能与行与自身之间的0距离有关,所以我用最小值1e-7剪裁了这些值,但没有任何运气。

    谢谢

    1 回复  |  直到 7 年前
        1
  •  0
  •   thebeancounter    7 年前

    似乎tf.norm受到了数字不稳定性的影响 here

    他们还建议使用更稳定的数值的l2范数,所以我尝试了这个方法,也得到了NaN值,这要归功于0梯度。所以我把它们和梯度削波结合起来,到目前为止效果很好,损失函数起作用,并设法收敛。

    定义最后一次尝试(是,是pred): 将TensorFlow导入为tf 将numpy导入为np

    loss = tf.zeros(1)
    
    for i in range(y_pred.shape[0]):
        dist = tf.gather(y_pred, [i], axis=0)
        y = y_true.numpy().squeeze()
        norm = tf.map_fn(tf.nn.l2_loss, dist-y_pred)
    
        d = norm.numpy()
        d[np.where(y != y[i])] = 0.0
        max_pos = tf.gather(norm, np.argmax(d))
    
        d = norm.numpy()
        d[np.where(y == y[i])] = np.inf
        min_neg = tf.gather(norm, np.argmin(d))
    
        loss += tf.clip_by_value(max_pos - min_neg + tf.constant(1, dtype=tf.float32),
                                 1e-8, 1e1)
    
    return loss
    

    有很大的空间优化这个函数,这里有一个参考我的另一个 SO question -正在努力。

    谢谢大家