张量流梯度 - 获取所有 nan 值
tensorflow gradient - getting all nan values
我在 anaconda 中使用 python 3,在 eager eval 中使用 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
。
我检查了 y_pred
是否由合法值组成 - 确实如此。
我尝试创建相对于自身的 y_pred * 2
的渐变并获得合法的渐变值。
我在这里错过了什么?距离矩阵创建中的索引是否有问题?
编辑:
y_pred
和loss
的数据类型都是tf.float32
编辑:在 tf 中发现了一个 open bug report - 这可能是问题所在吗?
编辑:
当我将范数轴更改为 0 或 1 时,我得到了合法值并且没有任何内容进入 nan
。我使用 norm with axis=2
的操作是矩阵中行对之间的成对距离,我怀疑这可能与行与自身之间的 0 距离有关,所以我用 min 剪裁了这些值1e-7 的值没有任何运气。
谢谢
tf.norm 似乎存在数值不稳定问题,正如 here
所解释的那样
他们还建议使用数值更稳定的 l2 范数,所以我试了一下,也得到了 nan 值,这要归功于 0 梯度。所以我将它们与梯度裁剪一起使用,到目前为止一切顺利,损失函数正在运行并设法收敛。
def last_attempt(y_true, y_pred):
import tensorflow as tf
import numpy as 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
该功能还有很大的优化空间,这里是对我的其他功能的参考 - 正在处理中。
我在 anaconda 中使用 python 3,在 eager eval 中使用 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
。
我检查了 y_pred
是否由合法值组成 - 确实如此。
我尝试创建相对于自身的 y_pred * 2
的渐变并获得合法的渐变值。
我在这里错过了什么?距离矩阵创建中的索引是否有问题?
编辑:
y_pred
和loss
的数据类型都是tf.float32
编辑:在 tf 中发现了一个 open bug report - 这可能是问题所在吗?
编辑:
当我将范数轴更改为 0 或 1 时,我得到了合法值并且没有任何内容进入 nan
。我使用 norm with axis=2
的操作是矩阵中行对之间的成对距离,我怀疑这可能与行与自身之间的 0 距离有关,所以我用 min 剪裁了这些值1e-7 的值没有任何运气。
谢谢
tf.norm 似乎存在数值不稳定问题,正如 here
所解释的那样他们还建议使用数值更稳定的 l2 范数,所以我试了一下,也得到了 nan 值,这要归功于 0 梯度。所以我将它们与梯度裁剪一起使用,到目前为止一切顺利,损失函数正在运行并设法收敛。
def last_attempt(y_true, y_pred):
import tensorflow as tf
import numpy as 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
该功能还有很大的优化空间,这里是对我的其他功能的参考